# EmulationStation Desktop Edition (ES-DE) v2.0 (development version) - Themes **Note:** This document is only relevant for the current ES-DE development version, if you would like to see the documentation for the latest stable release, refer to [THEMES.md](THEMES.md) instead. If creating theme sets specifically for ES-DE, please add `-DE` to the theme name, as in `slate-DE`. Because ES-DE theme functionality has deviated greatly from the RetroPie EmulationStation fork on which it was originally based, any newer themes will not work on such older forks. It would be confusing and annoying for users that attempt to use ES-DE theme sets in older EmulationStation forks as they would get unthemed systems, crashes, error messages or corrupted graphics. At least the -DE extension is a visual indicator that it's an ES-DE specific theme set. Table of contents: [[_TOC_]] ## Introduction ES-DE allows the grouping of themes for multiple game systems into a **theme set**. A theme is a collection of **elements**, each with their own **properties** that define the way they look and behave. These elements include things like text lists, carousels, images and animations. Internally ES-DE uses the concept of **components** to actually implement the necessary building blocks to parse and render the elements, and although this is normally beyond the scope of what a theme author needs to consider, it's still good to be aware of the term as it's sometimes used in the documentation. Every game system has its own subdirectory within the theme set directory structure, and these are defined in the systems configuration file `es_systems.xml` either via the optional `` tag, or otherwise via the mandatory `` tag. When ES-DE populates a system on startup it will look for a file named `theme.xml` in each such directory. By placing a theme.xml file directly in the root of the theme set directory, that file will be processed as a default if there is no system-specific theme.xml file available. In the example below, we have a theme set named `mythemeset-DE` which includes the `snes` and `nes` systems. Assuming you have some games installed for these systems, the files `mythemeset-DE/nes/theme.xml` and `mythemeset-DE/snes/theme.xml` will be processed on startup. If there are no games available for a system, its theme.xml file will be skipped. The directory structure of our example theme set could look something like the following: ``` ... themes/ mythemeset-DE/ core/ font.ttf bold_font.ttf frame.png nes/ theme.xml background.jpg logo.svg logo_video.svg snes/ theme.xml background.jpg logo.svg logo_video.svg fonts.xml theme.xml ``` The theme set approach makes it easy for users to install different themes and choose between them from the _UI Settings_ menu. There are two places that ES-DE can load theme sets from: * `[HOME]/.emulationstation/themes/[THEME_SET]/` * `[INSTALLATION PATH]/themes/[THEME_SET]/` An example installation path would be: \ `/usr/share/emulationstation/themes/slate-DE/` If a theme set with the same name exists in both locations, the one in the home directory will be loaded and the other one will be skipped. ## Differences to legacy RetroPie themes If you are not familiar with theming for RetroPie or similar forks of EmulationStation you can skip this section as it only describes the key differences between the updated ES-DE themes and these _legacy_ theme sets. The term _legacy_ is used throughout this document to refer to this older style of themes which ES-DE still fully supports for backward compatibility reasons. The old theme format is described in [THEMES-LEGACY.md](THEMES-LEGACY.md) although this document is basically a historical artifact by now. With ES-DE v2.0 a new theme engine was introduced that fundamentally changed some aspects of how theming works. The previous design used specific view styles (basic, detailed, video and grid) and this was dropped completely and replaced with _variants_ that can accomplish the same thing while being much more powerful and flexible. In the past EmulationStation basically had hardcoded view styles with certain elements always being present and only a limited ability to manipulate these via positioning, resizing, coloring etc. As well so-called _extras_ were provided to expand theming support somehow but even this was quite limited. With the new theme engine the view presets were removed and the only views now available, _system_ and _gamelist_, were rewritten to be much more flexible. Essentially the element selection and placement is now unlimited; any number of elements of any type can be used, although with a few notable exceptions as explained throughout this document. In addition to the variant support which provides an unlimited flexibility for creating custom theme profiles, support for specific aspect ratios was introduced. This makes it possible to define different theme configuration for different display aspect ratios and to provide the user with the option to choose between these from the _UI Settings_ menu. That could for example be choice between a 16:9 and a 4:3 layout, or perhaps also a vertical screen orientation layout in addition to these. As well new theming abilities like Lottie animations were added with the new theme engine. The following are the most important changes compared to the legacy theme structure: * View styles are now limited to only _system_ and _gamelist_ (there is a special _all_ view style as well but that is only used for navigation sounds as explained later in this document) * The hardcoded metadata attributes like _md_image_ and _md_developer_ are gone, but a new `` property is available for populating views with metadata information * The concept of _extras_ is gone as all element can now be used however the theme author wishes * The concept of _features_ is gone * The `` tag is gone as tracking theme versions doesn't make much sense after all * The `video` element properties `showSnapshotNoVideo` and `showSnapshotDelay` have been removed * The ambiguous `alignment` property has been replaced with the `horizontalAlignment` and `verticalAlignment` properties (the same is true for `logoAlignment` for the `carousel` element) * The `forceUppercase` property has been replaced with the more versatile `letterCase` property * Many property names for the carousel have been renamed, with _logo_ being replaced by _item_ as this element can now be used in both the gamelist and system views. As well, setting the alignment will not automatically add any margins as is the case for legacy themes. These can still be set manually using the `horizontalOffset` and `verticalOffset` properties if needed. The way that alignment works in general for both carousel items and the overall carousel has also changed * The rating elements were previously not sized and overlaid consistently, this has now been fixed and rating images should now be centered on the image canvas in order for this element to render correctly rather than being left-adjusted as has previously been done by some theme authors (likely as a workaround for the previous buggy implementation). Images of any aspect ratios are now also supported where previously only square images could be used * The carousel text element hacks `systemInfo` and `logoText` have been removed and replaced with proper carousel properties * The carousel property maxItemCount (formerly named maxLogoCount) is now in float format for more granular control of logo placement compared to integer format for legacy themes. However some legacy theme authors thought this property supported floats (as the theme documentation incorrectly stated this) and have therefore set it to fractional values such as 3.5. This was actually rounded up when loading the theme configuration, and this logic is retained for legacy themes for backward compatibility. But for current themes the float value is correctly interpreted which means a manual rounding of the value is required in order to retain an identical layout when porting theme sets to the new theme engine. As well carousels of the wheel type now have the amount of entries controlled by the two new properties `itemsBeforeCenter` and `itemsAfterCenter`. This provides more exact control, including the ability to setup assymetric wheels. * The helpsystem `textColorDimmed` and `iconColorDimmed` properties (which apply when opening a menu) were always defined under the system view configuration which meant these properties could not be separately set for the gamelist views. Now these properties work as expected with the possibility to configure separate values for the system and gamelist views * Correct theme structure is enforced more strictly than before, and deviations will generate error log messages and make the theme loading fail * Many additional elements and properties have been added, refer to the [Reference](THEMES-DEV.md#reference) section for more information Attempting to use any of the legacy logic in the new theme structure will make the theme loading fail, for example adding the _extra="true"_ attribute to any element. Except the points mentioned above, theme configuration looks pretty similar to the legacy theme structure, so anyone having experience with these older themes should hopefully feel quite at home with the new theme engine. Probably the most important thing to keep in mind is that as there are no longer any view presets available, some more effort is needed from the theme developer to define values for some elements. This is especially true for zIndex values as elements could now be hidden by other elements if care is not taken to explicitly set the zIndex for each of them. This additional work is however a small price to pay for the much more powerful and flexible theming functionality provided by the new theme engine. ## Simple example Here is a very simple theme that changes the color of the game name text: ```xml 00FF00 0.5 0.5 0.5 0.5 0.8 0.8 ./core/frame.png 10 ``` ## How it works All configuration must be contained within a `` tag pair. That is true for each separate .xml file used to build the completely theme set. The `` tag pair refers to the available views within ES-DE, which is either _system_ or _gamelist_. There is a special _all_ view available as well, but that is only used for defining the navigation sounds as these are always applied globally to both view types. Views are defined like this: ```xml ... define elements here ... ``` An element is a particular visual component such as an image, an animation or a piece of text. It has a mandatory _name_ attribute which is used by ES-DE to track each element entry. By using this name attribute it's possible to split up the definition of an element to different locations. For example you may want to define the color properties separately from where the size and position are configured (see the example below). The name attribute can be set to any string value. This is the element structure: ```xml ... define properties here ... ``` Finally _properties_ control how a particular element looks and behaves, for example its position, size, image path, animation controls etc. The property type determines what kinds of values you can use. You can read about each type below in the [Reference](THEMES-DEV.md#reference) section. Properties are defined like this: ```xml ValueHere ``` Let's now put it all together. The following is a simple example of a text element which has its definition split across two separate XML files. `themes.xml`: ```xml 0.27 0.32 0.5 0.5 0.12 0.41 40 ``` `colors.xml`: ```xml 707070 ``` As long as the name attribute is identical, the element configuration will be combined automatically. But that is only true for elements of the same type, so for instance an image element could be defined that also uses _system_name_ for its name attribute without colliding with the text element: ```xml 0.27 0.32 0.5 0.5 0.12 0.41 40 0.49 0.8 0.4 0.28 35 ``` Whether this is a good idea is another question, it would probably be better to set the name attribute for the image to _system_logo_ or similar for this example. In addition to this, if the name is used for the same element type but for different views, then there will also not be any collision: ```xml 0.04 0.73 0.5 0.5 0.12 0.22 40 0.27 0.32 0.5 0.5 0.12 0.41 40 ``` ## Debugging during theme development If you are writing a theme it's recommended to launch ES-DE with the `--debug` flag from a terminal window. You can also pass the `--resolution` flag to avoid having the application window fill the entire screen. By doing so, you can read error messages directly in the terminal window without having to open the es_log.txt file. You can also reload the current gamelist or system view with `Ctrl+r` if the `--debug` flag has been set. There is also support for highlighting the size and position of each image and animation element by using the `Ctrl+i` key combination and likewise to highlight each text element by using the `Ctrl+t` keys. Again, both of these require that ES-DE has been launched with the `--debug` command line option, for example: ``` emulationstation --debug --resolution 1280 720 ``` Enforcement of a correct theme configuration is quite strict, and most errors will abort the theme loading, leading to an unthemed system. In each such situation the log output will be very clear of what happened, for instance: ``` Jan 28 17:17:30 Error: ThemeData::parseElement(): "/home/myusername/.emulationstation/themes/mythemeset-DE/theme.xml": Property "origin" for element "image" has no value defined ``` Sanitization for valid data format and structure is done in this manner, but verification that property values are actually correct (or reasonable) is handled by the individual component that takes care of creating and rendering the specific theme element. What happens in many instances is that a warning log entry is created and the invalid property is reset to its default value. So for these situations, the system will not become unthemed. Here's an example where a badges element accidentally had its horizontalAlignment property set to _leftr_ instead of _left_: ``` Jan 28 17:25:27 Warn: BadgeComponent: Invalid theme configuration, set to "leftr" ``` Note however that warnings are not printed for all invalid properties as that would lead to an excessive amount of logging code. This is especially true for numeric values which are commonly just clamped to the allowable range without notifying the theme author. So make sure to check the [Reference](THEMES-DEV.md#reference) section of this document for valid values for each property. For more serious issues where it does not make sense to assign a default value or auto-adjust the configuration, an error log entry is generated and the element will in most instances not get rendered at all. Here's such an example where the imageType property for a video element was accidentally set to _covr_ instead of _cover_: ``` Jan 28 17:29:11 Error: VideoComponent: Invalid theme configuration, property defined as "covr" ``` ## Variants A core concept of ES-DE is the use of theme set _variants_ to provide different theme profiles. These are not fixed presets and a theme author can instead name and define whatever variants he wants for his theme (or possibly use no variants at all as they are optional). The variants could be purely cosmetic, such as providing light and dark mode versions of the theme set, or they could provide different functionality by for instance using different primary elements such as a carousel or a text list. Before a variant can be used it needs to be declared, which is done in the `capabilities.xml` file that must be stored in the root of the theme set directory tree. How to setup this file is described in detailed later in this document. The use of variants is straightforward, a section of the configuration that should be included for a certain variant is enclosed inside the `` tag pair. This has to be placed inside the `` tag pair, and it can only be used on this level of the hierarchy and not inside a `` tag pair for example. The mandatory _name_ attribute is used to specificy which variants to use, and multiple variants can be specified at the same time by separating them by commas or by whitespace characters (tabs, spaces or line breaks). It could be a good idea to separate the various variant configuration into separate files that are then included from the main theme file as this could improve the structure and readability of the theme set configuration. Here are some example uses of the `` functionality: ```xml ./../colors_light.xml ./../colors_dark.xml ./core/font.ttf 0.035 0.3 0.56 titlescreen true 42 titlescreen true 42 ``` ## Aspect ratios The aspect ratio support works almost identically to the variants support with the main difference that the available aspect ratios are hardcoded into ES-DE. The theme set can still decide which of the aspect ratios to support (or none at all in which cast the theme aspect ratios is left undefined) but it can't create entirely new aspect ratios. The reason for why aspect ratios were implemented at all instead of only using variants was that the amount of defined variants would have grown exponentially for all possible combinations, making the theme sets very hard to create and maintain. In the same manner as for the variants, the aspect ratios that the theme set provides need to be declared in the `capabilities.xml` file that must be stored in the root of the theme set directory tree. How to setup this file is described in detailed later in this document. Once the aspect ratios have been defined, they are applied to the theme configuration in exactly the same way as the variants: ```xml ./../layout_narrow.xml ./../layout_wide.xml ./../layout_ultrawide.xml ./core/font.ttf 0.035 0.3 0.56 0.42 0.31 0.3 0.56 ``` ## capabilities.xml Variant and aspect ratio values need to be declared before they can be used inside the actual theme set configuration files and that is done in the `capabilities.xml` file. This file needs to exist in the root of the theme directory, for example: ``` ~/.emulationstation/themes/mythemeset-DE/capabilities.xml ``` This file type was introduced with the new ES-DE theme engine in v2.0 and is an indicator that the theme set is of the new generation instead of being of the legacy type (i.e. a theme set backward compatible with RetroPie EmulationStation). In other words, if the capabilities.xml file is absent, the theme will get loaded as a legacy set. The structure of the file is simple, it just contains the declarations for the variants and aspect ratios, such as in this example: ```xml 16:9 4:3 4:3_vertical true true ``` The file format is hopefully mostly self-explanatory; this example provides three aspect ratios and two variants. The `