Make Simutrans speak your language.

CEGUI integration project

Started by Markohs, February 04, 2012, 12:12:48 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.


 Well, looking it might be possible to change the UI system to shift their design to the PAK designers, and seeing this change will only simplify Simutrans 3D development, I start another project to integrate CEGUI in the current simutrans code.

What's the purpose of this project?
- Base the UI in a library that allows modyfing it's appearance without recompiling Simutrans, since the description it's in external files.
- Make the UI more customizable.
- Free the Simutrans coders from the UI coding so they can spend time on other areas of the project.
- Throw all this responsability to the PAK creators. Simutrans has to have a default UI, that will look the more similar possible to the current one. Pak mantainers will be able to override the default GUI and customize it.
- To have a UI that's well suited for use in a 3D enviroment.

Design decisions so far:

- CEGUI supports various renderers, including DirectX, OpenGL , Ogre3D and Irrlitch. Since OpenGL is the more open and multiplatform one, I'll develop with it. Should be no problem to switch to other renderers.   
-  The idea is just porting the GUI to CEGUI, and render the rest of the scene in a framebuffer fashion, using the current code to write to a plain texture, that will stay after the GUI. This has been tested in simutrans 3D and has given acceptable framerate, very similar to current simutrans code.
- CEGUI doesn't handle inputs by itself. Thsi is a design decision. So the initial plan is to stick to SDL for the keyboard and mouse.

Problems that might arise:

- I might have chosen the wrong GUI framework for this project, even from what I saw, it looks like the more complete and suited one. A list can be found here.
- CEGUI might not work in Haiku, even I've read some comments about at least some package for it being developed.
- I don't see any information about Amiga OS, even through CEGUI has some AmigaOS widgets implemented, I don't know if it can be compiled there.
- Cegui has some dependences:
* FreeType2
*  Perl C Regular Expression
*  Xerces-C++
* ...

All those libraries seem reasonable to me, MIT and BSD are compatible with simutrans license as far as I know. Freetype handles non latin texts good I guess, even I'm not an expert, but I guess it supports unicode.

I'm open to all kind of comments from the whole simutrans community, just post here.


A more flexible UI framework allowing customization, great. Throwing it at the PAK creators, maybe not great; Simply for consistencies sake. Different PAKs are really just different graphics for the same game, same game ->> should be same basic UI. It's bad enough switching PAKs now with the annoyingly different key bindings, imagine a whole different UI in each. aaiieee!


Well, the idea is have a default UI that will work just as it works the current one. Just that the pak creators can customize windows borders, to put a recent example. And that whould only affect to the UI in that PAK. Or maybe different aligns in the finances windows or whatever. This GUI even allows the PAK developers to modify the UI even further, using LUA.

But the basic, default, non-modified GUI will do and look the same as the current one.

We can allways define what the PAK creators can and can't modify, if we feel it's a game breaking setting.

UPDATE: I'll need some gimp sessions to get the current bitmaps to work! :)

Just one question, the file that's shipped on the binaries skin/menu.WindowSkin.pak is generated from runk\skins.src\skins.* ? What's the aero version for?


This is an alternative skin, following the MAC look. (Try it out.)


I think the CEGUI framework looks very promising. I feel a bit uncertain since this effort overlaps so much with my ideas for Simutrans Iron Bite, but on the other hand we can also learn from each other. Let's see how things will evolve, I have good trust in you after your work with Simutrans3D!


I see, Prissi, thank you. :)

Don't worry Hajo, we'll find the way to make everyone happy :) .

ATM I'm messing around with makeobj and the pak format, to check out how can I extract the UI frames of the PAK on the fly. need to generate a bitmap with all the windows/buttons/mousecursors.

Another option whould require the PAK developers to supply an imagemap of all their widgets. I'll keep you updated.


By the way, I see simutrans fonts are in .bdf format, looks like Freetype supports them but I'm having problems opening them. Where did this fonts came from?

Also, the file skin\menu.WindowSkin.pak has just the minimum number is items to be able to show the pak selection screen, but how do you generate it? if it's from trunk\sinks\skins.png it lacks a mousecursor, how comes the SDL version comes with a mousecursor already?


There is a mouse pointer Pak in pakset. You browse the svn e.g. of pak128.


yeah, i grabbed the pak128 one already, but wondered where did the game get the default one from :)


The mouse cursor is from SDL.

freetype does not work on many platforms, thus it was not incorporated to simutrans.


ok, thank you. :)

Making some progresses here so far, but replicating the simutrans GUI it's a bit time consuming since I have to write all widget descriptions in the XML description CEGUI uses. I'm also having to learn to use GIMP again, but well.. :)

I didn't even began integrating it with simutrans, this will take some time.

About Freetype, well, it's not 100% necessary, image-mapped glyphs are supported. But anyway a platform that doesn't suport freetype it's prolly not going to suport OpenGL anyway.

I see simutrans can be built in: "Microsoft Windows, Linux, BeOS, Intel Mac OS X, iPhone and recently AmigaOS 4.x". I only see BeOS and AmigaOS as a problem here I guess, no?

Any platform without Freetype support doesn't really have much future, maybe. Even my old ipod has freetype libraries built in according the copyright.


Extending UI customisation would help with efforts to produce versions of the game for touch-based devices (e.g. iPhone) as well. Likewise use of OpenGL to render. I'd argue that giving pakset authors complete control of the UI would be a positive thing. Maybe we should stop thinking about Simutrans as a game, and start thinking of it as a game engine which allows multiple games (paksets) to exist.
Use Firefox? Interested in IPv6? Try SixOrNot the IPv6 status indicator for Firefox.
Why not try playing Simutrans online? See the Game Servers board for details.


