UI Skins - Grisgram/gml-raptor GitHub Wiki

What is a UI-Skin?

A set of sprites that define the look of all UI Elements throughout your game. You define the buttons, checkboxes, radiobuttons, window frames, etc...

Everything is skinnable!

Important

In raptor, everything is skinnable! As long as you have _raptorBase somewhere in the inheritance chain of your object, you can skin it.
Even though this chapter is named UI Skins and down this page I will refer to controls mostly, keep in mind, that you can skin anything, that is a _raptorBase.
This includes your player object, enemies, weapons, furniture... it's up to you.
The skins are one of the most powerful features, raptor has to offer!

When raptor applies a skin to an object, it takes care of different sprite sizes and scalings and will scale the new sprite to the exact same size, the former sprite had. It also takes the sprite_xoffset/yoffset into account, so even if they differ, the object will appear at the exact same position, after the skin is applied!
You literally throw "anything" on "any object"... raptor will do its best, to make it look good.

To exclude an object from being skinnable, _raptorBase has a bool variable definition skinnable, where you can turn off skinning for specific instances or entire object types. By default, skinnable is true for all objects.

Why should I use it?

Because this is the most easy way to create a flavored look for the elements of your game.

If you set up multiple skins for your game, you may switch between them at will. As an example, imagine your game plays partially in the "underworld" and on the "surface" of the world. While in the underworld, the UI could look darker, demonic, with fire elements and on the surface it could have a friendly, clean look. Just switch the skin when you switch between surface and underworld, and an effect like this is only an effort of a single line of code!

Use skins, create a SPOT (Single Point of Truth), also called SSOT (Single Source of Truth) for your UI appearance!

The UiSkinManager

One instance of this class is created at game startup for you. You can reach it through the global UI_SKINS macro.
It is used to manage all known skins and offers methods to switch, add, remove or get a skin reference.

UiSkinManager functions

/// @function add_skin(_skin, _activate_now = false)
/// @description Add a skin to the manager. If a skin with the same name already exists,
///              it is overwritten.
/// @function activate_skin(_skin_name)
/// @description Activate a registered skin. Does NOT requires room_restart, works instant!
/// @function remove_skin(_skin_name)
/// @description Delete a registered skin from the manager.
/// @function get_skin(_skin_name)
/// @description Access a registered skin through its name.

Access the currently active skin

Similar to the APP_THEME macro, there is an APP_SKIN macro available, which points to the instance of the active skin.

The UiSkin class

As you can see in the DefaultSkin class, you received with the project template in the _gml_raptor_ui_/skins folder, this is a simple, straightforward class, which just holds a ds_map, that assigns a struct to each control type.

Tip

Read it again: You assign a struct, not just a sprite asset! This means, you can change anything in an object when you skin it! You can even add/override methods in the object, raptor handles this and binds them through method(...) to the object. Change defaults, colors, animation times, methods, ... change anything in a skin!

Tip

As skins are just code classes, you can inherit them. If you use this clever, together with the inherit_skin function of the UiSkin class shown below, you can create css-like stylings for your game's assets!

This is the only function you will need for clever merging of skin parts:

/// @function inherit_skin(_skin_name)
/// @description Copy all values of the specified skin to the current skin

Define a skin - Basic

The most easy thinkable way of a skin is, to only change the sprite_index of an object, and maybe here and there change one or two other variable definitions.

It would look like this:

function MyBasicSkin() : UiSkin("basic") constructor {
	asset_skin[? "CheckBox"]	= { sprite_index: sprMyCoolCheckBox }
	asset_skin[? "InputBox"]	= { sprite_index: sprMyEvenCoolerInputBox }
	asset_skin[? "Label"]	= { sprite_index: sprBestOfAllLabels }
	asset_skin[? "MouseCursor"]	= { 
 						sprite_index: sprDefaultMouseCursor,
						mouse_cursor_sprite: sprDefaultMouseCursor,
 						mouse_cursor_sprite_sizing: sprDefaultMouseCursorSizing
 					  }
	asset_skin[? "Window"]	= { sprite_index: sprFancyWindowFrame }
}

Define a skin - Advanced

As mentioned above, you assign a struct to a map entry, when you create a skin.

Here are some parts of the DefaultSkin and WoodSkin classes, that show you, how can create skins with little effort, by defining template structs or even small methods, that return a detail struct for the skinned elements:

function DefaultSkin() : UiSkin("default") constructor {

	// First, define a template, you can use multiple times
	var text_control = function(spr) {
		return {
			sprite_index: spr,
			text_color: APP_THEME_MAIN,
			text_color_mouse_over: APP_THEME_MAIN,
			draw_color: APP_THEME_WHITE,
			draw_color_mouse_over: APP_THEME_WHITE,
		};
	}

	// ...you can use this then to apply the same structure to multiple elements
	asset_skin[? "CheckBox"]		= text_control(sprDefaultCheckbox);
	asset_skin[? "InputBox"]		= text_control(sprDefaultInputBox);
	asset_skin[? "Label"]			= text_control(sprDefaultLabel);

	// You don't have to create a function, you may as well create a template struct
	// (this is taken from the "wood" skin from the template project)
	var window_def = { 
		sprite_index: sprWoodWindow,
		draw_color: APP_THEME_WHITE,
		draw_color_mouse_over: APP_THEME_WHITE,
		focus_border_color: APP_THEME_WHITE,
		titlebar_height: 38
	}

	asset_skin[? "Window"]			= window_def;
	asset_skin[? "MessageBoxWindow"]	= window_def;
	asset_skin[? "DemoLoginWindow"]		= window_def;

}

The DefaultSkin

As mentioned above, one theme is delivered to you with the project template as the default skin of raptor.

Caution

DO NOT DELETE THIS SKIN.
It is set/added to the UiSkinManager in the raptor core when the game starts. You may adapt the sprite values in here at will, or simply derive your own skin and just use this file as a template. Whatever you do, just do not delete this one!

Default Sprites

To make designing your own theme easier, you can either look up the predefined default sprites in raptor, or in the repository in the _assets_/controls/flat_ui folder.

They are there in .png and .pdn formats. In case, you don't know, what .pdn files are, these are done with paint.net, a great free graphics program.

As an overview, here are the sprites contained in the default skin:

image

Extending skins with new objects

It's as easy as adding the object's name as key and the struct to use to the ds_map of the skin.
Just add it.
When you activate a skin, raptor loops through the keys and applies all struct elements on them!

⚠️ **GitHub.com Fallback** ⚠️