irrlicht is a 3D engine. While it has it’s own independent drawing capabilities, it’s primarily used as a wrapper for OpenGL and DirectX. More importantly: it’s free, open-source, and developed by a great community.
One of the nice features about the engine is it’s built-in GUI system.
I decided to extend the GUI system, making it easier to add GUI elements as well as adding new ones. These I’ve put on my website, on the Irrlicht Expansion Project page. You can read the short descriptions of things there, but I’d like to ramble and explain my reasoning for starting those projects and maybe you’ll get an idea of what they are primarily intended for… or not. Xp
Let’s start with the little stuff…
At first, I couldn’t think of how games managed to set things up so you could change the function of the keys… so I came up with this idea. Yeah…. actually it’s probably backwards from the way you should do that task, but this kept things very independent. *sigh*
Basically, a simple class for constructing and searching a Direct Object Model tree (DOM tree). It’s very, very flexible and convenient, with nice little functions. I can access it like a multidimensional array (provided there are sub-nodes), which keeps code clear and short. Overall, it’s one of the most professional things I’ve ever written. Perhaps I say that because of it’s brevity? I don’t know. I almost succeeded in making it independent of irrlicht, but I wanted the array wrapper (the wrapper is too convenient to not take advantage of, especially when the tree was intended for irrlicht anyways).
I implemented it as irrXMLTree to create trees that store XML data.
No way to I want to create a new loader every time I want to read an XML tree. Irrlicht already has an XML reader and I wrote the irrXMLTree, so now all I needed was a wrapper to take a string and spit out a DOM tree. That’s what this is.
Since irrlicht’s XML reader doesn’t handle errors in the XML file, that really messes things up along the rest of the chain of events… so I don’t handle those errors much either. What I can handle, I try.
Both irrTree and irrXMLTree were designed for this project, actually. On top of that, I decided to design irrWriteableInterface so I could output the loaded XML without having to worry about what I was writing it to.
As mentioned above, it was written specifically so I didn’t have to worry about what I was writing text to. For example, one implementation writes to a GUI text box. Another writes to the windows console. The only annoyance is that each time you write, it needs to be finalized. Why? This allows there to be an internal buffer in the writer that can be edited prior to finalizing. This is convenient for the implementation that writes to the windows console because obviously you cannot change what is already on the console.
When you’re designing a game, it’s nice to have a menu screen. I thought it would be nice if all you had to do was specify the button info once and use a user-implemented function that specified the locations where the buttons would be drawn without needing rectangles. I also want it to be able to access all of the buttons with a single get() function, etc. etc. Those are the ideas anyways… now I need to finish implementing them.
XPLOsion stands for “XML Program LayOut Arranger”. Yes, I realize it would have been better named “XML Program Layout Organizer” since that’s effectively the same thing, but I don’t really care to change it.
I programmed only a short time in HTML and CSS before I started to really appreciate the simplicity and the efficiency of the languages in generating potentially beautiful user interfaces. C++ on the other hand, is a pain. Fortunately, all of the GUI elements in irrlicht are serializable and deserializable – the latter being the most important part in this case – so that the GUI elements could be saved to and loaded from an XML file. The nasty part was the XML file irrlicht generates – it looks hideous. It’s not supposed to look pretty; it’s supposed to hold all of the data. However, the programmers set up an interface between the XML file and the GUI elements that needed to be deserialized. XPLOsion is a wrapper of that interface, but instead of loading from the XML files of the type that irrlicht outputs, I load from files that look like they were written in HTML and CSS. This allows me to program the layout without worrying about shifting around all of the text that indicates the GUI element properties and such.
Technically, XPLOsion is divided into three classes: XPLOsion, CSSLibrary, and GUIFunctionFire (the latter who’s need is being debated as I speak).
XPLOsion is the class that actually loads the XML file (using irrXMLStorage, btw!), creates the GUI elements, and makes requests to CSSLibrary and GUIFunctionFire for everything. IGNORE ITS DOCUMENTATION! It’s alittle outdated. Currently (Jan 26), it is capable of loading all of irrlicht’s native GUI elements (except tables, which I shall try to remember to do soon) and can be easily extended to do load more. Note, however, that to extend it also may require making additions to CSSLibrary.
CSSLibrary is a class that reads from a file formatted similar to CSS (but with different attributes instead of your typically web stuff (like “bottom-border-radius” and “font-family”)). This file contains GUI element information – which I call “styling” – that can be used for just about any element, though most attribute data isn’t interchangeable. Some styling can be included in the XML file read by XPLOsion, but like I said, the advantage of doing things with separate files is so you don’t have to worry about moving styling around.
The fact that CSSLibrary is completely separate and independent of XPLOsion means it could almost act as a CSS reader for a browser. I’ve never tested it in that respect, but the design could certainly be adapted to that case. Unfortunately, the job as a whole might only be easy if the browser were written using irrlicht. This is because CSSLibrary is tied ridiculously to irrlicht’s ioexhange objects classes (which made it easy for me to put it together in the first place).
GUIFunctionFire is a class to which XPLOsion can add IDs of buttons and such and tie multiple buttons and divisions to functions. But the only GUI element this benefits is sdiv (a class I wrote for XPLOsion that acts like a div in HTML), a class that can’t act like a button on it’s own. In fact, I haven’t even tested it as a button, so it may not work at all!
An aside: sdiv is an interesting class. It’s intended to be just like an HTML div in C++ and it accomplishes its job for the most part. I’m actually quite proud of it for that reason. It can generate scroll-bars if the overflow is hidden and I so choose to have the scroll-bars. It can have a user-defined background color (or none at all). It can also have a background image, one that can be replicated horizontally, vertically, or both. The only thing left to do on it is make the background image scrollable. So yeah, it’s a nice GUI element.
Back on topic: GUIFunctionFire is probably unnecessary. The basic idea is to hold a list of functions and have each function hold a list of function IDs. Functions are added to the main list with a name. In the XML file, the button declares a name of a function it wants to find. So in effect, it’s probably the reverse of the way things should be (and the way I plan on implementing them later) – where the class gets to sort through the buttons to find if it wants to use it or not.
Finally! I get to talk about this!
irrlicht doesn’t have a native graph GUI element, so I wrote one. After I began this project, I discovered people had already made graphs, but like every other programmer with a special need, none of the graphs did quite what I wanted.
The features list is available on the page already, and I keep adding to it. I recently added auto-adjusting of the graph size.
Why make a graph? First, it’s a GUI element. I’ve been wanting to write one (and I’ll probably do a color selection box to replace the horrid native one). Second, it’s a fairly straightforward challenge. Yeah….
I messed up when I first started the project. I thought “Hey, I’ll have it call a function from another class that it needs to get data from…” Once again, this was backwards thinking. (I need to start flipping data transfer methods around with my programming solutions. That seems to be my biggest issue.) It’s much easier to have other things draw on the graph and all the graph has to do is keep track of a list of points. Fortunately when I realized this, the change didn’t require altering the existing code very much. No major overhaul, no headache, no unnecessary implementation of other classes. Then I got to add a bunch of features… and voila!