Quote from: Timothy on February 06, 2012, 09:36:34 AM
Maybe we should stop thinking about Simutrans as a game, and start thinking of it as a game engine which allows multiple games (paksets) to exist.

Yeah, I think that way too. The hard part of this integration seems to be getting each pak icons straight from the PAK and not forcing the PAK to supply a imagemap of all it's buttons.

This includes:
- Top buttonbar
- Extra toolbars for each way type
- Mouse icons
- In the vehicle depot window(vehicles preview and selection)
- In the line management window there is also a pixmap for each line type.

I'm sure I miss a few still.

It whould be way easier if I could just use a super imagemap supplied by each PAK, with all the required icons and a description of their purpose.

Another option is modifyng the pak creation tools so they ALSO create a descriptor and a imagemap I could use. I had a look to the makeobj source and this should not be hard to do.

On this first design I'm just thinking about a golbal UI that will apply to all pak's.  Allowing each pak to override the default behaviour is the second part of the project, and should be planned carefully.

Quite tedious work, to be honest, but it's needed now anyway for Simutrans 3D, I can't postpone this any longer. :)

Even through my initial inention was leave the GUI as it is now.


Since you're touching the toolbar icons, could the pakset provide globally the background button and the single pak only the image on it (with 0xE7FFFF transparency) ?
This way a pakset could switch easily the buttons layout e.g. from grey to blue without having to re-make manually scores of them.


 I'd like to use 32-bit pixels here, with a 8-bit alphachannel and 8 bit per pixel.

Yes, that can be done and I'll do it. But current icon images don't have transparent zones, they will have to be redone to take advantage of this, and then they will not be backwards compatible.

But it's ok, I'll do it.


Well, removing a known background (i.e. the  empty base button) is rather straightforward using Imagemagick.
For backward compatibility, I would say this can wait till your development is merged into trunk, then this replacement could take place painlessly.


At the moment I honestly am not sure that there will be a simutrans version release with require OpenGL HW support to work for the next few years.

But for the 3D enhanced paks anyway new paks will be reuired. Thus those efforts will be realized there first, imho.

Do not underestimate backwards compatibility. During all that time, simutrans only required very very few radical changes to paksets. (The last was the new menu system, and before 16 bit graphics.) Simutrans till can use vehicles made for 84.00.


 I understand your predictions, prissi, but I really hope I have a working HW-accelerated simutrans in 6 months or so.

And about the backwards-compatibility, that's true, but it's also true if has limited the game development in some ways, like for example partial transparencies on sprites to menction a recent request. It has maybe taken you developers to spend time on some places of the code just to mantain compatibility while you might have liked to spend it anywere else. But you are the developers, you know way better than me where do you spind the more time coding in. I think sprite drawing and GUI maintenance have taken lots of your time, but I might be wrong.

This project I have in my hands will allow partially transparent GUI elements, windows animations and to give a bit more sophisticated look to simutrans, and simplify the GUI maintenance since most of the descriptions are in XML files now, not compiled in in C++. And faster performance in the future when I apply the HW support to the game map too.

But I'm not asking for a change, yet. I want to deliver the new engine, show to everybody that works, and it works at least as fast as the current simutrans engine. Backwards compatibility can allways be achieved by developing tools to upgrade old PAK files.

Then the changes will come, if the version has acceptation in the community.


By the way, does any 2D artist volunteers to some small works for this projects? it's a easy task, it's basically making a skin for basic simutrans, not really much work, but my skills on Gimp make me lose lots of time, and it looks awful :)

It's basically adding and rework items to this image, making them similar to current simutrans frames:

Here is the model:

I'll tell you the details if you mail me.


Ok, I worded it wrongly. I think there will be still not only HW-accelerated required version of simutrans released for some time, as this would out many of the players.


Maybe I should have used some smileys, my english it's not good and I might have sounded harsh. :)

No, really, I understand what you said, I was just explaining my view of the situation. I planned it that way, I think it's reasonable to think I will have a playable HW-accelerated version in sixth months, but I can't be sure, because I find new difficulties on the project every step I take. But now I think I'm on the right track. :)


This thread inspired me into making a version of that uses OpenGL instead of GDI to actually put the pixels on the screen. Unfortuanatly, I could not get the dirty rectangle stuff to work, so everything is copied to the screen (via texture) every frame. Runs smoothly in near HD resolutions nevertheless.

I don't know if this would be useful for just integrating CEGUI into Simutrans, where CEGUI could then be rendered on top of the quad textured with the Simutrans map, or maybe the Simutrans map texture could be applied to a CEGUI component. My code is Windows specific, but it should be possible to use SDL to set up OpenGL. Maybe I'll look into that next, unless Markohs wants to code it.


Any new backend is highly embraced. But why using OpenGL on windows and not "native" DirectX?


Maybe because it's not so "native" in other OSes?

Perhaps the purpose is not to work twice...


He wrote he used windows specific functions. (I would really suggest to post a patch.) If window specific function, then the natural question is why not using DirectX in the first place?


Yea, I'm very curious to see that patch, Ters, didn't see your post yet till now. :)

I've had problems with the dirty tile code too, check the asserts in simgraph, they triggered for me, don't really know yet were is the problem. About copying it to screen I don't know what do you mean, don't you use OpenGL to render straight to the window? Why do you use GDI, where do you copy from and were to?

Yes, mixing CEGUI with your code should be easy, using a render-to-texture overlay or making both components write on the same buffer one after the other.

