GUI Skins

From Pragma
Jump to: navigation, search

Description

Pragma's skin system allows you to completely customize the look of all GUI elements (or specific ones) and switch between skins during runtime.

All skins are located in the "lua/gui" directory. They're defined in lua to allow high levels of customization.

Note: GUI skins have their own lua-state,

GUI

. You will not be able to call any server- or client-specific functions!

Applying a skin

There are two ways to apply a skin.

You can change the main GUI skin using gui.SetSkin. This will apply it to all existing GUI elements, as well as all newly created ones.

To only apply a skin to a specific GUI element, you can use WIElement:SetSkin. This way it will be applied to the element, as well as all of its children. Elements with a skin specified this way will not be affected by any further changes through gui.SetSkin.

Creating a new skin

To create a new skin, create a new lua-file in "lua/gui". This file will be loaded automatically when the game is started.

Then, first off all, start by checking if the skin has already been loaded:

local skinName = "testSkin"
if(gui.SkinExists(skinName) == true) then return end
[...]

This makes sure the skin isn't loaded more than once if another skin derives from it. After that, it is recommended to add a table for some global settings. This isn't required, but will make it easier to edit the skin later on:

Settings

[...]
-------------------------------------------
------------ START OF SETTINGS ------------
-------------------------------------------

local t = {}

-- WIButton
t.BUTTON_HEIGHT = 24
t.BUTTON_BACKGROUND_COLOR = Color(255,0,0,255)

-------------------------------------------
------------- END OF SETTINGS -------------
-------------------------------------------
[...]

This is basically just a table with some variables which will be used for the actual skin. Anything that can be defined beforehand should be defined beforehand!

Skin table

The main skin is defined as a table, as such:

[...]
local skin = {}
------------ WIButton ------------
skin["wibutton"] = {
	[...]
}
----------------------------------
[...]

Each key in the table has to be the class name of a GUI element. The example above will apply for all buttons.

To actually do something, you have to specify an "Initialize"-function for each class table:

[...]
local skin = {}
------------ WIButton ------------
skin["wibutton"] = {
	Initialize = function(GUI,pElement)
		pElement:SetHeight(GUI.BUTTON_HEIGHT)

		pElement.m_tSkinElements = {}
		local bg = gui.Create("WIRect",pElement)
		bg:SetColor(GUI.BUTTON_BACKGROUND_COLOR)
		bg:SetName("background")
		bg:SetAutoAlignToParent(true)
		bg:SetZPos(-2)
		table.insert(pElement.m_tSkinElements,bg)
	end,
	Release = function(GUI,pElement)
		if(pElement.m_tSkinElements ~= nil) then
			for _,el in ipairs(pElement.m_tSkinElements) do
				if(el:IsValid()) then el:Remove() end
			end
			pElement.m_tSkinElements = nil
		end
	end
}
----------------------------------
[...]

The code above will set the height of all buttons to 24 pixels and add a red background.

Note: When creating new elements during the "Initialize"-process, make sure to add a "Release"-function as well to remove them when the skin is unloaded!

Nesting

You can also create definitions for child elements for specific parents by using the "children" sub-table:

[...]
local skin = {}
------------ WIButton ------------
skin["wibutton"] = {
	Initialize = function(GUI,pElement)
		[...]
	end,
	Release = function(GUI,pElement)
		[...]
	end,
	children = {
		["witext"] = {
			Initialize = function(GUI,pElement)
				pElement:SetText(pElement:GetText():upper())
				pElement:SizeToContents()
			end
		}
	}
}
----------------------------------
[...]

This will change the text for all "WIText" elements which are parented to a "WIButton" element to uppercase letters. The structure can be nested further in the same way as shown above. Additional children can simply be appended to the "children" sub-table.

Custom style classes

Aside from GUI Element classes, you can also use custom style classes. This works in conjunction with WIElement:AddStyleClass.

[...]
local skin = {}
------------ WIButton ------------
skin["teststyle"] = {
	Initialize = function(GUI,pElement)
		pElement:SetWidth(250)
	end
}
----------------------------------
[...]

Now you can apply "teststyle" to any element using WIElement:AddStyleClass("teststyle"). You can apply multiple style classes on the same element and nesting can be combined with both GUI classes and custom style classes.

Registering a skin

After you have defined the skin tables, you have to register the actual skin. To do that, use:

[...]
gui.RegisterSkin(skinName,t,skin)
[...]

After that you can apply the skin using gui.SetSkin("testSkin") or WIElement:SetSkin("testSkin").

Deriving skins

You can derive a skin from another by specifying the base skin as the third parameter to gui.RegisterSkin (The base skin has to be loaded first!):

if(gui.SkinExists("testSkin2") == true) then return end
include("skin_test.lua")

local t = {}
[...]
local skin = {}
[...]
gui.RegisterSkin("testSkin2",t,skin,"testSkin")

The new skin will inherit all data from the base skin, however base definitions can be overwritten if desired.

See Also