Aloshi / EmulationStation

A flexible emulator front-end supporting keyboardless navigation and custom system themes.
MIT License
2.06k stars 905 forks source link

Theme System Changes #139

Closed Aloshi closed 10 years ago

Aloshi commented 10 years ago

So the next EmulationStation "update" (when I merge the unstable branch into master) is going to break everything to hell (but there's an integrated scraper now!). In particular there's the new XML format for es_systems.cfg format and the theming of the fast select box completely changing (which no one was using anyway). I feel these are honestly pretty minor changes, but breaking backwards compatibility is not to be taken lightly.

There is one more big change I have been considering: changing the theme system. I'm bringing this up now because I'd like to break everything in one update, rather than two.

The current theming system is incredibly flexible. This was good when there wasn't really a strong sense of how the game list would look. It gave people much more artistically inclined than myself the option to tweak things as much as they wanted. When there was only one screen (the game list), it worked well. Now, the game list has settled on a few basic elements: a background image, a header, game art, scrolling game info, and maybe a divider.

I think the biggest mistake I made designing the current theming system was allowing each system's theme to create elements individually. That flexibility comes at a price: introducing new ways of viewing the game list will fundamentally require new themes for every system, similar to the distinction between <theme> and <basicTheme> now. It also makes consistently animating elements somewhat difficult (there isn't a way to tell "this is a header" or "this is a background").

I see a few ways to go:

(A) Completely get rid of the current system, only allow themes to specify resource paths. Layouts become completely hardcoded. This offers the most developer control and the least artist flexibility, but it would be possible to get any theme to work and look mostly consistent across multiple views without changes to the theme.xml. Consistent resource naming and typing is obviously very heavily enforced. An example:

<theme>
    <backgroundImage tile="true"> generalArt/mybg.png </backgroundImage>
    <scrollSound> generalSounds/mysound.wav </scrollSound>
</theme>

<!-- How this gets used is completely up to the C++ code.  Pretty much all layout customization vanishes. -->

(B) Split themes into "resource" and "layout" definitions. This would require significant work, but almost completely keeps flexibility. Instead of allowing a system's theme to move elements, only new resource paths and parameters can be specified. Almost all of view design complexity is moved from C++ to XML. So long as themes follow resource naming consistencies, introducing new views should not be too much of a problem. Animation details can be worked into the layout format. This option runs the risk of being overkill/I'm too infatuated with the idea of it and go too far.

Detailed example, I am making this up as I go along:

<!-- in a theme.xml -->
<resources>
    <resource name="backgroundImage" tile="true"> systemArt/mybg.png </resource>
    <resource name="headerImage"> systemArt/myheader.png </resource>
    <resource name="scrollSound"> systemSounds/mysound.wav </resource>
    <resource name="gamelistPrimaryColor">0xFFFFFF</resource>
    <resource name="gamelistSecondaryColor">0x00FF00FF</resource>
    <resource name="gamelistFont" size="0.1">generalFonts/myfont.ttf</resource>
    <resource name="infoFont" size="0.05">generalFonts/myfont.ttf</resource>
</resources>