About using OpenGL, it's okay, because it's multiplatform, my approach was using ogre, to get more flexibility, some layer of abstraction, easier scene manipulation and the possibility of choosing betweek OpenGL or Direct3D by the user.

I'd like to have a look to your code. :)

Well, I was going to update this thread with my progress this week. It has not been much.

I spent some time managing to mix OpenGL with a SDL window, plus CEGUI working on it. I've managed to get it working, without much problems.

What has been more time-exhausting is learning more about the CEGUI framework and its XML layout, lookandfeel and event modules, plus some pixelart editing (that at the end I discarded and decided to proceed with the defautl skin and wait for some artists to do the magic in the future).

Well, I don't have much to show yet, I'll just post a SS with the current PAK selection window, that doesn't really work and it's just a stub. But well, it's the first window that looks more-or-less ok. All that layout is 100% customizable editing .xml files, no code recompilation needed.

To give an idea of how this window is created, you just import the layout. There is even a visual layout editor where you can position all the widgets easily and create the .layout.

Of course, all data now is static, the only dynamic is the Add PAK, that just adds one line, with a static text. But of course this can be done dynamic easy.

This window for example is defined as:

<?xml version="1.0" encoding="UTF-8"?>

<GUILayout >
        <Window Type="WindowsLook/FrameWindow" Name="FrameWindow" >
            <Property Name="Text" >PAK Selection
            <Property Name="AlwaysOnTop" Value="True" />
            <Property Name="TitlebarFont" Value="Commonwealth-10" />
            <Property Name="TitlebarEnabled" Value="True" />
            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.05,0},{0.95,0},{0.95,0}}" />
            <Property Name="DragMovingEnabled" Value="False" />
            <Property Name="CloseButtonEnabled" Value="False" />
            <Window Type="WindowsLook/StaticText" Name="StaticText" >
                <Property Name="Text" >Choose one graphics set for playing.
To avoid seeing this dialogue define a path by:
- adding &apos;pak_file_path = pak/&apos; to your
- using &apos;-objects pakxyz/&apos; on the command line</Property>
                <Property Name="HorzExtent" Value="402" />
                <Property Name="VertExtent" Value="92.6897" />
                <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{0.2,0}}" />
                <Window Type="WindowsLook/Button" Name="ADDPAK" >
                    <Property Name="Text" Value="Add PAK" />
                    <Property Name="UnifiedAreaRect" Value="{{0.631118,0},{0.327662,0},{0.881118,0},{0.577662,0}}" />
            <Window Type="WindowsLook/ItemListbox" Name="PakList" >
                <Property Name="UnifiedAreaRect" Value="{{0.000868,0},{0.2,0},{1,0},{1,0}}" />

and each "entry" is:

<?xml version="1.0" encoding="UTF-8"?>

<GUILayout >
    <Window Type="WindowsLook/ListboxItem" Name="PakLine" >
        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
        <Window Type="WindowsLook/StaticText" Name="PakLine/Name" >
            <Property Name="Text" Value="TEST" />
            <Property Name="HorzExtent" Value="80" />
            <Property Name="VertExtent" Value="27.6283" />
            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{0.5,0},{1,0}}" />


I used OpenGL because it's easier to get off the ground, as long as one stick to version 1.1 functions. With Direct3D, one needs to use vertex buffers from the start. When I started, I also did not know how little platform neutral OpenGL code I would end up with, so I thought it could be somewhat easy to port. But what is most important about the choice of OpenGL was that I almost started writing this on my Linux computer.
As for my problem with dirty rectangles, it mostly worked, except when the entire screen needed a repaint, such as when panning. When printing out the coordinates and sizes passed to dr_textur, it appeared that full screen refreshes are done using many full width strips of limited height. OpenGL, on my machine at least, appears to not like that for some reason.


DirectX has also a 2D interface (was it DirectDraw?). But in the end it just uses the GDI routines, which were anyway hardware accelerated ...


CEGUI appears to work with 3D APIs only, so DirectDraw isn't an option in this thread.


Directdraw 2D APIS have been removed from DirectX, since version 9 I think. All must be done in 3D if I'm not wrong.


I went to Wikipedia to get updated about the state of DirectDraw. Back when I last did DirectX programming, DirectDraw just seemed to have reached a point where there was nothing more to add, so Microsoft just stopped making new versions. It is still possible to use the old ones, though.

But at the end of the article, there is a link to something called Direct2D. Looks like there still is need for accelerated 2D, but it appears that Direct2D is not a pure raster graphics API like DirectDraw. It's Windows 6.1 only, however, so it would be less portable than an older Windows API.


But anyway, Ters, I think there is no need to use 2D routines, just rendering the shapes with a camera with identity projection ash I guess you do now should be enough, no?

I don't understand exactly what does your code do, you said:

This thread inspired me into making a version of that uses OpenGL instead of GDI to actually put the pixels on the screen. Unfortuanatly, I could not get the dirty rectangle stuff to work, so everything is copied to the screen (via texture)

So, if you are using OpenGL to put the pixels on the screen, why do you need extra windows-native code?

Are you just drawing to a texture using the code as it is now and you just project the texture to screen? Or do you hook in the dr_textur method and just project using a texture in that section of the screen?

On both aproaches I don't know where you have the windows dependency.

My code started as just simutrans writing to a texture instead of the SDL framebuffer, and just rendering the texture full screen each frame.

That approach worked, but had no performance advantage compared to the current SDL/native version, they had almost the same performance, but 3D code was sightly slower. And that's normal, because the only thing that changed is witing to a texture, instead of the screen.

I made a second approach, substituting that texture writing process by renderoperations, basically each display_img_aux, etc, turned into one renderoperation of the image. This approach was slower than current code.

