Tagaro updates: Flexible graphics sources, work on TagaroInterface January 9, 2011

You may have observed a reduced density of posts on my blog, which is due to increased coding activity in Project Tagaro (the upcoming next generation of libkdegames). About last week, I have merged in the theming-2.0 branch which refactors big parts of TagaroGraphics and brings in some new features.

If you do not know about it yet, TagaroGraphics originated from KGameRenderer, the vector graphics rendering library used by a dozen KDE games in the upcoming 4.6 release. KGameRenderer is only able to render graphics elements from SVG files. The new TagaroGraphics framework allows multiple types of graphics sources. Currently, the additional sources “image” and “color” are available, as can be seen in the following screenshot:

Both apps are the same example application. The first one gets the sprites from a PNG image (note the pixelation), while the sprites in the second screenshot are solid-colored rectangles. The graphics sources are specified by the configuration of the selected theme. Multiple graphics sources can be used by one theme. For example, some KDiamond themes have big raster images for the scene background; these are currently stored in the SVG file, which greatly increases the loading time of the SVG renderer. This can be optimized by storing the background image as an independent image file.

This split also allows us to be clever about further optimizations: TagaroGraphics (just like KGameRenderer, or Plasma::Svg) uses worker threads for the rendering of single SVG elements, but not for image or color elements, where the benefit of increased application responsibility is less than the overhead of setting up the worker thread.

Enough about TagaroGraphics. More important work is currently happening in TagaroInterface, where I have committed (to a work branch in my personal clone) first pieces of an generic interface element hierarchy. The basic idea is that there are several rendering frameworks (QPainter, QGraphicsView, SceneGraph) and graphics primitives or widget sets (QWidget, QGraphicsView primitives, plain QML items, QtComponents) out there currently and in the future. Support for specific widget sets or similar is a huge part of our codebase of at least 40 games.

For maintainability reasons alone, it can therefore be a good idea to abstract this stuff into a central library. It will never be able to serve all needs, but 95% or even 80% is enough. Furthermore, this step makes it easy to switch all interfaces from QWidget to e.g. SceneGraph with QtComponents, should the need arise. And even more: Abstraction makes it possible to change the widgets at runtime: Consider a game which can be run on the desktop or on a smartphone. On the desktop, you probably want the traditional WIMP interface with toolbars and statusbars. On the cellphone, you need to maximize the available screen space and minimize the size of controls, possibly hiding them completely until explicitly shown by e.g. hitting a hardware Menu key.

So the approach of TagaroInterface is to define its lowest common denominator set of interface elements. Visual representations can be instantiated on multiple backends, with the first one being QWidget. For testing, we have one element of each but one of the planned categories available by now: a display element (TiLabel), an input element (TiLineInput), an action element (TiPushButton), and a layout element (TiRow). The only missing category is top-level elements: These determine where elements show up on screen. I’m currently planning TiPanel (for controls that are permanently visible at a window edge), TiDialog (for full-window overlays), TiMenu (for actions), and possibly TiToolBar and TiStatusBar.

Now to put the fun in all this, all of this is available in QML (with the aforementioned Ti* type names). For example:



import Tagaro 1.0

TiRow {

title: "QML test"

TiLineInput {

id: input

}

TiLabel {

text: input.text

}

}



Because we’re at an early stage, there is not yet any integration into, say, QGraphicsView or QMainWindow. There is, however, a simple debug interface to instantiate QWidgets for these InterfaceElements, and everything seems to work as expected.

Let me once again reiterate why there is nothing like this yet (a matter which I discussed at length with Nokia people at the Mobile sprint in November). It’s not about instantiating QWidgets: Plain C++ and Designer files fulfil this job perfectly. I do also not want to replace QtComponents; QtComponents both on QGraphicsView+QML and SceneGraph will become important backends for TagaroInterface in the future. But QtComponents is by its nature tied to QML and (in its current incarnation) to QGraphicsView. I want something that works well in all circumstances and can be controlled without much trouble from C++ (all mentioned Ti* classes have easily accessible C++ counterparts).

And of course, my work is not unrelated to what is happening in other parts of the KDE community. I especially want to rely heavily on the upcoming QML support for core classes of kdelibs, most notably KLocalizedString, KAction (for the whole menubar and toolbar stuff) and possibly KGuiItem (and the plethora of standard KGuiItems and KActions).

P.S. At the aforementioned Mobile sprint, some people saw me playing with QAbstractItemModels for describing user interfaces. This is a fun idea, but the different controls are just too different to be squeezed into one set of roles. One can possibly do a lot of hinting, but it’s not worth the effort if there are simpler alternatives like QML.