From 2345663efbf06de752c7b96ed0ba387fc1f81eae Mon Sep 17 00:00:00 2001 From: Saran Tunyasuvunakool Date: Fri, 15 May 2026 14:26:00 -0700 Subject: [PATCH] Change title to "MuJoCo Live" and respect system colour scheme. PiperOrigin-RevId: 916183118 Change-Id: I760be720cb001038e993383a5e523a2de8496a7c --- src/experimental/studio/app.cc | 14 ++++++++++---- src/experimental/studio/app.h | 7 +++++++ src/experimental/studio/emscripten.cc | 19 ++++++++++++------- src/experimental/studio/live.js | 4 +++- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/experimental/studio/app.cc b/src/experimental/studio/app.cc index 48b038f3..cf7d28e9 100644 --- a/src/experimental/studio/app.cc +++ b/src/experimental/studio/app.cc @@ -81,9 +81,15 @@ static constexpr const char* ICON_UNDO_SPEC = platform::ICON_FA_UNDO; static constexpr const char* ICON_REDO_SPEC = platform::ICON_FA_REPEAT; App::App(Config config) - : ini_path_(std::move(config.ini_path)), gfx_mode_(config.gfx_mode) { + : app_title_(std::move(config.title)), + ini_path_(std::move(config.ini_path)), + gfx_mode_(config.gfx_mode) { SwitchGraphicsMode(config.width, config.height, config.gfx_mode); + if (config.initial_theme.has_value()) { + ui_.theme = *config.initial_theme; + } + ImPlot::CreateContext(); mjv_defaultPerturb(&perturb_); mjv_defaultCamera(&camera_); @@ -100,7 +106,7 @@ void App::SwitchGraphicsMode(int width, int height, platform::Window::Config window_config; window_config.gfx_mode = gfx_mode_; - window_ = std::make_unique("MuJoCo Studio", width, height, + window_ = std::make_unique(app_title_, width, height, window_config); renderer_ = std::make_unique( window_->GetNativeWindowHandle(), gfx_mode_); @@ -147,9 +153,9 @@ void App::LoadModelFromFile(const std::string& filepath) { UpdateFilePaths(resolved_file); if (model() && model()->names) { // Assumes the first string in the model is the name of the model itself. - window_->SetTitle("MuJoCo Studio : " + std::string(model()->names)); + window_->SetTitle(app_title_ + " : " + std::string(model()->names)); } else { - window_->SetTitle("MuJoCo Studio : " + + window_->SetTitle(app_title_ + " : " + std::filesystem::path(filepath).stem().string()); } } else { diff --git a/src/experimental/studio/app.h b/src/experimental/studio/app.h index b38d551b..175b3fee 100644 --- a/src/experimental/studio/app.h +++ b/src/experimental/studio/app.h @@ -55,6 +55,12 @@ class App { // The graphics configuration used for initializing the window. platform::GraphicsMode gfx_mode = platform::GraphicsMode::FilamentVulkan; + + // The initial GUI theme. If set, overrides the default (kLight). + std::optional initial_theme; + + // The application title shown in the window title bar. + std::string title = "MuJoCo Studio"; }; explicit App(Config config); @@ -227,6 +233,7 @@ class App { bool has_model() const { return model_holder_ && model_holder_->model(); } bool has_data() const { return model_holder_ && model_holder_->data(); } + std::string app_title_; std::string ini_path_; std::string model_name_; // Used if model_kind_ is kModelFromBuffer. std::string model_path_; diff --git a/src/experimental/studio/emscripten.cc b/src/experimental/studio/emscripten.cc index f399ebfb..0e427626 100644 --- a/src/experimental/studio/emscripten.cc +++ b/src/experimental/studio/emscripten.cc @@ -148,7 +148,7 @@ void RegisterAsset(std::string filename, std::string contents) { } // Javascript-facing function to initialize the app. -void Init() { +void Init(const std::string& title, bool dark_theme) { // Note: dimensions do not matter as window will be resized to fit canvas. const int width = 100; const int height = 100; @@ -224,12 +224,17 @@ void Init() { github_provider.prefix = "github"; mjp_registerResourceProvider(&github_provider); - g_app = new mujoco::studio::App({ - .width = width, - .height = height, - .ini_path = ini_path, - .gfx_mode = mujoco::platform::GraphicsMode::FilamentWebGl, - }); + mujoco::studio::App::Config config; + config.width = width; + config.height = height; + config.ini_path = ini_path; + config.gfx_mode = mujoco::platform::GraphicsMode::FilamentWebGl; + config.initial_theme = dark_theme ? mujoco::platform::GuiTheme::kDark + : mujoco::platform::GuiTheme::kLight; + if (!title.empty()) { + config.title = title; + } + g_app = new mujoco::studio::App(std::move(config)); g_app->InitEmptyModel(); } diff --git a/src/experimental/studio/live.js b/src/experimental/studio/live.js index 19ecb32d..c479f40f 100644 --- a/src/experimental/studio/live.js +++ b/src/experimental/studio/live.js @@ -96,7 +96,9 @@ var Module = { Promise.all(assetPromises) .then(() => { try { - Module.init(); + const prefersDark = !(window.matchMedia && + window.matchMedia('(prefers-color-scheme: light)').matches); + Module.init("MuJoCo Live", prefersDark); // Check for a ?model= URL parameter and load from URL. const params = new URLSearchParams(window.location.search);