Tool coding [2]
In the previous post I mentioned that we found out that it wasn’t a very hot idea to try coding our GUI using the .NET Framework. Now, this is not necessarily because the framework isn’t any good, but it was because we were not really using it in the way it was really intended. At that time, .NET was fairly new (it was just after the release of VS.NET 2003 I think) and what we were trying to do was tie our C++ based engine to a C# GUI. Sounds simple, right? Well, no.
Nowadays, you’d use a tool like SWIG to generate a bunch of bindings from your C++ code to C#. We had to do this ourselves. Not too much of a problem per se, but it becomes quite a big hassle when you’re used to doing things in a reasonably iterative way. We had a design document, but it was basically just saying “It should do this, this and that”, without any complete specifications. The upshot of this was that there were a lot of rewrites of that wrapping code. Not fun.
An additional problem was that interop debugging was, to use the technical term, slow as shit. It’s fixed in the current VS release, apparently, but it was absolutely tedious in .NET 2002. Not only that, but it was impossible to step into some methods, and doing too much debugging caused devenv.exe to hang, requiring a reboot. A fairly arduous process, then.
Finally, our design required two-way communication between the engine and the GUI. So the wrapper code had to be extended to allow for a rudimentary messaging system to be implemented as well. So once we did all that, we were…well, where exactly? John-Pierre did some cool stuff on the C# side with a basic GUI with all the fancy things like dockable widgets, an undo/redo stack, a simple library viewer, things like that. On my end of things, I completed a basic engine, supporting spline-keyframing, different parameter types and so on. Too bad it was so utterly mind-numbingly difficult to get these two pieces of software to communicatie properly. Also, we made some rudimentary design decisions that weren’t necessarily wrong, but required a lot of extra stuff to be implemented before we would even be able to do a simple test-64k intro.
We based our design on Adobe After Effects and to a lesser extent Macromedia (well, nowadays it’s Adobe again) Flash. After Effects is based on the concept of “Layers” that are grouped in “Compositions”. A layer can contain a picture, a movie-clip, some audio, text or, and that’s the clever bit, another composition. Optionally it can become an adjustment layer that affects the layers beneath it. All in all it’s very similar to Photoshop. Now, if you made a cool logo animation you’d stick this in a composition. This composition then becomes available to other compositions, so you can then stick your logo on top of all other compositions you made. Pretty neat.
Our GUI worked in the same way, the idea being that you’d create an “Item” (our “Composition”). This item would then contain one single ”generator” and an infinite number of “modifiers”, a bit like the modifier stack in 3DS Max. So you’d start with a “Cube” generator, for instance, and then add a number of “subdivide”, “bend”, “make cool” modifiers. Every generator/modifier had a bunch of parameters you could animate, and that’s how you’d create your 3d scene. So let’s say you combined a bunch of items into a new item called a “House” (e.g. a cube for the base and a pyramid for the roof). “House” would then be, essentially, an atomic item. So instead of having to build your items from a generator “Cube” or “Sphere” you’d be able to use “House” as a generator as well.
Sounds nice in theory, but it’s really awfully limiting and complex to do it that way. Let’s say you want to apply two materials to the house. One to the base and one to the roof. No problem. But once you start working with the atomic ”House” item you no longer have access to those materials. So what if you want a city containing 99 houses with a red roof and 1 house with a blue roof? You’d need to generate another “House” item with a different material for the roof part. But that would require duplicating the original “House” which would mean extra storage requirements (and please remember, we’re trying to do a tiny 64k intro here). So you could make an instance of “House”, which is basically just a cross-reference to the original, so when the original changes the instance changes as well, except for the stuff you’ve overriden (the material of the roof, in this case). Whoa.
As you can see, even in a ridiculously simple example like this, a system such as this becomes needlessly complex and convoluted. This is what we found out as well, when we started trying to actually use our tool. It kinda fizzled out after that, since we spent too much time on something that was fairly useless.
So what have I been working on in late April/early May? Find out next time! (Cliffhangers are cool)