From df9f07e96fe26da0457e045e6ac0b48503bc8b51 Mon Sep 17 00:00:00 2001 From: Shuyan Hu Date: Wed, 26 Mar 2025 00:22:38 +0800 Subject: [PATCH 1/3] GObject can set active/inactive state in editor panel --- engine/3rdparty/imgui/imgui.cpp | 10 ++--- engine/3rdparty/imgui/imgui.h | 2 +- engine/3rdparty/imgui/imgui_internal.h | 4 +- engine/3rdparty/imgui/imgui_widgets.cpp | 4 +- engine/asset/level/1-1.level.json | 31 +++++++++++++ engine/source/editor/source/editor_ui.cpp | 26 ++++++++++- .../function/framework/object/object.cpp | 45 ++++++++++++++++++- .../function/framework/object/object.h | 11 +++++ .../runtime/function/render/render_scene.cpp | 1 + .../runtime/resource/res_type/common/object.h | 1 + 10 files changed, 122 insertions(+), 13 deletions(-) diff --git a/engine/3rdparty/imgui/imgui.cpp b/engine/3rdparty/imgui/imgui.cpp index ce2c9dd38..d60ccf706 100644 --- a/engine/3rdparty/imgui/imgui.cpp +++ b/engine/3rdparty/imgui/imgui.cpp @@ -3035,7 +3035,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end // Default clip_rect uses (pos_min,pos_max) // Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges) -void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) +void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect, const ImGuiCol_ gui_col) { // Perform CPU side clipping for single clipped element to avoid using scissor state ImVec2 pos = pos_min; @@ -3055,15 +3055,15 @@ void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, co if (need_clipping) { ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y); - draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect); + draw_list->AddText(NULL, 0.0f, pos, GetColorU32(gui_col), text, text_display_end, 0.0f, &fine_clip_rect); } else { - draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL); + draw_list->AddText(NULL, 0.0f, pos, GetColorU32(gui_col), text, text_display_end, 0.0f, NULL); } } -void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) +void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect, const ImGuiCol_ gui_col) { // Hide anything after a '##' string const char* text_display_end = FindRenderedTextEnd(text, text_end); @@ -3073,7 +3073,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect); + RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect, gui_col); if (g.LogEnabled) LogRenderedText(&pos_min, text, text_display_end); } diff --git a/engine/3rdparty/imgui/imgui.h b/engine/3rdparty/imgui/imgui.h index 97ee1dcbe..8a9697736 100644 --- a/engine/3rdparty/imgui/imgui.h +++ b/engine/3rdparty/imgui/imgui.h @@ -618,7 +618,7 @@ namespace ImGui // Widgets: Selectables // - A selectable highlights when hovered, and can display another color when selected. // - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous. - IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height + IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0), const bool is_disable = false); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. // Widgets: List Boxes diff --git a/engine/3rdparty/imgui/imgui_internal.h b/engine/3rdparty/imgui/imgui_internal.h index 9a5c7d9bc..d04105774 100644 --- a/engine/3rdparty/imgui/imgui_internal.h +++ b/engine/3rdparty/imgui/imgui_internal.h @@ -3028,8 +3028,8 @@ namespace ImGui // NB: All position are in absolute pixels coordinates (we are never using window coordinates internally) IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); - IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); - IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); + IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL, const ImGuiCol_ gui_col = ImGuiCol_Text); + IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL, const ImGuiCol_ gui_col = ImGuiCol_Text); IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); diff --git a/engine/3rdparty/imgui/imgui_widgets.cpp b/engine/3rdparty/imgui/imgui_widgets.cpp index c0593bd9e..a475faf82 100644 --- a/engine/3rdparty/imgui/imgui_widgets.cpp +++ b/engine/3rdparty/imgui/imgui_widgets.cpp @@ -6200,7 +6200,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFl // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id. // With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowItemOverlap are also frequently used flags. // FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported. -bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) +bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg, const bool is_disable) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6332,7 +6332,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl else if (span_all_columns && g.CurrentTable) TablePopBackgroundChannel(); - RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); + RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb, is_disable ? ImGuiCol_TextDisabled : ImGuiCol_Text); // Automatically close popups if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.LastItemData.InFlags & ImGuiItemFlags_SelectableDontClosePopup)) diff --git a/engine/asset/level/1-1.level.json b/engine/asset/level/1-1.level.json index 8e7bbb5d9..489f98de2 100644 --- a/engine/asset/level/1-1.level.json +++ b/engine/asset/level/1-1.level.json @@ -33,6 +33,7 @@ } } ], + "active": true, "definition": "asset/objects/environment/particle/particle.object.json" }, { @@ -62,6 +63,7 @@ } } ], + "active": true, "definition": "asset/objects/character/player/player.object.json" }, { @@ -91,6 +93,7 @@ "$typeName": "TransformComponent" } ], + "active": true, "definition": "asset/objects/environment/wall/wall.object.json" }, { @@ -120,6 +123,7 @@ "$typeName": "TransformComponent" } ], + "active": true, "definition": "asset/objects/environment/wall/wall.object.json" }, { @@ -149,10 +153,12 @@ "$typeName": "TransformComponent" } ], + "active": true, "definition": "asset/objects/environment/wall/wall.object.json" }, { "name": "Wall_4", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -182,6 +188,7 @@ }, { "name": "Wall_5", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -211,6 +218,7 @@ }, { "name": "Wall_6", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -240,6 +248,7 @@ }, { "name": "Wall_7", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -269,6 +278,7 @@ }, { "name": "Wall_8", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -298,6 +308,7 @@ }, { "name": "Wall_9", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -327,6 +338,7 @@ }, { "name": "Wall_10", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -356,6 +368,7 @@ }, { "name": "Wall_11", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -385,6 +398,7 @@ }, { "name": "Wall_12", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -414,6 +428,7 @@ }, { "name": "Wall_13", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -443,6 +458,7 @@ }, { "name": "Wall_14", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -472,6 +488,7 @@ }, { "name": "Wall_15", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -501,6 +518,7 @@ }, { "name": "Wall_16", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -530,6 +548,7 @@ }, { "name": "Wall_17", + "active": true, "definition": "asset/objects/environment/wall/wall.object.json", "instanced_components": [ { @@ -559,6 +578,7 @@ }, { "name": "WallWithDoor_1", + "active": true, "definition": "asset/objects/environment/wall/wall_with_door.object.json", "instanced_components": [ { @@ -588,6 +608,7 @@ }, { "name": "WallWithDoor_2", + "active": true, "definition": "asset/objects/environment/wall/wall_with_door.object.json", "instanced_components": [ { @@ -617,6 +638,7 @@ }, { "name": "WallWithDoor_3", + "active": true, "definition": "asset/objects/environment/wall/wall_with_door.object.json", "instanced_components": [ { @@ -646,6 +668,7 @@ }, { "name": "WallWithDoor_4", + "active": true, "definition": "asset/objects/environment/wall/wall_with_door.object.json", "instanced_components": [ { @@ -675,6 +698,7 @@ }, { "name": "WallWithDoor_5", + "active": true, "definition": "asset/objects/environment/wall/wall_with_door.object.json", "instanced_components": [ { @@ -704,6 +728,7 @@ }, { "name": "WallWithWindow_1", + "active": true, "definition": "asset/objects/environment/wall/wall_with_window.object.json", "instanced_components": [ { @@ -733,6 +758,7 @@ }, { "name": "WallWithWindow_2", + "active": true, "definition": "asset/objects/environment/wall/wall_with_window.object.json", "instanced_components": [ { @@ -762,6 +788,7 @@ }, { "name": "WallBlock_1", + "active": true, "definition": "asset/objects/environment/wall/wall_block.object.json", "instanced_components": [ { @@ -791,6 +818,7 @@ }, { "name": "WallBlock_2", + "active": true, "definition": "asset/objects/environment/wall/wall_block.object.json", "instanced_components": [ { @@ -820,6 +848,7 @@ }, { "name": "Stairs", + "active": true, "definition": "asset/objects/environment/stairs/stairs.object.json", "instanced_components": [ { @@ -849,6 +878,7 @@ }, { "name": "Ground", + "active": true, "definition": "asset/objects/environment/floor/floor.object.json", "instanced_components": [ { @@ -886,6 +916,7 @@ "z": 0 } }, + "active": true, "definition": "asset/objects/environment/fence/fence.object.json", "instanced_components": [ { diff --git a/engine/source/editor/source/editor_ui.cpp b/engine/source/editor/source/editor_ui.cpp index 3d4185075..3bbce8258 100644 --- a/engine/source/editor/source/editor_ui.cpp +++ b/engine/source/editor/source/editor_ui.cpp @@ -416,10 +416,12 @@ namespace Piccolo const GObjectID object_id = id_object_pair.first; std::shared_ptr object = id_object_pair.second; const std::string name = object->getName(); + const bool is_active = object->isActive(); if (name.size() > 0) { if (ImGui::Selectable(name.c_str(), - g_editor_global_context.m_scene_manager->getSelectedObjectID() == object_id)) + g_editor_global_context.m_scene_manager->getSelectedObjectID() == object_id, + 0, ImVec2(0, 0), !is_active)) { if (g_editor_global_context.m_scene_manager->getSelectedObjectID() != object_id) { @@ -557,6 +559,26 @@ namespace Piccolo ImGui::SameLine(); ImGui::InputText("##Name", cname, IM_ARRAYSIZE(cname), ImGuiInputTextFlags_ReadOnly); + // active state + bool is_active = selected_object->isActive(); + if (is_active) + { + if (ImGui::Button("Active")) + { + is_active = !is_active; + selected_object->setActive(is_active); + } + } + else + { + if (ImGui::Button("Inactive")) + { + is_active = !is_active; + selected_object->setActive(is_active); + } + } + + static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings; auto&& selected_object_components = selected_object->getComponents(); for (auto component_ptr : selected_object_components) @@ -919,7 +941,7 @@ namespace Piccolo ImVec4* colors = style->Colors; colors[ImGuiCol_Text] = ImVec4(0.4745f, 0.4745f, 0.4745f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.20f, 0.20f, 0.20f, 1.00f); colors[ImGuiCol_WindowBg] = ImVec4(0.0078f, 0.0078f, 0.0078f, 1.00f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); diff --git a/engine/source/runtime/function/framework/object/object.cpp b/engine/source/runtime/function/framework/object/object.cpp index 5380fc76a..00a35e9a9 100644 --- a/engine/source/runtime/function/framework/object/object.cpp +++ b/engine/source/runtime/function/framework/object/object.cpp @@ -13,6 +13,8 @@ #include #include +#include "editor/include/editor_global_context.h" +#include "function/render/render_system.h" #include "_generated/serializer/all_serializer.h" namespace Piccolo @@ -40,6 +42,11 @@ namespace Piccolo void GObject::tick(float delta_time) { + if (!isActive()) + { + return; + } + for (auto& component : m_components) { if (shouldComponentTick(component.getTypeName())) @@ -67,6 +74,8 @@ namespace Piccolo setName(object_instance_res.m_name); + m_active = object_instance_res.m_active; + // load object instanced components m_components = object_instance_res.m_instanced_components; for (auto component : m_components) @@ -107,6 +116,40 @@ namespace Piccolo out_object_instance_res.m_definition = m_definition_url; out_object_instance_res.m_instanced_components = m_components; + out_object_instance_res.m_active = m_active; } -} // namespace Piccolo \ No newline at end of file + // enable state + void GObject::setActive(bool active) + { + if (m_active != active) + { + m_active = active; + onActiveStateChange(); + } + } + + void GObject::onActiveStateChange() + { + if (isActive()) + { + onActive(); + } + else + { + onInactive(); + } + } + + void GObject::onActive() + { + TransformComponent* transform_component = tryGetComponent(TransformComponent); + transform_component->setDirtyFlag(true); // update render scene + } + + void GObject::onInactive() const + { + RenderSwapContext& swap_context = g_editor_global_context.m_render_system->getSwapContext(); + swap_context.getLogicSwapData().addDeleteGameObject(GameObjectDesc {getID(), {}}); + } +} // namespace Piccolo diff --git a/engine/source/runtime/function/framework/object/object.h b/engine/source/runtime/function/framework/object/object.h index 6d7571918..f735f7cc5 100644 --- a/engine/source/runtime/function/framework/object/object.h +++ b/engine/source/runtime/function/framework/object/object.h @@ -26,6 +26,10 @@ namespace Piccolo bool load(const ObjectInstanceRes& object_instance_res); void save(ObjectInstanceRes& out_object_instance_res); + // enable state + void setActive(bool active); + bool isActive() const { return m_active; } + GObjectID getID() const { return m_id; } void setName(std::string name) { m_name = name; } @@ -69,9 +73,16 @@ namespace Piccolo GObjectID m_id {k_invalid_gobject_id}; std::string m_name; std::string m_definition_url; + bool m_active {true}; // we have to use the ReflectionPtr due to that the components need to be reflected // in editor, and it's polymorphism std::vector> m_components; + + private: + void onActiveStateChange(); + void onActive(); + void onInactive() const; + }; } // namespace Piccolo diff --git a/engine/source/runtime/function/render/render_scene.cpp b/engine/source/runtime/function/render/render_scene.cpp index e8bd4965d..0688688f2 100644 --- a/engine/source/runtime/function/render/render_scene.cpp +++ b/engine/source/runtime/function/render/render_scene.cpp @@ -71,6 +71,7 @@ namespace Piccolo if (it->m_instance_id == find_guid) { m_render_entities.erase(it); + m_instance_id_allocator.freeGuid(find_guid); break; } } diff --git a/engine/source/runtime/resource/res_type/common/object.h b/engine/source/runtime/resource/res_type/common/object.h index 6ed3fee91..6e3054078 100644 --- a/engine/source/runtime/resource/res_type/common/object.h +++ b/engine/source/runtime/resource/res_type/common/object.h @@ -36,6 +36,7 @@ namespace Piccolo public: std::string m_name; std::string m_definition; + bool m_active; std::vector> m_instanced_components; }; From 115c901da2f8813923c574d5f3ef696dcf2a2532 Mon Sep 17 00:00:00 2001 From: Shuyan Hu Date: Wed, 26 Mar 2025 20:43:10 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine/3rdparty/JoltPhysics/Jolt/Core/Core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/3rdparty/JoltPhysics/Jolt/Core/Core.h b/engine/3rdparty/JoltPhysics/Jolt/Core/Core.h index 0821bad61..232e3df28 100644 --- a/engine/3rdparty/JoltPhysics/Jolt/Core/Core.h +++ b/engine/3rdparty/JoltPhysics/Jolt/Core/Core.h @@ -217,6 +217,7 @@ JPH_SUPPRESS_WARNINGS_STD_BEGIN #include #include #include +#include JPH_SUPPRESS_WARNINGS_STD_END #if defined(JPH_USE_SSE) #include From 8427cc2d0007521f35e960b0fdfbe1295053d8b6 Mon Sep 17 00:00:00 2001 From: Shuyan Hu Date: Wed, 26 Mar 2025 21:01:18 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine/3rdparty/vulkanmemoryallocator/include/vk_mem_alloc.h | 1 + engine/source/runtime/core/meta/reflection/reflection.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/engine/3rdparty/vulkanmemoryallocator/include/vk_mem_alloc.h b/engine/3rdparty/vulkanmemoryallocator/include/vk_mem_alloc.h index 0a4e59ac2..a5b668ebd 100644 --- a/engine/3rdparty/vulkanmemoryallocator/include/vk_mem_alloc.h +++ b/engine/3rdparty/vulkanmemoryallocator/include/vk_mem_alloc.h @@ -2566,6 +2566,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString( #undef VMA_IMPLEMENTATION #include +#include #include #include #include diff --git a/engine/source/runtime/core/meta/reflection/reflection.cpp b/engine/source/runtime/core/meta/reflection/reflection.cpp index 43193f0f3..cfff8474f 100644 --- a/engine/source/runtime/core/meta/reflection/reflection.cpp +++ b/engine/source/runtime/core/meta/reflection/reflection.cpp @@ -1,4 +1,5 @@ #include "reflection.h" +#include #include #include