Feb 22, 2011

Progress Report: Windowing System

At the moment I'm working on the windowing system for the UI. Simple things like Buttons and Checkboxes and all those standard UI controls we take for granted in Windows or other platforms need to be developed from scratch when you're working outside of their standard UI framework, which is exactly what happens when you use a graphics library like DirectX or OpenGL.

So far I've implemented the Window control and the Button control, which is a surprising amount of work once you start having to develop a control hierarchy, and have a way for controls to receive mouse up/down events. It's not overly complex work, but it's one of those situations where you need to put in a whole lot of work before you can get anything remotely functional.

Hand in hand with the windowing system is the skinning system. Since we're dealing with a 3D world, at its simplest level the visual aspect of the control is a mesh that you then slap a texture on. The skinning system manages that process in such a way that you can resize the control without having to redesign the texture in a paint program and it still have it look correct.

The textures I'm currently using for the windowing system are 64x64 pixels, and an example of one I'm using for window controls is below:

Source texture for window control

If you take this window texture and naively stretch it to the size of a 300x200 pixel window this is the result:

EWWWW... UGLY!

Simply stretching the image doesn't look very good at all. We could solve the problem by redrawing the window texture at 300x200 in Photoshop, and the result will look nice, but then we'd need to draw a window texture for every window that might pop up in the application, and we lose the ability to dynamically size a window based on content without encountering the same issue above.

A solution to this problem is to break the original image down into a 3x3 grid and then tile each component (corner, edge, centre) using different methods. Stretching still becomes an issue with the edge and centre parts if the texture is not homogenous in the direction of stretching, so instead of stretching the image, I tile it. The layout/tiling scheme works as follows:

  • Corners: no tiling.
  • Edges: tiling in 1 axis only.
  • Centre: tiling in both axes.


Tiling Scheme (image scaled to 4x normal size)

In my windowing system I use control points located at (15,15) and (47,47), meaning the edges are all 16 pixels and the centre is a 32x32 pixel block.

Internally the skinning system actually breaks the source texture into 4 sub-textures to get it to be able to tile correctly, as the tiling would be across the entire texture not just the parts we want. In addition, as a consequence of the 3x3 layout of the texturing, the mesh for the controls is more complex, consisting of 18 triangles instead of just two.

Below is an example of the finished result as it would appear in the app:

The tiled window.

The beauty of having the look of the control be derived from a simple 64x64 texture is that it is relatively simple to alter the look of the entire UI of the application, which is a great benefit when you're in the early stages of development and haven't settled on a final look and feel.

As I mentioned at the start of the post, I've gotten the Button and Window controls working, and will probably spend a bit more time tidying them up and then move onto drag and drop functionality, which is necessary for the inventory screen.

No comments:

Post a Comment