Open main menu

We plan to implement a new GUI look & feel in ScummVM, roughly based on the new look of our web site. Some concept drafts of the new look can be found here: http://www.thekrest.de/wip/scummvm/

You can also read the documentation on the GUI Themes.

To Do

  • Add possibility to specify shadow types to widget classes and to individual widgets
  • Theme hints too
  • List widget
    • get mock-up from Krest
    • shadows under lists. We do not enable those because of missing scrollbar mock-up
    • right side padding
    • fix caret misaligning
  • PopUp widget (aka drop-down list)
    • get mock-up from Krest
    • shadow is wrong
    • right side text padding
  • Tab widget
    • tab widget is drawn completely wrong now
      • though it would be nice to leave current drawing style and select them via widget property
  • Editable text widget
    • fix caret misaligning
  • Button widget
    • top line should be drawn with lighter color to make it look more natural
  • Slider Widget
    • top line should be drawn with lighter color to make it look more natural
  • Checkbox widget
    • smaller version of widget for 320xY resolution
  • Dialogs
    • Scumm save/load dialog
      • put thumbnail and save properties inside one container. Container code is missing now
    • About dialog
      • looks bad. Probably add some shadows and text padding
      • fix glitch at the top of the dialog where part of the characters get stuck
      • [Classic theme] Text seems to be drawn over the dialog frame. At least at the top of the dialog.
      • Often (always?) crashes when changing from 1x to 2x, or from 2x to 3x scaler.
    • Chooser dialog (add/edit game)
      • proper coloring and list shadow
      • The text "Norwegian BokmÃ¥l" isn't rendered correctly since our fonts do not have the letter "Ã…".
        • If we decide to use Latin-1 fonts instead, we should also update the About dialog to use accented characters where appropriate.
    • Debug console
      • Slow when typing commands. Perhaps the redrawing could be made more intelligent. (I haven't looked at how it works currently.)
      • The text is bordering on unreadably small.
      • Does not restore the old mouse cursor when closed.
  • Cursor handling
    • Cursor "jumps" in SCUMM games when opening/closing the F5 menu. (Or, more likely, when going between overlay and non-overlay mode.)
    • ScummVM crashes if, while in the GUI, changing from a 2x to 1x scaler while the cursor is in the upper right area of the screen.
      • The crash happens in the backend, when it tries to update a rectangle with completely bogus width. Perhaps a negative width stored in an unsigned variable?

Ideas & plans

The new GUI will rely on bitmaps / pixmaps for drawing the GUI widgets, like buttons, edit fields, tabs etc. This poses various problems and challenges but also some nice benefits (besides the obvious one, the improved look and feel :-).

Some random thoughts, ideas and statements:

  • Using pixmaps has the drawback of taking more memory, and possibly more CPU power. So as a fallback, it would be good if we could still work w/o the pixmaps (possibly reverting to the current UI).
  • To make that easy, use a kind of "ThemeManager" or "AppearanceManager", which is used by widgets to render themselves
  • This means we should try to seperate widget logic (what happens if a click occurs, managing data contained in the widget etc.) from widget drawing as much as possible. Ideally, widgets only know how to react to events etc. and whenever they need to draw something, they invoke suitable methods of the AppearanceManager
  • We'd provide two basic apperances: The current one, re-tooled to use a special AppearanceManager "plugin"/"module", and a new one, which uses pixmaps to render all widgets. Care should be taken to make it possible to add new ones or disable the pixmap based ones (for ports that are low on memory)
  • Anti-aliased fonts: Some of the concept drafts use anti-aliased fonts; while that looks nice and nifty, it also adds a lot to the complexity of text rendering. For now we'll try to work without it.
  • Image data can both be stored in external files as well as be compiled into the executable, or generated on-the-fly. To this end, we have a ImageManager class which helps separate the code using image data from the code used to loading the image data.
  • We should support all our primary resolutions: 320x200, 320x240, 640x400, 640x480. Ideally, we should support all resolutions (not just the ones I mentioned). Also, ideally every theme should support all, but if that is not possible, at least we should smoothly degrade to another theme (e.g. the 'classic' theme which doesn't use pixmaps to render itself), instead of e.g. crashing
  • ...

Customizability

We have been asked several times in the past to offer skinning support in ScummVM. With the new GUI code, this would be possible...

However, I (Fingolfin) think that this is a bad idea, and currently am opposed to this. IMHO, skinning is an excuse for not being able / willing to design a proper, nice, and usable default UI for your application (and in fact, the first famous skinable app, a certain MP3 player you may know, added skins precisely because of this).

Actually, "opposed" may not be the right word: I think that skinning should be very last thing we worry about. If we can add skinning w/o much hassle, w/o wasting resources that could otherwise be used to design and implement a great new default UI, we can consider it. But I am not willing to compromise our code design or the quality of the new GUI just to allow for skinning. I want ScummVM to look good and be easy to use "out of the box", this is the first (and the second and third :-) priority, IMNSHO...


Data formats

We probably will use BMP as the format for our pixmaps, optionally compressed using zlib / gzip. Reason: It's very easy to read BMPs (or at least certain BMPs, we don't have to implement a fully generic BMP loader), and we already use zlib. So this causes the least overhead (compared to using e.g. libpng for PNG support), and the resulting file sizes are not much bigger than those of PNGs.

It will also be possible to integrate pixmaps into the array, in the form of global/static arrays. We'll probably provide a tool that takes a BMP and generates a C++ source file from it. Note that here, zlib compression can be used, too (to reduce the size of the ScummVM binary).

Some pages that contain information about the BMP format:

The BMP "standard" doesn't really cover 16 bit data (the bit depth normally used by ScummVM). Sometimes, 15 and 16 are used to indicate 555 and 565 mode.

Some components of the new GUI code

ImageManager / GraphicsManager (singleton)

  • a singleton (?) which manages a set of graphic objects
  • client code can register graphics by name / ID
 imageMan->registerGraphic("button_leftSide", surface);
  • client code can query for a graphic by a name and/or an ID
 surface = imageMan->getGraphic("button_leftSide");
  • data stored/returned as a Graphics::Surface
  • client code must unregister images when the corresponding surface is deleted, else crashes may occur!
  • The idea of being able to "register" images is that it makes it possible to load image data both from files and from static arrays, as part of the executable
  • If an image is request which has not been registered, the ImageManager will search for image files matching the name, e.g. in the above example it might search for
 button_leftSide.bmp
 button_leftSide.bmp.gz

The precise list of supported file types could be hardcoded (easier to write, maintain, port, takes up less resources, but also is less flexible); or we could make it plugable so that arbitrary formats can be supported. My oppinion: Let's start simple, if we need multiple formats we already have an abstraction layer in place and can safely rewrite the internals of ImageManager later on


ImageLoader / ImageDecoder

Not sure whether we really need this class; it could encapsulate the code used to load & decode BMPs, and would in the future allow loading other formats, too (if desired), like PNG


AppearanceManager

This could be a very simple singleton which only manages a list of "Appearances" or "Themes". The real work would be then done by instances / subclasses of GUI::Theme or so...

 class Theme {
 public:
    virtual int getButtonHeight();
    virtual void drawButton(Rect r, String label);
    virtual void drawDialogBackground(Rect r);
    virtual void drawCheckbox(Rect r, String label, bool checked);
    ...
  };


Widget

We need to modify all Widget subclasses to use the active Theme to draw themselves.



How to render widgets

TODO: Include graphics in each subsection to demonstrate how the corresponding widget would look

Dialog background

TODO


Dialog tabs

TODO


Buttons

We should limit ourselves to buttons of a single height, that makes UI design more consistent, and rendering them simpler. To render a button using pixmaps, one needs at least three pixmaps: one of the left border, one for the right border, and one (which can be replicated and tiled) for the middle part. To draw a button, you first place the left/right borders, then tile the middle image, and finally render the label atop it.

One needs different pixmaps for the basic states a button can be in: Normal, pressed/clicked, disabled.

The slow way is to do all of this every time the button is drawn. The fast (but memory intensive) way is to cache the button in a graphic surface (all of its three states). We only generate the cached version of the button once it is used (e.g. a disabled button doesn't need to cache the normal/clicked version)


Checkboxes

TODO


Slider

TODO


Popup buttons

TODO


Lists

TODO


Scrollbars

TODO -- concept art is missing, too


Input fields

TODO


Radio buttons

TODO -- this widget actually doesn't exist currently