Move model_, data_, and spec_ into private accessors.

This is in preparation for an upcoming change.

PiperOrigin-RevId: 865332731
Change-Id: I74041b3caf5de841f583f76682e1ced049557202
This commit is contained in:
Haroon Qureshi
2026-02-04 04:02:22 -08:00
committed by Copybara-Service
parent 0add985a15
commit c2ede20d08
2 changed files with 90 additions and 81 deletions
+83 -81
View File
@@ -229,8 +229,7 @@ void App::LoadModelFromBuffer(std::span<const std::byte> buffer,
resource.name = (char*)filename.data(); resource.name = (char*)filename.data();
spec = mju_decodeResource(&resource, content_type.data(), &vfs); spec = mju_decodeResource(&resource, content_type.data(), &vfs);
} else { } else {
SetLoadError( SetLoadError("Unknown content type; expected text/xml or application/mjb");
"Unknown content type; expected text/xml or application/mjb");
return; return;
} }
if (err[0]) { if (err[0]) {
@@ -327,20 +326,20 @@ void App::SetLoadError(std::string error) {
} }
void App::ResetPhysics() { void App::ResetPhysics() {
mj_resetData(model_, data_); mj_resetData(model(), data());
mj_forward(model_, data_); mj_forward(model(), data());
step_error_ = ""; step_error_ = "";
} }
void App::UpdatePhysics() { void App::UpdatePhysics() {
if (model_ == nullptr) { if (!has_model()) {
return; return;
} }
bool stepped = false; bool stepped = false;
platform::ForEachModelPlugin([&](platform::ModelPlugin* plugin) { platform::ForEachModelPlugin([&](platform::ModelPlugin* plugin) {
if (plugin->do_update) { if (plugin->do_update) {
if (plugin->do_update(plugin, model_, data_)) { if (plugin->do_update(plugin, model(), data())) {
stepped = true; stepped = true;
} }
} }
@@ -348,21 +347,22 @@ void App::UpdatePhysics() {
if (!stepped) { if (!stepped) {
if (!step_control_.IsPaused()) { if (!step_control_.IsPaused()) {
mju_zero(data_->xfrc_applied, 6 * model_->nbody); mju_zero(data()->xfrc_applied, 6 * model()->nbody);
mjv_applyPerturbPose(model_, data_, &perturb_, 0); mjv_applyPerturbPose(model(), data(), &perturb_, 0);
mjv_applyPerturbForce(model_, data_, &perturb_); mjv_applyPerturbForce(model(), data(), &perturb_);
} else { } else {
mjv_applyPerturbPose(model_, data_, &perturb_, 1); mjv_applyPerturbPose(model(), data(), &perturb_, 1);
} }
if (data_) { if (has_data()) {
for (int i = 0; i < mjNTIMER; i++) { for (int i = 0; i < mjNTIMER; i++) {
data_->timer[i].duration = 0; data()->timer[i].duration = 0;
data_->timer[i].number = 0; data()->timer[i].number = 0;
} }
} }
platform::StepControl::Status status = step_control_.Advance(model_, data_); platform::StepControl::Status status =
step_control_.Advance(model(), data());
if (status == platform::StepControl::Status::kPaused) { if (status == platform::StepControl::Status::kPaused) {
// do nothing // do nothing
} else if (status == platform::StepControl::Status::kOk) { } else if (status == platform::StepControl::Status::kOk) {
@@ -374,18 +374,18 @@ void App::UpdatePhysics() {
} else if (status == platform::StepControl::Status::kDiverged) { } else if (status == platform::StepControl::Status::kDiverged) {
stepped = true; stepped = true;
for (mjtWarning w : platform::StepControl::kDivergedWarnings) { for (mjtWarning w : platform::StepControl::kDivergedWarnings) {
if (data_->warning[w].number > 0) { if (data()->warning[w].number > 0) {
step_error_ = mju_warningText(w, data_->warning[w].lastinfo); step_error_ = mju_warningText(w, data()->warning[w].lastinfo);
} }
} }
} }
} }
if (stepped) { if (stepped) {
profiler_.Update(model_, data_); profiler_.Update(model(), data());
std::span<mjtNum> state = history_.AddToHistory(); std::span<mjtNum> state = history_.AddToHistory();
if (!state.empty()) { if (!state.empty()) {
mj_getState(model_, data_, state.data(), mjSTATE_INTEGRATION); mj_getState(model(), data(), state.data(), mjSTATE_INTEGRATION);
} }
} }
} }
@@ -397,8 +397,8 @@ void App::LoadHistory(int offset) {
step_control_.Pause(); step_control_.Pause();
// Load the state into the data buffer. // Load the state into the data buffer.
mj_setState(model_, data_, state.data(), mjSTATE_INTEGRATION); mj_setState(model(), data(), state.data(), mjSTATE_INTEGRATION);
mj_forward(model_, data_); mj_forward(model(), data());
} }
} }
@@ -430,16 +430,16 @@ void App::Render() {
} else { } else {
pixels_.clear(); pixels_.clear();
} }
renderer_->Render(model_, data_, &perturb_, &camera_, &vis_options_, renderer_->Render(model(), data(), &perturb_, &camera_, &vis_options_,
width * scale, height * scale, pixels_); width * scale, height * scale, pixels_);
window_->EndFrame(); window_->EndFrame();
window_->Present(pixels_); window_->Present(pixels_);
if (data_) { if (has_data()) {
for (int i = 0; i < mjNTIMER; i++) { for (int i = 0; i < mjNTIMER; i++) {
data_->timer[i].duration = 0; data()->timer[i].duration = 0;
data_->timer[i].number = 0; data()->timer[i].number = 0;
} }
} }
} }
@@ -487,7 +487,7 @@ void App::HandleMouseEvents() {
return; return;
} }
if (!model_ || !data_) { if (!has_model() || !has_data()) {
return; return;
} }
@@ -522,9 +522,9 @@ void App::HandleMouseEvents() {
const mjtPertBit active = const mjtPertBit active =
action == mjMOUSE_MOVE_V ? mjPERT_TRANSLATE : mjPERT_ROTATE; action == mjMOUSE_MOVE_V ? mjPERT_TRANSLATE : mjPERT_ROTATE;
if (active != perturb_.active) { if (active != perturb_.active) {
platform::InitPerturb(model_, data_, &camera_, &perturb_, active); platform::InitPerturb(model(), data(), &camera_, &perturb_, active);
} }
platform::MovePerturb(model_, data_, &camera_, &perturb_, action, platform::MovePerturb(model(), data(), &camera_, &perturb_, action,
mouse_dx, mouse_dy); mouse_dx, mouse_dy);
} }
} }
@@ -559,7 +559,7 @@ void App::HandleMouseEvents() {
// Left double click. // Left double click.
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
platform::PickResult picked = platform::PickResult picked =
platform::Pick(model_, data_, &camera_, mouse_x, mouse_y, platform::Pick(model(), data(), &camera_, mouse_x, mouse_y,
window_->GetAspectRatio(), &vis_options_); window_->GetAspectRatio(), &vis_options_);
if (picked.body >= 0) { if (picked.body >= 0) {
perturb_.select = picked.body; perturb_.select = picked.body;
@@ -568,8 +568,8 @@ void App::HandleMouseEvents() {
// Compute the local position of the selected object in the world. // Compute the local position of the selected object in the world.
mjtNum tmp[3]; mjtNum tmp[3];
mju_sub3(tmp, picked.point, data_->xpos + 3 * picked.body); mju_sub3(tmp, picked.point, data()->xpos + 3 * picked.body);
mju_mulMatTVec(perturb_.localpos, data_->xmat + 9 * picked.body, tmp, 3, mju_mulMatTVec(perturb_.localpos, data()->xmat + 9 * picked.body, tmp, 3,
3); 3);
} else { } else {
perturb_.select = 0; perturb_.select = 0;
@@ -581,7 +581,7 @@ void App::HandleMouseEvents() {
// Right double click. // Right double click.
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Right)) { if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Right)) {
platform::PickResult picked = platform::PickResult picked =
platform::Pick(model_, data_, &camera_, mouse_x, mouse_y, platform::Pick(model(), data(), &camera_, mouse_x, mouse_y,
window_->GetAspectRatio(), &vis_options_); window_->GetAspectRatio(), &vis_options_);
mju_copy3(camera_.lookat, picked.point); mju_copy3(camera_.lookat, picked.point);
if (picked.body > 0 && io.KeyCtrl) { if (picked.body > 0 && io.KeyCtrl) {
@@ -618,14 +618,14 @@ void App::HandleKeyboardEvents() {
} else if (ImGui_IsChordJustPressed(ImGuiKey_P | ImGuiMod_Ctrl)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_P | ImGuiMod_Ctrl)) {
tmp_.file_dialog = UiTempState::FileDialog_SaveScreenshot; tmp_.file_dialog = UiTempState::FileDialog_SaveScreenshot;
} else if (ImGui_IsChordJustPressed(ImGuiKey_C | ImGuiMod_Ctrl)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_C | ImGuiMod_Ctrl)) {
std::string keyframe = platform::KeyframeToString(model_, data_, false); std::string keyframe = platform::KeyframeToString(model(), data(), false);
platform::MaybeSaveToClipboard(keyframe); platform::MaybeSaveToClipboard(keyframe);
} else if (ImGui_IsChordJustPressed(ImGuiKey_L | ImGuiMod_Ctrl)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_L | ImGuiMod_Ctrl)) {
RequestModelReload(); RequestModelReload();
} else if (ImGui_IsChordJustPressed(ImGuiKey_Q | ImGuiMod_Ctrl)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_Q | ImGuiMod_Ctrl)) {
tmp_.should_exit = true; tmp_.should_exit = true;
} else if (ImGui_IsChordJustPressed(ImGuiKey_A | ImGuiMod_Ctrl)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_A | ImGuiMod_Ctrl)) {
mjv_defaultFreeCamera(model_, &camera_); mjv_defaultFreeCamera(model(), &camera_);
} else if (ImGui_IsChordJustPressed(ImGuiKey_Tab | ImGuiMod_Shift)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_Tab | ImGuiMod_Shift)) {
tmp_.inspector_panel = !tmp_.inspector_panel; tmp_.inspector_panel = !tmp_.inspector_panel;
} else if (ImGui_IsChordJustPressed(ImGuiKey_Tab)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_Tab)) {
@@ -651,7 +651,7 @@ void App::HandleKeyboardEvents() {
} else if (ImGui_IsChordJustPressed(ImGuiKey_Backspace)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_Backspace)) {
ResetPhysics(); ResetPhysics();
} else if (ImGui_IsChordJustPressed(ImGuiKey_PageUp)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_PageUp)) {
SelectParentPerturb(model_, perturb_); SelectParentPerturb(model(), perturb_);
} else if (ImGui_IsChordJustPressed(ImGuiKey_F1)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_F1)) {
ToggleWindow(tmp_.help); ToggleWindow(tmp_.help);
} else if (ImGui_IsChordJustPressed(ImGuiKey_F2)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_F2)) {
@@ -740,16 +740,16 @@ void App::HandleKeyboardEvents() {
ToggleFlag(vis_options_.geomgroup[4]); ToggleFlag(vis_options_.geomgroup[4]);
} else if (ImGui_IsChordJustPressed(ImGuiKey_5)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_5)) {
ToggleFlag(vis_options_.geomgroup[5]); ToggleFlag(vis_options_.geomgroup[5]);
} else if (model_) { } else if (has_model()) {
if (ImGui_IsChordJustPressed(ImGuiKey_Escape)) { if (ImGui_IsChordJustPressed(ImGuiKey_Escape)) {
ui_.camera_idx = ui_.camera_idx =
platform::SetCamera(model_, &camera_, platform::kTumbleCameraIdx); platform::SetCamera(model(), &camera_, platform::kTumbleCameraIdx);
} else if (ImGui_IsChordJustPressed(ImGuiKey_LeftBracket)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_LeftBracket)) {
ui_.camera_idx = ui_.camera_idx =
platform::SetCamera(model_, &camera_, ui_.camera_idx - 1); platform::SetCamera(model(), &camera_, ui_.camera_idx - 1);
} else if (ImGui_IsChordJustPressed(ImGuiKey_RightBracket)) { } else if (ImGui_IsChordJustPressed(ImGuiKey_RightBracket)) {
ui_.camera_idx = ui_.camera_idx =
platform::SetCamera(model_, &camera_, ui_.camera_idx + 1); platform::SetCamera(model(), &camera_, ui_.camera_idx + 1);
} }
// WASD camera controls for free camera. // WASD camera controls for free camera.
@@ -843,7 +843,7 @@ void App::SetSpeedIndex(int idx) {
void App::MoveCamera(platform::CameraMotion motion, mjtNum reldx, void App::MoveCamera(platform::CameraMotion motion, mjtNum reldx,
mjtNum reldy) { mjtNum reldy) {
platform::MoveCamera(model_, data_, &camera_, motion, reldx, reldy); platform::MoveCamera(model(), data(), &camera_, motion, reldx, reldy);
} }
void App::BuildGui() { void App::BuildGui() {
@@ -919,15 +919,15 @@ void App::BuildGui() {
ImGui::SetNextWindowPos(chart_pos, ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(chart_pos, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(chart_size, ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(chart_size, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Solver", &tmp_.chart_solver)) { if (ImGui::Begin("Solver", &tmp_.chart_solver)) {
platform::CountsGui(model_, data_); platform::CountsGui(model(), data());
platform::ConvergenceGui(model_, data_); platform::ConvergenceGui(model(), data());
} }
ImGui::End(); ImGui::End();
} }
if (tmp_.picture_in_picture) { if (tmp_.picture_in_picture) {
if (ImGui::Begin("Picture-in-Picture", &tmp_.picture_in_picture)) { if (ImGui::Begin("Picture-in-Picture", &tmp_.picture_in_picture)) {
PipGui(model_, data_, window_.get(), renderer_.get(), &tmp_.pips); PipGui(model(), data(), window_.get(), renderer_.get(), &tmp_.pips);
} }
ImGui::End(); ImGui::End();
} }
@@ -949,7 +949,7 @@ void App::BuildGui() {
style.Var(ImGuiStyleVar_Alpha, 0.6f); style.Var(ImGuiStyleVar_Alpha, 0.6f);
if (ImGui::Begin("Stats", &tmp_.stats)) { if (ImGui::Begin("Stats", &tmp_.stats)) {
const float fps = renderer_->GetFps(); const float fps = renderer_->GetFps();
platform::StatsGui(model_, data_, step_control_.IsPaused(), fps); platform::StatsGui(model(), data(), step_control_.IsPaused(), fps);
} }
ImGui::End(); ImGui::End();
} }
@@ -1042,14 +1042,14 @@ void App::ModelOptionsGui() {
ImGui::BeginChild("PhysicsGui", {0, 0}, child_flags); ImGui::BeginChild("PhysicsGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Physics Settings", node_flags)) { if (ImGui::TreeNodeEx("Physics Settings", node_flags)) {
platform::PhysicsGui(model_, min_width); platform::PhysicsGui(model(), min_width);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::BeginChild("RenderingGui", {0, 0}, child_flags); ImGui::BeginChild("RenderingGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Rendering Settings", node_flags)) { if (ImGui::TreeNodeEx("Rendering Settings", node_flags)) {
platform::RenderingGui(model_, &vis_options_, renderer_->GetRenderFlags(), platform::RenderingGui(model(), &vis_options_, renderer_->GetRenderFlags(),
min_width); min_width);
ImGui::TreePop(); ImGui::TreePop();
} }
@@ -1057,21 +1057,21 @@ void App::ModelOptionsGui() {
ImGui::BeginChild("GroupsGui", {0, 0}, child_flags); ImGui::BeginChild("GroupsGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Visibility Groups", node_flags)) { if (ImGui::TreeNodeEx("Visibility Groups", node_flags)) {
platform::GroupsGui(model_, &vis_options_, min_width); platform::GroupsGui(model(), &vis_options_, min_width);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::BeginChild("VisualizationGui", {0, 0}, child_flags); ImGui::BeginChild("VisualizationGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Visualization", node_flags)) { if (ImGui::TreeNodeEx("Visualization", node_flags)) {
platform::VisualizationGui(model_, &vis_options_, &camera_, min_width); platform::VisualizationGui(model(), &vis_options_, &camera_, min_width);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
} }
void App::DataInspectorGui() { void App::DataInspectorGui() {
if (data_ == nullptr) { if (!has_data()) {
ImGui::Text("No mjData loaded."); ImGui::Text("No mjData loaded.");
return; return;
} }
@@ -1087,7 +1087,7 @@ void App::DataInspectorGui() {
float noise_scale = 0; float noise_scale = 0;
float noise_rate = 0; float noise_rate = 0;
step_control_.GetNoiseParameters(noise_scale, noise_rate); step_control_.GetNoiseParameters(noise_scale, noise_rate);
platform::NoiseGui(model_, data_, noise_scale, noise_rate); platform::NoiseGui(model(), data(), noise_scale, noise_rate);
step_control_.SetNoiseParameters(noise_scale, noise_rate); step_control_.SetNoiseParameters(noise_scale, noise_rate);
ImGui::TreePop(); ImGui::TreePop();
} }
@@ -1095,36 +1095,36 @@ void App::DataInspectorGui() {
ImGui::BeginChild("JointsGui", {0, 0}, child_flags); ImGui::BeginChild("JointsGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Joints", node_flags)) { if (ImGui::TreeNodeEx("Joints", node_flags)) {
platform::JointsGui(model_, data_, &vis_options_); platform::JointsGui(model(), data(), &vis_options_);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::BeginChild("ControlsGui", {0, 0}, child_flags); ImGui::BeginChild("ControlsGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Controls", node_flags)) { if (ImGui::TreeNodeEx("Controls", node_flags)) {
platform::ControlsGui(model_, data_, &vis_options_); platform::ControlsGui(model(), data(), &vis_options_);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::BeginChild("SensorGui", {0, 0}, child_flags); ImGui::BeginChild("SensorGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Sensor", node_flags)) { if (ImGui::TreeNodeEx("Sensor", node_flags)) {
platform::SensorGui(model_, data_); platform::SensorGui(model(), data());
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::BeginChild("WatchGui", {0, 0}, child_flags); ImGui::BeginChild("WatchGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("Watch", node_flags)) { if (ImGui::TreeNodeEx("Watch", node_flags)) {
platform::WatchGui(model_, data_, ui_.watch_field, sizeof(ui_.watch_field), platform::WatchGui(model(), data(), ui_.watch_field,
ui_.watch_index); sizeof(ui_.watch_field), ui_.watch_index);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::BeginChild("StateGui", {0, 0}, child_flags); ImGui::BeginChild("StateGui", {0, 0}, child_flags);
if (ImGui::TreeNodeEx("State", node_flags)) { if (ImGui::TreeNodeEx("State", node_flags)) {
platform::StateGui(model_, data_, tmp_.state, tmp_.state_sig, min_width); platform::StateGui(model(), data(), tmp_.state, tmp_.state_sig, min_width);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::EndChild(); ImGui::EndChild();
@@ -1140,7 +1140,7 @@ void DisplayElementTree(mjsElement* element) {
} }
void App::SpecExplorerGui() { void App::SpecExplorerGui() {
if (spec_ == nullptr) { if (!has_spec()) {
ImGui::Text("No mjSpec loaded."); ImGui::Text("No mjSpec loaded.");
return; return;
} }
@@ -1149,7 +1149,7 @@ void App::SpecExplorerGui() {
ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_Framed; ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_Framed;
auto display_group = [this](mjtObj type, const std::string& prefix) { auto display_group = [this](mjtObj type, const std::string& prefix) {
mjsElement* element = mjs_firstElement(spec_, type); mjsElement* element = mjs_firstElement(spec(), type);
while (element) { while (element) {
const int id = mjs_getId(element); const int id = mjs_getId(element);
@@ -1164,14 +1164,14 @@ void App::SpecExplorerGui() {
tmp_.element_id = id; tmp_.element_id = id;
} }
element = mjs_nextElement(spec_, element); element = mjs_nextElement(spec(), element);
} }
}; };
if (ImGui::TreeNodeEx("Bodies", flags)) { if (ImGui::TreeNodeEx("Bodies", flags)) {
// We don't use `display_group` here because we do additional selection // We don't use `display_group` here because we do additional selection
// logic tied to the `perturb_` field. // logic tied to the `perturb_` field.
mjsElement* element = mjs_firstElement(spec_, mjOBJ_BODY); mjsElement* element = mjs_firstElement(spec(), mjOBJ_BODY);
while (element) { while (element) {
const int id = mjs_getId(element); const int id = mjs_getId(element);
@@ -1191,7 +1191,7 @@ void App::SpecExplorerGui() {
perturb_.select = id; perturb_.select = id;
} }
element = mjs_nextElement(spec_, element); element = mjs_nextElement(spec(), element);
} }
ImGui::TreePop(); ImGui::TreePop();
} }
@@ -1217,18 +1217,20 @@ void App::PropertiesGui() {
case mjOBJ_BODY: case mjOBJ_BODY:
ImGui::Text("Body"); ImGui::Text("Body");
ImGui::Separator(); ImGui::Separator();
platform::BodyPropertiesGui(model_, data_, tmp_.element, tmp_.element_id); platform::BodyPropertiesGui(model(), data(), tmp_.element,
tmp_.element_id);
break; break;
case mjOBJ_JOINT: case mjOBJ_JOINT:
ImGui::Text("Joint"); ImGui::Text("Joint");
ImGui::Separator(); ImGui::Separator();
platform::JointPropertiesGui(model_, data_, tmp_.element, platform::JointPropertiesGui(model(), data(), tmp_.element,
tmp_.element_id); tmp_.element_id);
break; break;
case mjOBJ_SITE: case mjOBJ_SITE:
ImGui::Text("Site"); ImGui::Text("Site");
ImGui::Separator(); ImGui::Separator();
platform::SitePropertiesGui(model_, data_, tmp_.element, tmp_.element_id); platform::SitePropertiesGui(model(), data(), tmp_.element,
tmp_.element_id);
break; break;
default: default:
// ignore other types // ignore other types
@@ -1431,8 +1433,8 @@ void App::ToolBarGui() {
if (ImGui::BeginCombo("##Camera", cameras[camera_idx], combo_flags)) { if (ImGui::BeginCombo("##Camera", cameras[camera_idx], combo_flags)) {
for (int n = 0; n < cameras.size(); n++) { for (int n = 0; n < cameras.size(); n++) {
if (ImGui::Selectable(cameras[n], (camera_idx == n))) { if (ImGui::Selectable(cameras[n], (camera_idx == n))) {
ui_.camera_idx = platform::SetCamera( ui_.camera_idx = platform::SetCamera(model(), &camera_,
model_, &camera_, n + platform::kTumbleCameraIdx); n + platform::kTumbleCameraIdx);
} }
} }
ImGui::EndCombo(); ImGui::EndCombo();
@@ -1440,7 +1442,7 @@ void App::ToolBarGui() {
ImGui::SetItemTooltip("%s", "Camera"); ImGui::SetItemTooltip("%s", "Camera");
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button(ICON_COPY_CAMERA)) { if (ImGui::Button(ICON_COPY_CAMERA)) {
std::string camera_string = platform::CameraToString(data_, &camera_); std::string camera_string = platform::CameraToString(data(), &camera_);
platform::MaybeSaveToClipboard(camera_string); platform::MaybeSaveToClipboard(camera_string);
} }
ImGui::SetItemTooltip("%s", "Copy Camera"); ImGui::SetItemTooltip("%s", "Copy Camera");
@@ -1524,7 +1526,7 @@ void App::StatusBarGui() {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (model_ == nullptr) { if (!has_model()) {
ImGui::Text("No model loaded"); ImGui::Text("No model loaded");
} else if (step_control_.IsPaused()) { } else if (step_control_.IsPaused()) {
ImGui::Text("Paused"); ImGui::Text("Paused");
@@ -1645,16 +1647,16 @@ void App::MainMenuGui() {
ImGui::Separator(); ImGui::Separator();
if (ImGui::BeginMenu("Keyframes")) { if (ImGui::BeginMenu("Keyframes")) {
ImGui::SetNextItemWidth(200); ImGui::SetNextItemWidth(200);
ImGui::SliderInt("##Key", &ui_.key_idx, 0, model_->nkey); ImGui::SliderInt("##Key", &ui_.key_idx, 0, model()->nkey);
if (ImGui::MenuItem("Load")) { if (ImGui::MenuItem("Load")) {
mj_resetDataKeyframe(model_, data_, ui_.key_idx); mj_resetDataKeyframe(model(), data(), ui_.key_idx);
mj_forward(model_, data_); mj_forward(model(), data());
} }
if (ImGui::MenuItem("Save")) { if (ImGui::MenuItem("Save")) {
mj_setKeyframe(model_, data_, ui_.key_idx); mj_setKeyframe(model(), data(), ui_.key_idx);
} }
if (ImGui::MenuItem("Copy")) { if (ImGui::MenuItem("Copy")) {
std::string str = platform::KeyframeToString(model_, data_, false); std::string str = platform::KeyframeToString(model(), data(), false);
platform::MaybeSaveToClipboard(str); platform::MaybeSaveToClipboard(str);
} }
ImGui::EndMenu(); ImGui::EndMenu();
@@ -1748,25 +1750,25 @@ void App::FileDialogGui() {
RequestModelLoad(res.path); RequestModelLoad(res.path);
break; break;
case UiTempState::FileDialog_SaveXml: case UiTempState::FileDialog_SaveXml:
mj_saveLastXML(res.path.c_str(), model_, nullptr, 0); mj_saveLastXML(res.path.c_str(), model(), nullptr, 0);
break; break;
case UiTempState::FileDialog_SaveMjb: case UiTempState::FileDialog_SaveMjb:
mj_saveModel(model_, res.path.c_str(), nullptr, 0); mj_saveModel(model(), res.path.c_str(), nullptr, 0);
break; break;
case UiTempState::FileDialog_SaveScreenshot: { case UiTempState::FileDialog_SaveScreenshot: {
const int width = window_->GetWidth(); const int width = window_->GetWidth();
const int height = window_->GetHeight(); const int height = window_->GetHeight();
std::vector<std::byte> buffer(width * height * 3); std::vector<std::byte> buffer(width * height * 3);
renderer_->RenderToTexture(model_, data_, &camera_, width, height, renderer_->RenderToTexture(model(), data(), &camera_, width, height,
buffer.data()); buffer.data());
platform::SaveToWebp(width, height, buffer.data(), res.path); platform::SaveToWebp(width, height, buffer.data(), res.path);
break; break;
} }
case UiTempState::FileDialog_PrintModel: case UiTempState::FileDialog_PrintModel:
mj_printModel(model_, res.path.c_str()); mj_printModel(model(), res.path.c_str());
break; break;
case UiTempState::FileDialog_PrintData: case UiTempState::FileDialog_PrintData:
mj_printData(model_, data_, res.path.c_str()); mj_printData(model(), data(), res.path.c_str());
break; break;
default: default:
break; break;
@@ -1818,14 +1820,14 @@ float App::GetExpectedLabelWidth() {
std::vector<const char*> App::GetCameraNames() { std::vector<const char*> App::GetCameraNames() {
if (tmp_.camera_names.empty()) { if (tmp_.camera_names.empty()) {
tmp_.camera_names.reserve(model_->ncam + 3); tmp_.camera_names.reserve(model()->ncam + 3);
tmp_.camera_names.push_back("Free: tumble"); tmp_.camera_names.push_back("Free: tumble");
tmp_.camera_names.push_back("Free: wasd"); tmp_.camera_names.push_back("Free: wasd");
tmp_.camera_names.push_back("Tracking (-1)"); tmp_.camera_names.push_back("Tracking (-1)");
for (int i = 0; i < model_->ncam; i++) { for (int i = 0; i < model()->ncam; i++) {
if (model_->names[model_->name_camadr[i]]) { if (model()->names[model()->name_camadr[i]]) {
tmp_.camera_names.push_back(model_->names + model_->name_camadr[i]); tmp_.camera_names.push_back(model()->names + model()->name_camadr[i]);
} else { } else {
tmp_.camera_names.push_back("Unnamed"); tmp_.camera_names.push_back("Unnamed");
} }
+7
View File
@@ -207,6 +207,13 @@ class App {
float GetExpectedLabelWidth(); float GetExpectedLabelWidth();
std::vector<const char*> GetCameraNames(); std::vector<const char*> GetCameraNames();
mjSpec* spec() { return spec_; }
mjModel* model() { return model_; }
mjData* data() { return data_; }
bool has_spec() const { return spec_ != nullptr; }
bool has_model() const { return model_ != nullptr; }
bool has_data() const { return data_ != nullptr; }
std::string ini_path_; std::string ini_path_;
std::string model_name_; // Used if model_kind_ is kModelFromBuffer. std::string model_name_; // Used if model_kind_ is kModelFromBuffer.
std::string model_path_; std::string model_path_;