Theme update during run of program

Started by Garwin, 01 May 2022, 13:01:25

Garwin

First, I would like to thank you for finding time to answer my questions. Your TGUI is very nice and complex.

I have another question. I want to create my theme for my simple game and the best way is to have an immediately updated theme in the program.
For such reason, I added that function into the prototype of the menu (using buttons).

However it does not work.

I have this code as part of constructor of "GameStateOptions" class.

tgui::Theme::setDefault ("data/TGUI/theme.txt");

m_gui.setWindow (m_game->m_window);
m_newGame = tgui::Button::create();
m_difficulty = tgui::Button::create();
m_picture = tgui::Button::create();
m_score = tgui::Button::create();
m_exit = tgui::Button::create();

using namespace tgui;
m_gui.add (m_newGame);
m_gui.add (m_difficulty);
m_gui.add (m_picture);
m_gui.add (m_score);
m_gui.add (m_exit);

m_newGame-> setPosition(300,100);
m_difficulty-> setPosition(300,200);
m_picture-> setPosition(300,300);
m_score-> setPosition(300,400);
m_exit-> setPosition(300,500);

m_newGame-> setText("NEW GAME");
m_difficulty-> setText("DIFFICULTY");
m_picture-> setText("PICTURE");
m_score-> setText("HIGHEST SCORE");
m_exit-> setText("EXIT");


On top of that I have function "handleInput" which handles all input (keys, mouse) and if F9 is pressed it should reread theme from file. Part of the code is:
         case sf::Event::KeyPressed:
{
if (event.key.code == sf::Keyboard::Escape) m_game->m_window.close();
else if (event.key.code == sf::Keyboard::F9)
{
tgui::Theme::setDefault("data/TGUI/theme.txt");
Log::log ("Pressing F9 key.");
}
break;
}


Then my procedure (expected) is:
1. start the program
2. look at menu ==> decided theme adjustment
3. edit the theme file and change it
4. press F9 key in-game to update the theme
5. going to point 2. till I am satisfied with the look of the theme

However during point 4. after pressing F9 theme is not updated in the buttons.
Looking at my log file, F9 was pressed so the added tgui::Theme::setDefault("data/TGUI/theme.txt") was called but does not update default theme.

texus

#1
TGUI indeed assumes that a theme file doesn't change at runtime. It caches the file contents when it reads it the first time. This is undocumented behavior, but you can clear the cache by adding the following line of code:
tgui::DefaultThemeLoader::flushCache();

The static flushCache function can be given a filename as parameter if you only want to remove the cache of a single file instead of all theme files.

Garwin

This is exactly what I was looking for however it does not work.

Adding line:
tgui::DefaultThemeLoader::flushCache()

just before reloading:
tgui::Theme::setDefault("data/TGUI/theme.txt");

does not work. I have no idea why.

texus

Are you calling widget->getRenderer() anywhere? That would disconnect the renderer from the theme so that tgui::Theme::setDefault will no longer update that widget.

Garwin

Not at all, all code is mentioned above.

All I have is members in the class:
tgui::Gui m_gui;

tgui::Button::Ptr m_newGame;
tgui::Button::Ptr m_difficulty;
tgui::Button::Ptr m_picture;
tgui::Button::Ptr m_score;
tgui::Button::Ptr m_exit;



and in draw function have:
m_gui.draw();


texus

#5
Apparently the code I was testing with was slightly different. There::setDefault only affects new widgets, not existing widgets, so you would need to recreate your widgets. The following code works, but not perfectly:
tgui::DefaultThemeLoader::flushCache();
tgui::Theme::getDefault()->load("data/TGUI/theme.txt");


It will change the renderers of existing widgets, but it doesn't seem to reset some properties: e.g. the old theme has a border and the new theme doesn't have a border, then the widget will have the look of the new theme but with a border. So this is a bug that I'll need to look into.

Edit: The bug in the load function is a small mistake, using getDefault()->load will soon work properly for your use case.

Garwin

Thanks for help, I have just tried it in simple test program and it works.

Same thing is in case you change theme during runtime. Changing shared pointer this way works.

Garwin

Just finding that in source files xxxproperties are all properties that can be set to xxx widget in the theme or directly in code.

I think it would be good to mention it in the theme tutorial.

texus

#8
One place you can also find which renderer properties exist for a widget without looking at the source code is the documentation for the Renderer class (e.g. ButtonRenderer: https://tgui.eu/documentation/0.10/classtgui_1_1ButtonRenderer.html), but the source code itself might still be clearer.

I intent to add a guide for each widget to the tutorials, which amongst other things would include a list of its renderer properties. That would make it easier to find that information. This has technically been on the TODO list for many years already, but I'm planning on actually starting with this once I have the Release Candidate for upcoming TGUI version ready.

The Theme::load function has been fixed in the development version in the meantime btw, which solves issues in case you would be removing properties when editing the theme (otherwise there is probably no need to update TGUI).