Skins

Introduction

Creating a skin for YaZZle is fairly straightforward, though due to the amount of things that can be skinned, and multiple ways to accomplish a task, there can be quite a bit of work involved. Besides some first necessary steps though, most things after that are optional. In general, a skin is just a collection of images (can be just a few) and one or more textfiles (with .ini extension) which hold commands on where and how to display the images.

What you need first is a new folder and a textfile renamed to 'main.ini'. Start it with these lines/properties - they'll be displayed in the skin choosing dialog:

[General]
Name=Name of skin
Author=Your name
Description=Short line with description

Comments

If you want to add comments in your .ini files, explaining things (which is considered an nice gesture to other skinners disecting yours), put a semicolon before these lines; these will not be read by Yazzle.

We'll now go through all parts of the skin. Note you can zoom in on the images used in this tutorial by hovering your cursor over them. Also hovering anyway marked words could get you a more detailed (tooltip) explanation.

In general, it's a good idea to copy the files of an existing skin with options you want to a new folder and go from there. This tutorial uses the 'plastique' skin as an example, as it's not designed to be good looking, but to show off Yazzle options.

Wherever images are involved, this tutorial uses .bmp. In your skin though, you can also use .png and .jpg.

Main window

Basically, there's two ways to do your background image. Most simple is creating a 24-bit colored image and let Yazzle stretch it for you when being resized. You'll only need these lines in main.ini:

[Background]
Image=background.bmp

This could be your Yazzle skin, the only thing required to display it is defining the playing area (required in all skins):

[PlayingArea]
X=8
Y=37
W=80
H=8

The x, y properties define starting point of playing area in pixels; w, h width and height (thus where it ends, calculated by Yazzle). When whole bitmap gets stretched, playing area gets stretched likewise. Use this to define parts at edges you don't want covered by cards. This could already be your full skin.

But, stretching an image blurs it, and doesn't necessarily look good. Most skinners will look for a way to get more pixel precision. For this, create an image - it can be very small - with corners exactly as you want, and sides plus middle that can be either tiled or stretched. Here's the plastique .bmp:

In this skin corners are displayed exactly as is, sides and center are tiled by defining this in the .ini:

[Background]
Image=background.bmp
StretchResize=0
CenterTiled=1
TopLeftWidth=9
TopRightWidth=86
TopHeight=38
BottomLeftWidth=9
BottomRightWidth=10
BottomHeight=37
LeftTopHeight=38
LeftBottomHeight=37
LeftWidth=9
RightTopHeight=38
RightBottomHeight=37
RightWidth=10

The last 12 properties make Yazzle stop resizing whole bitmap. For each side, there's 3 properties in which you define width (top/bottom) or height (left/right) of the beginning and end of the side, then height (top/bottom) or width (left/right) of whole side. Here's result in our case:

No Tic-Tac-Toe

Ofcourse, it's most easy to create an evenly divided 9 square. But if you want to get fancy, you got to understand what Yazzle is doing here.

What happens is this. Top, bottom, left and right side are drawn seperately. They all have 3 parts, a beginning, middle and end. Including center, that's 13 parts, as opposed to the 9 parts you see here, they overlap. As such, you can create more complicated frames, once you know drawing order.

Order is this: top beginning, top middle, top end, bottom beginning, bottom middle, bottom end, left beginning, left middle, left end, right beginning, right middle, right end, center.

The property ‘StretchResize=0’ - defines that middle parts are to be tiled. Default is ‘1’, stretched (no need for this line at all if you want that).

Other property, ‘CenterTiled=1’ tells that the center part is to be tiled (0 being default, no need for this line if you want that).

There's only one way to add transparency to the background, and that's using magenta (RGB 255 0 255 aka ‘magic pink’, a long established skinning tradition). Other parts of the skin can have alphablended transparency, main window has just this. Notable is this is applied to the window with all other parts (buttons, text) drawn, meaning if a button is over a transparent area, transparency will apply to the button too. If transparency is applied to parts that will be stretched or tiled, transparent part gets treated likewise.

A last, sensible thing to add is a minimum size (of whole application) to this section:

[Background]
MinWidth=640
MinHeight=480

