*claps* What's up world? It's... *stares at wrist* FRIIIIDAY!!!
OK, maybe it is Wednesday. I’ve been done with the features related to this post on the mental outline of the post since Friday, but only now have I gotten around to post. Oh well, it can happen to the best of us…
You know what is fun? Creating a world and tweaking it until it comes alive right before your eyes. What else is fun? All the other things that are fun. But wasting days trying to make two toolkits work together well is not fun.
DwarvesH is written with the help of two toolkits. For my GUI needs and general functionality I’m using U++. For hardware accelerated graphics I’m using Irrlicht. Why combine the two? Well, U++ is absolutely great for GUI work. One of the best I’ve seen. It also has an excellent standard library replacement. But it is has no features for hardware accelerated graphics. As said in a previous post, I needed a new toolkit for graphics because rendering performance has become unacceptable. This is where Irrlicht comes in. But Irrlicht also has a GUI component. But while the graphical capabilities of Irrlicht are great, its GUI component is kind of “meh”. It does a lot that previous GUI toolkits have done wrong and I mean the kind of things that make programmers sigh when hearing they need to do GUI work. It also uses the horribly outdated ID system for identifying widgets. Here is one of the golden rules that should be followed by everyone: a logical entity should not be represented by two different entities at the same when working with them, unless this is the nature of your given entity. So if you have a widgets and you are manipulating it through its instance variable you are not supposed to interact with it by other means, like by assigning every widget a unique ID. You already have the widget. There is no need for an ID system, IDs that are invariably constant integers and which fall under the responsibility of the programmer to keep track of them. Incidentally, all great GUI toolkits follow this rule and most not that great ones don’t and all horrible ones don’t. Coincidence? Who knows? As for the rest of Irrlicht, it is generally good, but it does have some other annoying factors. Like using reference counting as the general rule. I have nothing against garbage collection (but reference counting is the absolute worst kind of GC system and I have something against it) but not in C++. And not in 2010. C++ allows full automatic deterministic management of resource lifetimes (including memory) without the user having to write code for this by using RAII and the scoping rules of the language. You basically have the means to have the equivalent of a deterministic GC and all you need to do is follow a few coding conventions and have a library that plays nice with those coding conventions. And no, not with the use of smart pointers. Or dumb pointers. Or average intellect pointers who enjoy a wide array of musical genres without thinking about the musical merit of such pieces.
But enough ranting. So basically U++ gives a nice general purpose library and nice GUI toolkit and Irrlicht gives stellar performance for rendering. It also abstracts away the underlying system, so I don’t have to care about OpenGL or DirectX programming. Did I mention that it is also portable? So Linux version is in! So what could go wrong? Well, as it turns out, the two don’t really work together the way I hoped through no fault of their own. So I have the following choices:
1. Go on. Use the same flow as before. This solution comes with a few caveats. I can’t have full screen resolution changing views as is customary for games. Also, I can’t write or draw widgets on top of the hardware accelerated views. So if I wish to put a widget on top of the view, I need to place it first in a new window.
2. U++ is relatively pluggable. I could change the central point where drawing is handled to use Irrlicht devices instead and allow free mixing of the two. Not that hard but it takes some time and I’m not in the mood for it.
3. Separate the central game view from the rest of the GUI. Maybe create a game executable and a world editor executable. Each with its own toolkit.
4. Bite the bullet and use Irrlicht not only for graphics, but also for GUI. The amount of GUI in such a game is minimal, so it wouldn’t be that much work.
I chose something in the line of 4. Any smart person would make a choice (in my case 4) and go with it. But not me. I like my U++ work flow. I like my automatic resource management. I like my lack of pointers. In the entire application there are two cases where you can see “->”: in the A* implementation and in the core of Irrlicht integration. And “*” is used only for multiplication. Going full Irrlicht would bring these operators out of the closet and into my code! Can’t have that. So I wrote a U++/Irrlicht bridge/wrapper. It is very short and extremely hacky. I still fear its eventual explosion, but until then, I can pretty much take my existing U++ code, change the namespace of the widgets and recompile. Then do a few minor modifications which I hope to get rid of in the future and voila: I now have widgets that have U++ interfaces but behind the scenes are using “native” Irrlicht widgets. Porting from U++ to the bridge or vice-versa takes minutes. It is both an experiment and a failsafe. If in the future I somehow find Irrlicht not good anymore (very low chance; even with some negative stuff I said above it is an excellent library and I recommend it to others) I can “port” my application back to “native” U++ in a couple of hours.
I was going post some screenshots on Friday to show that no regression was caused by this massive change, but since then I continued working and no longer have a version of the application in that stage. MUST… INSTALL…GIT… Also, I am skipping statistics for the same reason.
But the great news is that I have been working on the primordial form of the Z axis. It is time to give the land some elevation! Also trees are done! And they don’t die in winter like other plants do.
See you next time!