<!-- in a different, EmulationStation-wide file -->
<listLayout>
    <!-- Vector dimensions are now delimited by a comma.

    $variable now refers to named components.  Some position and dimension "properties" accessde with the period operator exist to simplify expression:
        $variable.x, $variable.y, $variable.left, $variable.right, $variable.top, $variable.bottom

    @variable now refers to a resource.  The period operator can be used to access XML attributes. The variable name itself will refer to the XML value. 
    @metadata is a special, automatically generated resource that refers to what you would expect. 

    This would probably be heavily dependant on something like boost::lexical_cast and factories. -->

    <image name="background">
        <pos>0, 0</pos>
        <dim>1, 1</dim>
        <origin>0, 0</origin>
        <tile>@backgroundImage.tile</tile>
        <value>@backgroundImage</value>
    </image>

    <!-- Roughly equivalent to the following C++ code:
    GuiComponent* comp = new ImageComponent(window);
    comp->setPosition(0, 0);
    comp->setSize(Renderer::getScreenWidth(), Renderer::getScreenHeight());
    comp->setTiled(true);
    comp->setValue("generalArt/mybg.png");
    -->

    <image name="header">
        <pos>0.5, 0</pos>
        <dim>0, 0.2</dim>
        <origin>0.5, 0</origin>
        <value>@headerImage</value>
    </image>

    <image name="gameImage">
        <pos>0.05, 0.2</pos>
        <dim>0, 0.4</dim>
        <origin>0, 0</origin>
        <value>@metadata.image>
    </image>

    <scrollableContainer name="gameInfo">
        <pos>$gameImage.left, $gameImage.bottom + 0.05</pos>
        <dim>$gameImage.width, $screen.width - $this.top</dim>

        <!-- Can define new elements as children.
        Constants are percentages of the parent's size. 
        (0, 0) refers to the parent's position, (1, 1) refers to its bottom right corner. -->

        <datetime name="gameReleasedate">
            <pos>0, 0</pos>
            <dim>0, 0</dim>
            <font>
                <size>@infoFont.size</size>
                <path>@infoFont</path>
            </font>
            <value>@metadata.releasedate</value>
        </datetime>

        <rating name="gameRating">
            <pos>$gameRating.right + 0.02, 0</pos>
            <dim>0, $gameReleasedate.height</dim>
            <value>@metadata.rating</value>
        </rating>

        <text>
            <pos>0, $gameRating.bottom</pos>
            <dim>1, 0</dim>
            <font>
                <size>@infoFont.size</size>
                <path>@infoFont</path>
            </font>
            <value>@metadata.description</value>
        </text>

    </scrollableContainer>

    <gamelist>
        <pos>0.52, $gameImage.top</pos>
        <dim>0.46, 1 - $this.y</dim>

        <!--gamelist-specific attributes -->
        <font>
            <size>@gamelistFont.size</size>
            <path>@gamelistFont</path>
        </font>
        <primaryColor>@gamelistPrimaryColor</primaryColor>
        <secondaryColor>@gamelistSecondaryColor</secondaryColor>
    </gamelist>
</listLayout>

(C) Don't change the theme system. Add new tags like <gameTilesTheme> as new views are introduced. The problems can be hacked around, and theme.xmls will need to be updated as new views are introduced.

This has serious consequences for folks who use EmulationStation and potentially spent a lot of time tweaking their themes to get them just the way they like, so I'd like to ask the community:

leandromacrini commented 10 years ago

pro&cons A) the beauty & closed heaven. break down compatibility with previous versions, is good for user experience, people can still personalize their system with custom background or icons but the look and feel will be the same on every system. good maintainability and ability to create a complex GUI with hardcoded animations and features.

B) the coding hell. in this case you are not building a frontend for emulation, you are building a animation e GUI framework. like LUA. you will have to code every feature and create a XML interface to let the user use it in the themes files. emulationstation will never have a user experience, everyone will do each own (or copy it from somebody) and probably you will need a team just for take over the open bugs and features requests.

C) the maintenance purgatory. if you code a nice feature you will have to put it the themes system and any old themes will no longer be valid (or look ugly) so everyone will need to update it.

sorry for bad english ;)

Aloshi commented 10 years ago

You're exactly right, I think. :smile:

I think I'm going to go with A.

B works for the current game list example I gave and maybe a "tile view" example...but indeed evolves into basically building a scripting language as you do anything complex (by "complex" I mean something on the level of pretty much any XBMC view or displaying more than one game's metadata at a time).

Going through the existing RetroPie themes, I think that it should be possible to encompass almost every existing design with:

The only outlier might be the Genesis theme (its header is designed to take up the top left corner). Since this seriously affects RetroPie, what do you think @petrockblog?

petrockblog commented 10 years ago

I would also prefer a unique look and feel, so option A) sounds good!

Doing a bit of brainstorming, I am additionally thinking of

I am not sure if these ideas fit into the context of this thread, though.

jlpubarch commented 10 years ago

I find myself re-theming after each update, so I would prefer to blow the whole thing up once rather than do it incrementally.

petrockblog commented 10 years ago

Hi @Aloshi ! I just found myself fiddling around with the theming capabilities of the current stable branch of ES. I was wondering about the current state of the major update ES that you are working on (which is said to have a whole new theming engine ;-) )?

Aloshi commented 10 years ago

