Unify new editor tree filter host

This commit is contained in:
2026-04-23 01:12:36 +08:00
parent 03e0b362f7
commit d52eefe2ff
7 changed files with 856 additions and 53 deletions

View File

@@ -1,5 +1,6 @@
#include "HierarchyPanel.h"
#include "Rendering/Assets/BuiltInIcons.h"
#include <XCEditor/Foundation/UIEditorPanelInputFilter.h>
#include <XCEditor/Foundation/UIEditorTheme.h>
#include "Scene/EditorSceneRuntime.h"
#include "State/EditorCommandFocusService.h"
@@ -85,6 +86,8 @@ void HierarchyPanel::SetBuiltInIcons(const BuiltInIcons* icons) {
}
void HierarchyPanel::ResetInteractionState() {
m_filterHostState = {};
m_filterHostFrame = {};
m_treeInteractionState = {};
m_treeFrame = {};
m_dragState = {};
@@ -301,11 +304,20 @@ UIRect HierarchyPanel::BuildRenameBounds(
const Widgets::UIEditorTreeViewLayout& layout) const {
return BuildUIEditorTreeViewInlineRenameBounds(
layout,
m_treeItems,
GetPresentedTreeItems(),
itemId,
ResolveUIEditorTreeViewHostedTextFieldMetrics());
}
const std::vector<Widgets::UIEditorTreeViewItem>& HierarchyPanel::GetPresentedTreeItems() const {
return ResolveUIEditorFilterableTreeHostItems(m_filterHostFrame);
}
const ::XCEngine::UI::Widgets::UIExpansionModel&
HierarchyPanel::GetPresentedExpansionModel() const {
return ResolveUIEditorFilterableTreeHostExpansionModel(m_filterHostFrame);
}
bool HierarchyPanel::HasActivePointerCapture() const {
return TreeDrag::HasActivePointerCapture(m_dragState) ||
HasActiveUIEditorTreeViewPointerCapture(m_treeInteractionState);
@@ -417,12 +429,16 @@ void HierarchyPanel::ProcessDragAndFrameEvents(
const std::vector<UIInputEvent>& inputEvents,
const UIRect& bounds,
const UIEditorHostedPanelDispatchEntry& dispatchEntry) {
const std::vector<Widgets::UIEditorTreeViewItem>& presentedItems =
GetPresentedTreeItems();
const std::vector<UIInputEvent> filteredEvents = BuildUIEditorHostedTreeViewInputEvents(
bounds,
inputEvents,
UIEditorHostedTreeViewInputOptions{
.allowInteraction = dispatchEntry.allowInteraction,
.hasInputFocus = dispatchEntry.focused,
.hasInputFocus =
dispatchEntry.focused &&
!IsUIEditorFilterableTreeHostSearchFocused(m_filterHostState),
.captureActive = HasActivePointerCapture()
},
dispatchEntry.focusGained,
@@ -473,7 +489,7 @@ void HierarchyPanel::ProcessDragAndFrameEvents(
TreeDrag::ProcessInputEvents(
m_dragState,
m_treeFrame.layout,
m_treeItems,
presentedItems,
filteredEvents,
bounds,
callbacks,
@@ -484,10 +500,17 @@ void HierarchyPanel::ProcessDragAndFrameEvents(
}
if (dragResult.dropCommitted) {
SyncModelFromScene();
m_filterHostFrame = UpdateUIEditorFilterableTreeHost(
m_filterHostState,
m_filterHostFrame.layout.bounds,
"Hierarchy.TreeFilter",
{},
m_treeItems,
m_expansion);
m_treeFrame.layout = Widgets::BuildUIEditorTreeViewLayout(
bounds,
m_treeItems,
m_expansion,
GetPresentedTreeItems(),
GetPresentedExpansionModel(),
ResolveUIEditorTreeViewMetrics(),
m_treeInteractionState.verticalOffset);
EmitReparentEvent(
@@ -519,31 +542,57 @@ void HierarchyPanel::Update(
}
m_visible = true;
const std::vector<UIInputEvent> filteredEvents = BuildUIEditorHostedTreeViewInputEvents(
const std::vector<UIInputEvent> panelFilteredEvents = BuildUIEditorPanelInputEvents(
dispatchEntry.bounds,
inputEvents,
UIEditorHostedTreeViewInputOptions{
.allowInteraction = dispatchEntry.allowInteraction,
.hasInputFocus = dispatchEntry.focused,
.captureActive = HasActivePointerCapture()
UIEditorPanelInputFilterOptions{
.allowPointerInBounds = dispatchEntry.allowInteraction,
.allowPointerWhileCaptured = HasActivePointerCapture(),
.allowKeyboardInput = dispatchEntry.focused,
.allowFocusEvents =
dispatchEntry.focused ||
HasActivePointerCapture() ||
dispatchEntry.focusGained ||
dispatchEntry.focusLost,
.includePointerLeave =
dispatchEntry.allowInteraction || HasActivePointerCapture()
},
dispatchEntry.focusGained,
dispatchEntry.focusLost);
SyncTreeFocusState(filteredEvents);
m_filterHostFrame = UpdateUIEditorFilterableTreeHost(
m_filterHostState,
dispatchEntry.bounds,
"Hierarchy.TreeFilter",
panelFilteredEvents,
m_treeItems,
m_expansion);
if (m_filterHostFrame.result.queryChanged) {
m_treeInteractionState.verticalOffset = 0.0f;
}
if (IsUIEditorFilterableTreeHostSearchFocused(m_filterHostState)) {
m_treeInteractionState.treeViewState.focused = false;
}
SyncTreeFocusState(panelFilteredEvents);
TryClaimHostedPanelCommandFocus(
m_commandFocusService,
EditorActionRoute::Hierarchy,
filteredEvents,
panelFilteredEvents,
dispatchEntry.bounds,
dispatchEntry.allowInteraction);
const std::vector<Widgets::UIEditorTreeViewItem>& presentedItems =
GetPresentedTreeItems();
const Widgets::UIEditorTreeViewMetrics treeMetrics =
ResolveUIEditorTreeViewMetrics();
::XCEngine::UI::Widgets::UIExpansionModel* activeExpansionModel =
m_filterHostFrame.result.filteringActive
? &m_filterHostFrame.filteredExpansionModel
: &m_expansion;
const Widgets::UIEditorTreeViewLayout layout =
Widgets::BuildUIEditorTreeViewLayout(
dispatchEntry.bounds,
m_treeItems,
m_expansion,
m_filterHostFrame.layout.treeRect,
presentedItems,
*activeExpansionModel,
treeMetrics,
m_treeInteractionState.verticalOffset);
@@ -551,23 +600,35 @@ void HierarchyPanel::Update(
m_treeFrame.layout = layout;
m_treeFrame.result = {};
TryStartQueuedRenameSession(layout);
UpdateRenameSession(filteredEvents, layout);
UpdateRenameSession(panelFilteredEvents, layout);
return;
}
const std::vector<UIInputEvent> treeEvents = BuildUIEditorHostedTreeViewInputEvents(
m_filterHostFrame.layout.treeRect,
inputEvents,
UIEditorHostedTreeViewInputOptions{
.allowInteraction = dispatchEntry.allowInteraction,
.hasInputFocus =
dispatchEntry.focused &&
!IsUIEditorFilterableTreeHostSearchFocused(m_filterHostState),
.captureActive = HasActivePointerCapture()
},
dispatchEntry.focusGained,
dispatchEntry.focusLost);
const std::vector<UIInputEvent> interactionEvents =
TreeDrag::BuildInteractionInputEvents(
m_dragState,
layout,
m_treeItems,
filteredEvents,
presentedItems,
treeEvents,
kDragThreshold);
m_treeFrame = UpdateUIEditorTreeViewInteraction(
m_treeInteractionState,
m_treeSelection,
m_expansion,
dispatchEntry.bounds,
m_treeItems,
*activeExpansionModel,
m_filterHostFrame.layout.treeRect,
presentedItems,
interactionEvents,
treeMetrics);
if (m_treeFrame.result.renameRequested &&
@@ -580,23 +641,34 @@ void HierarchyPanel::Update(
ProcessDragAndFrameEvents(
inputEvents,
dispatchEntry.bounds,
m_filterHostFrame.layout.treeRect,
dispatchEntry);
}
void HierarchyPanel::Append(UIDrawList& drawList) const {
if (!m_visible ||
m_treeFrame.layout.bounds.width <= 0.0f ||
m_treeFrame.layout.bounds.height <= 0.0f) {
m_filterHostFrame.layout.bounds.width <= 0.0f ||
m_filterHostFrame.layout.bounds.height <= 0.0f) {
return;
}
const std::vector<Widgets::UIEditorTreeViewItem>& presentedItems =
GetPresentedTreeItems();
const Widgets::UIEditorTreeViewPalette palette = ResolveUIEditorTreeViewPalette();
const Widgets::UIEditorTreeViewMetrics metrics = ResolveUIEditorTreeViewMetrics();
drawList.AddFilledRect(m_filterHostFrame.layout.bounds, palette.surfaceColor);
AppendUIEditorFilterableTreeHostSearchField(
drawList,
m_filterHostFrame,
m_filterHostState);
if (m_treeFrame.layout.bounds.width <= 0.0f ||
m_treeFrame.layout.bounds.height <= 0.0f) {
return;
}
AppendUIEditorTreeViewBackground(
drawList,
m_treeFrame.layout,
m_treeItems,
presentedItems,
m_treeSelection,
m_treeInteractionState.treeViewState,
palette,
@@ -604,7 +676,7 @@ void HierarchyPanel::Append(UIDrawList& drawList) const {
AppendUIEditorTreeViewForeground(
drawList,
m_treeFrame.layout,
m_treeItems,
presentedItems,
palette,
metrics);
@@ -621,7 +693,7 @@ void HierarchyPanel::Append(UIDrawList& drawList) const {
AppendUIEditorTreeViewDropPreview(
drawList,
m_treeFrame.layout,
m_treeItems,
presentedItems,
m_dragState.dragging && m_dragState.validDropTarget,
m_dragState.dropToRoot,
m_dragState.dropTargetItemId,