The new aproach I have pending is actually using OpenGL to draw the entire row in less passes, one for each texture atlas.

The idea is:

1) Create a textureatlas for all the ground shapes.
2) Create n textureatlas for the rest of objects, they won't fit in a textureatlas.

3) On each frame:
   a) Render the whole terrain fundaments in just one pass. Cost: O(1)
   b) Render the rest of objects, in steps of one line, from the top row to the one in the bottom, using the needed atlases. Cost: O(height*num_atlas)

If all the dings and objects fitted in one big textureatlas we whould be able to render step b in just one pass too, but simutrans pak's have too much sprites to do that, they won't fit even on a 8K x 8K texture.


simsys_* includes also other code like the processing of keystrokes or opening viewports and mouse support. If OpenGL can do all this, a should be easily possible.


Yes it can, I have that already, so far I've done 2 versions:

- Ogre3D as renderer and OIS to handle input.
- OpenGL as renderer and SDL to handle input (this one has the advantage to not having to rewrite the event handling code, specially important on the keyboard part).

The perfect mix whould be Ogre3D as renderer and SDL for input, I'll use that at the end, I think. It's perfectly possible according this.


In addition to what prissi writes about simsys_*.cc, the functions to set up OpenGL are specific to each platform. OpenGL is only a set of commands to draw graphics somewhere. Platform specific functions are needed to create a window, change display resoulution (for fullscreen) and make it clear that the following OpenGL commands should go to that window.
As long as Simutrans doesn't go full 3D, running CEGUI directly on OpenGL would require less dependencies than Ogre3D, since OpenGL is available on most platforms of interest pretty much by default. On platforms without OpenGL support, Ogre3D would be of little help anyway.
With full 3D, libraries like Ogre3D will be worth including, but that's another thread.


Yes, agree with you, atm OpenGL is the target, Ogre is not required yet and it's just a unnecessary overhead.

If it's just OpenGL window opening and init, SDL does that for you already if it's compiled with OpenGL support. The one shipped with simutrans already is. That makes your code plattform independent.

The code in my program is (note the SDL_OPENGL parameter):

#ifdef _WIN32
int CALLBACK WinMain(HINSTANCE const hInstance, HINSTANCE, LPSTR, int)
int main(int argc, char **argv)
#ifdef _WIN32
   int    const argc = __argc;
   char** const argv = __argv;
   char         pathname[1024];


   SDL_Surface * screen;
   atexit (SDL_Quit);
   screen = SDL_SetVideoMode (600, 480, 0, SDL_OPENGL);
   if (screen == NULL) {
      fprintf (stderr, "Video: %s\n", SDL_GetError ());
      exit (1);

   renderer = &CEGUI::OpenGLRenderer::bootstrapSystem    (    CEGUI::OpenGLRenderer::TTT_AUTO   );

   SDL_ShowCursor (SDL_DISABLE);
   SDL_EnableUNICODE (1);



Skipping the CEGUI line you should have platform idependent code.

The rest of the relevant code to your interests is:

void inject_input (bool & must_quit)
        SDL_Event e;
        /* go through all available events */
        while (SDL_PollEvent(&e)) {
            /* we use a switch to determine the event type */
            switch (e.type) {
                /* mouse motion handler */
            case SDL_MOUSEMOTION:
                /* we inject the mouse position directly. */

                /* mouse down handler */
            case SDL_MOUSEBUTTONDOWN:
                /* let a special function handle the mouse button down event */
                handle_mouse_down (e.button.button);

                /* mouse up handler */
            case SDL_MOUSEBUTTONUP:
                /* let a special function handle the mouse button up event */
                handle_mouse_up (e.button.button);

                /* key down */
            case SDL_KEYDOWN:
                /* to tell CEGUI that a key was pressed, we inject the scancode. */
                /* as for the character it's a litte more complicated.
                * we'll use for translated unicode value.
                * this is described in more detail below.
                if ((e.key.keysym.unicode & 0xFF80) == 0) {
                    CEGUI::System::getSingleton().injectChar(e.key.keysym.unicode & 0x7F);

                /* key up */
            case SDL_KEYUP:
                /* like before we inject the scancode directly. */

                /* WM quit event occured */
            case SDL_QUIT:
                must_quit = true;

            case SDL_VIDEORESIZE:
                renderer->setDisplaySize(CEGUI::Size(e.resize.w, e.resize.h));
    catch(CEGUI::Exception &e){
        printf("CEGUI Error: %s", e.getMessage().c_str());
        MessageBoxA( NULL, e.getMessage().c_str(), "Fatal Error", MB_ICONEXCLAMATION|MB_OK );

void inject_time_pulse(double& last_time_pulse)
        /* get current "run-time" in seconds */
        double t = 0.001*SDL_GetTicks();
        /* inject the time that passed since the last call */
        CEGUI::System::getSingleton().injectTimePulse( float(t-last_time_pulse) );
        /* store the new time as the last time */
        last_time_pulse = t;
    }catch(CEGUI::Exception &e){
        printf("CEGUI Error: %s", e.getMessage().c_str());
        MessageBoxA( NULL, e.getMessage().c_str(), "Fatal Error", MB_ICONEXCLAMATION|MB_OK );

void render_gui()
    /* clear the colour buffer */
    glClear( GL_COLOR_BUFFER_BIT );
    /* render the GUI */
    }catch(CEGUI::Exception &e){
        printf("CEGUI Error: %s", e.getMessage().c_str());
        MessageBoxA( NULL, e.getMessage().c_str(), "Fatal Error", MB_ICONEXCLAMATION|MB_OK );
    /* Update the screen */

void main_loop ()
    bool must_quit = false;
    /* get "run-time" in seconds */
    double last_time_pulse = 0.001*static_cast<double>(SDL_GetTicks());
    while (!must_quit) {
        inject_input (must_quit);
        inject_time_pulse (last_time_pulse);
        render_gui ();

This code can be easily merged in

setup() only does things relevant to CEGUI.

I'd be happy if you could please upload your code when you want to the simutrans3d branch for further development. :)


Since you got OpenGL up and running from SDL, all I've got are dr_textur, dr_flush, dr_textur_init and dr_textur_resize. But I must rewrite these for SDL first.


I want to voice again my support for the 3D branch and this project, because I think an OpenGL rendering backend and a new UI library address some very important issues in Simutrans.


Thx, Hajo.

I could use some help on the CEGUI GUI re-implementation, plus pixelart if you are interested, by the way. ;)

There are lots of bitmaps to be designed, windows to be layout and code to be implemented.

I can post my TODO here to see if you or anyone is interested in some of the work needed.

This cegui project opens the door to lots of creative work, now you can scale, rotate, alphablend items very easy, I'm pretty sure many cool things can be done and added to simutrans.


Here's a changed that sets up OpenGL, draws to an OpenGL texture and renders a quad with this texture. On its own, a very pointless thing to do.
Somehow the dirty rectangle stuff works here, though I use the same OpenGL commands at the same places. I'm not sure why, but I do not reuse the same texture after resize if it's big enough like does and my OpenGL version of that did.
This code assumes that the system supports textures of any size.
For the way forward, I would suggest putting the existing user interface into a CEGUI component and gradually move windows out of it into CEGUI. Is whatever has been done with CEGUI on its own available somewhere like Simutrans 3D is?


okay, i'll mix this with mi cegui code and upload it to simutrans3d svn as soon as I can. thank you


Okay, I just added a new visual studio project named SimutransCEGUI to the simutrans3d branch, with your code replacing simsys.

Had to update to svn HEAD since my copy wasa bit older and had a old version of simsys.h that was incompatible, since they fixed some parameters and code like 2 weeks ago. Now we are in sync with simutrans code.

This update also broke current simutrans3D code but well, not really important since CEGUI is my focus now.

It works good for me too, except a window resize renders a whole white screen here. I'll have it a look to your code to try to see what's wrong.

My CEGUI code so far it's on a separate project without integrating to sumutrans yet. I can post it here if you want but it's notthing too interesting, I'll mix it to simutransCEGUI today so everybody can help with the development if they want.

Thank you!


A white screen means that the texture was not created properly, or that the texture created is unusable.


Works good on a ATI Radeon card, but fails on the resize on nVidia


Getting closer to make this work, still something wrong, through ;)


ummm... I always suspected there's something wrong with my screen. Thanks for pointing out.

* IgorEliezer goes upside down.


Not so wrong as my first OpenGL version, which used glDrawPixels rather than a textured quad. It was both upside down and not at the same time. Very confusing to look at, almost like seeing the map from below.


Quote from: Markohs on February 14, 2012, 01:12:16 AM
Getting closer to make this work, still something wrong, through ;)

That is easy, Markoh.  It is due to the city being in the southern hemisphere.  Just move it...  :D ;D


haha ;)

I hope I can give it a look soon, a bit busy with work and final project again till the weekend comes. :)

