Another inquiry post. I’m thinking about removing the custom mouse interaction code in Palapeli. The situation is that whereas most applications hardcode what certain mouse buttons do (e.g. left button = click, right button = context menu), Palapeli allows the user to configure which mouse button (or wheel) does what. For reference, this is the default configuration:

Problem is that the code behind these mouse button associations is awkwardly complex.¹ I plan to remove this mess and replace it with a sane default configuration because I feel it’s just adding clutter without providing much added value.

So if you want me to keep this code, please write back. Besides that, I also accept recommendations for a better default configuration.

¹ In numbers: 1127 LOC where the whole application is about 6000 LOC.

Any users of libkdegames?

January 31, 2012

Since we’re thinking about updating libkdegames, I was just wondering if any developer outside kdegames uses libkdegames. If you are or know such a developer, please write a comment.

The fact that KDiamond is included by default in Plasma Active’s default set of “Favorite applications” (among rekonq-active, calligra-active, and friends) finally made me hack a bit on kdegames stuff again. The main problem I see with KDiamond on a mobile form factor is that menubar and toolbar waste quite some vertical space. Also, the menubar is awful to use on a touchscreen; the toolbar is much better in this regard.

Can we combine these observations into an interface that saves space, yet is as approachable as a simple toolbar? We can.

In the back is the normal menubar/toolbar chrome. In the front is my first draft of an “Active” version of it. The menus “Game” and “Move” are completely gone, all contained actions are now on this first level of the toolbar. The “Settings” and “Help” menus have turned into toolbar buttons. Upon pressing one of these, the toolbar descends into that subcategory:

After selecting something from a subcategory, the toolbar automatically returns to the default category. For example, if you click on “Settings”, then on “Configure KDiamond”, the theme selection dialog comes up. When you’re done with that, you come back to the main window and find the default toolbar with the relevant New/Pause/Hint actions again.

What do you think? A first step in a good direction? Something you would even want on the desktop? Or just plain awful? Please let me know. BTW the source is available on ReviewBoard.

P.S. To get that straight: This is only for games with a small set of menu actions (about 28 of 40 KDE games, according to my counting). Apps like KGoldRunner or KTuberling just don’t fit the idea behind this proposal and will therefore not be affected.

P.P.S. I’m aware that vertical space is still wasted. I’m going to experiment with moving the toolbar to the side for displays which are wider than tall.

Now on Twitter

April 2, 2011

My last post was quite big, so I’ve split out the news part to ensure that it gets some attention. I’m now on Twitter as @stefanmajewsky. Follow me for updates on my KDE development, esp. Palapeli and Tagaro. My blog posts should also be syndicated there automatically; this post is the test balloon.

The Blue Wonder Meeting last week was an excellent opportunity to do some work on Palapeli. One thing that I wanted to do for at least a year was to rewrite the multithreading code around the (fairly central) Palapeli::Puzzle class. The new class has an aspect-oriented design, where single components of the puzzle (like the metadata or the contents) are always made available by worker threads, by casting existing components. For example, a puzzle file can be casted into metadata by reading the latter from the puzzle file. The possible casting paths are actually so convoluted that I documented them in an image inside the source code directory:

Yet there are still areas where Palapeli’s concurrency needs to improve. Much of the puzzle loading is done in the GUI thread, which causes the loading animation to freeze frequently. But that’s for another day. Moving back from what I should do to what I actually did, I noticed that Palapeli’s memory usage is awful. During the sprint, I wanted to demo Palapeli’s performance with big piece counts, and created a puzzle with the maximum of 2000 pieces from a 5000×5000 px image. It actually rendered fluently, but only because I upgraded my notebook’s RAM to 2 GB last year. Palapeli used an enormous 1.6 gigabytes of memory.

I figured that’s a bit much, and looked yesterday evening into how this can be optimized. I was testing with a 30 pieces puzzle from a 4000x4000px image. After having started Palapeli and having loaded the puzzle, the application used about 800 MB memory. The first, and simple, optimization was to remove some intermediary images which are only used while loading the image. That saved something like 100 MB of memory. But wait! Shouldn’t a 4000×4000 pixel image need only 61 MB (four bytes per pixel)? Yes, that’s true, but actually we’re not talking about one big image, but about 30 images, one for each piece. While pieces might have an arbitrary shape, their image must internally be rectangular all the time, even if big parts (e.g. around the plugs) are fully transparent. This means that the memory usage for the 30 pieces is bigger than what one might expect from the complete image.

A randomly chosen piece was 855×1098 pixels big, so by a rough approximation, all 30 pieces take 30*855*1098*4 bytes = 107 MB in memory. That still does not explain why the process still occupies 700 MB. But what’s that?

There’s a shadow around the pieces! This shadow is not added by the slicer when the puzzle is created, but by the engine when the puzzle is loaded. And because we need to control how shadows cover other pieces, we cannot render the shadows into the piece image, but must store them as separate images! And to make matters even worse, we need different shadow images for selected and unselected pieces (note the difference between blue and black shadows). The shadow size for the test image is 0.15 * (width + height) = 300 pixels on each side. Putting everything together, the memory usage of piece images + normal shadows + selected shadows is about 700 MB, i.e. everything can be explained by the pure size of the displayed images. The second optimization therefore was to restrict the shadow size to 50 pixels. This reduces the memory consumption to 380 MB, and allows to play even 5000×5000 px (i.e. 25 megapixel) images with below 1 GB of RAM.

More sophisticated optimizations are certainly possible, but let’s stop at this 50% improvement for now. There’s another thing I want to show: Palapeli’s mainwindow has been cleaned up. I really liked the old tab interface. It had its time and justification, but I want to move forward and need a cleaner, more standard interface for that. So now Palapeli has only a menubar and toolbar, just like all the other apps:

This change was possible after I realized that all toolbar actions for the collection also make sense on the puzzle table: Delete and Export work on the current puzzle. Newly created or imported puzzled will be loaded into the puzzle table afterwards. The “Back to collection” button replaces the “My collection” and “Puzzle table” tabs.

No time to blog yesterday! The Gluon guys were at my flat and we spent the evening cooking some tasty vegetarian meals. (No idea where the photos from this ground-breaking event ended up, though.)

Of course, we had some productive sprint session before that, which Josef covered yesterday already. The only missing part for now is the obligatory group photo below, which is (along with other photos) available from the git repository at kde:scratch/majewsky/blue-wonder-meeting.

From left to right: Josef, Laszlo, Felix, Shantanu, Arjen, Dan, me, Friedrich, Julian and Jeffrey.

KDE Games Sprint, day 0

March 24, 2011

The KDE Games Sprint (aka “The Blue Wonder Meeting”) is about to start. The zeroth day is for early arrivers, which gives me the opportunity to continue my code refactoring in Palapeli and possibly put Android+Necessitas on my N810. If you’re interested in more activity happening around the Games Sprint in the next few days, watch out on the Planet for posts with the blue sign which you see on the left.

From the 4.7 dept.: The puzzle list in Palapeli 1.3 will have sorting (by title and piece count) and filtering by title.

Games sprint?

January 19, 2011

Looks like we can organize a venue for a games sprint in Dresden around the end of March. If you would like to come, please enter your name in the table on this wiki page, and tell us when you could come. This is not a final reservation; we just want to estimate attendance.

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:

Using different graphics sources in Tagaro

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.