Load last saved GUI configuration on first load.
Also save theme to the configuration. PiperOrigin-RevId: 843710929 Change-Id: I7ce9ce0f026d2cb5f79addf6c16c9b540bf11954
This commit is contained in:
committed by
Copybara-Service
parent
499291e5c2
commit
43bcbb158c
@@ -47,9 +47,12 @@ static constexpr const char ICON_FA_SUN[] = "\xEF\x86\x85";
|
||||
static constexpr const char ICON_FA_TACHOMETER[] = "\xEF\x83\xA4";
|
||||
static constexpr const char ICON_FA_UNDO[] = "\xEF\x83\xA2";
|
||||
|
||||
|
||||
using KeyValues = std::unordered_map<std::string, std::string>;
|
||||
|
||||
// This is a workaround to fix compilation on gcc <= 12 and clang <= 16
|
||||
template <typename T>
|
||||
struct dependent_false : std::false_type {};
|
||||
|
||||
// Appends key/value pairs to an Ini file.
|
||||
void AppendIniSection(std::string& ini, const std::string& section,
|
||||
const KeyValues& key_values);
|
||||
@@ -58,6 +61,27 @@ void AppendIniSection(std::string& ini, const std::string& section,
|
||||
KeyValues ReadIniSection(const std::string& contents,
|
||||
const std::string& section);
|
||||
|
||||
template <typename T>
|
||||
T ReadIniValue(const KeyValues& key_values, const std::string& key, T def) {
|
||||
auto iter = key_values.find(key);
|
||||
if (iter == key_values.end()) {
|
||||
return def;
|
||||
}
|
||||
if constexpr (std::is_same_v<T, int>) {
|
||||
return std::stoi(iter->second);
|
||||
} else if constexpr (std::is_same_v<T, float>) {
|
||||
return std::stof(iter->second);
|
||||
} else if constexpr (std::is_same_v<T, double>) {
|
||||
return std::stod(iter->second);
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
return iter->second;
|
||||
} else if constexpr (std::is_enum_v<T>) {
|
||||
return static_cast<T>(std::stoi(iter->second));
|
||||
} else {
|
||||
static_assert(dependent_false<T>::value, "Unsupported type");
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class for setting ImGui style options; automatically resets the
|
||||
// styles when going out of scope.
|
||||
struct ScopedStyle {
|
||||
@@ -179,10 +203,6 @@ struct ImGuiOpts {
|
||||
const char* format = std::is_floating_point_v<T> ? "%.3g" : "%d";
|
||||
};
|
||||
|
||||
// This is a workaround to fix compilation on gcc <= 12 and clang <= 16
|
||||
template <typename T>
|
||||
struct dependent_false : std::false_type {};
|
||||
|
||||
// A compile-time wrapper around ImGui::InputScalarN. This is useful because
|
||||
// MuJoCo uses an `mjtNum` type which is an alias for float or double.
|
||||
//
|
||||
|
||||
@@ -742,7 +742,7 @@ void App::LoadSettings() {
|
||||
if (!ini_path_.empty()) {
|
||||
std::string settings = platform::LoadText(ini_path_);
|
||||
if (!settings.empty()) {
|
||||
ui_.FromDict(platform::ReadIniSection(settings, "[Simulate][Data]"));
|
||||
ui_.FromDict(platform::ReadIniSection(settings, "[Studio][UX]"));
|
||||
ImGui::LoadIniSettingsFromMemory(settings.data(), settings.size());
|
||||
}
|
||||
}
|
||||
@@ -751,7 +751,7 @@ void App::LoadSettings() {
|
||||
void App::SaveSettings() {
|
||||
if (!ini_path_.empty()) {
|
||||
std::string settings = ImGui::SaveIniSettingsToMemory();
|
||||
platform::AppendIniSection(settings, "[Simulate][Data]", ui_.ToDict());
|
||||
platform::AppendIniSection(settings, "[Studio][UX]", ui_.ToDict());
|
||||
platform::SaveText(settings, ini_path_);
|
||||
}
|
||||
}
|
||||
@@ -912,6 +912,10 @@ void App::BuildGui() {
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (tmp_.first_frame) {
|
||||
LoadSettings();
|
||||
tmp_.first_frame = false;
|
||||
}
|
||||
if (io.WantSaveIniSettings) {
|
||||
SaveSettings();
|
||||
io.WantSaveIniSettings = false;
|
||||
@@ -922,6 +926,7 @@ void App::SetupTheme(platform::GuiTheme theme) {
|
||||
if (!tmp_.style_editor) {
|
||||
platform::SetupTheme(theme);
|
||||
ui_.theme = theme;
|
||||
ImGui::GetIO().WantSaveIniSettings = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1747,11 +1752,13 @@ std::vector<const char*> App::GetCameraNames() {
|
||||
|
||||
App::UiState::Dict App::UiState::ToDict() const {
|
||||
return {
|
||||
{"theme", std::to_string(static_cast<int>(theme))},
|
||||
};
|
||||
}
|
||||
|
||||
void App::UiState::FromDict(const Dict& dict) {
|
||||
*this = UiState();
|
||||
theme = ReadIniValue(dict, "theme", theme);
|
||||
}
|
||||
|
||||
int App::LoadAssetCallback(const char* path, void* user_data,
|
||||
|
||||
@@ -90,6 +90,7 @@ class App {
|
||||
// UI state that is transient and only needed while the application runs
|
||||
struct UiTempState {
|
||||
bool should_exit = false;
|
||||
bool first_frame = true;
|
||||
|
||||
// Windows.
|
||||
bool help = false;
|
||||
|
||||
Reference in New Issue
Block a user