I've almost got everything in the unstable branch working as well as the stable branch. I think all that's missing right now is some of the metadata display and the animation for when game images come in/go out. Here's a partial changelog. The new theming system is a lot more limited than the old system was, so I'm pretty hesitant to call it a feature.

You should be able to test it out with my RetroPie-Setup fork, which uses the unstable branch. The only thing it's missing right now is a way to install SDL2, since it's not in the repositories (well, 2.0.1 isn't, at least). If you install it manually before compiling ES it should work fine (download, run ./configure, make, and sudo make install). It will also download the new set of themes from my website (obviously this will be changed once it's ready for release).

nilsbyte commented 10 years ago

Hi @Aloshi and @petrockblog,

I recently set up RetroPie and now i am about to customize my themes for EmulationStation. Attached a first impression of what a theme could look like based on the current ones. I did the SNES theme first because it's my favourite retro console :-)

13-12-snes_theme

What do you think? ... and is this possible with the new theming system? I am using a build of ES from Nov, 3rd.

I am a graphic artist and familiar with interface design, so for me it wouldn't be so good to restrict the possibilities in theming. I would love to see EmulationStation with a theming system like XBMC where the user has complete freedom.

billipo commented 10 years ago

Wow! Looks great. I hope you work with Aloshi in the future to further refine the look of ES. I know he has mentioned in the past that he does not have the graphic design background. Hopefully you can be that link.

Aloshi commented 10 years ago

Hello, @retrofan87!

That design is mostly possible with the old theming system (which is what is currently in RetroPie). I think the only thing that is not is moving the description text to be on the right of the game image.

Now that the theming system has been re-implemented I'll show it off a little...(you can see all these pictures in their original resolutions in this album if you prefer)

snes detailed

This is the current "detailed gamelist view" screen. It's almost identical to the old one. I still haven't re-added the fade in/out animations or the extra metadata to the description text.

nes detailed

Another for NES (the box art is too big here to display the description...better add some better resizing stuff later!).

The theming system has changed how it loads "defaults" now. It starts out with the initial programmer-defined defaults (useful because default images can be compiled into the source now). Next, it loads the $HOME/es_theme_default.xml file if it exists. Next, it loads the system's theme.

So these are the magical theme files that make those two pictures:

<theme>
    <listFont>
        <path>./default_theme/pixeljosh6.ttf</path>
    </listFont>

    <descriptionFont>
        <path>./default_theme/pixeljosh6.ttf</path>
    </descriptionFont>

    <fastSelectLetterFont>
        <path>./default_theme/pixeljosh6.ttf</path>
    </fastSelectLetterFont>

    <scrollSound>./default_theme/sounds/GS25.wav</scrollSound>
    <gameSelectSound>./default_theme/sounds/GS42.wav</gameSelectSound>
    <backSound>./default_theme/sounds/GS28.wav</backSound>
    <menuOpenSound>./default_theme/sounds/SNES5.wav</menuOpenSound>
</theme>
<theme>
    <listPrimaryColor>E4E1E5</listPrimaryColor>
    <descriptionColor>48474D</descriptionColor>
    <listSelectorColor>fc0c18</listSelectorColor>

    <backgroundImage>
        <path>./snes_art/snes_bg.png</path>
        <tile>true</tile>
    </backgroundImage>

    <headerImage>
        <path>./snes_art/snes_logo_basic.png</path>
    </headerImage>

    <systemImage>
        <path>./snes_art/console.png</path>
    </systemImage>
</theme>
<theme>
    <listPrimaryColor>A61600</listPrimaryColor>
    <descriptionColor>DDDDDD</descriptionColor>
    <listSelectorColor>818181</listSelectorColor>

    <backgroundImage>
        <path>./nes_art/nes_bg_stripes.png</path>
        <tile>true</tile>
    </backgroundImage>

    <headerImage>
        <path>./nes_art/nes_logo.png</path>
    </headerImage>

    <infoBackgroundImage>
        <path>./nes_art/nes_bg_grey.jpg</path>
        <tile>false</tile>
    </infoBackgroundImage>

    <systemImage>
        <path>./nes_art/nes_console.png</path>
    </systemImage>
</theme>

As you can see, it's really easy to do. There's also no more duplicate definitions all over the place.

