Add persistent shared editor tree interactions

This commit is contained in:
2026-03-27 23:21:43 +08:00
parent 0c8a3e90ec
commit 291d1a7e41
6 changed files with 240 additions and 40 deletions

View File

@@ -10,6 +10,25 @@
#include "UI/UI.h"
#include <imgui.h>
namespace {
void DrawHierarchyTreePrefix(const XCEngine::Editor::UI::TreeNodePrefixContext& context) {
if (!context.drawList) {
return;
}
const ImVec4 color = XCEngine::Editor::UI::NavigationTreePrefixColor(context.selected, context.hovered);
const float size = 9.0f;
const float centerX = context.min.x + (context.max.x - context.min.x) * 0.5f;
const float centerY = context.min.y + (context.max.y - context.min.y) * 0.5f;
const ImVec2 min(centerX - size * 0.5f, centerY - size * 0.5f);
const ImVec2 max(centerX + size * 0.5f, centerY + size * 0.5f);
context.drawList->AddRect(min, max, ImGui::GetColorU32(color), 1.5f);
context.drawList->AddLine(ImVec2(min.x, centerY), ImVec2(max.x, centerY), ImGui::GetColorU32(color), 1.0f);
}
} // namespace
namespace XCEngine {
namespace Editor {
@@ -122,27 +141,33 @@ void HierarchyPanel::RenderEntity(::XCEngine::Components::GameObject* gameObject
CommitRename();
}
} else {
UI::TreeNodeOptions nodeOptions;
nodeOptions.selected = m_context->GetSelectionManager().IsSelected(gameObject->GetID());
nodeOptions.leaf = gameObject->GetChildCount() == 0;
UI::TreeNodeDefinition nodeDefinition;
nodeDefinition.options.selected = m_context->GetSelectionManager().IsSelected(gameObject->GetID());
nodeDefinition.options.leaf = gameObject->GetChildCount() == 0;
const std::string persistenceKey = std::to_string(gameObject->GetUUID());
nodeDefinition.persistenceKey = persistenceKey;
nodeDefinition.prefix.width = UI::NavigationTreePrefixWidth();
nodeDefinition.prefix.draw = DrawHierarchyTreePrefix;
nodeDefinition.callbacks.onInteraction = [this, gameObject](const UI::TreeNodeResult& node) {
if (node.clicked) {
Actions::HandleHierarchySelectionClick(*m_context, gameObject->GetID(), ImGui::GetIO().KeyCtrl);
}
if (node.doubleClicked) {
BeginRename(gameObject);
}
};
nodeDefinition.callbacks.onRenderExtras = [this, gameObject]() {
Actions::BeginHierarchyEntityDrag(gameObject);
Actions::AcceptHierarchyEntityDrop(*m_context, gameObject);
Actions::DrawHierarchyEntityContextPopup(*m_context, gameObject);
};
const UI::TreeNodeResult node = UI::DrawTreeNode(
&m_treeState,
(void*)gameObject->GetUUID(),
gameObject->GetName().c_str(),
nodeOptions);
if (node.clicked) {
Actions::HandleHierarchySelectionClick(*m_context, gameObject->GetID(), ImGui::GetIO().KeyCtrl);
}
if (node.doubleClicked) {
BeginRename(gameObject);
}
Actions::BeginHierarchyEntityDrag(gameObject);
Actions::AcceptHierarchyEntityDrop(*m_context, gameObject);
Actions::DrawHierarchyEntityContextPopup(*m_context, gameObject);
nodeDefinition);
if (node.open) {
for (size_t i = 0; i < gameObject->GetChildCount(); i++) {