By default display of the cards is limited to the playing area. If you want them displayed over whole program (can't have them over whole screen), add ‘ClipPlayingArea=0’ to this section of the .ini.

Adding text fields & color other text

Now, you'll want some text added to our window, like which game is actually being played in a titlebar. There's 6 text sections you can add, and some font settings to go with that. Lets start with general font formatting:

[DefaultFont]
Name=trebuchet ms
File=trebuc.ttf
Size=10
Bold=1
Italic=0
Red=0
Green=0
Blue=0
Shadow=2
ShadowRed=121
ShadowGreen=148
ShadowBlue=173
MouseOverRed=198
MouseOverGreen=57
MouseOverBlue=57
HighlightRed=152
HighlightGreen=219
HighlightBlue=86

It's all pretty self-explanatory. First line defines font be be used by its friendly name, optionally, when using a non-standard font (that's distributable), you can include it in skins folder (‘File=’). Size, weight and italic can be set. Optional shadow - bottom-right direction - distance can be set, and its color. The MouseOverRGB and HighlightRGB settings are not used in main window, will be used later for additional dialogs. Now here's the text fields these will apply to:

[GameTitle]
Displays current game, prefixed with easy/hard.
[GameTime]
Displays playing time.
[GameNumber]
Displays number of current game.
[GameMoves]
Displays number of moves made.
[GameScore]
Displays number of cards that are played free to foundation.
[WallClock]
Displays current time, in format you choose.

All these are added as new sections in main.ini and follow same format:

[TextSection]
X=#
Y=#
W=#
H=#
C=1 ;other options are 2, 3, 4
HorzCentered=0|1
VertCentered=0|1
LeftAligned=0|1
RightAligned=0|1
TopAligned=0|1
BottomAligned=0|1

Percentual placement

Now what if you want something placed in middle of a side, whatever size Yazzle has. Use XP & YP instead of X & Y, and a number between 0-99.

X and Y are the numbers that define horizontal and vertical placement of the textfield respectivily, in pixels. These apply to buttons and other things too. Due to Yazzle being resizable, these values get set in relation to one of the corners. ‘C’ tells Yazzle from which corner to start calculating, Topleft (1), Topright (2), Bottomleft (3) or Bottomright (4). No need for negative values, Yazzle reads them upwards and leftwards when corner is ‘4’, for instance.

