Creating Skins
So far this page contains a few thoughts randomly scattered around as I (centipede) learn how to create skins. It may be worth a reading though.
What the artist should know about programming CEGUI
If you are more of an artist than a programmer, and you intend to make skins for CEGUI, but have practically no experience with how to program it then all those definition files (imageset, scheme, looknfeel) and other things will be wildly confusing. You need to have a basic idea of how the code works before things will make any sense, but once you do it all seems so naturally logical. The reason this wiki-entry has been written is that the author is right in the transition from foggy confusion to perfect clarity, and he wants to put his experience into writing before he becomes a silent member of the crowd of people who thinks these matters are so obvious that they hardly need to be expended upon. If you are wise, you will add your thoughts and experience too.
The programmer lives in the C++ world whereas the artist lives in the XML world. They are brought together in the Look-plugins: FalagardLook (and previously TaharezLook and WindowsLook). It works a bit like the Model/View paradigm. The Core library is not at all concerned with how things look. It is only interested in behaviour: What state is the button in right now, and what would happen if the user moved the mouse away while keeping the button pressed etc. The core library relies on the Look-modules to supply the visual aspect. They are the ones that handles all the stuff the artist specify in the XML files.
Child, NamedArea, states and optional configurations
So basically the Core has a set of logical elements/widgets which the Look-plugins turns into a set of physical elements/widgets using the information in the XML files. This is why certain things are mandatory in the looknfeel files.
Some widgets are logically composed of a few smaller widgets. A FrameWindow consists of a TitleBar and a SystemButton and a ListBox has a vertical and a horizontal Scrollbar. FalagardLook, being totally configurable as it is, can really make no assumptions about how things are arranged by the artist, so it absolutely relies on the <Child> elements of the <WidgetLook> to specify where to put those subelements in the physical space of the FrameWindow. Notice how the following code from the Vanilla.looknfeel is really just a specification of an area on the total FrameWindow where the titlebar should be placed:
<Child type="Vanilla/Titlebar" nameSuffix="__auto_titlebar__"> <Area> <Dim type="LeftEdge" ><AbsoluteDim value="0" /></Dim> <Dim type="TopEdge" ><AbsoluteDim value="0" /></Dim> <Dim type="Width" ><UnifiedDim scale="1" type="Width" /></Dim> <Dim type="Height" ><FontDim type="LineSpacing" padding="14" /></Dim> </Area> <Property name="AlwaysOnTop" value="False" /> </Child>
Some widgets can have a logical interaction (e.g. writing text in an EditBox) which forces the poor ignorant FalagardLook module to demand of the poor all-knowing artist to specify where to put the text. Putting it at position (0,0) it usually not a very good idea, so the artist must specify a <NamedArea> that FalagardLook can read and use when rendering text. Here is an example of a specified "client area" of a FrameWindow, which is the area inside the window where subwidgets can be placed (i.e. all the window except titlebar and border):
<NamedArea name="ClientWithTitleWithFrame"> <Area> <Dim type="LeftEdge"><AbsoluteDim value="7" /></Dim> <Dim type="TopEdge"><WidgetDim widget="__auto_titlebar__" dimension="BottomEdge" /></Dim> <Dim type="RightEdge"><UnifiedDim scale="1" offset="-7" type="RightEdge" /></Dim> <Dim type="BottomEdge"><UnifiedDim scale="1" offset="-7" type="BottomEdge" /></Dim> </Area> </NamedArea>
One thing worth noting above is that a FrameWindow must have not just one client area specified but four! This is because the programmer that uses CEGUI can request four different kinds of subwindows: With/without a titlebar and with/without a border. The artists must be prepared for this and perhaps even go to the extreme of painting four kinds of windows. Falagard can't possibly deduce where the client area is placed in the four situations, so it will have to know from the XML files.
So, how DO I make a skin?
Here are some quick ideas on how to get around the job without spending too many hours. There is nothing wrong with reusing things. You can always add more detail later on, but for a start it would be fairly nice to have something that just resembles a GUI rather fast. Remember that in Falagard you can layer things which makes it particularly easy to reuse pixels.
Things you will need for a minimal gui
Assembling the stuff
FrameWindow Remember that the titlebar and the rest are drawn separately (i.e. the titlebar is a Child of the FrameWindow and as such is a separate Falagard element). You will most likely have a few rows of "glue pixels" between the titlebar and the bottom of the FrameWindow. [Should they be put in the titlebar or the rest? Don't know yet]