The code is in SVN for the case someone wants to code and patch something meanwhile.


I could give this a look at the expense of the time I should have spent for friday's presentation. ;)

It works! I just attached a test window. It's all based on Ters code. Just a alpha enabled window on top of simutrans. Events are first processed by CEGUI and if it's not catched by one of it's windows, passed to simutrans. Both the cegui window and simutrans receive the clicks and mousemoves.

I hope to be able to get some of current dialogs rendered with cegu soon, but PAK icons extraction and cegui's imagemap generation have to be done before, at last for the construction toolbars.

The only dialog that's not PAK-dependant is the PAK selection screen.

Perfromance is good, but the screen it's a bit blurry because of the pixels interpolation done by CEGUI, since I didn't rendered on top of the framebuffer as Ter's code does, I mapped the OpenGL texture to a CEGUI/StaticImage that's on the root of the GUI (as background)


It's ironic to have to reassemble an imageset from one or more pak files, when the pak files themselves are made from an imageset.

I've begun experimenting with CEGUI myself. It looks like some custom renderers and window types are required. And I have to say I don't like CEGUI's abuse of references. Not when it was introduced, not now, and probably never.


 Yes, I understand what you say, but we can't avoid that, this game is based in current PAK format and we can't change that now. Once we have the project running and working good, we might be able to shift current PAK's to just a .zip with png imagemaps and textual image/objects descriptions.

I don't like references either, I prefer plain pointers, but they are suposed to make code less error prone, more secure and legible. I try to get used, I never used them before, and I wish they never existed. :) In fact the error I showed two posts ago, was originated from a reference.

The way I thought this so far is making a .scheme, with all the base items, clone WindowsLoook .lookandfeel and make our own. I choosed WindowsLook because I think it looks more similar to current simutrans UI than TharezLook.

The plan whould be:

- Create a simutrans.scheme from windowslook.scheme
- Add all needed widgets to .lookandfeel
- Customize WindowsLook imageset to look like simutrans.
- Create .layout for all windows, and .clone them when needed.

CEGUI documentation is a bit poor too, and they change some things often from release to release, looks like. I'm using 0.7.6 atm.

