You know, graphics is amazing, graphics are interesting, challenging, funny and rewarding. I love reading siggraph papers as much as any other out there, but there’s a thing that I love the most: designing and coding those little helper systems that make your life easier.
Today, for first time in my blog, I will start sharing pieces of code of that pet engine I’m coding at home :) And today’s piece is the tiny Information Item System.
You know, many times you need to get runtime information from the application, information like observer position, memory consumption, frames per second or even runtime profiling information. In previous implementations I had hardcoded that information, that was clumpsy and not very scalable to be honest, so now I had the opportunity to start it all again I decided to do it better, scalable, datadriven and with all those fancy properties that are so cool today.
The idea behind it is very simple, and the system itself is stupidily simple so let’s start explaining it:
I’ve decided that every piece of information I need can fall in one of those 2 categories
- Text: The information can be retrieved as a string
- TextTree: The information can be retrieved as a tree of strings
In fact, to be honest, the TextTree was added lately in the design phase, when I realized that profiling could be added to this information system. But having that in mind the design was as simple as it can be.
Every information item would have this properties:
- There would be only one item for each category (no duplicity)
- Each item would be capable of gathering all the information needed, process it and format it.
So with that in mind I ended with this UML diagram
Info Item Class Diagram
Well, I know, it’s stupidily simple! And of course, at this momment I only need 2 InfoItems (and those are the ones that are implemented).
All this items are stored into a singleton named, let’s be original, InfoItemManager. This is the only place where this info items should be stored.
Info Item Manager
Now, how all this thing work?
Pretty easy, on Init time the manager registers all the info items. Later, on update time InfoItemManager will call to update on each info item, there each info item will process and generate the message that it will return. As I told you, it was easy :)
Ok ok, you will say, the info items have the info, but that doesn’t mean I can use it. Indeed, the information is there, you only need a way to access to it, right?
Each one of the InfoItems have 3 key methods: GetId(), GetType() and GetInfo().
- GetId returns the Id type of the info item (FPS, POSTION, OBJECTS and so on)
- GetType returns if the Info Item returns a single string or a Tree
- GetInfo returns an union, with a char* in case of being a string or … well, at this momment it only returns that
So here it goes, in case you want to access to, let’s say the Position string you could do something like this
InfoItemManager::GetInstance()->GetInfoItemId(III_POSITION)->GetInfo()
That would return you an InfoItemValue union, that, knowing that III_POSITION returns an string well, you can use it directly to write it down wherever you want.
Well, the code of the manager and the info items can be downloaded here . It’s a bit dirty and such, and it’s exactly how it’s working in my engine. You will notice some weird way to get the position on the InfoItemPosition, and you will see that InfoItemFPS does the actual calculation of the frames per second, but it should be pretty easy to adapt it to any engine (after all they’re only 3 classes!)
Further improvement
Right now this design does exactly what I need, but that doesn’t mean it can’t be improved does it?. Here are a few:
- Allowing not returning only strings, but actual data, like vec4.
- Ensuring that there’s only one instance for each infoitem. That is, in fact pretty easy. Lately, in some of my class hierarchies I’m starting to add an static method named Create in the top most base class. This method takes the type of the object to create and returns an instance of the corresponding class. Well specifiying a Create method in InfoItem we could check if InfoItemManager already has an instance of that method (and it should, Init() method in manager ensures that). If the instance exists we only have to return that instance, otherwise we can create an instance, register it in the Manager and return it.
Well, that’s all, a pretty easy, simple, little example of code. The next one, I’m still thinking if it will be the Graphic Driver or the widgets system.
Stay tuned :)