Garry's Mod Wiki

Revision Difference

Derma_Skin_Creation#515821

<cat>Dev.UI</cat> # Introduction As a developer you may be familiar with <page>PANEL:Paint</page> and <page>PANEL:PaintOver</page>. They are functions to draw your Derma objects. But one day you wanted to make your own Derma design. You may think that redrawing is too complicated: <page>surface</page>, <page>draw</page>, <page>render</page>. So many functions, aren't they? Is there a way to make it easier and fancy? Yes, this page will show you how to create your own Derma Skin. Exactly same method uses default Derma and it's defined in Lua. # How Derma skins work? First thing to know, they're located in `"garrysmod/lua/skins/"`. Default Derma skin is in "default.lua". It contains [UV texture mapping](https://en.wikipedia.org/wiki/UV_mapping), <page>Global.Color</page> definitions and <page text="Derma Hooks">derma/SkinHook</page>. UV mapping is possible through <page>GWEN</page>. Some GWEN functions require a <page>IMaterial</page> in last argument, but it can be empty: GWEN will use **SKIN.GwenTexture** variable instead. Default skin texture can be found in **Garry's Mod .vpk** file in `"materials/gwenskin/gmoddefault.png"`. Inside file there're bunch of Derma Hooks. They're used in conjunction with <page>derma.SkinHook</page> (used in <page>Global.Derma_Hook</page>). ## Example This is in **"default.lua"**. ``` function SKIN:PaintFrame( panel, w, h ) if ( panel.m_bPaintShadow ) then -- This is DFrame shadow DisableClipping( true ) SKIN.tex.Shadow( -4, -4, w+10, h+10 ) -- This is drawing function, that contains a piece of our texture DisableClipping( false ) end if ( panel:HasHierarchicalFocus() ) then -- Checks if DFrame is in focus and decide how to paint it self.tex.Window.Normal( 0, 0, w, h ) -- This is drawing function, that contains a piece of our texture else self.tex.Window.Inactive( 0, 0, w, h ) -- This is drawing function, that contains a piece of our texture end end ``` And this is in `"lua/vgui/**dframe.lua**"` where <page>DFrame</page> is defined. ``` function PANEL:Paint( w, h ) -- ... derma.SkinHook( "Paint", "Frame", self, w, h ) -- This creates hook to derma library, derma library is connected to our skin -- ... end ``` ---- Last thing that skin file does is adding skin to Derma skins list. This action is done by <page>derma.DefineSkin</page>. # Preparing to create Derma skin 1. Get [Adobe Photoshop](https://www.adobe.com/products/photoshop.html) 1. Extract `"materials/gwenskin/gmoddefault.psd"` (You can do this with [GCFScape](http://nemesis.thewavelength.net/index.php?p=26)) 1. Copy code (or file) from `"lua/skins/**default.lua**"` 1. Create lua file in `"lua/skins/"`. For this tutorial we will name it **"myskin.lua"**. 1. Create lua file in `"lua/autorun/"`. You can name it how you want it, just make it unique, for example **"myskin_include.lua"**. ## Code for myskin_include.lua ``` if SERVER then AddCSLuaFile("skins/myskin.lua") else include("skins/myskin.lua") end ``` This file adds our skin to whitelist for server and includes for client on load. # Reference ``` SKIN ``` Table SKIN is a global variable. It's made global to work with <page>GWEN</page>. Table SKIN is a global variable. It's made global to work with <page>GWEN</page>. <page>derma.DefineSkin</page>(skin name, skin description, SKIN table) ``` derma.DefineSkin( "Default", "Made to look like regular VGUI", SKIN ) ``` This function will add your skin to list of all Derma skins. <page>derma.GetSkinTable</page>() ``` for k,v in pairs(derma.GetSkinTable()) do print(k) end -- Prints all defined skins ``` <page>derma.RefreshSkins</page>() This function will clear cache from Derma objects and set their skin again. # Tester snippet To test out your Derma skin you can use this snippet. ``` concommand.Add( "derma_setskin", function(_,_,args) if GetConVar("sv_allowcslua"):GetInt() == 0 then return end for k,v in pairs(vgui.GetWorldPanel():GetChildren()) do v:SetSkin(args[1]) end end,nil,"Sets skin for all Derma objects.") local function deepskin(children,skin) for k,v in pairs(children) do v:SetSkin(skin) if #v:GetChildren() != 0 then deepskin(v:GetChildren(),skin) end end end concommand.Add( "derma_deepsetskin", function(_,_,args) if GetConVar("sv_allowcslua"):GetInt() == 0 then return end deepskin(vgui.GetWorldPanel():GetChildren(),args[1]) end,nil,"Forces skin set for all Derma objects and their children.") concommand.Add( "derma_updateskin", function() if GetConVar("sv_allowcslua"):GetInt() == 0 then return end for k,v in pairs(derma.GetSkinTable()) do if v.GwenTexture then local tex = v.GwenTexture:GetTexture("$basetexture") if tex then tex:Download() end end end derma.RefreshSkins() end,nil,"Updates skins for all Derma objects.") ``` Derma objects can't update themselves because skin that they used is **cached**. Due to skins are being **cached**, Derma objects can't update themselves while you're editing. So we need to clear cache by typing command **derma_updateskin**. Also its material can't update itself, to fix that, it uses <page>ITexture:Download</page>. Function **derma_setskin *skin name*** allows you to apply Derma skin on all Derma object through the console. If some panels didn't update use **derma_deepsetskin *skin name***. For safety, you can't use these functions when **sv_allowcslua is 0**. You can remove this check if you don't forget to remove tester later. To test your skin you can type **derma_controls** to preview. # Part One: SKIN variables SKIN table has a lot of variables. These are for info. SKIN variables. Information variables | -------------------------------------| | PrintName | My New Skin | Name for your skin to display | | Author | Garry Newman | Author of the skin | | DermaVersion | 1 | Version of the skin | | GwenTexture | ``` Material( "gwenskin/GModDefault.png" ) ``` | Texture path of the skin. This is used to draw Derma objects. This is internally used by <page>GWEN</page>. | Next you will see lots of <page>Global.Color</page> variables. But not all of them are actually visible in game. This list contains variables which were tested for changes. SKIN variables. Color variables | -------------------------------| | colTextEntryText | ``` Color( 20, 20, 20 ) ``` | Used for typed text color in <page>DTextEntry</page> and it's derivatives | <note>Color can display incorrectly in game.</note> | | colTextEntryTextHighlight | ``` Color( 20, 200, 250 ) ``` | Used for highlight color in <page>DTextEntry</page> and it's derivatives | <note>Color can display incorrectly in game.</note> | | colTextEntryTextCursor | ``` Color( 0, 0, 100 ) ``` | Used for cursor color in <page>DTextEntry</page> and it's derivatives | | | colTextEntryTextPlaceholder | ``` Color( 128, 128, 128 ) ``` | Used for [SetPlaceholderText](/gmod/DTextEntry/SetPlaceholderText) color in <page>DTextEntry</page> and it's derivatives | <note>Color can display incorrectly in game.</note> | Column "In game" note: `Right filled square represents real color. Left screenshot represents in-game render.` Other Color variables doesn't work because Derma objects use texture instead. <note>ULX uses **SKIN.text_dark** for some labels</note> # Part Two: UV Texture ## Named Textures &lt;center&gt; `UV mapping zones. Can be found in .psd file in folder "Overlay".` <note>Even in UV texture not all of textures are used in GMod!</note>&lt;/center&gt; List of named layers (From left top to right bottom) | ----------------------------------------------------| | style="text-align:center;" | Window (In Focus) | style="text-align:center;" | Window - Active | Texture of <page>DFrame</page> when [HasHierarchicalFocus](/gmod/Panel/HasHierarchicalFocus) is **true** | | style="text-align:center;" | Window (Out Focus) | style="text-align:center;" | Window - Active (copy) | Texture of <page>DFrame</page> when [HasHierarchicalFocus](/gmod/Panel/HasHierarchicalFocus) is **false** | | style="text-align:center;" | Generic Panel (Only left top is used) | style="text-align:center;" | Panels - Generic Panel - Normal | Texture of <page>DPanel</page> by default. This texture can be colored by [SetBackgroundColor](/gmod/DPanel/SetBackgroundColor) | | style="text-align:center;" | Btn Nrml | style="text-align:center;" | Buttons - Regular | Texture of <page>DButton</page> when [IsHovered](/gmod/Panel/IsHovered) is **false** and [IsDown](/gmod/DButton/IsDown) is **false** | | style="text-align:center;" | Btn Hvr | style="text-align:center;" | Buttons - Hovered | Texture of <page>DButton</page> when [IsHovered](/gmod/Panel/IsHovered) is **true** and [IsDown](/gmod/DButton/IsDown) is **false** | | style="text-align:center;" | Btn Dsbld | style="text-align:center;" | Buttons - Dead | Texture of <page>DButton</page> when [IsEnabled](/gmod/Panel/IsEnabled) is **false** | | style="text-align:center;" | Btn Down | style="text-align:center;" | Buttons - Down | Texture of <page>DButton</page> when [IsDown](/gmod/DButton/IsDown) is **true** | | style="text-align:center;" | Chk | style="text-align:center;" | Buttons - Checkbox - Enabled | Textures of <page>DCheckBox</page> when [IsEnabled](/gmod/Panel/IsEnabled) is **true** | | style="text-align:center;" | Chk Dsbld | style="text-align:center;" | Buttons - Checkbox - Disabled | Textures of <page>DCheckBox</page> when [IsEnabled](/gmod/Panel/IsEnabled) is **false** | | style="text-align:center;" | Expnd | style="text-align:center;" | Buttons - Tree | Textures of <page>DExpandButton</page> | | style="text-align:center;" | Tree Background | style="text-align:center;" | Panels - Tree Panel | Texture of <page>DTree</page>. This texture can be colored by [SetBackgroundColor](/gmod/DPanel/SetBackgroundColor) | | style="text-align:center;" | Mnu rght | style="text-align:center;" | Menu - Right Arrow | Texture of Arrow in [AddSubMenu](/gmod/DMenu/AddSubMenu) option <note><page>DMenu</page> doesn't derive panel's skin when called by <page>Global.DermaMenu</page>. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in <page>DMenuBar</page>.</note> | | style="text-align:center;" | Menu Strip | style="text-align:center;" | Menu - MenuStrip | Texture of <page>DMenuBar</page> <note><page>DMenu</page> doesn't derive panel's skin when called by <page>Global.DermaMenu</page>. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in <page>DMenuBar</page>.</note> | | style="text-align:center;" | Menu Background | style="text-align:center;" | Menu - With Border | Texture of <page>DMenuOption</page> when [GetDrawColumn](/gmod/DMenu/GetDrawColumn) is **true** <note><page>DMenu</page> doesn't derive panel's skin when called by <page>Global.DermaMenu</page>. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in <page>DMenuBar</page>.</note> | | style="text-align:center;" | Menu BG No Border | style="text-align:center;" | Menu - Without Border | Texture of <page>DMenuOption</page> when [GetDrawColumn](/gmod/DMenu/GetDrawColumn) is **false** <note><page>DMenu</page> doesn't derive panel's skin when called by <page>Global.DermaMenu</page>. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in <page>DMenuBar</page>.</note> | | style="text-align:center;" | Menu Selected | style="text-align:center;" | Menu - Hover | Texture of <page>DMenuOption</page> when [IsHovered](/gmod/Panel/IsHovered) is **true** <note><page>DMenu</page> doesn't derive panel's skin when called by <page>Global.DermaMenu</page>. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in <page>DMenuBar</page>.</note> | | style="text-align:center;" | Text Entry Normal | style="text-align:center;" | Text Entry - Normal | Texture of <page>DTextEntry</page> when [IsEditing](/gmod/DTextEntry/IsEditing) is **false** | | style="text-align:center;" | Text Entry Focused | style="text-align:center;" | Text Entry - Focus | Texture of <page>DTextEntry</page> when [IsEditing](/gmod/DTextEntry/IsEditing) is **true** | | style="text-align:center;" | Text Entry Disabled | style="text-align:center;" | Text Entry - Disabled | Texture of <page>DTextEntry</page> when [IsEnabled](/gmod/Panel/IsEnabled) is **false** | | style="text-align:center;" | Scroller Track V | style="text-align:center;" | Scrollbar - Vertical | Texture of <page>DVScrollBar</page> track | | style="text-align:center;" | VScrollbar - Normal | style="text-align:center;" | Scrollbar - Vertical | Texture of <page>DVScrollBar</page>**.btnGrip** when [IsHovered](/gmod/Panel/IsHovered) is **false** and [IsDown](/gmod/DButton/IsDown) is **false** | | style="text-align:center;" | VScrollbar - Hovered | style="text-align:center;" | Scrollbar - Vertical | Texture of <page>DVScrollBar</page>**.btnGrip** when [IsHovered](/gmod/Panel/IsHovered) is **true** and [IsDown](/gmod/DButton/IsDown) is **false** | | style="text-align:center;" | VScrollbar - Pressed | style="text-align:center;" | Scrollbar - Vertical | Texture of <page>DVScrollBar</page>**.btnGrip** when [IsDown](/gmod/DButton/IsDown) is **true** | | style="text-align:center;" | VScrollbar - Disabled | style="text-align:center;" | Scrollbar - Vertical | Texture of <page>DVScrollBar</page>**.btnGrip** when [IsEnabled](/gmod/Panel/IsEnabled) is **false** | | style="text-align:center;" | Tab Panel BG | style="text-align:center;" | Tabbed - Body | Texture of <page>DPropertySheet</page> where [GetActiveTab](/gmod/DPropertySheet/GetActiveTab) is docked | | style="text-align:center;" | Tab Top | style="text-align:center;" | Tabbed - Active | Texture of <page>DTab</page> when [IsActive](/gmod/DTab/IsActive) is **true** | | style="text-align:center;" | Unfcs Top | style="text-align:center;" | Tabbed - Inactive | Texture of <page>DTab</page> when [IsActive](/gmod/DTab/IsActive) is **false** | | style="text-align:center;" | List Box | style="text-align:center;" | ListBox - Background | Texture of <page>DListBox</page>. This class is deprecated, but it's still in game | | <note>This list contains only named textures which are used in GMod! For example, RadioButton is not listed here.</note> ## Unnamed Textures &lt;center&gt;&lt;/center&gt; List of unnamed layers | ----------------------| | style="text-align:center;" | 1 | Texture of <page>DProgress</page> main body | | style="text-align:center;" | 2 | Texture of <page>DProgress</page> progress body | | style="text-align:center;" | 3 | Texture of <page>DFrame</page> outside shadow <bug>Will be used shadow texture from last loaded skin! To fix it change **SKIN** in functions **PaintShadow** and **PaintFrame** to **self**.</bug> | | style="text-align:center;" | 4 | Texture of selection for <page>DTree</page> and <page>DIconBrowser</page> | | style="text-align:center;" | 5 | Texture of <page>DTooltip</page> <bug><page>DTooltip</page> doesn't derive panel's skin. So it will be always "Default" skin. Works only when you set skin for it when it's visible.</bug> | | style="text-align:center;" | 6 | Textures of **default**, **hovered** and **pressed** <page>DSlider</page> knob | | style="text-align:center;" | 7 | Unused. Can be texture of vertical slider | | style="text-align:center;" | 8 | Textures of **default**, **hovered** and **pressed** <page>DNumberWang</page> | | style="text-align:center;" | 9 | Texture of <page>DMenu</page> check icon <note><page>DMenu</page> doesn't derive panel's skin when called by <page>Global.DermaMenu</page>. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in <page>DMenuBar</page>.</note> | | style="text-align:center;" | 10 | Textures of **default**, **hovered** and **pressed** <page>DScrollPanel:GetVBar</page> and <page>DHorizontalDivider</page>. Textures of **default**, **hovered** and **pressed** <page>DComboBox</page> button | | style="text-align:center;" | 11 | Texture of selected <page>DListView_Line</page> | | style="text-align:center;" | 12 | Texture of altered <page>DListView_Line</page>. To separate one line from another, DListView automatically color odd lines to slight dark color. Can be called by internal function <page>DListView_Line:SetAltLine</page> | | style="text-align:center;" | 13 | Unused. Can be textures of alternative colors for <page>DListView_Line</page> | | style="text-align:center;" | 14 | Texture of **hovered** <page>DListView_Line</page> | | style="text-align:center;" | 15 | Unused | | style="text-align:center;" | 16 | Texture of **default** <page>DComboBox</page> | | style="text-align:center;" | 17 | Texture of **hovered** <page>DComboBox</page> | | style="text-align:center;" | 18 | Texture of **pressed** <page>DComboBox</page> | | style="text-align:center;" | 19 | Texture of **disabled** <page>DComboBox</page> | | style="text-align:center;" | 20 | Texture of folded <page>DCategoryList</page> and <page>DCollapsibleCategory</page> | | style="text-align:center;" | 21 | Texture of unfolded <page>DCategoryList</page> and <page>DCollapsibleCategory</page> | | style="text-align:center;" | 22 | Texture of <page>DCategoryList</page> body | | style="text-align:center;" | 23 | Unused | | style="text-align:center;" | 24 | Textures of <page>DFrame</page>**.btnClose** button | | style="text-align:center;" | 25 | Textures of <page>DFrame</page>**.btnMinim** button | | style="text-align:center;" | 26 | Textures of <page>DFrame</page>**.btnMaxim** button | | style="text-align:center;" | 27 | Unused. Can be textures of <page>DFrame</page> "Restore" button | ## Color Pallete Texture &lt;center&gt;&lt;/center&gt; Color Pallete Table | -------------------| | rowspan="2" | 1 | A | No Color / Not Used | | B | Color of <page>DFrame</page> title when [HasHierarchicalFocus](/gmod/Panel/HasHierarchicalFocus) is **true** | | rowspan="2" | 2 | A | No Color / Not Used | | B | Color of <page>DFrame</page> title when [HasHierarchicalFocus](/gmod/Panel/HasHierarchicalFocus) is **false** | | rowspan="2" | 3 | A | Color of <page>DButton</page> text when [IsDown](/gmod/DButton/IsDown) is **true** | | B | Color of <page>DButton</page> default text | | rowspan="2" | 4 | A | Color of <page>DButton</page> text when [IsEnabled](/gmod/Panel/IsEnabled) is **false** | | B | Color of <page>DButton</page> text when [IsHovered](/gmod/Panel/IsHovered) is **true** | | rowspan="2" | 5 | A | Color of <page>DTab</page> text when [IsActive](/gmod/DTab/IsActive) is **true** and [IsDown](/gmod/DButton/IsDown) is **true** | | B | Color of <page>DTab</page> default text when [IsActive](/gmod/DTab/IsActive) is **true** | | rowspan="2" | 6 | A | Color of <page>DTab</page> text when [IsActive](/gmod/DTab/IsActive) is **true** and [IsEnabled](/gmod/Panel/IsEnabled) is **false** | | B | Color of <page>DTab</page> text when [IsActive](/gmod/DTab/IsActive) is **true** and [IsHovered](/gmod/Panel/IsHovered) is **true** | | rowspan="2" | 7 | A | Color of <page>DTab</page> text when [IsActive](/gmod/DTab/IsActive) is **false** and [IsDown](/gmod/DButton/IsDown) is **true** | | B | Color of <page>DTab</page> default text when [IsActive](/gmod/DTab/IsActive) is **false** | | rowspan="2" | 8 | A | Color of <page>DTab</page> text when [IsActive](/gmod/DTab/IsActive) is **false** and [IsEnabled](/gmod/Panel/IsEnabled) is **false** | | B | Color of <page>DTab</page> text when [IsActive](/gmod/DTab/IsActive) is **false** and [IsHovered](/gmod/Panel/IsHovered) is **true** | | rowspan="2" | 9 | A | Color of <page>DLabel</page> and <page>DListView_Line</page> label when [GetDark](/gmod/DLabel/GetDark) is **true** | | B | Color of <page>DLabel</page> and <page>DListView_Line</page> label when default | | rowspan="2" | 10 | A | Color of <page>DLabel</page> and <page>DListView_Line</page> label when [GetHighlight](/gmod/DLabel/GetDark) is **true** | | B | Color of <page>DLabel</page> and <page>DListView_Line</page> label when [GetBright](/gmod/DLabel/GetDark) is **true** | | rowspan="2" | 11 | A | Color of <page>DTree_Node_Button</page> text when [IsHovered](/gmod/Panel/IsHovered) is **true** and <page>DForm:ControlHelp</page> text | | B | Not Used. `Colours.Tree.Lines` | | rowspan="2" | 12 | A | Color of <page>DTree_Node_Button</page> text when [IsSelected](/gmod/Panel/IsSelected) is **true** | | B | Color of <page>DTree_Node_Button</page> text when default | | rowspan="2" | 13 | A | Not Used. `Colours.Properties.Line_Hover` | | B | Not Used. `Colours.Properties.Line_Normal` | | rowspan="2" | 14 | A | Color of <page>DProperties</page> category label | | B | Not Used. `Colours.Properties.Line_Selected` | | rowspan="2" | 15 | A | Not Used. `Colours.Properties.Column_Hover` | | B | Not Used. `Colours.Properties.Column_Normal` | | rowspan="2" | 16 | A | Color of <page>DProperties</page> border between rows and columns | | B | Color of <page>DProperties</page> cell when row is being edited | | rowspan="2" | 17 | A | Not Used. `Colours.Properties.Label_Hover` | | B | Color of <page>DProperties</page> cell label when row isn't being edited | | rowspan="2" | 18 | A | No Color / Not Used | | B | Color of <page>DProperties</page> cell label when row is being edited | | rowspan="2" | 19 | A | Color of <page>DCategoryHeader</page> title when [GetExpanded](/gmod/DCollapsibleCategory/GetExpanded) is **false** | | B | Not Used. Named as "ModalBackground" | | rowspan="2" | 20 | A | Color of <page>DCategoryHeader</page> title when [GetExpanded](/gmod/DCollapsibleCategory/GetExpanded) is **true** | | B | Not Used. Named as "TooltipText" (Real tooltip text uses 27A) | | rowspan="2" | 21 | A | Color of <page>DCollapsibleCategory:Add</page> button text when **not Atled** and [IsDown](/gmod/DButton/IsDown) is **true** | | B | Color of <page>DCollapsibleCategory:Add</page> button text when **not Atled** | | rowspan="2" | 22 | A | Not Used. `Colours.Category.Line.Button` | | B | Color of <page>DCollapsibleCategory:Add</page> button text when **not Atled** and [IsHovered](/gmod/Panel/IsHovered) is **true** | | rowspan="2" | 23 | A | Color of <page>DCollapsibleCategory:Add</page> button text when **Atled** | | B | Not Used. `Colours.Category.Line.Button_Hover` | | rowspan="2" | 24 | A | Color of <page>DCollapsibleCategory:Add</page> button text when **Atled** and [IsHovered](/gmod/Panel/IsHovered) is **true** | | B | Not Used. `Colours.Category.Line.Button_Selected` | | rowspan="2" | 25 | A | Not Used. `Colours.Category.LineAlt.Button_Hover` | | B | Color of <page>DCollapsibleCategory:Add</page> button text when **not Atled** and [IsDown](/gmod/DButton/IsDown) is **true** | | rowspan="2" | 26 | A | Not Used. `Colours.Category.LineAlt.Button_Selected` | | B | Not Used. `Colours.Category.LineAlt.Button` | | rowspan="2" | 27 | A | Color of <page>DTooltip</page> text. <bug>Currently broken.</bug> | | B | No Color / Not Used | # Demo For tutorial was created a Demo Addon with Windows 10 UI skin for Derma. You can download it here: [Download from Steam Workshop](https://steamcommunity.com/sharedfiles/filedetails/?id=1633684835) Addon uses this hook for painting all Derma objects: ``` hook.Add("ForceDermaSkin","Windows10SkinForce",function() return "Windows" -- This will paint all Derma objects to new skin end) ``` # Discussion Ask questions, share your skins and more about Derma skins you can find here: [GMod Forum Thread](https://forum.facepunch.com/gmoddev/buvqm/Derma-Skins-Discussion-and-Sharing-Corner/1/)