Also, on the current code I map your OpenGL texture to a background StaticImage Widget, at the borders of the screen you can see the border of the widget. I did this to see this is possible, since we'll need in the future for example on the vehicle window, where you see a sub-render of the vehicle ingame, that will be a StaticImage with a texture over it, rendered. But I think we'll better start with dr_flush just writing straight to the window, and let CEGUI write on top of it each frame, I think.

This is my media folder, for the case you want to have it a look, nothing too special there, still.


Back to your original code, I'm trying to figure why resizing doesn't work on my computer here with a nVidia card and why does it work on other with a ATI one.

I found this page dunno if you had it already, Ters.

There it suggests OpenGL context might be destroyed on each SDL_SetVideoMode, but I see you recreate the viewport and the texture after dr_textur_resize.

Do you have any idea where can the problem be?


Quote from: Markohs on February 16, 2012, 12:35:34 AM
Back to your original code, I'm trying to figure why resizing doesn't work on my computer here with a nVidia card and why does it work on other with a ATI one.

I found this page dunno if you had it already, Ters.

There it suggests OpenGL context might be destroyed on each SDL_SetVideoMode, but I see you recreate the viewport and the texture after dr_textur_resize.

Do you have any idea where can the problem be?

I don't reset all states on resize. More specifically, the state that enables texturing: glEnable(GL_TEXTURE_2D). I think that's the only state I set once and for all.

Quote from: Markohs on February 15, 2012, 06:56:51 PM
I don't like references either, I prefer plain pointers, but they are suposed to make code less error prone, more secure and legible. I try to get used, I never used them before, and I wish they never existed. :) In fact the error I showed two posts ago, was originated from a reference.
References are good, as long as they are used correctly. CEGUI sometimes uses them as pointers, which makes it unclear that they should be treated pointers and not references. They have different uses.


I managed to fix it, it needed a glEnable(GL_TEXTURE_2D) after the SDL_SetVideoMode. Just uploaded to SVN.

It whould be nice if someone tried this in linux to see if it's working too.

I'ts built as the SDL version just replacing with and including and linking against OpenGL too.

I started translating the comments, and I have one question. Is there any plan to document the code javadoc style? I'll use @author, @param etc on the comments if you don't mind, to document it and to give proper credit to Ters and me.

EDIT: I compiled a release Windows version also, I'd appreciate enybody that can spare some minutes to try it and report any problems and sucesses, with some basic system information (Windows version and video card). Download from here.


QuoteI started translating the comments, and I have one question. Is there any plan to document the code javadoc style? I'll use @author, @param etc on the comments if you don't mind, to document it and to give proper credit to Ters and me.
please do! Then doxygen can generate some sensible documentation.

Edit: it compiles. The colors are tuned to make every pakset look excentrique.

I did not follow this thread nor the svn logs, which files did you modify to make opengl version running? Would it make sense to commit the opengl stuff to standard (including proper Makefile support).

Parsley, sage, rosemary, and maggikraut.


 Hi, thank you for trying it out.

Ok, I'll comment it then. :)

The opengl version just needs the new, it's standalone. I think it's a good idea to include the opengl version straight  in standard branch since it's just another backend that might be useful for something, even performance should be the same as, but can work better in some plattforms (I read somewere that the SDL version doesn't work on Mac good enough).

But first I'd like to document it better, fix that excentrique bug and of course make the Makefile to work. I did add a 'opengl' backend in the Makefile, did that work?

From the screenshot I think the components are picked wrong in the texture, looks like it doesn't have a green channel, that might be the problem, I'll have it a look. :)


Quote from: Markohs on February 17, 2012, 08:39:08 AM
I did add a 'opengl' backend in the Makefile, did that work?
Did not saw that first, I hand-edited the sdl-backend branch. There were two extra )'s, which I removed now, it compiles for me using backend=opengl.
Parsley, sage, rosemary, and maggikraut.


Sorry, you mean the 3D branch? Or did I miss something in my week away? I see no standalone OpenGL-support ???


Yea prissi, the branches/simutrans3d/ is a standalone OpenGL backend, no other files modified. Might have some bugs yet, but it works good in windows, looks like.


Okay, I'll try to explain the situation.

CEGUI works sightly different than the curren UI:

- It's rendered to a separate texture, once each frame, using the 3D engine, so the dirty areas management code is useless, the result is blended with the backgraound after that.
- It already has a container hierarchy implemented, so widgets inside a framed window,, move with them automatically.
- Uses unified screen dimensions, X=> 0..1, Y=>0..1
- It's based on widget callbacks, like the current simutrans does with action_listener and gui_action_creator_t classes. Centralizing the event handling in a single callback simutrans stype is nto something the CEUI creator likes but looks like it's possible.
- dialogs layout can be done in-code, C++ sentences like current simutrans code does, or thay can be read from a separate .layout XML file, making it possible to change the dialogs without the need to recompile the project.

So, how can I implement this? there are verious approaches I'd like you to give your oppinion in, in all approaches I assume we'll need non-CEGUI, simutrans interface, so we can change CEGUI for another GUI library in the future if we want to.