W(idth) and H(eight are then used to reserve proper space for the textfield. The last six lines you can use to further align the text within this space. Note you only have to add the lines you set to ‘1’. These all can be set to false (0, which is default) or true (1) only.

[WallClock] has two extra properties available:

[WallClock]
Format=%#H:%M
Lowercase=0|1 (False/true)

Here's the list of valid options to add to first property (with nothing defined, it defaults to %#I:%M:%S %p):

%a3 letter weekday of the week name
%Afull weekday of the week name
%b3 letter month of the year name
%Bfull month of the year name
%cday and time formatted for locale
%dday of the month number
%Hhour of the day number (24 hour format)
%Ihour of the day number (12 hour format)
%jday of the year number
%mmonth of the year number
%Mminute of the hour number
%pA.M./P.M. indicator for 12 hour clock
%Sseconds of the minute number
%Uweek of the year number (Sun as first weekday)
%wweekday of the week number
%Wweek of the year number (Mon as first weekday)
%xdate as formatted for the locale
%Xtime as formatted for the locale
%y2 digit year of the century number
%Y4 digit year of the century number
%ztime zone name or abbreviation
%Ztime zone name or abbreviation
%%percent sign
#when used with a numeric format, removes any leading zeros, e.g., %#I:%M will display 17:00 hours as "5:00 PM"
#when used with the %x format, converts the date to the locale's long representation, e.g, %#x will convert "03/14/95" to "Tuesday, March 14, 1995"
#when used with the %c format, converts the date and time to the locale's long format, e.g, %#c will convert "03/14/95 12:41:29" to "Tuesday, March 14, 1995, 12:41:29"

More font and color settings apply to the rightclickmenu (optional displayed by adding a button that pops them up).

[MenuFont]
Name=trebuchet ms
File=trebuc.ttf
Size=10
Bold=0
Italic=0
Red=0
Green=0
Blue=0
Shadow=2
ShadowRed=121
ShadowGreen=148
ShadowBlue=173
HighlightRed=255
HighlightGreen=255
HighlightBlue=255

Same rules apply as with [DefaultFont], MouseOverRGB properties do not apply here though. The HighlightRGB properties define textcolor of the item in menu that's hovered.

Another part of menu colors is defined in a different section of the .ini, though:

[MainMenu]
HiliteRed=151
HiliteGreen=175
HiliteBlue=197
NormalRed=151
NormalGreen=175
NormalBlue=197
DisabledRed=79
DisabledGreen=115
DisabledBlue=148

Why here ? Well, [MainMenu] used to be a button section only (button that pops up this menu); this is only part of the properties that can be set for this section.

The HiliteRGB properties define color of background of a hovered item, while the NormalRGB properties define backgroundcolor of menu and items not hovered. The DisabledRGB properties finally, are for textcolor of any menu item not currently available.

Additionally, you can define background- and fontcolor of the provided tooltips by adding them to [background] section:

[Background]
TipTextRed=0
TipTextGreen=0
TipTextBlue=0
TipBkgndRed=255
TipBkgndGreen=255
TipBkgndBlue=255

Adding pilemat images

Now, when playing, it's conveniënt having some indication where cards are supposed to go, and if applicable, which rank restrictions there are for a pile. Yazzle provides the option to display two versions (more are planned), a regular one and one for piles that have restrictions - typically displaying the rank of the card that should be added there first. Both have to be seperate images and behave much like the background.bmp. In main.ini, both require a seperate section (one or both will not be displayed if not set, though you can point both to same .bmp):

[PileMatPlain]|[PileMatSuits]
Image=pilematplain.bmp
HasTransparency=1
CenterTiled=1
TopLeftWidth=3
TopRightWidth=3
TopHeight=3
BottomLeftWidth=3
BottomRightWidth=3
BottomHeight=3
LeftTopHeight=3
LeftBottomHeight=3
LeftWidth=3
RightTopHeight=3
RightBottomHeight=3
RightWidth=3

For the options to tile or center the pilemat (they get resized depending on cardset), refer back to main window section, behavior is the same. For transparency, there's more options in this case: transparency section.

Inevitably, you'll also want to create an image to display the ranks on the pilemat, when there's restrictions. Another section in main.ini needed:

[PileMatRanks]
Image=ranks.bmp
;Alpha=ranks_alpha.bmp
HasTransparency=1
TransparencyRed=0
TransparencyGreen=0
TransparencyBlue=0

The image has to contain 13 equal sized blocks, each containing a rank, in this order: A 2 3 4 5 6 7 8 9 10 J Q K. For transparency, again refer to transparency section.

Adding buttons

Every Yazzle option is available in its rightclick menu. You can make any or all of them available as a button on your skin. Most simple is display them at your background image. Check out the included ‘XP’ skin. The buttons are drawn on background.bmp, in main.ini it states:

[Close]
X=21
Y=6
W=16
H=16
C=2

This is what we saw with the textfields. The close button is 21 px from right side (C=2, topright corner), and 6 px from top. It's also 16x16 px and clicking that area should close Yazzle. Simple.

Yet, you can have buttons with effects when hovered, and being pushed. For this, you need to create an appropiate image. The image contains either 1, 2, 3 (regular buttons) or 6 (buttons that toggle an option) versions of the same button, in a horizontal ‘filmstrip’.

In main.ini, you need to add a new section for every button you want shown:

[ButtonName]
X=#
Y=#
C=#
Image=button_for_this_action.bmp
Images=#

Buttonname is the section header, and has to be a known command. Here's the list (all but ‘PlayMenu’ are demonstrated in plastique skin):

A gripper

There's an additional ‘button’, [Gripper]. This one will produce an area that will, when hovered, show a resize cursor and enable you to resize Yazzle.

[MainMenu] [PlayMenu]
[GameHelp] [Minimize]
[Maximize]* [Close]
[NewGame] [PauzeGame]
[ReplayGame] [PlayPrevGame]
[PlayGame#] [PlayNextGame]
[UndoMove] [FoundationMove]
[HighlightNext] [LockPosition]*
[ToggleMusic]* [ToggleSound]*

X and Y are the numbers that define horizontal and vertical placement of the button respectivily, in pixels. Due to Yazzle being resizable, these values get set in relation to one of the corners. ‘C’ tells Yazzle from which corner to start calculating, Topleft (1), Topright (2), Bottomleft (3) or Bottomright (4). No need for negative values, Yazzle reads them upwards and leftwards when corner is ‘4’, for instance.

Finally, ‘Images=#’ tells Yazzle how many variations of the button you put in (# being either 1, 2, 3 or 6), so it can calculate width and height of the button, and what to display when hovered etc. You could stick with one image for all buttons, stick to 3 versions for the toggle buttons, but you can only add so much versions the command can handle.

Regular buttons can have 1, 2 or 3 frames, order being normal - hovered - down. Toggle buttons (marked* above) can have either 3, unchecked - ? - checked, or 6, unchecked - unchecked hovered - unchecked down - checked - checked hovered - checked down.

Transparency & alphablending

We saw main background could have transparent parts. There's 3 ways to add transparency to the pilemats, pilemat ranks, buttons, splash screens and dialogs (shadow effect) too. First, most simple is to use magenta for a plain non-visibility again. You only need to add this line at appropiate section:

[SectionName]
HasTransparency=1

Second still creates a plain non-visibility. Now you can use any color in the image, for example black(RGB 0 0 0). Few more lines to add:

[SectionName]
HasTransparency=1
TransparencyRed=0
TransparencyGreen=0
TransparencyBlue=0

Third is more sophisticated, and uses two images. First is full-color, and has all parts that need being displayed. The second image is greyscale and is laid over first as a mask. If a pixel in mask is black, matching pixel in first image is fully not shown. If it's white, it's shown 100%. Anything in between, from white to black, is increasingly blended with background.

[SectionName]
Image=button.bmp
Alpha=button_alpha.bmp

You can use this to blend in buttons on non-solid backgrounds, smoothen font display on pilemats, add effects to your splash screens and shadow to menu's.

Splash- & pauze screen

By default, Yazzle gets 'dimmed' (a native Windows effect) when pauzed or not having focus. Optionally, you can have a custom pauze screen displayed, and also a loading screen at startup of Yazzle. The dimming effect still gets displayed underneath the screen, but can also be turned off:

[Background]
DimPlayingArea=0

The screens require new images. Rules for these are quite alike those for other images, with notable exception that they're displayed in Playingarea, and centered by default. Only new value is 'stretch=0|1'. Default is no (0). Have a quick look over example, you just need to add new sections in main.ini, can have transparency and even build them like background and pilemats are drawn:

[PauseDialog]
Image=pauze.bmp
Alpha=pauze_alpha.bmp
Stretch=0

[SplashDialog]
Image=splash.bmp
Stretch=1
TopLeftWidth=618
TopRightWidth=0
TopHeight=355
BottomLeftWidth=0
BottomRightWidth=578
BottomHeight=54

Dialogs

Ideally, in the end, Yazzle will have the option to have all dialogs (options, card deck choice, skin selection etc) skinned - they are displayed centered over whole of main window (fixed). For now, only main messagebox is (the one telling you've won, how results where and what to do next). Preparing for future though, this one is done with a new .ini file, messagebox.ini. Format is alike main.ini, and nothing inside that will scare you if you've come this far. You'll need one bitmap (exactly as gonna be displayed) of the dialog and - optionally - one to handle alphablending:

Tooltips

If you applied custom tooltip colors for main window, copy and apply them here too - [Background] section. Usability wise, mostly a good choice to use same colors, yet dialog could have much contrast with main window in your skin.

[General]
Name=plastique
Author=plastic
Description=messagebox

[Background]
Image=dialog.bmp
Alpha=dialog_alpha.bmp

After this there's 3 things to have displayed on the dialog, message itself and a 'yes' and 'no' button; they're called [Button1] and [Button2] here, respectivily. Not much to explain, they follow same rules as textfields and buttons in main window:

[MessageText]
X=15
Y=15
W=394
H=60
HorzCentered=1
TopAligned=1

[Button1]
X=180
Y=83
Image=yes.bmp
Images=3

[Button2]
X=218
Y=83
Image=no.bmp
Images=3

A note about the .bmp for the alphablending effect. You could blend the dialog in or something, but most skinners will use this opportunity to add a shadow beneath their dialog. Do this by reserving space for the shadow in the dialog bitmap, and use a color to have the blending tinted in skins' colors. Then create the alpha bitmap, with real dialog part pure white, background black, then create the shadow effect alike here:

Adding additional bitmaps

Occasionally, you might find a need to display additional bitmaps on the skin. You could, ofcourse, add them to your background bitmap, but if you need to place it more flexible (using percentual values, to have it next to text/buttons aligned likewise, or even fixed, but not wanting your background image to be huge), here's how. First, you need an extra line in [Background] section, defining number of images you want displayed. After that, create new sections [Pic1], [Pic2] etc. They somewhat follow same rules as any button. They do not allow multiple states, but they do listen to transparency values. The 'plastique' skin uses two of these, one to be shown before gamenumber, one acting as seperator between move/score counters (explore).

Put into perspective

Not all extra imaging is better off as a seperately added bitmap. You'll notice the seperators between sections in both title- as bottombar in 'plastique' skin. Could have been seperate images, but adding them to button images gave much more pixel precize results, and does the job too. Just something to consider.

[Background]
PicCount=2

[Pic1]
XP=46
Y=27
C=3
Image=nr.bmp

[Pic2]
XP=75
Y=27
C=3
Image=score.bmp

Conclusion (perspective)

What's been described, is a mature, tested skinning format. Intentions are it will grow. Don't expect your skins to be broken, do expect extra options (no deadline involved whatsoever). As indicated, more pilemat differencing and more dialogs to be skinned are planned. Maybe more. But go ahead and have a go, you're safe.