Derma Skin Creation
Introduction
As a developer you may be familiar with PANEL:Paint and PANEL:PaintOver. 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: surface, draw, render. 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, Color definitions and Derma Hooks.
UV mapping is possible through GWEN. Some GWEN functions require a IMaterial 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 derma.SkinHook (used in Derma_Hook).
Example
This is in "default.lua".
And this is in "lua/vgui/dframe.lua"
where DFrame is defined.
Last thing that skin file does is adding skin to Derma skins list. This action is done by derma.DefineSkin.
Preparing to create Derma skin
- Get Adobe Photoshop
- Extract
"materials/gwenskin/gmoddefault.psd"
(You can do this with GCFScape) - Copy code (or file) from
"lua/skins/default.lua"
- Create lua file in
"lua/skins/"
. For this tutorial we will name it "myskin.lua". - 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
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 GWEN.
derma.DefineSkin(skin name, skin description, SKIN table)
This function will add your skin to list of all Derma skins.
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.
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 ITexture:Download.
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 GWEN. |
Next you will see lots of Color 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 DTextEntry and it's derivatives | <note>Color can display incorrectly in game.</note> |
colTextEntryTextHighlight | Color( 20, 200, 250 ) |
Used for highlight color in DTextEntry and it's derivatives | <note>Color can display incorrectly in game.</note> |
colTextEntryTextCursor | Color( 0, 0, 100 ) |
Used for cursor color in DTextEntry and it's derivatives | |
colTextEntryTextPlaceholder | Color( 128, 128, 128 ) |
Used for SetPlaceholderText color in DTextEntry 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.
Part Two: UV Texture
Named Textures
UV mapping zones. Can be found in .psd file in folder "Overlay".
List of named layers (From left top to right bottom) | ||
---|---|---|
Window (In Focus) | Window - Active | Texture of DFrame when HasHierarchicalFocus is true |
Window (Out Focus) | Window - Active (copy) | Texture of DFrame when HasHierarchicalFocus is false |
Generic Panel (Only left top is used) | Panels - Generic Panel - Normal | Texture of DPanel by default. This texture can be colored by SetBackgroundColor |
Btn Nrml | Buttons - Regular | Texture of DButton when IsHovered is false and IsDown is false |
Btn Hvr | Buttons - Hovered | Texture of DButton when IsHovered is true and IsDown is false |
Btn Dsbld | Buttons - Dead | Texture of DButton when IsEnabled is false |
Btn Down | Buttons - Down | Texture of DButton when IsDown is true |
Chk | Buttons - Checkbox - Enabled | Textures of DCheckBox when IsEnabled is true |
Chk Dsbld | Buttons - Checkbox - Disabled | Textures of DCheckBox when IsEnabled is false |
Expnd | Buttons - Tree | Textures of DExpandButton |
Tree Background | Panels - Tree Panel | Texture of DTree. This texture can be colored by SetBackgroundColor |
Mnu rght | Menu - Right Arrow | Texture of Arrow in AddSubMenu option <note>DMenu doesn't derive panel's skin when called by DermaMenu. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in DMenuBar.</note> |
Menu Strip | Menu - MenuStrip | Texture of DMenuBar <note>DMenu doesn't derive panel's skin when called by DermaMenu. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in DMenuBar.</note> |
Menu Background | Menu - With Border | Texture of DMenuOption when GetDrawColumn is true <note>DMenu doesn't derive panel's skin when called by DermaMenu. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in DMenuBar.</note> |
Menu BG No Border | Menu - Without Border | Texture of DMenuOption when GetDrawColumn is false <note>DMenu doesn't derive panel's skin when called by DermaMenu. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in DMenuBar.</note> |
Menu Selected | Menu - Hover | Texture of DMenuOption when IsHovered is true <note>DMenu doesn't derive panel's skin when called by DermaMenu. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in DMenuBar.</note> |
Text Entry Normal | Text Entry - Normal | Texture of DTextEntry when IsEditing is false |
Text Entry Focused | Text Entry - Focus | Texture of DTextEntry when IsEditing is true |
Text Entry Disabled | Text Entry - Disabled | Texture of DTextEntry when IsEnabled is false |
Scroller Track V | Scrollbar - Vertical | Texture of DVScrollBar track |
VScrollbar - Normal | Scrollbar - Vertical | Texture of DVScrollBar.btnGrip when IsHovered is false and IsDown is false |
VScrollbar - Hovered | Scrollbar - Vertical | Texture of DVScrollBar.btnGrip when IsHovered is true and IsDown is false |
VScrollbar - Pressed | Scrollbar - Vertical | Texture of DVScrollBar.btnGrip when IsDown is true |
VScrollbar - Disabled | Scrollbar - Vertical | Texture of DVScrollBar.btnGrip when IsEnabled is false |
Tab Panel BG | Tabbed - Body | Texture of DPropertySheet where GetActiveTab is docked |
Tab Top | Tabbed - Active | Texture of DTab when IsActive is true |
Unfcs Top | Tabbed - Inactive | Texture of DTab when IsActive is false |
List Box | ListBox - Background | Texture of DListBox. This class is deprecated, but it's still in game |
Unnamed Textures
Will be used shadow texture from last loaded skin! To fix it change SKIN in functions PaintShadow and PaintFrame to self.
List of unnamed layers | |
---|---|
1 | Texture of DProgress main body |
2 | Texture of DProgress progress body |
3 | Texture of DFrame outside shadow |
4 | Texture of selection for DTree and DIconBrowser |
5 | Texture of DTooltip <bug>DTooltip 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> |
6 | Textures of default, hovered and pressed DSlider knob |
7 | Unused. Can be texture of vertical slider |
8 | Textures of default, hovered and pressed DNumberWang |
9 | Texture of DMenu check icon <note>DMenu doesn't derive panel's skin when called by DermaMenu. So it will be always "Default" skin. Works only when you set skin for it when it's visible or in DMenuBar.</note> |
10 | Textures of default, hovered and pressed DScrollPanel:GetVBar and DHorizontalDivider. Textures of default, hovered and pressed DComboBox button |
11 | Texture of selected DListView_Line |
12 | Texture of altered DListView_Line. To separate one line from another, DListView automatically color odd lines to slight dark color. Can be called by internal function DListView_Line:SetAltLine |
13 | Unused. Can be textures of alternative colors for DListView_Line |
14 | Texture of hovered DListView_Line |
15 | Unused |
16 | Texture of default DComboBox |
17 | Texture of hovered DComboBox |
18 | Texture of pressed DComboBox |
19 | Texture of disabled DComboBox |
20 | Texture of folded DCategoryList and DCollapsibleCategory |
21 | Texture of unfolded DCategoryList and DCollapsibleCategory |
22 | Texture of DCategoryList body |
23 | Unused |
24 | Textures of DFrame.btnClose button |
25 | Textures of DFrame.btnMinim button |
26 | Textures of DFrame.btnMaxim button |
27 | Unused. Can be textures of DFrame "Restore" button |
Color Palette Texture
Color Palette Table | |
---|---|
1 A | No Color / Not Used |
1 B | Color of DFrame title when HasHierarchicalFocus is true |
2 A | No Color / Not Used |
2 B | Color of DFrame title when HasHierarchicalFocus is false |
3 A | Color of DButton text when IsDown is true |
3 B | Color of DButton default text |
4 A | Color of DButton text when IsEnabled is false |
4 B | Color of DButton text when IsHovered is true |
5 A | Color of DTab text when IsActive is true and IsDown is true |
5 B | Color of DTab default text when IsActive is true |
6 A | Color of DTab text when IsActive is true and IsEnabled is false |
6 B | Color of DTab text when IsActive is true and IsHovered is true |
7 A | Color of DTab text when IsActive is false and IsDown is true |
7 B | Color of DTab default text when IsActive is false |
8 A | Color of DTab text when IsActive is false and IsEnabled is false |
8 B | Color of DTab text when IsActive is false and IsHovered is true |
9 A | Color of DLabel and DListView_Line label when GetDark is true |
9 B | Color of DLabel and DListView_Line label when default |
10 A | Color of DLabel and DListView_Line label when GetHighlight is true |
10 B | Color of DLabel and DListView_Line label when GetBright is true |
11 A | Color of DTree_Node_Button text when IsHovered is true and DForm:ControlHelp text |
11 B | Color of DFileBrowser treeline |
12 A | Color of DTree_Node_Button text when IsSelected is true |
12 B | Color of DTree_Node_Button text when default |
13 A | Not Used. Colours.Properties.Line_Hover |
13 B | Not Used. Colours.Properties.Line_Normal |
14 A | Color of DProperties category label |
14 B | Not Used. Colours.Properties.Line_Selected |
15 A | Not Used. Colours.Properties.Column_Hover |
15 B | Not Used. Colours.Properties.Column_Normal |
16 A | Color of DProperties border between rows and columns |
16 B | Color of DProperties cell when row is being edited |
17 A | Not Used. Colours.Properties.Label_Hover |
17 B | Color of DProperties cell label when row isn't being edited |
18 A | No Color / Not Used |
18 B | Color of DProperties cell label when row is being edited |
19 A | Color of DCategoryHeader title when GetExpanded is false |
19 B | Not Used. Named as "ModalBackground" |
20 A | Color of DCategoryHeader title when GetExpanded is true |
20 B | Not Used. Named as "TooltipText" (Real tooltip text uses 27A) |
21 A | Color of DCollapsibleCategory:Add button text when not Atled and IsDown is true |
21 B | Color of DCollapsibleCategory:Add button text when not Atled |
22 A | Color of DCategoryList:AddItem element when Altered |
22 B | Color of DCollapsibleCategory:Add button text when not Atled and IsHovered is true |
23 A | Color of DCollapsibleCategory:Add button text when Atled |
23 B | Color of DCategoryList:AddItem element when Altered and IsHovered is true |
24 A | Color of DCollapsibleCategory:Add button text when Atled and IsHovered is true |
24 B | Color of DCategoryList:AddItem element when Altered and IsSelected is true |
25 A | Color of DCategoryList:AddItem element when IsHovered is true |
25 B | Color of DCollapsibleCategory:Add button text when not Atled and IsDown is true |
26 A | Color of DCategoryList:AddItem element when IsSelected is true |
26 B | Color of DCategoryList:AddItem element |
27 A | Color of DTooltip text. <bug>Currently broken.</bug> |
27 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.
Addon uses this hook for painting all Derma objects: