From 778f4c044dbbb10572f503c8e70b156703760be0 Mon Sep 17 00:00:00 2001 From: Dean Blackborough Date: Sun, 7 Jun 2026 15:21:33 +0100 Subject: [PATCH 1/2] Simplify inspector code - Added tracked_property_table to handle most of the tracking and keep inspector code simpler --- CMakeLists.txt | 1 + .../tooling/editor/tracked_property_table.cpp | 202 ++++++++++++++++ .../tooling/editor/tracked_property_table.hpp | 86 +++++++ src/prune/tooling/inspector.cpp | 223 ++++++------------ src/prune/tooling/inspector.hpp | 12 +- 5 files changed, 366 insertions(+), 158 deletions(-) create mode 100644 src/prune/tooling/editor/tracked_property_table.cpp create mode 100644 src/prune/tooling/editor/tracked_property_table.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d73df28..67c6389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ add_executable(Prune src/prune/tooling/inspector.cpp src/prune/tooling/command_history.cpp src/prune/tooling/sprite_picker.cpp + src/prune/tooling/editor/tracked_property_table.cpp src/prune/tooling/controls.cpp src/prune/tooling/options.cpp src/prune/tooling/stats.cpp diff --git a/src/prune/tooling/editor/tracked_property_table.cpp b/src/prune/tooling/editor/tracked_property_table.cpp new file mode 100644 index 0000000..c6f2967 --- /dev/null +++ b/src/prune/tooling/editor/tracked_property_table.cpp @@ -0,0 +1,202 @@ +#include "imgui.h" + +#include "prune/tooling/editor/tracked_property_table.hpp" +#include "prune/scene/scene.hpp" +#include "prune/tooling/imgui/property_table.hpp" +#include "prune/tooling/sprite_picker.hpp" + +namespace prune::tooling::editor::tracked_property_table { + + namespace { + + [[nodiscard]] bool command_object_changed( + EditorCommandType type, + const GameObject& before, + const GameObject& after + ) noexcept { + switch (type) { + case EditorCommandType::MoveObject: + case EditorCommandType::ChangeObjectPosition: + return before.transform.x != after.transform.x || before.transform.y != after.transform.y; + + case EditorCommandType::ChangeObjectSize: + return before.size.width != after.size.width || before.size.height != after.size.height; + + case EditorCommandType::ChangeObjectRenderType: + return before.render.type != after.render.type; + + case EditorCommandType::ChangeObjectColour: + return before.render.rectangle.color[0] != after.render.rectangle.color[0] || + before.render.rectangle.color[1] != after.render.rectangle.color[1] || + before.render.rectangle.color[2] != after.render.rectangle.color[2]; + + case EditorCommandType::ChangeObjectFlag: + return before.lifecycle.active != after.lifecycle.active || + before.render.visible != after.render.visible || + before.collision.solid != after.collision.solid; + + case EditorCommandType::ChangeSprite: + return before.render.sprite.sprite_key != after.render.sprite.sprite_key || + before.render.sprite.flip_x != after.render.sprite.flip_x; + + case EditorCommandType::RenameObject: + return before.identity.name != after.identity.name; + + case EditorCommandType::CreateObject: + case EditorCommandType::DeleteObject: + case EditorCommandType::MoveViewport: + return true; + } + + return true; + } + + } + + void ObjectEditTracker::capture_if_activated(const GameObject& before) + { + if (ImGui::IsItemActivated()) { + m_before = before; + } + } + + void ObjectEditTracker::commit_if_deactivated_after_edit( + Scene& scene, + EditorCommandType type, + const GameObject& after + ) { + if (!ImGui::IsItemDeactivatedAfterEdit()) { + return; + } + + if (!m_before.has_value()) { + return; + } + + const GameObject before = m_before.value(); + m_before.reset(); + + commit_if_changed(scene, type, before, after); + } + + void ObjectEditTracker::reset() noexcept + { + m_before.reset(); + } + + bool drag_float( + ObjectEditTracker& tracker, + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + float& value, + float speed, + float min, + float max, + const char* format + ) { + const GameObject before = object; + const bool changed = ::prune::tooling::imgui::property_table::drag_float(label, id, value, speed, min, max, format); + + tracker.capture_if_activated(before); + tracker.commit_if_deactivated_after_edit(scene, type, object); + + return changed; + } + + bool slider_int( + ObjectEditTracker& tracker, + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + int& value, + int min, + int max + ) { + const GameObject before = object; + const bool changed = ::prune::tooling::imgui::property_table::slider_int(label, id, value, min, max); + + tracker.capture_if_activated(before); + tracker.commit_if_deactivated_after_edit(scene, type, object); + + return changed; + } + + bool color3( + ObjectEditTracker& tracker, + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + float color[3] + ) { + const GameObject before = object; + const bool changed = ::prune::tooling::imgui::property_table::color3(label, id, color); + + tracker.capture_if_activated(before); + tracker.commit_if_deactivated_after_edit(scene, type, object); + + return changed; + } + + bool checkbox( + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + bool& value + ) { + const GameObject before = object; + + if (!::prune::tooling::imgui::property_table::checkbox(label, id, value)) { + return false; + } + + commit_if_changed(scene, type, before, object); + return true; + } + + bool sprite_picker( + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + std::string& sprite_key + ) { + const GameObject before = object; + + if (!::prune::tooling::draw_sprite_picker(label, id, sprite_key)) { + return false; + } + + commit_if_changed(scene, type, before, object); + return true; + } + + bool commit_if_changed( + Scene& scene, + EditorCommandType type, + const GameObject& before, + const GameObject& after + ) { + if (before.identity.id != after.identity.id || !command_object_changed(type, before, after)) { + return false; + } + + scene.record_editor_command(make_object_command( + type, + editor_command_type_label(type), + before, + after + )); + + return true; + } +} diff --git a/src/prune/tooling/editor/tracked_property_table.hpp b/src/prune/tooling/editor/tracked_property_table.hpp new file mode 100644 index 0000000..6465763 --- /dev/null +++ b/src/prune/tooling/editor/tracked_property_table.hpp @@ -0,0 +1,86 @@ +#pragma once + +#include +#include + +#include "prune/editor/editor_command.hpp" +#include "prune/scene/game_object.hpp" + +namespace prune { + class Scene; +} + +namespace prune::tooling::editor::tracked_property_table { + + class ObjectEditTracker { + public: + void capture_if_activated(const GameObject& before); + void commit_if_deactivated_after_edit(Scene& scene, EditorCommandType type, const GameObject& after); + void reset() noexcept; + + private: + std::optional m_before; + }; + + bool drag_float( + ObjectEditTracker& tracker, + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + float& value, + float speed = 1.0f, + float min = 0.0f, + float max = 0.0f, + const char* format = "%.3f" + ); + + bool slider_int( + ObjectEditTracker& tracker, + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + int& value, + int min, + int max + ); + + bool color3( + ObjectEditTracker& tracker, + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + float color[3] + ); + + bool checkbox( + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + bool& value + ); + + bool sprite_picker( + Scene& scene, + EditorCommandType type, + GameObject& object, + const char* label, + const char* id, + std::string& sprite_key + ); + + bool commit_if_changed( + Scene& scene, + EditorCommandType type, + const GameObject& before, + const GameObject& after + ); + +} diff --git a/src/prune/tooling/inspector.cpp b/src/prune/tooling/inspector.cpp index be1ab7c..c395332 100644 --- a/src/prune/tooling/inspector.cpp +++ b/src/prune/tooling/inspector.cpp @@ -6,7 +6,6 @@ #include "prune/tooling/inspector.hpp" #include "prune/tooling/imgui/layout.hpp" #include "prune/tooling/imgui/property_table.hpp" -#include "prune/tooling/sprite_picker.hpp" namespace prune { @@ -202,15 +201,27 @@ namespace prune { if (tooling::imgui::property_table::begin("##transform")) { ImGui::BeginDisabled(!can_move); - GameObject before = *selected; - tooling::imgui::property_table::drag_float("X", "transform_x", selected->transform.x, 1.0f); - capture_object_edit_start(before); - commit_object_edit(scene, EditorCommandType::ChangeObjectPosition, *selected); + tooling::editor::tracked_property_table::drag_float( + m_object_edit_tracker, + scene, + EditorCommandType::ChangeObjectPosition, + *selected, + "X", + "transform_x", + selected->transform.x, + 1.0f + ); - before = *selected; - tooling::imgui::property_table::drag_float("Y", "transform_y", selected->transform.y, 1.0f); - capture_object_edit_start(before); - commit_object_edit(scene, EditorCommandType::ChangeObjectPosition, *selected); + tooling::editor::tracked_property_table::drag_float( + m_object_edit_tracker, + scene, + EditorCommandType::ChangeObjectPosition, + *selected, + "Y", + "transform_y", + selected->transform.y, + 1.0f + ); ImGui::EndDisabled(); tooling::imgui::property_table::end(); @@ -221,15 +232,29 @@ namespace prune { if (tooling::imgui::property_table::begin("##size")) { ImGui::BeginDisabled(!can_edit); - GameObject before = *selected; - tooling::imgui::property_table::slider_int("Width", "##width", selected->size.width, k_min_object_size, k_max_object_size); - capture_object_edit_start(before); - commit_object_edit(scene, EditorCommandType::ChangeObjectSize, *selected); + tooling::editor::tracked_property_table::slider_int( + m_object_edit_tracker, + scene, + EditorCommandType::ChangeObjectSize, + *selected, + "Width", + "##width", + selected->size.width, + k_min_object_size, + k_max_object_size + ); - before = *selected; - tooling::imgui::property_table::slider_int("Height", "##height", selected->size.height, k_min_object_size, k_max_object_size); - capture_object_edit_start(before); - commit_object_edit(scene, EditorCommandType::ChangeObjectSize, *selected); + tooling::editor::tracked_property_table::slider_int( + m_object_edit_tracker, + scene, + EditorCommandType::ChangeObjectSize, + *selected, + "Height", + "##height", + selected->size.height, + k_min_object_size, + k_max_object_size + ); ImGui::EndDisabled(); tooling::imgui::property_table::end(); @@ -254,58 +279,49 @@ namespace prune { ? RenderType::Rectangle : RenderType::Sprite; - scene.record_editor_command(make_object_command( + tooling::editor::tracked_property_table::commit_if_changed( + scene, EditorCommandType::ChangeObjectRenderType, - editor_command_type_label(EditorCommandType::ChangeObjectRenderType), before, *selected - )); + ); } switch (selected->render.type) { case RenderType::Rectangle: { - const GameObject before = *selected; - tooling::imgui::property_table::color3( + tooling::editor::tracked_property_table::color3( + m_object_edit_tracker, + scene, + EditorCommandType::ChangeObjectColour, + *selected, "Colour", "##colour", selected->render.rectangle.color ); - capture_object_edit_start(before); - commit_object_edit(scene, EditorCommandType::ChangeObjectColour, *selected); } break; case RenderType::Sprite: { - const GameObject before = *selected; - if (tooling::draw_sprite_picker( + tooling::editor::tracked_property_table::sprite_picker( + scene, + EditorCommandType::ChangeSprite, + *selected, "Sprite", "##sprite_key", selected->render.sprite.sprite_key - )) { - scene.record_editor_command(make_object_command( - EditorCommandType::ChangeSprite, - editor_command_type_label(EditorCommandType::ChangeSprite), - before, - *selected - )); - } + ); } { - const GameObject before = *selected; - if (tooling::imgui::property_table::checkbox( + tooling::editor::tracked_property_table::checkbox( + scene, + EditorCommandType::ChangeSprite, + *selected, "Flip X", "##sprite_flip_x", selected->render.sprite.flip_x - )) { - scene.record_editor_command(make_object_command( - EditorCommandType::ChangeSprite, - editor_command_type_label(EditorCommandType::ChangeSprite), - before, - *selected - )); - } + ); } break; } @@ -360,52 +376,36 @@ namespace prune { ImGui::BeginDisabled(!can_edit); { - const GameObject before = *selected; - if (tooling::imgui::property_table::checkbox( + tooling::editor::tracked_property_table::checkbox( + scene, + EditorCommandType::ChangeObjectFlag, + *selected, "Lifecycle Active", "##active", selected->lifecycle.active - )) - { - scene.record_editor_command(make_object_command( - EditorCommandType::ChangeObjectFlag, - editor_command_type_label(EditorCommandType::ChangeObjectFlag), - before, - *selected - )); - } + ); } { - const GameObject before = *selected; - if (tooling::imgui::property_table::checkbox( + tooling::editor::tracked_property_table::checkbox( + scene, + EditorCommandType::ChangeObjectFlag, + *selected, "Render Visible", "##visible", selected->render.visible - )) { - scene.record_editor_command(make_object_command( - EditorCommandType::ChangeObjectFlag, - editor_command_type_label(EditorCommandType::ChangeObjectFlag), - before, - *selected - )); - } + ); } { - const GameObject before = *selected; - if (tooling::imgui::property_table::checkbox( + tooling::editor::tracked_property_table::checkbox( + scene, + EditorCommandType::ChangeObjectFlag, + *selected, "Collision Solid", "##solid", selected->collision.solid - )) { - scene.record_editor_command(make_object_command( - EditorCommandType::ChangeObjectFlag, - editor_command_type_label(EditorCommandType::ChangeObjectFlag), - before, - *selected - )); - } + ); } ImGui::EndDisabled(); @@ -440,77 +440,4 @@ namespace prune { ); } - void Inspector::capture_object_edit_start(const GameObject& before) - { - if (ImGui::IsItemActivated()) { - m_pending_object_edit = before; - } - } - - void Inspector::commit_object_edit(Scene& scene, EditorCommandType type, const GameObject& after) - { - if (!ImGui::IsItemDeactivatedAfterEdit()) { - return; - } - - if (!m_pending_object_edit.has_value()) { - return; - } - - const GameObject before = m_pending_object_edit.value(); - m_pending_object_edit.reset(); - - if (before.identity.id != after.identity.id || !command_object_changed(type, before, after)) { - return; - } - - scene.record_editor_command(make_object_command( - type, - editor_command_type_label(type), - before, - after - )); - } - - bool Inspector::command_object_changed( - EditorCommandType type, - const GameObject& before, - const GameObject& after - ) noexcept { - switch (type) { - case EditorCommandType::MoveObject: - case EditorCommandType::ChangeObjectPosition: - return before.transform.x != after.transform.x || before.transform.y != after.transform.y; - - case EditorCommandType::ChangeObjectSize: - return before.size.width != after.size.width || before.size.height != after.size.height; - - case EditorCommandType::ChangeObjectRenderType: - return before.render.type != after.render.type; - - case EditorCommandType::ChangeObjectColour: - return before.render.rectangle.color[0] != after.render.rectangle.color[0] || - before.render.rectangle.color[1] != after.render.rectangle.color[1] || - before.render.rectangle.color[2] != after.render.rectangle.color[2]; - - case EditorCommandType::ChangeObjectFlag: - return before.lifecycle.active != after.lifecycle.active || - before.render.visible != after.render.visible; - - case EditorCommandType::ChangeSprite: - return before.render.sprite.sprite_key != after.render.sprite.sprite_key || - before.render.sprite.flip_x != after.render.sprite.flip_x; - - case EditorCommandType::RenameObject: - return before.identity.name != after.identity.name; - - case EditorCommandType::CreateObject: - case EditorCommandType::DeleteObject: - case EditorCommandType::MoveViewport: - return true; - } - - return true; - } - } diff --git a/src/prune/tooling/inspector.hpp b/src/prune/tooling/inspector.hpp index fbd3004..f09b9ad 100644 --- a/src/prune/tooling/inspector.hpp +++ b/src/prune/tooling/inspector.hpp @@ -7,6 +7,7 @@ #include "prune/scene/game_object.hpp" #include "prune/scene/game_object_manager.hpp" #include "prune/scene/scene.hpp" +#include "prune/tooling/editor/tracked_property_table.hpp" namespace prune { @@ -26,17 +27,8 @@ namespace prune { void draw_flags(Scene& scene, GameObjectManager& objects); void sync_rename_buffer(const GameObject* selected); - void capture_object_edit_start(const GameObject& before); - void commit_object_edit(Scene& scene, EditorCommandType type, const GameObject& after); - - [[nodiscard]] static bool command_object_changed( - EditorCommandType type, - const GameObject& before, - const GameObject& after - ) noexcept; - std::optional m_rename_target_id; - std::optional m_pending_object_edit; + tooling::editor::tracked_property_table::ObjectEditTracker m_object_edit_tracker; std::array m_rename_buffer{}; }; } \ No newline at end of file From 32081b0be55dbd9137ba5561c5a9301d4bd0f510 Mon Sep 17 00:00:00 2001 From: Dean Blackborough Date: Sun, 7 Jun 2026 15:46:29 +0100 Subject: [PATCH 2/2] Add detail text for command history --- src/prune/editor/editor_command.cpp | 30 ++++++++---- src/prune/editor/editor_command.hpp | 23 +++++++--- src/prune/scene/scene_interaction.cpp | 9 ++-- src/prune/scene/world_scene.cpp | 2 +- src/prune/tooling/command_history.cpp | 28 +++++++---- .../tooling/editor/tracked_property_table.cpp | 36 +++++++++------ .../tooling/editor/tracked_property_table.hpp | 26 ++++++++--- src/prune/tooling/inspector.cpp | 46 +++++++++++++------ 8 files changed, 137 insertions(+), 63 deletions(-) diff --git a/src/prune/editor/editor_command.cpp b/src/prune/editor/editor_command.cpp index c8605e1..8418b31 100644 --- a/src/prune/editor/editor_command.cpp +++ b/src/prune/editor/editor_command.cpp @@ -110,13 +110,15 @@ namespace prune { EditorCommand make_object_command( EditorCommandType type, - std::string label, + std::string_view label, const GameObject& before, - const GameObject& after + const GameObject& after, + std::string_view detail ) { EditorCommand command{}; command.type = type; - command.label = std::move(label); + command.label = std::string(label); + command.detail = std::string(detail); command.object_id = after.identity.id; command.before_object = before; command.after_object = after; @@ -124,22 +126,28 @@ namespace prune { return command; } - EditorCommand make_create_object_command(const GameObject& created) - { + EditorCommand make_create_object_command( + const GameObject& created, + std::string_view detail + ) { EditorCommand command{}; command.type = EditorCommandType::CreateObject; command.label = editor_command_type_label(EditorCommandType::CreateObject); + command.detail = std::string(detail); command.object_id = created.identity.id; command.after_object = created; return command; } - EditorCommand make_delete_object_command(const GameObject& deleted) - { + EditorCommand make_delete_object_command( + const GameObject& deleted, + std::string_view detail + ) { EditorCommand command{}; command.type = EditorCommandType::DeleteObject; command.label = editor_command_type_label(EditorCommandType::DeleteObject); + command.detail = std::string(detail); command.object_id = deleted.identity.id; command.before_object = deleted; @@ -147,13 +155,15 @@ namespace prune { } EditorCommand make_viewport_command( - std::string label, + std::string_view label, const Camera& before, - const Camera& after + const Camera& after, + std::string_view detail ) { EditorCommand command{}; command.type = EditorCommandType::MoveViewport; - command.label = std::move(label); + command.label = std::string(label); + command.detail = std::string(detail); command.before_camera = before; command.after_camera = after; diff --git a/src/prune/editor/editor_command.hpp b/src/prune/editor/editor_command.hpp index 902cb7f..92232af 100644 --- a/src/prune/editor/editor_command.hpp +++ b/src/prune/editor/editor_command.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "prune/scene/game_object.hpp" @@ -27,6 +28,7 @@ namespace prune { struct EditorCommand { EditorCommandType type = EditorCommandType::MoveObject; std::string label; + std::string detail; GameObjectId object_id = k_invalid_game_object_id; std::optional before_object; @@ -62,18 +64,27 @@ namespace prune { [[nodiscard]] EditorCommand make_object_command( EditorCommandType type, - std::string label, + std::string_view label, const GameObject& before, - const GameObject& after + const GameObject& after, + std::string_view detail = {} ); - [[nodiscard]] EditorCommand make_create_object_command(const GameObject& created); - [[nodiscard]] EditorCommand make_delete_object_command(const GameObject& deleted); + [[nodiscard]] EditorCommand make_create_object_command( + const GameObject& created, + std::string_view detail = {} + ); + + [[nodiscard]] EditorCommand make_delete_object_command( + const GameObject& deleted, + std::string_view detail = {} + ); [[nodiscard]] EditorCommand make_viewport_command( - std::string label, + std::string_view label, const Camera& before, - const Camera& after + const Camera& after, + std::string_view detail = {} ); } diff --git a/src/prune/scene/scene_interaction.cpp b/src/prune/scene/scene_interaction.cpp index 7b08934..d6a3a27 100644 --- a/src/prune/scene/scene_interaction.cpp +++ b/src/prune/scene/scene_interaction.cpp @@ -54,7 +54,8 @@ namespace prune { scene.record_editor_command(make_viewport_command( editor_command_type_label(EditorCommandType::MoveViewport), m_viewport_pan_start, - after + after, + "Mouse pan" )); } @@ -110,7 +111,8 @@ namespace prune { EditorCommandType::MoveObject, editor_command_type_label(EditorCommandType::MoveObject), before, - *object + *object, + "Mouse drag" )); } } @@ -233,7 +235,8 @@ namespace prune { EditorCommandType::MoveObject, editor_command_type_label(EditorCommandType::MoveObject), before, - *selected + *selected, + "Keyboard nudge" )); } } diff --git a/src/prune/scene/world_scene.cpp b/src/prune/scene/world_scene.cpp index 7ac969c..b4e6ca7 100644 --- a/src/prune/scene/world_scene.cpp +++ b/src/prune/scene/world_scene.cpp @@ -97,7 +97,7 @@ namespace prune { if (ImGui::Button(action.label.data())) { const GameObjectId created_id = create_scene_object(action.id); if (const GameObject* created = m_state.objects.get_by_id(created_id)) { - record_editor_command(make_create_object_command(*created)); + record_editor_command(make_create_object_command(*created, action.label)); } } ImGui::PopID(); diff --git a/src/prune/tooling/command_history.cpp b/src/prune/tooling/command_history.cpp index 850ec25..152c561 100644 --- a/src/prune/tooling/command_history.cpp +++ b/src/prune/tooling/command_history.cpp @@ -48,14 +48,26 @@ namespace prune { ImGui::BeginDisabled(); } - ImGui::Text( - "%s%zu. %s", - applied ? "" : "redo: ", - command_index + 1, - command.label.empty() - ? editor_command_type_label(command.type) - : command.label.c_str() - ); + const char* label = command.label.empty() + ? editor_command_type_label(command.type) + : command.label.c_str(); + + if (command.detail.empty()) { + ImGui::Text( + "%s%zu. %s", + applied ? "" : "redo: ", + command_index + 1, + label + ); + } else { + ImGui::Text( + "%s%zu. %s: %s", + applied ? "" : "redo: ", + command_index + 1, + label, + command.detail.c_str() + ); + } if (command.object_id != k_invalid_game_object_id) { ImGui::SameLine(); diff --git a/src/prune/tooling/editor/tracked_property_table.cpp b/src/prune/tooling/editor/tracked_property_table.cpp index c6f2967..fbbea19 100644 --- a/src/prune/tooling/editor/tracked_property_table.cpp +++ b/src/prune/tooling/editor/tracked_property_table.cpp @@ -63,7 +63,8 @@ namespace prune::tooling::editor::tracked_property_table { void ObjectEditTracker::commit_if_deactivated_after_edit( Scene& scene, EditorCommandType type, - const GameObject& after + const GameObject& after, + std::string_view detail ) { if (!ImGui::IsItemDeactivatedAfterEdit()) { return; @@ -76,7 +77,7 @@ namespace prune::tooling::editor::tracked_property_table { const GameObject before = m_before.value(); m_before.reset(); - commit_if_changed(scene, type, before, after); + commit_if_changed(scene, type, before, after, detail); } void ObjectEditTracker::reset() noexcept @@ -95,13 +96,14 @@ namespace prune::tooling::editor::tracked_property_table { float speed, float min, float max, - const char* format + const char* format, + std::string_view detail ) { const GameObject before = object; const bool changed = ::prune::tooling::imgui::property_table::drag_float(label, id, value, speed, min, max, format); tracker.capture_if_activated(before); - tracker.commit_if_deactivated_after_edit(scene, type, object); + tracker.commit_if_deactivated_after_edit(scene, type, object, detail); return changed; } @@ -115,13 +117,14 @@ namespace prune::tooling::editor::tracked_property_table { const char* id, int& value, int min, - int max + int max, + std::string_view detail ) { const GameObject before = object; const bool changed = ::prune::tooling::imgui::property_table::slider_int(label, id, value, min, max); tracker.capture_if_activated(before); - tracker.commit_if_deactivated_after_edit(scene, type, object); + tracker.commit_if_deactivated_after_edit(scene, type, object, detail); return changed; } @@ -133,13 +136,14 @@ namespace prune::tooling::editor::tracked_property_table { GameObject& object, const char* label, const char* id, - float color[3] + float color[3], + std::string_view detail ) { const GameObject before = object; const bool changed = ::prune::tooling::imgui::property_table::color3(label, id, color); tracker.capture_if_activated(before); - tracker.commit_if_deactivated_after_edit(scene, type, object); + tracker.commit_if_deactivated_after_edit(scene, type, object, detail); return changed; } @@ -150,7 +154,8 @@ namespace prune::tooling::editor::tracked_property_table { GameObject& object, const char* label, const char* id, - bool& value + bool& value, + std::string_view detail ) { const GameObject before = object; @@ -158,7 +163,7 @@ namespace prune::tooling::editor::tracked_property_table { return false; } - commit_if_changed(scene, type, before, object); + commit_if_changed(scene, type, before, object, detail); return true; } @@ -168,7 +173,8 @@ namespace prune::tooling::editor::tracked_property_table { GameObject& object, const char* label, const char* id, - std::string& sprite_key + std::string& sprite_key, + std::string_view detail ) { const GameObject before = object; @@ -176,7 +182,7 @@ namespace prune::tooling::editor::tracked_property_table { return false; } - commit_if_changed(scene, type, before, object); + commit_if_changed(scene, type, before, object, detail); return true; } @@ -184,7 +190,8 @@ namespace prune::tooling::editor::tracked_property_table { Scene& scene, EditorCommandType type, const GameObject& before, - const GameObject& after + const GameObject& after, + std::string_view detail ) { if (before.identity.id != after.identity.id || !command_object_changed(type, before, after)) { return false; @@ -194,7 +201,8 @@ namespace prune::tooling::editor::tracked_property_table { type, editor_command_type_label(type), before, - after + after, + detail )); return true; diff --git a/src/prune/tooling/editor/tracked_property_table.hpp b/src/prune/tooling/editor/tracked_property_table.hpp index 6465763..a395d29 100644 --- a/src/prune/tooling/editor/tracked_property_table.hpp +++ b/src/prune/tooling/editor/tracked_property_table.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "prune/editor/editor_command.hpp" #include "prune/scene/game_object.hpp" @@ -15,7 +16,12 @@ namespace prune::tooling::editor::tracked_property_table { class ObjectEditTracker { public: void capture_if_activated(const GameObject& before); - void commit_if_deactivated_after_edit(Scene& scene, EditorCommandType type, const GameObject& after); + void commit_if_deactivated_after_edit( + Scene& scene, + EditorCommandType type, + const GameObject& after, + std::string_view detail = {} + ); void reset() noexcept; private: @@ -33,7 +39,8 @@ namespace prune::tooling::editor::tracked_property_table { float speed = 1.0f, float min = 0.0f, float max = 0.0f, - const char* format = "%.3f" + const char* format = "%.3f", + std::string_view detail = {} ); bool slider_int( @@ -45,7 +52,8 @@ namespace prune::tooling::editor::tracked_property_table { const char* id, int& value, int min, - int max + int max, + std::string_view detail = {} ); bool color3( @@ -55,7 +63,8 @@ namespace prune::tooling::editor::tracked_property_table { GameObject& object, const char* label, const char* id, - float color[3] + float color[3], + std::string_view detail = {} ); bool checkbox( @@ -64,7 +73,8 @@ namespace prune::tooling::editor::tracked_property_table { GameObject& object, const char* label, const char* id, - bool& value + bool& value, + std::string_view detail = {} ); bool sprite_picker( @@ -73,14 +83,16 @@ namespace prune::tooling::editor::tracked_property_table { GameObject& object, const char* label, const char* id, - std::string& sprite_key + std::string& sprite_key, + std::string_view detail = {} ); bool commit_if_changed( Scene& scene, EditorCommandType type, const GameObject& before, - const GameObject& after + const GameObject& after, + std::string_view detail = {} ); } diff --git a/src/prune/tooling/inspector.cpp b/src/prune/tooling/inspector.cpp index c395332..1069eb1 100644 --- a/src/prune/tooling/inspector.cpp +++ b/src/prune/tooling/inspector.cpp @@ -68,7 +68,8 @@ namespace prune { EditorCommandType::RenameObject, editor_command_type_label(EditorCommandType::RenameObject), before, - *selected + *selected, + selected->identity.name )); } @@ -91,7 +92,7 @@ namespace prune { const GameObject deleted = *selected; const GameObjectId id_to_remove = selected->identity.id; if (objects.remove_object(id_to_remove)) { - scene.record_editor_command(make_delete_object_command(deleted)); + scene.record_editor_command(make_delete_object_command(deleted, deleted.identity.name)); } tooling::imgui::property_table::end(); @@ -118,7 +119,7 @@ namespace prune { if (GameObject* created = objects.get_by_id(clone_id)) { created->identity.name = objects.make_unique_name(source_name, clone_id); - scene.record_editor_command(make_create_object_command(*created)); + scene.record_editor_command(make_create_object_command(*created, created->identity.name)); } objects.select(clone_id); @@ -209,7 +210,11 @@ namespace prune { "X", "transform_x", selected->transform.x, - 1.0f + 1.0f, + 0.0f, + 0.0f, + "%.3f", + "X" ); tooling::editor::tracked_property_table::drag_float( @@ -220,7 +225,11 @@ namespace prune { "Y", "transform_y", selected->transform.y, - 1.0f + 1.0f, + 0.0f, + 0.0f, + "%.3f", + "Y" ); ImGui::EndDisabled(); @@ -241,7 +250,8 @@ namespace prune { "##width", selected->size.width, k_min_object_size, - k_max_object_size + k_max_object_size, + "Width" ); tooling::editor::tracked_property_table::slider_int( @@ -253,7 +263,8 @@ namespace prune { "##height", selected->size.height, k_min_object_size, - k_max_object_size + k_max_object_size, + "Height" ); ImGui::EndDisabled(); @@ -283,7 +294,8 @@ namespace prune { scene, EditorCommandType::ChangeObjectRenderType, before, - *selected + *selected, + (selected->render.type == RenderType::Rectangle) ? "Rectangle" : "Sprite" ); } @@ -297,7 +309,8 @@ namespace prune { *selected, "Colour", "##colour", - selected->render.rectangle.color + selected->render.rectangle.color, + "Rectangle colour" ); } break; @@ -310,7 +323,8 @@ namespace prune { *selected, "Sprite", "##sprite_key", - selected->render.sprite.sprite_key + selected->render.sprite.sprite_key, + "Sprite key" ); } { @@ -320,7 +334,8 @@ namespace prune { *selected, "Flip X", "##sprite_flip_x", - selected->render.sprite.flip_x + selected->render.sprite.flip_x, + "Flip X" ); } break; @@ -382,7 +397,8 @@ namespace prune { *selected, "Lifecycle Active", "##active", - selected->lifecycle.active + selected->lifecycle.active, + "Lifecycle Active" ); } @@ -393,7 +409,8 @@ namespace prune { *selected, "Render Visible", "##visible", - selected->render.visible + selected->render.visible, + "Render Visible" ); } @@ -404,7 +421,8 @@ namespace prune { *selected, "Collision Solid", "##solid", - selected->collision.solid + selected->collision.solid, + "Collision Solid" ); } ImGui::EndDisabled();