Another period of not much happening. This has mainly been caused by another spike in the complexity of the code I’m writing at work - the more complicated it gets, the less inclined I am to sit at a keyboard when I get home. The code I get paid to write takes precedence over the code I write for myself, unfortunately.
Anyhoo. One of the problems with Woopsi at the moment is that it uses a “gadget type” enum to identify the type of each gadget (window, screen, button, etc). The reason for this was to avoid using runtime type identification (RTTI), which I’d heard was too slow to be useful. Much the same criticism has been levelled at reflection in .NET, but I’ll use that when I need to - if performance is critical, you don’t use .NET in the first place.
Jeff pointed out that using the gadget type variable was causing a problem in his code - he’s working on subclassing Woopsi’s gadgets in order to extend their functionality, so having a set list of possible gadgets will limit what he can achieve. A valid point.
To be honest, I wasn’t expecting anyone to to use Woopsi at the level Jeff is - if anyone used it at all, I was working on the assumption that people would cobble together GUIs using the existing gadgets rather than create their own. I’d planned to write documentation to allow for it, but having someone jump straight into advanced coding at such an early stage has swapped my priorities around somewhat, and I’ve been concentrating on tidying things up and improving the code rather than adding new functionality.
I’ve been looking into ways around the gadget type problem. Everything I’ve read about RTTI suggests that it isn’t appropriate for the DS. It was omitted from the Embedded C++ spec because it adds bulk to binaries, and every article that discusses C++ performance says to avoid it. There’s a hugely informative set of pages here by an XBox developer that discusses C++ optimisation, and his advice is to not only avoid RTTI, but refactor if you find yourself in a situation where RTTI is a valid solution. You should never need to detect the type of an object - you should be able to call the same function on all of your objects and have the object decide what to do with that call. For example, Woopsi’s window class does this in its click() function:
loop through gadgets if gadget is a depth gadget remember clicked gadget swap depths else end click to gadget end next
The gadget type check should not be there - all of the code to detect clicks within the depth gadget should be contained within the depth gadget class.
That’s easy enough, but then I run into another problem. Each gadget’s vector of sub-gadgets can contain decorations that are really a part of the parent (depth gadgets, borders, etc), and genuine children (buttons, bitmaps, etc). If I depth-swap a window, I don’t want it to swap depths with its parent screen’s title bar, which is what would happen if I remove type checking.
One solution I came up with for this was to introduce another gadget vector to store nothing but gadget decorations, but then I’d need arrays of vectors in order to pass everything through the collision and drawing functions. It’ll end up being a mess. The other solution I’ve come up with is to store both decorations and children in the same vector, but keep a count of the number of decorations (and thus the index value of the first child). I’d need new “addDecoration()” and “removeDecoration()” functions, and a “_decorationCount” variable. Each time a new decoration is added, the decoration count increases. Each time a decoration is removed, the decoration count decreases. When I run any of the depth swap routines (or anything else that should operate on children, not decorations), I work only with those gadgets higher up the array than the decorations. This removes the need for the second vector or any gadget type identification.