If you're wondering what the <systemImage> tag does, it's for the new "system select" menu: snes system select (I'm still unhappy with the system select menu; I'd really like to try throwing in a simple particle sim as a backdrop ala this (requires WebGL), but it might not go well with the rest of the UI. Another idea is to just use the same background as the gamelist view.)

You can't see it, but the transitions between gamelists are also waaay nicer now too.

And to address the problem of making things more restrictive...here's one of the perks to doing it this way.

snes image grid nes image grid

This new "grid view" was written in a couple of afternoons, and requires no changes to the existing theme file(s) to work.

There's no perfect answer. Making something like XBMC is possible, but really beginner-unfriendly. It's hard to say for sure, but I think most people would rather not take the time to learn to use complex but powerful tools. Anything you could do through any scripting layer I add can be done (and usually done better) on the C++ side. That said, it would be possible to bring back most of the old functionality through some sort of view-specific "add extra components" tag. I am not sure if I want to do this yet.

Secret bonus: sometimes I get bored while debugging and this happens

Happy holidays!

nilsbyte commented 10 years ago

Hi @Aloshi,

thank you for showing us the work you've done so far. As i am more from the graphics and UI side, i don't know if i did understand everything in your post. I will try to explain how i see it.

So EmulationStation will provide a hardcoded default theme if no XML files are present. If $HOME/es_theme_default.xml is created by the user, he can put some global adjustments like fonts and sounds here. Finally when, for example the file $HOME/snes/theme.xml for the SNES system is created by the user, he can customize appearance of the theme using images and colors.

The problem i see here is that all the elements have fixed positions and dimensions, because there are no attributes in the XML to control that. That would restrict creative freedom in creating themes a lot. I would go a different approach, very much like the old system where the user can use and place pre-defined elements like "boxart", "description", "list", "header" where each element has various attributes like "font", "size", "position", "tiling" and so on. I think this approach is more in the mind of the users out there because freedom is everything for a community. Theming should be entirely XML based and not hardcoded. The stock-version of ES could provide themes which the user can modify or replace by his own. that said, i would love to work together with you to create the stock-themes for EmulationStation.

As for the grid views, i think that's a great idea. As for the system select menu: Are you planning a sort of hierarchic menu structure where the user first selects the system, then the game from list or grid view? i personally think there is no need for the system menu, i mean it's nice but it's a step more to get to the game you want to play. besides, the list or grid view communicates which platform you are viewing at the moment, so thats another reason to drop that screen.

No matter if you want to restrict theming functionality or not, i would love to work together with you to create solid and nice-looking stock-themes. That would be a project i always wanted to do.

Can we talk about theming in a greater depth? I'll drop you an email.

billipo commented 10 years ago

@retrofan87, could you provide me with the theme that you have shown above? I am almost done with my RetroPie, and I would love to use your theme. My email is billipo at yahoo.com

Again, I hope you and Aloshi are able to work together in the future to really refine the look of Emulation Station. I believe it's one of the best emulator platforms available for 80's and 90's games.

Thanks!

Peteyjay commented 10 years ago

Hey there!

I am using a build on my Pi called Ultraslim. It features ES with Retroarch and XBMC etc.. I'm sure you're all aware of it.

Anyway, the themes above (grid view etc), are these attainable at the moment with an update? Or are these still in development? The system selection menu seems fantastic and I would love to implement it into my build.

Aloshi commented 10 years ago

Still in development. The system select screen has been redone since then to work like an endless carousel (picture). I've been working with @retrofan87 over the past couple of months, and a lot has changed. The theming system has been rewritten again because he finally convinced me it was a stupid idea to remove such an important feature from ES. We've finally got a plan for how ES should work, and are slowly putting it into action - for example, here's the first version of the new menu style (not final!).

That said, there is still a lot to do. The biggest reason no one can really try it out yet is because no themes exist for the new theming system (except my private rewrite of the RetroPie SNES theme and @retrofan87's SNES theme).

It's still going to be a while, unfortunately.

nilsbyte commented 10 years ago

retrofan87 speaking :-) changed my nick to my default one. After @Aloshi and me have implemented all the UI stuff (menus, help system etc.) i will finish building the system-specific themes (shown earlier in this post) including the system select screen posted by @Aloshi. The themes for the different systems will be similar to each other, only the logos and the box art will change. my goal is to create a very clean and uniform theme-set.