1) First, simplest solution is just implement the current widgets using CEGUI widgets, and try to disable zeichnen (draw) calls. This implementation is feasible, with some changes like the widgets have to be attached to the parent window and some minor adjustements I think.
2) The second option is having all dialogs load a external XML layout, and define default actions to be linked with some buttons. For example the File selection layout will be searched for a "Load" button, and if it has one, linked with the Load file action.
3) The third option is like the second one, but exposing a list of actions in the layout, and implement all the functionality in the LUA language, exposing if to the dialog creator, so he can decide how to manage the dialog events, and extend its functionality (like for example, showing minimap screenshots of the savegames, a game summary, or spawning new dialogs.

From option 2 and beyound, I was thinking on the possibility of decoupling the gui dialogs from the actions, implementing "actions" on their own, like "load savegame", "spawn a confirmation dialog", "delete a file", "spawn finances dialog", "read this directory".

What do you think of all of this, I'm overdoing this and I should just try to go option 1?


Quote from: Markohs on February 23, 2012, 09:54:47 AM
- Uses unified screen dimensions, X=> 0..1, Y=>0..1

My head is not made for math, so maybe it's all good already. But I want to ask if a transform from 0..1 to 0..1024 will put a line with one pixel with exactly on a pixel boundary? Will it be blurred over two pixels?

If there is pixel precise rounding, then, imagine this:

Assuming that you have a button width of 0.05 and like a button position of 0.1

Further assuming that the 0.1 position will result in pixel 100.2 and the width will be 50.3 pixels. This button will then strech from pxiel 100.2 rounded to 100 to pixel 150.5 rounded to 150.

And even further assuming that a second button exist with width 0.05 and a position of 0.102

That second button might then start at pixel 100.4 and run for 50.3 pixels, this time starting at 100 (rounded) but ending at 150.7 rounded to 151

Will the second button be 1 pixel wider then, even that both have a width of 0.05 defined?

My numbers are most likely not correct - I just try to sketch a scenario where a rounding action will lead to a one pixel difference, and I'm asking if such can happen with CEGUI or if this is mathmatically impossible.

edit: ... or unimportant. Just curious what actually will happen there :)


I'll have it a look after I come back from the hairdresser and explain it further, but basically the 3D engine will interpolate and blur around the pixel positions. :)


Well, okay, I think I understand your question.

There is no extra rounding appart of what a C++ float variable has, and that's about 7-8 decimal digits if I'm not wrong (I just googled it). that gives us a maximum window size of 10.000.000x10.000.000 pixels. So until displays get bigger than that, there should be no problem in positioning lines of a exact pixel with.

Another issue is how do you place a pixel in a exact position of a screen making it to no start "polluting" pixels next to it. from the top of my head, I guess you just:

float f_pos_x = ((float)i_pos_x+0.5) / w_width_x;

Another issue that arises sometimes is what happens when a image is scaled when you draw it on a screen, like this:

Here you can see, in the "shadow" of the trees and the borders of the trees, that in my code I initialized the transparent areas to "transparent WHITE". when the image is rendered on screen, near the edges of the pixels, the interpolation gives a gradient between the non-transparent pixel and the transparent one. Since those pixels are stored in 1 bit alpha and 5 for each color (16 packed), there is no gradient between transparent and not transparent, creating that white effect on the border.

I don't know the exact details of how CEGUI manages this, but I guess the code just makes sure the coordinates you give are near the center of a pixel, but even if it didn't, you as a programmer will for sure create the coordinates manually with a statement like the one I typed before, so it will end in coordinates very near to the center of the real pixels of the renders. The only exception to this whould be when you use animated effects to deform the GUI elements, where pixels will for sure end in position more near to be in-between the pixels. Or if you rendered the GUI to a texture, that has a different resolution than the final window.

But that just is not very important, I guess, since usually you will apply a antialias as a postprocess anyway, so all the image will look even smoother.

Isaac Eiland-Hall

Wow, that latest image reminds me very much of an old DOS golfing game I played in the late 80s or very early 90s... hehe

Can I just occasionally post a cheerleading post in here? Let me know if I'm a bother, because I can't say much on-topic, but I still wanted to say: Wow. I love how this is progressing!


Sure, I like to hear comments from people, it makes me feel like someone cares. ;) Thank you!


Quote from: Markohs on February 24, 2012, 02:21:30 AM
it makes me feel like someone cares. ;) Thank you!
Hehe... Someone and beyond.

I believe most of people would not feel like posting when they don't have a lengthy post in mind. I don't know but a lot of online communities out there have a "no flood" rule: don't post if you don't have anything significant to say or whatever, then people kind of refrain themselves from posting.

On the other hand, things have taught me that, while for an admin or moderator a post which contains only "I like it" or "Nice!" may sound like a "pointless post", posts like that may be important for people who are working on project. Feedbacks, even if it's just "I like it", are always encouraging.

Isaac Eiland-Hall

Quote from: IgorEliezer on February 24, 2012, 04:31:52 AM
Feedbacks, even if it's just "I like it", are always encouraging.

I like it! ;-)


I uploaded a new update to the svn, with a draft of the design of the new GUI, documentation can be found here.

Any comment is welcome.


Small update:

Just a small demo video showing what's working so far, just pak selection and loading screen, but all that look-and-feel is customizable/skinnable without the need to recompile simutrans.

I know the design is not really nice at the eyes, but I hope some graphical artist gets bored some day and starts skinning that properly. :)

The idea is using that loading screen layout for all processes that use a progressbar (enlarge map, load savegame), maybe with some alpha blending in the logo, or some animation, we'll see.


oh, good news, CEGUI has been chosen this year for Google Summer of Code, so looks like we did a good decision using it. :)

Btw, a question for the forum administrators. Where do you think I should keep this topic in the board? It's nto a Bug report, I think hehe. :)

I'd like to keep posting when I make some advances I can show, but I'd also like coders to be able to review it if the fancy and have the time. The topic is ok in this forum?


Quote from: Markohs on April 05, 2012, 11:26:05 AM
Btw, a question for the forum administrators. Where do you think I should keep this topic in the board? It's nto a Bug report, I think hehe. :)

It is in Larger projects, now ;)

