Refactor new editor scene runtime ownership

This commit is contained in:
2026-04-18 00:45:14 +08:00
parent 2fe1076218
commit b48760ca3d
12 changed files with 792 additions and 326 deletions

View File

@@ -1,10 +1,16 @@
#include "HierarchyPanelInternal.h"
#include "Scene/EditorSceneRuntime.h"
#include <XCEditor/Fields/UIEditorFieldStyle.h>
#include <XCEditor/Fields/UIEditorTextField.h>
#include <utility>
namespace XCEngine::UI::Editor::App {
using namespace HierarchyPanelInternal;
namespace TreeDrag = TreeItemDragDrop;
namespace {
@@ -26,11 +32,23 @@ UIEditorHostCommandDispatchResult BuildDispatchResult(
return result;
}
bool HasValidBounds(const UIRect& bounds) {
return bounds.width > 0.0f && bounds.height > 0.0f;
}
} // namespace
void HierarchyPanel::Initialize() {
m_model = HierarchyModel::BuildDefault();
RebuildItems();
SyncModelFromScene();
}
void HierarchyPanel::SetSceneRuntime(EditorSceneRuntime* sceneRuntime) {
if (m_sceneRuntime == sceneRuntime) {
return;
}
m_sceneRuntime = sceneRuntime;
SyncModelFromScene();
}
void HierarchyPanel::SetBuiltInIcons(const BuiltInIcons* icons) {
@@ -42,6 +60,7 @@ void HierarchyPanel::ResetInteractionState() {
m_treeInteractionState = {};
m_treeFrame = {};
m_dragState = {};
ClearRenameState();
ResetTransientState();
}
@@ -58,39 +77,89 @@ const UIEditorPanelContentHostPanelState* HierarchyPanel::FindMountedHierarchyPa
void HierarchyPanel::ResetTransientState() {
m_frameEvents.clear();
m_dragState.requestPointerCapture = false;
m_dragState.requestPointerRelease = false;
TreeDrag::ResetTransientRequests(m_dragState);
}
void HierarchyPanel::SyncModelFromScene() {
if (m_sceneRuntime != nullptr) {
m_sceneRuntime->RefreshScene();
}
const HierarchyModel sceneModel =
HierarchyModel::BuildFromScene(
m_sceneRuntime != nullptr
? m_sceneRuntime->GetActiveScene()
: nullptr);
if (!m_model.HasSameTree(sceneModel) || m_treeItems.empty()) {
m_model = sceneModel;
if (m_sceneRuntime != nullptr && !m_model.Empty()) {
m_sceneRuntime->EnsureSceneSelection();
}
RebuildItems();
return;
}
if (m_sceneRuntime != nullptr && !m_model.Empty()) {
m_sceneRuntime->EnsureSceneSelection();
}
SyncTreeSelectionFromSceneRuntime();
}
void HierarchyPanel::RebuildItems() {
const auto icon = ResolveGameObjectIcon(m_icons);
const std::string previousSelection =
m_selection.HasSelection() ? m_selection.GetSelectedId() : std::string();
m_treeItems = m_model.BuildTreeItems(icon);
m_expansion.Expand("player");
m_expansion.Expand("environment");
m_expansion.Expand("props");
SyncTreeSelectionFromSceneRuntime();
}
if (!previousSelection.empty() && m_model.ContainsNode(previousSelection)) {
m_selection.SetSelection(previousSelection);
void HierarchyPanel::SyncTreeSelectionFromSceneRuntime() {
if (m_sceneRuntime == nullptr) {
m_treeSelection.ClearSelection();
return;
}
if (!m_treeItems.empty()) {
m_selection.SetSelection(m_treeItems.front().itemId);
const std::string selectedItemId = m_sceneRuntime->GetSelectedItemId();
if (!selectedItemId.empty() && m_model.ContainsNode(selectedItemId)) {
m_treeSelection.SetSelection(selectedItemId);
return;
}
m_selection.ClearSelection();
m_treeSelection.ClearSelection();
}
void HierarchyPanel::SyncSceneRuntimeSelectionFromTree() {
if (m_sceneRuntime == nullptr) {
return;
}
if (m_treeSelection.HasSelection()) {
if (!m_sceneRuntime->SetSelection(m_treeSelection.GetSelectedId())) {
m_sceneRuntime->RefreshScene();
}
} else {
m_sceneRuntime->ClearSelection();
}
if (!m_model.Empty()) {
m_sceneRuntime->EnsureSceneSelection();
}
SyncTreeSelectionFromSceneRuntime();
}
const HierarchyNode* HierarchyPanel::GetSelectedNode() const {
if (!m_selection.HasSelection()) {
if (m_sceneRuntime != nullptr) {
const std::string selectedItemId = m_sceneRuntime->GetSelectedItemId();
if (!selectedItemId.empty()) {
return m_model.FindNode(selectedItemId);
}
}
if (!m_treeSelection.HasSelection()) {
return nullptr;
}
return m_model.FindNode(m_selection.GetSelectedId());
return m_model.FindNode(m_treeSelection.GetSelectedId());
}
void HierarchyPanel::EmitSelectionEvent() {
@@ -127,6 +196,155 @@ void HierarchyPanel::EmitRenameRequestedEvent(std::string_view itemId) {
m_frameEvents.push_back(std::move(event));
}
void HierarchyPanel::ClearRenameState() {
m_renameState = {};
m_renameFrame = {};
m_pendingRenameItemId.clear();
}
void HierarchyPanel::QueueRenameSession(std::string_view itemId) {
if (itemId.empty() || !m_model.ContainsNode(itemId)) {
return;
}
if (m_renameState.active && m_renameState.itemId == itemId) {
return;
}
m_pendingRenameItemId = std::string(itemId);
}
bool HierarchyPanel::TryStartQueuedRenameSession(
const Widgets::UIEditorTreeViewLayout& layout) {
if (m_pendingRenameItemId.empty()) {
return false;
}
const HierarchyNode* node = m_model.FindNode(m_pendingRenameItemId);
if (node == nullptr) {
m_pendingRenameItemId.clear();
return false;
}
const UIRect bounds = BuildRenameBounds(m_pendingRenameItemId, layout);
if (!HasValidBounds(bounds)) {
return false;
}
const Widgets::UIEditorTextFieldMetrics textFieldMetrics =
BuildUIEditorInlineRenameTextFieldMetrics(
bounds,
BuildUIEditorPropertyGridTextFieldMetrics(
ResolveUIEditorPropertyGridMetrics(),
ResolveUIEditorTextFieldMetrics()));
UIEditorInlineRenameSessionRequest request = {};
request.beginSession = true;
request.itemId = m_pendingRenameItemId;
request.initialText = node->label;
request.bounds = bounds;
m_renameFrame = UpdateUIEditorInlineRenameSession(
m_renameState,
request,
{},
textFieldMetrics);
if (m_renameFrame.result.sessionStarted) {
m_pendingRenameItemId.clear();
return true;
}
return false;
}
void HierarchyPanel::UpdateRenameSession(
const std::vector<UIInputEvent>& inputEvents,
const Widgets::UIEditorTreeViewLayout& layout) {
if (!m_renameState.active) {
return;
}
if (!m_model.ContainsNode(m_renameState.itemId)) {
ClearRenameState();
return;
}
const UIRect bounds = BuildRenameBounds(m_renameState.itemId, layout);
if (!HasValidBounds(bounds)) {
ClearRenameState();
return;
}
const Widgets::UIEditorTextFieldMetrics textFieldMetrics =
BuildUIEditorInlineRenameTextFieldMetrics(
bounds,
BuildUIEditorPropertyGridTextFieldMetrics(
ResolveUIEditorPropertyGridMetrics(),
ResolveUIEditorTextFieldMetrics()));
UIEditorInlineRenameSessionRequest request = {};
request.itemId = m_renameState.itemId;
request.initialText = m_renameState.textFieldSpec.value;
request.bounds = bounds;
m_renameFrame = UpdateUIEditorInlineRenameSession(
m_renameState,
request,
inputEvents,
textFieldMetrics);
if (!m_renameFrame.result.sessionCommitted) {
return;
}
if (m_renameFrame.result.valueChanged &&
m_sceneRuntime != nullptr) {
m_sceneRuntime->RenameGameObject(
m_renameFrame.result.itemId,
m_renameFrame.result.valueAfter);
}
SyncModelFromScene();
EmitSelectionEvent();
}
void HierarchyPanel::SyncTreeFocusState(
const std::vector<UIInputEvent>& inputEvents) {
for (const UIInputEvent& event : inputEvents) {
if (event.type == ::XCEngine::UI::UIInputEventType::FocusGained) {
m_treeInteractionState.treeViewState.focused = true;
} else if (event.type == ::XCEngine::UI::UIInputEventType::FocusLost) {
m_treeInteractionState.treeViewState.focused = false;
}
}
}
UIRect HierarchyPanel::BuildRenameBounds(
std::string_view itemId,
const Widgets::UIEditorTreeViewLayout& layout) const {
if (itemId.empty()) {
return {};
}
const std::size_t visibleIndex =
FindVisibleIndexForItemId(layout, m_treeItems, itemId);
if (visibleIndex == UIEditorTreeViewInvalidIndex ||
visibleIndex >= layout.rowRects.size() ||
visibleIndex >= layout.labelRects.size()) {
return {};
}
const Widgets::UIEditorTextFieldMetrics hostedMetrics =
BuildUIEditorPropertyGridTextFieldMetrics(
ResolveUIEditorPropertyGridMetrics(),
ResolveUIEditorTextFieldMetrics());
const UIRect& rowRect = layout.rowRects[visibleIndex];
const UIRect& labelRect = layout.labelRects[visibleIndex];
const float x = (std::max)(rowRect.x, labelRect.x - hostedMetrics.valueTextInsetX);
const float right = rowRect.x + rowRect.width - 8.0f;
const float width = (std::max)(120.0f, right - x);
return UIRect(x, rowRect.y, width, rowRect.height);
}
bool HierarchyPanel::WantsHostPointerCapture() const {
return m_dragState.requestPointerCapture;
}
@@ -136,7 +354,7 @@ bool HierarchyPanel::WantsHostPointerRelease() const {
}
bool HierarchyPanel::HasActivePointerCapture() const {
return m_dragState.dragging;
return TreeDrag::HasActivePointerCapture(m_dragState);
}
const std::vector<HierarchyPanel::Event>& HierarchyPanel::GetFrameEvents() const {
@@ -193,20 +411,27 @@ UIEditorHostCommandDispatchResult HierarchyPanel::DispatchEditCommand(
const std::string selectedNodeId = selectedNode->nodeId;
const std::string selectedNodeLabel = selectedNode->label;
if (m_sceneRuntime == nullptr) {
return BuildDispatchResult(false, "Hierarchy scene runtime is unavailable.");
}
if (commandId == "edit.rename") {
QueueRenameSession(selectedNodeId);
EmitRenameRequestedEvent(selectedNodeId);
if (m_visible) {
TryStartQueuedRenameSession(m_treeFrame.layout);
}
return BuildDispatchResult(
true,
"Hierarchy rename requested for '" + selectedNodeLabel + "'.");
}
if (commandId == "edit.delete") {
if (!m_model.DeleteNode(selectedNodeId)) {
if (!m_sceneRuntime->DeleteGameObject(selectedNodeId)) {
return BuildDispatchResult(false, "Failed to delete the selected hierarchy object.");
}
RebuildItems();
SyncModelFromScene();
EmitSelectionEvent();
return BuildDispatchResult(
true,
@@ -214,13 +439,13 @@ UIEditorHostCommandDispatchResult HierarchyPanel::DispatchEditCommand(
}
if (commandId == "edit.duplicate") {
const std::string duplicatedNodeId = m_model.DuplicateNode(selectedNodeId);
const std::string duplicatedNodeId =
m_sceneRuntime->DuplicateGameObject(selectedNodeId);
if (duplicatedNodeId.empty()) {
return BuildDispatchResult(false, "Failed to duplicate the selected hierarchy object.");
}
RebuildItems();
m_selection.SetSelection(duplicatedNodeId);
SyncModelFromScene();
EmitSelectionEvent();
const HierarchyNode* duplicatedNode = m_model.FindNode(duplicatedNodeId);
@@ -234,115 +459,6 @@ UIEditorHostCommandDispatchResult HierarchyPanel::DispatchEditCommand(
return BuildDispatchResult(false, "Hierarchy does not expose this edit command.");
}
std::vector<UIInputEvent> HierarchyPanel::BuildInteractionInputEvents(
const std::vector<UIInputEvent>& inputEvents,
const UIRect& bounds,
bool allowInteraction,
bool panelActive) const {
const std::vector<UIInputEvent> rawEvents = FilterHierarchyInputEvents(
bounds,
inputEvents,
allowInteraction,
panelActive,
HasActivePointerCapture());
struct DragPreviewState {
std::string armedItemId = {};
UIPoint pressPosition = {};
bool armed = false;
bool dragging = false;
};
const Widgets::UIEditorTreeViewLayout layout =
m_treeFrame.layout.bounds.width > 0.0f
? m_treeFrame.layout
: Widgets::BuildUIEditorTreeViewLayout(
bounds,
m_treeItems,
m_expansion,
ResolveUIEditorTreeViewMetrics());
DragPreviewState preview = {};
preview.armed = m_dragState.armed;
preview.armedItemId = m_dragState.armedItemId;
preview.pressPosition = m_dragState.pressPosition;
preview.dragging = m_dragState.dragging;
std::vector<UIInputEvent> filteredEvents = {};
filteredEvents.reserve(rawEvents.size());
for (const UIInputEvent& event : rawEvents) {
bool suppress = false;
switch (event.type) {
case UIInputEventType::PointerButtonDown:
if (event.pointerButton == UIPointerButton::Left) {
UIEditorTreeViewHitTarget hitTarget = {};
const Widgets::UIEditorTreeViewItem* hitItem =
ResolveHitItem(layout, m_treeItems, event.position, &hitTarget);
if (hitItem != nullptr && hitTarget.kind == UIEditorTreeViewHitTargetKind::Row) {
preview.armed = true;
preview.armedItemId = hitItem->itemId;
preview.pressPosition = event.position;
} else {
preview.armed = false;
preview.armedItemId.clear();
}
}
if (preview.dragging) {
suppress = true;
}
break;
case UIInputEventType::PointerMove:
if (preview.dragging) {
suppress = true;
break;
}
if (preview.armed &&
ComputeSquaredDistance(event.position, preview.pressPosition) >=
kDragThreshold * kDragThreshold) {
preview.dragging = true;
suppress = true;
}
break;
case UIInputEventType::PointerButtonUp:
if (event.pointerButton == UIPointerButton::Left) {
if (preview.dragging) {
suppress = true;
preview.dragging = false;
}
preview.armed = false;
preview.armedItemId.clear();
} else if (preview.dragging) {
suppress = true;
}
break;
case UIInputEventType::PointerLeave:
if (preview.dragging) {
suppress = true;
}
break;
case UIInputEventType::FocusLost:
preview.armed = false;
preview.dragging = false;
preview.armedItemId.clear();
break;
default:
break;
}
if (!suppress) {
filteredEvents.push_back(event);
}
}
return filteredEvents;
}
void HierarchyPanel::ProcessDragAndFrameEvents(
const std::vector<UIInputEvent>& inputEvents,
const UIRect& bounds,
@@ -356,125 +472,70 @@ void HierarchyPanel::ProcessDragAndFrameEvents(
HasActivePointerCapture());
if (m_treeFrame.result.selectionChanged) {
SyncSceneRuntimeSelectionFromTree();
EmitSelectionEvent();
}
if (m_treeFrame.result.renameRequested &&
!m_treeFrame.result.renameItemId.empty()) {
Event event = {};
event.kind = EventKind::RenameRequested;
event.itemId = m_treeFrame.result.renameItemId;
if (const HierarchyNode* node = m_model.FindNode(event.itemId); node != nullptr) {
event.label = node->label;
struct HierarchyTreeDragCallbacks {
::XCEngine::UI::Widgets::UISelectionModel& selection;
HierarchyModel& model;
EditorSceneRuntime* sceneRuntime = nullptr;
bool IsItemSelected(std::string_view itemId) const {
return selection.IsSelected(itemId);
}
m_frameEvents.push_back(std::move(event));
bool SelectDraggedItem(std::string_view itemId) {
return selection.SetSelection(std::string(itemId));
}
bool CanDropOnItem(
std::string_view draggedItemId,
std::string_view targetItemId) const {
return model.CanReparent(draggedItemId, targetItemId);
}
bool CanDropToRoot(std::string_view draggedItemId) const {
return model.GetParentId(draggedItemId).has_value();
}
bool CommitDropOnItem(
std::string_view draggedItemId,
std::string_view targetItemId) {
return sceneRuntime != nullptr &&
sceneRuntime->ReparentGameObject(draggedItemId, targetItemId);
}
bool CommitDropToRoot(std::string_view draggedItemId) {
return sceneRuntime != nullptr &&
sceneRuntime->MoveGameObjectToRoot(draggedItemId);
}
} callbacks{ m_treeSelection, m_model, m_sceneRuntime };
const TreeDrag::ProcessResult dragResult =
TreeDrag::ProcessInputEvents(
m_dragState,
m_treeFrame.layout,
m_treeItems,
filteredEvents,
bounds,
callbacks,
kDragThreshold);
if (dragResult.selectionForced) {
SyncSceneRuntimeSelectionFromTree();
EmitSelectionEvent();
}
for (const UIInputEvent& event : filteredEvents) {
switch (event.type) {
case UIInputEventType::PointerButtonDown:
if (event.pointerButton == UIPointerButton::Left) {
UIEditorTreeViewHitTarget hitTarget = {};
const Widgets::UIEditorTreeViewItem* hitItem =
ResolveHitItem(m_treeFrame.layout, m_treeItems, event.position, &hitTarget);
if (hitItem != nullptr && hitTarget.kind == UIEditorTreeViewHitTargetKind::Row) {
m_dragState.armed = true;
m_dragState.armedItemId = hitItem->itemId;
m_dragState.pressPosition = event.position;
} else {
m_dragState.armed = false;
m_dragState.armedItemId.clear();
}
}
break;
case UIInputEventType::PointerMove:
if (m_dragState.armed &&
!m_dragState.dragging &&
ComputeSquaredDistance(event.position, m_dragState.pressPosition) >=
kDragThreshold * kDragThreshold) {
m_dragState.dragging = !m_dragState.armedItemId.empty();
m_dragState.draggedItemId = m_dragState.armedItemId;
m_dragState.dropTargetItemId.clear();
m_dragState.dropToRoot = false;
m_dragState.validDropTarget = false;
if (m_dragState.dragging) {
m_dragState.requestPointerCapture = true;
if (!m_selection.IsSelected(m_dragState.draggedItemId)) {
m_selection.SetSelection(m_dragState.draggedItemId);
EmitSelectionEvent();
}
}
}
if (m_dragState.dragging) {
UIEditorTreeViewHitTarget hitTarget = {};
const Widgets::UIEditorTreeViewItem* hitItem =
ResolveHitItem(m_treeFrame.layout, m_treeItems, event.position, &hitTarget);
m_dragState.dropTargetItemId.clear();
m_dragState.dropToRoot = false;
m_dragState.validDropTarget = false;
if (hitItem != nullptr &&
(hitTarget.kind == UIEditorTreeViewHitTargetKind::Row ||
hitTarget.kind == UIEditorTreeViewHitTargetKind::Disclosure)) {
m_dragState.dropTargetItemId = hitItem->itemId;
m_dragState.validDropTarget =
m_model.CanReparent(m_dragState.draggedItemId, m_dragState.dropTargetItemId);
} else if (ContainsPoint(bounds, event.position)) {
m_dragState.dropToRoot = true;
m_dragState.validDropTarget =
m_model.GetParentId(m_dragState.draggedItemId).has_value();
}
}
break;
case UIInputEventType::PointerButtonUp:
if (event.pointerButton != UIPointerButton::Left) {
break;
}
if (m_dragState.dragging) {
if (m_dragState.validDropTarget) {
const std::string draggedItemId = m_dragState.draggedItemId;
const std::string dropTargetItemId = m_dragState.dropTargetItemId;
const bool changed =
m_dragState.dropToRoot
? m_model.MoveToRoot(draggedItemId)
: m_model.Reparent(draggedItemId, dropTargetItemId);
if (changed) {
RebuildItems();
EmitReparentEvent(
m_dragState.dropToRoot ? EventKind::MovedToRoot : EventKind::Reparented,
draggedItemId,
dropTargetItemId);
}
}
m_dragState.armed = false;
m_dragState.dragging = false;
m_dragState.armedItemId.clear();
m_dragState.draggedItemId.clear();
m_dragState.dropTargetItemId.clear();
m_dragState.dropToRoot = false;
m_dragState.validDropTarget = false;
m_dragState.requestPointerRelease = true;
} else {
m_dragState.armed = false;
m_dragState.armedItemId.clear();
}
break;
case UIInputEventType::FocusLost:
if (m_dragState.dragging) {
m_dragState.requestPointerRelease = true;
}
m_dragState = {};
break;
default:
break;
}
if (dragResult.dropCommitted) {
SyncModelFromScene();
m_treeFrame.layout = Widgets::BuildUIEditorTreeViewLayout(
bounds,
m_treeItems,
m_expansion,
ResolveUIEditorTreeViewMetrics());
EmitReparentEvent(
dragResult.droppedToRoot ? EventKind::MovedToRoot : EventKind::Reparented,
dragResult.draggedItemId,
dragResult.dropTargetItemId);
}
}
@@ -491,28 +552,67 @@ void HierarchyPanel::Update(
m_visible = false;
m_treeFrame = {};
m_dragState = {};
ClearRenameState();
return;
}
if (m_treeItems.empty()) {
RebuildItems();
SyncModelFromScene();
if (m_renameState.active && !m_model.ContainsNode(m_renameState.itemId)) {
ClearRenameState();
} else if (!m_pendingRenameItemId.empty() &&
!m_model.ContainsNode(m_pendingRenameItemId)) {
m_pendingRenameItemId.clear();
}
m_visible = true;
const std::vector<UIInputEvent> interactionEvents =
BuildInteractionInputEvents(
inputEvents,
const std::vector<UIInputEvent> filteredEvents = FilterHierarchyInputEvents(
panelState->bounds,
inputEvents,
allowInteraction,
panelActive,
HasActivePointerCapture());
SyncTreeFocusState(filteredEvents);
const Widgets::UIEditorTreeViewMetrics treeMetrics =
ResolveUIEditorTreeViewMetrics();
const Widgets::UIEditorTreeViewLayout layout =
Widgets::BuildUIEditorTreeViewLayout(
panelState->bounds,
allowInteraction,
panelActive);
m_treeItems,
m_expansion,
treeMetrics);
if (m_renameState.active || !m_pendingRenameItemId.empty()) {
m_treeFrame.layout = layout;
m_treeFrame.result = {};
TryStartQueuedRenameSession(layout);
UpdateRenameSession(filteredEvents, layout);
return;
}
const std::vector<UIInputEvent> interactionEvents =
TreeDrag::BuildInteractionInputEvents(
m_dragState,
layout,
m_treeItems,
filteredEvents,
kDragThreshold);
m_treeFrame = UpdateUIEditorTreeViewInteraction(
m_treeInteractionState,
m_selection,
m_treeSelection,
m_expansion,
panelState->bounds,
m_treeItems,
interactionEvents,
ResolveUIEditorTreeViewMetrics());
treeMetrics);
if (m_treeFrame.result.renameRequested &&
!m_treeFrame.result.renameItemId.empty()) {
QueueRenameSession(m_treeFrame.result.renameItemId);
EmitRenameRequestedEvent(m_treeFrame.result.renameItemId);
TryStartQueuedRenameSession(m_treeFrame.layout);
return;
}
ProcessDragAndFrameEvents(
inputEvents,
panelState->bounds,
@@ -533,7 +633,7 @@ void HierarchyPanel::Append(UIDrawList& drawList) const {
drawList,
m_treeFrame.layout,
m_treeItems,
m_selection,
m_treeSelection,
m_treeInteractionState.treeViewState,
palette,
metrics);
@@ -544,6 +644,33 @@ void HierarchyPanel::Append(UIDrawList& drawList) const {
palette,
metrics);
if (m_renameState.active) {
const Widgets::UIEditorTextFieldPalette textFieldPalette =
BuildUIEditorPropertyGridTextFieldPalette(
ResolveUIEditorPropertyGridPalette(),
ResolveUIEditorTextFieldPalette());
const Widgets::UIEditorTextFieldMetrics textFieldMetrics =
BuildUIEditorInlineRenameTextFieldMetrics(
BuildRenameBounds(m_renameState.itemId, m_treeFrame.layout),
BuildUIEditorPropertyGridTextFieldMetrics(
ResolveUIEditorPropertyGridMetrics(),
ResolveUIEditorTextFieldMetrics()));
Widgets::AppendUIEditorTextFieldBackground(
drawList,
m_renameFrame.layout,
m_renameState.textFieldSpec,
m_renameState.textFieldInteraction.textFieldState,
textFieldPalette,
textFieldMetrics);
Widgets::AppendUIEditorTextFieldForeground(
drawList,
m_renameFrame.layout,
m_renameState.textFieldSpec,
m_renameState.textFieldInteraction.textFieldState,
textFieldPalette,
textFieldMetrics);
}
if (!m_dragState.dragging || !m_dragState.validDropTarget) {
return;
}
@@ -557,7 +684,7 @@ void HierarchyPanel::Append(UIDrawList& drawList) const {
return;
}
const std::size_t visibleIndex = FindVisibleIndexForItemId(
const std::size_t visibleIndex = TreeDrag::FindVisibleIndexForItemId(
m_treeFrame.layout,
m_treeItems,
m_dragState.dropTargetItemId);