I'm moving there also 3D. The purpose of that board is to host threads for complex projects, spanning for several months. There there'll be few of them, so they are harder to lose, compared to the other development boards.


Quote from: Fabio on April 05, 2012, 11:49:04 AM
It is in Larger projects, now ;)

I'm moving there also 3D. The purpose of that board is to host threads for complex projects, spanning for several months. There there'll be few of them, so they are harder to lose, compared to the other development boards.



I've been stuck a bit on this because I was unsure on how to retouch the less possible to be able to manipulate the new "gui_frame_templated" windows, that will replace "gui_frame_t" gradually.

At the end, I've decided replicating the code when necessary to make the routines to interact with both types of windows, it's all a bit dirty now but for the time it will sufice until I find a new and cleaner way of handling this.

Well, here you can see the new Loading Screen and banner, not very artistic, but well, progressing again.

Had to add templated versions of win_is_open,destroy_win,destroy_framed_win, create_win, and add code to destroy_all_win, process_kill_list. The good thing is that new templated frames have the event handling and drawing refresh routines built in automatically, so I won't need to mess the rest of the routines I think (and hope).


Nice. :) It gives Simutrans a much more modern look.


Nice! There is no comparison between the new dialog (although it needs tweaking, of course!) and the standard ones.


Yep, needs some work with aesthetic taste. I can scale, move, blend, animate the logo and everything and can't figure how to do it making it look good! :)

I'll finish the dialogs first, and give them a second look when they are functional. :)


btw, happy birthday, Fabio. ;) Facebook told me!


A more modern look, just copied a MIT licensed one (it's more for RPG games) to see how it can look here, looks pretty cool, specially the transparent progressbar! :)


Thank you Markohs ;D

By the way, this latter look is very, very cool! Simutrans indeed deserves better than current UI.


This semi-transparent style doesn't like me as much as the other. Our gui needs a bit of love, but that last one looks confusing to me... maybe it's the colour, which is dark (rpg style, as you said). We might look for an average between both though...


Choosing among an external library or a self-made one has both advantages and disadvantages.  When ST was created, the situation was also different.  We must be kind to the present GUI...

If you make your own GUI, the program is not bloated with unneeded functionality you don't use, you get rid of an additional external dependency that may make your program unusable if the external library is upgraded, you get exact control on what is done and how it looks like, and you are sure that the program will work for a larger variety of systems, now and in the future.

The main disadvantage of your own GUI is that, of course, you reinvent the wheel, and not a very good one if you compare it with more mature libraries.


semi transparent! splendid. It works also with light windows, when the opacity is a bit reduced.


Quote from: isidoro on April 19, 2012, 09:51:22 PM
We must be kind to the present GUI...
I try to be kind, actually it works... but it's old fashioned, that's all :)

Anyway I agree there are pros/cons by both using own and external library for the gui, and I agree with the ones you exposed. I'm not involved in order to give an opinion in favor or not though.


@Isidoro: what you say is true. Even I try to abstract the simutrans GUI code from CEGUI in itself, of course they are inherently coupled together, mainly because each gui sheet it's written in a XML form that's only interpretable with CEGUI.

What I did was creating a class where the forms inherit from, it needs a string parameter in the constructor. That's the name of the .XML file that will be loaded and shown on screen. Later, the sub-class defines some "actions", and hooks them to "labels". The actions are basically a enumeration of possible general actions (LOAD_PAK, QUIT_GAME, .... ) and a optional parameter. They are stored as a void * so you can store anything there. The "labels"are just identifiers taht will be searched on the templated loaded frame, and it will hook the action there, if the item is found.

When CEGUI receives a event, my code checks whether the triggered element has a action hooked, and fires it. CEGUI does some actions by itself anyway, like hover, mouse, taking care of the scrollbars...

It's a bit more generic that using CEGUI straight, and can maybe be implemented with other external GUI libraries. But yes, this is a dependency.

Implementing the same actual working where the GUI forms are created programatically could have been done, but it lacked flexibility.

But look, for example, there is quite a lot of code about filesystem access already coupled to the GUI classes, for example in gui/loadsave_frame.h and gui/ . This is imho a sign that a ad-hoc GUI like the one we have, has some deficiencies, also.

But I plan to add this in a way that the old code can coexist with the new ones, that's the best way. I want to see both versions working, and we'll see where does the project ends going to.


About the style Fabio,Zeno and sdoc comment, I agree this theme is not suited for a game like simutrans, it was just to show the ponential of this new UI, with the advantage that we can just create a defaul skin that resembles the current one closely, just with some transparencies where we think it's good to use it (I like it on the progress bar, for example, but we can also use it for for example more sophisticated graphics on the loading screen, or on the window frames, or on inactive toolbars/windows, even on the ticker).

The goood thing about this system is that we open the door for some artists creating alternate skins or give the pak creators the chance to refine the GUI even further, like for example on the pak.britain they could use some patterns, shapes and effects typical from there, the pak.scfi could use a more futuristic GUI and the comic another one. Not just replacing bitmaps, this even allows for font changes.

I know this window dragging effect is horrible, but ilustrattes possibilities we can explore:


@Zeno: my comments didn't refer to yours explicitly.  It was general and not to give a biased view on this, but a more balanced one.

Markohs' efforts will give more configuration and, most probably, a better look to the program, but it doesn't come at no price.


Quote from: isidoro on April 20, 2012, 10:58:22 AM
@Zeno: my comments didn't refer to yours explicitly.
I wasn't offended either, no problem :) Just wanted to note that we are respectful with what we have, but we talk about how improving it anyway.


Please note that ongoing GUI rewriting renders this project obsolete.  :police:

Moved to denied board.