fix(new_editor): stabilize inspector add-component layout and project browser scrolling
This commit is contained in:
@@ -100,18 +100,29 @@ Widgets::UIEditorPropertyGridLayout TranslatePropertyGridLayoutForScroll(
|
||||
return translated;
|
||||
}
|
||||
|
||||
float ResolvePropertyGridContentBottom(
|
||||
const Widgets::UIEditorPropertyGridLayout& gridLayout,
|
||||
const UIRect& contentBounds) {
|
||||
float contentBottom = contentBounds.y;
|
||||
if (!gridLayout.sectionHeaderRects.empty()) {
|
||||
const UIRect& lastSectionRect = gridLayout.sectionHeaderRects.back();
|
||||
contentBottom =
|
||||
(std::max)(contentBottom, lastSectionRect.y + lastSectionRect.height);
|
||||
}
|
||||
if (!gridLayout.fieldRowRects.empty()) {
|
||||
const UIRect& lastFieldRect = gridLayout.fieldRowRects.back();
|
||||
contentBottom =
|
||||
(std::max)(contentBottom, lastFieldRect.y + lastFieldRect.height);
|
||||
}
|
||||
|
||||
return contentBottom;
|
||||
}
|
||||
|
||||
float ResolveAddComponentButtonTop(
|
||||
const Widgets::UIEditorPropertyGridLayout& gridLayout,
|
||||
const UIRect& contentBounds) {
|
||||
if (!gridLayout.fieldRowRects.empty()) {
|
||||
const UIRect& lastFieldRect = gridLayout.fieldRowRects.back();
|
||||
return lastFieldRect.y + lastFieldRect.height + kAddComponentButtonTopGap;
|
||||
}
|
||||
if (!gridLayout.sectionHeaderRects.empty()) {
|
||||
const UIRect& lastSectionRect = gridLayout.sectionHeaderRects.back();
|
||||
return lastSectionRect.y + lastSectionRect.height + kAddComponentButtonTopGap;
|
||||
}
|
||||
return contentBounds.y;
|
||||
return ResolvePropertyGridContentBottom(gridLayout, contentBounds) +
|
||||
kAddComponentButtonTopGap;
|
||||
}
|
||||
|
||||
Widgets::UIEditorScrollViewPalette BuildInspectorScrollPalette() {
|
||||
@@ -342,13 +353,7 @@ float InspectorPanel::MeasureScrollableContentHeight(
|
||||
m_presentation.sections,
|
||||
m_sectionExpansion,
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridMetrics());
|
||||
if (!layout.fieldRowRects.empty()) {
|
||||
const UIRect& lastFieldRect = layout.fieldRowRects.back();
|
||||
contentBottom = lastFieldRect.y + lastFieldRect.height;
|
||||
} else if (!layout.sectionHeaderRects.empty()) {
|
||||
const UIRect& lastSectionRect = layout.sectionHeaderRects.back();
|
||||
contentBottom = lastSectionRect.y + lastSectionRect.height;
|
||||
}
|
||||
contentBottom = ResolvePropertyGridContentBottom(layout, contentBounds);
|
||||
}
|
||||
|
||||
if (ShouldShowAddComponentButton()) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "ProjectPanel.h"
|
||||
#include "Rendering/Assets/BuiltInIcons.h"
|
||||
#include <XCEditor/Collections/UIEditorScrollView.h>
|
||||
#include <XCEditor/Collections/UIEditorTreeView.h>
|
||||
#include <XCEditor/Foundation/UIEditorTheme.h>
|
||||
#include <algorithm>
|
||||
@@ -84,6 +85,8 @@ void AppendTilePreview(
|
||||
const UIRect& previewRect,
|
||||
bool directory,
|
||||
const UITextureHandle* texture);
|
||||
Widgets::UIEditorScrollViewPalette BuildProjectBrowserScrollPalette();
|
||||
int ResolveAssetGridColumnCount(float gridWidth);
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
|
||||
@@ -214,6 +217,23 @@ void AppendTilePreview(
|
||||
drawList.AddRectOutline(sheetRect, kTilePreviewOutlineColor, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
Widgets::UIEditorScrollViewPalette BuildProjectBrowserScrollPalette() {
|
||||
Widgets::UIEditorScrollViewPalette palette =
|
||||
ResolveUIEditorScrollViewPalette();
|
||||
palette.surfaceColor.a = 0.0f;
|
||||
palette.borderColor.a = 0.0f;
|
||||
palette.focusedBorderColor.a = 0.0f;
|
||||
return palette;
|
||||
}
|
||||
|
||||
int ResolveAssetGridColumnCount(float gridWidth) {
|
||||
const float effectiveTileWidth = kGridTileWidth + kGridTileGapX;
|
||||
int columnCount = effectiveTileWidth > 0.0f
|
||||
? static_cast<int>((gridWidth + kGridTileGapX) / effectiveTileWidth)
|
||||
: 1;
|
||||
return (std::max)(columnCount, 1);
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
@@ -358,6 +378,9 @@ void ProjectPanel::SetTextMeasurer(const UIEditorTextMeasurer* textMeasurer) {
|
||||
void ProjectPanel::ResetInteractionState() {
|
||||
m_assetDragState = {};
|
||||
m_treeDragState = {};
|
||||
m_browserScrollInteractionState = {};
|
||||
m_browserScrollFrame = {};
|
||||
m_browserVerticalOffset = 0.0f;
|
||||
m_treeInteractionState = {};
|
||||
m_treeFrame = {};
|
||||
m_contextMenu = {};
|
||||
@@ -383,6 +406,7 @@ ProjectPanel::CursorKind ProjectPanel::GetCursorKind() const {
|
||||
|
||||
bool ProjectPanel::HasActivePointerCapture() const {
|
||||
return m_splitterDragging ||
|
||||
HasActiveUIEditorScrollViewPointerCapture(m_browserScrollInteractionState) ||
|
||||
GridDrag::HasActivePointerCapture(m_assetDragState) ||
|
||||
TreeDrag::HasActivePointerCapture(m_treeDragState) ||
|
||||
HasActiveUIEditorTreeViewPointerCapture(m_treeInteractionState);
|
||||
@@ -668,7 +692,7 @@ void ProjectPanel::SyncAssetSelectionFromRuntime() {
|
||||
|
||||
Widgets::UIEditorTreeViewMetrics ProjectPanel::RebuildPanelLayout(const UIRect& bounds) {
|
||||
const Widgets::UIEditorTreeViewMetrics treeMetrics = ResolveUIEditorTreeViewMetrics();
|
||||
m_layout = BuildLayout(bounds);
|
||||
m_layout = BuildLayout(bounds, {}, 0.0f);
|
||||
m_treeFrame.layout = Widgets::BuildUIEditorTreeViewLayout(
|
||||
m_layout.treeRect,
|
||||
GetWindowTreeItems(),
|
||||
@@ -678,6 +702,74 @@ Widgets::UIEditorTreeViewMetrics ProjectPanel::RebuildPanelLayout(const UIRect&
|
||||
return treeMetrics;
|
||||
}
|
||||
|
||||
float ProjectPanel::MeasureBrowserContentHeight(const UIRect& browserContentRect) const {
|
||||
if (!HasValidBounds(browserContentRect)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const float gridWidth =
|
||||
ClampNonNegative(browserContentRect.width - kGridInsetX * 2.0f);
|
||||
if (gridWidth <= 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const std::size_t assetCount = GetBrowserModel().GetAssetEntries().size();
|
||||
const int columnCount = ResolveAssetGridColumnCount(gridWidth);
|
||||
const std::size_t rowCount =
|
||||
assetCount == 0u
|
||||
? 0u
|
||||
: (assetCount + static_cast<std::size_t>(columnCount) - 1u) /
|
||||
static_cast<std::size_t>(columnCount);
|
||||
|
||||
float contentHeight = kGridInsetY * 2.0f;
|
||||
if (rowCount > 0u) {
|
||||
contentHeight +=
|
||||
static_cast<float>(rowCount) * kGridTileHeight +
|
||||
static_cast<float>(rowCount - 1u) * kGridTileGapY;
|
||||
} else {
|
||||
contentHeight += 18.0f;
|
||||
}
|
||||
|
||||
return contentHeight;
|
||||
}
|
||||
|
||||
void ProjectPanel::RebuildBrowserScrollLayout() {
|
||||
m_browserScrollFrame = {};
|
||||
|
||||
if (!HasValidBounds(m_layout.browserBodyRect)) {
|
||||
m_browserVerticalOffset = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
const Widgets::UIEditorScrollViewMetrics& scrollMetrics =
|
||||
ResolveUIEditorScrollViewMetrics();
|
||||
|
||||
float contentHeight = MeasureBrowserContentHeight(m_layout.browserBodyRect);
|
||||
m_browserVerticalOffset = Widgets::ClampUIEditorScrollViewOffset(
|
||||
m_layout.browserBodyRect,
|
||||
contentHeight,
|
||||
m_browserVerticalOffset,
|
||||
scrollMetrics);
|
||||
m_browserScrollFrame.layout = Widgets::BuildUIEditorScrollViewLayout(
|
||||
m_layout.browserBodyRect,
|
||||
contentHeight,
|
||||
m_browserVerticalOffset,
|
||||
scrollMetrics);
|
||||
|
||||
contentHeight = MeasureBrowserContentHeight(m_browserScrollFrame.layout.contentRect);
|
||||
m_browserVerticalOffset = Widgets::ClampUIEditorScrollViewOffset(
|
||||
m_layout.browserBodyRect,
|
||||
contentHeight,
|
||||
m_browserVerticalOffset,
|
||||
scrollMetrics);
|
||||
m_browserScrollFrame.layout = Widgets::BuildUIEditorScrollViewLayout(
|
||||
m_layout.browserBodyRect,
|
||||
contentHeight,
|
||||
m_browserVerticalOffset,
|
||||
scrollMetrics);
|
||||
m_browserScrollFrame.result.verticalOffset = m_browserVerticalOffset;
|
||||
}
|
||||
|
||||
bool ProjectPanel::NavigateToFolder(std::string_view itemId, EventSource source) {
|
||||
if (!ResolveProjectRuntime()->NavigateToFolder(itemId)) {
|
||||
return false;
|
||||
@@ -704,6 +796,11 @@ bool ProjectPanel::OpenProjectItem(std::string_view itemId, EventSource source)
|
||||
if (navigated && HasValidBounds(m_layout.bounds)) {
|
||||
SyncSelectionsFromRuntime();
|
||||
RebuildPanelLayout(m_layout.bounds);
|
||||
RebuildBrowserScrollLayout();
|
||||
m_layout = BuildLayout(
|
||||
m_layout.bounds,
|
||||
m_browserScrollFrame.layout.contentRect,
|
||||
m_browserVerticalOffset);
|
||||
m_hoveredAssetItemId.clear();
|
||||
EmitEvent(
|
||||
EventKind::FolderNavigated,
|
||||
@@ -1198,6 +1295,11 @@ UIEditorHostCommandDispatchResult ProjectPanel::DispatchAssetCommand(
|
||||
NavigateToFolder(target.containerFolder->itemId, EventSource::GridSecondary);
|
||||
if (HasValidBounds(m_layout.bounds)) {
|
||||
RebuildPanelLayout(m_layout.bounds);
|
||||
RebuildBrowserScrollLayout();
|
||||
m_layout = BuildLayout(
|
||||
m_layout.bounds,
|
||||
m_browserScrollFrame.layout.contentRect,
|
||||
m_browserVerticalOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1230,6 +1332,11 @@ UIEditorHostCommandDispatchResult ProjectPanel::DispatchAssetCommand(
|
||||
NavigateToFolder(target.containerFolder->itemId, EventSource::GridSecondary);
|
||||
if (HasValidBounds(m_layout.bounds)) {
|
||||
RebuildPanelLayout(m_layout.bounds);
|
||||
RebuildBrowserScrollLayout();
|
||||
m_layout = BuildLayout(
|
||||
m_layout.bounds,
|
||||
m_browserScrollFrame.layout.contentRect,
|
||||
m_browserVerticalOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1485,6 +1592,33 @@ void ProjectPanel::Update(
|
||||
m_navigationWidth = ClampNavigationWidth(m_navigationWidth, dispatchEntry.bounds.width);
|
||||
const Widgets::UIEditorTreeViewMetrics treeMetrics =
|
||||
RebuildPanelLayout(dispatchEntry.bounds);
|
||||
const auto refreshBrowserLayout = [&]() {
|
||||
RebuildBrowserScrollLayout();
|
||||
m_layout = BuildLayout(
|
||||
dispatchEntry.bounds,
|
||||
m_browserScrollFrame.layout.contentRect,
|
||||
m_browserVerticalOffset);
|
||||
};
|
||||
const auto updateBrowserScrollInteraction = [&]() {
|
||||
RebuildBrowserScrollLayout();
|
||||
if (HasValidBounds(m_layout.browserBodyRect)) {
|
||||
m_browserScrollFrame = UpdateUIEditorScrollViewInteraction(
|
||||
m_browserScrollInteractionState,
|
||||
m_browserVerticalOffset,
|
||||
m_layout.browserBodyRect,
|
||||
m_browserScrollFrame.layout.contentHeight,
|
||||
filteredEvents,
|
||||
ResolveUIEditorScrollViewMetrics());
|
||||
} else {
|
||||
m_browserScrollFrame = {};
|
||||
m_browserVerticalOffset = 0.0f;
|
||||
}
|
||||
|
||||
m_layout = BuildLayout(
|
||||
dispatchEntry.bounds,
|
||||
m_browserScrollFrame.layout.contentRect,
|
||||
m_browserVerticalOffset);
|
||||
};
|
||||
if (m_contextMenu.open) {
|
||||
RebuildContextMenu();
|
||||
}
|
||||
@@ -1497,6 +1631,7 @@ void ProjectPanel::Update(
|
||||
}
|
||||
|
||||
if (m_renameState.active || !m_pendingRenameItemId.empty()) {
|
||||
updateBrowserScrollInteraction();
|
||||
TryStartQueuedRenameSession();
|
||||
UpdateRenameSession(filteredEvents);
|
||||
return;
|
||||
@@ -1522,6 +1657,7 @@ void ProjectPanel::Update(
|
||||
CloseContextMenu();
|
||||
NavigateToFolder(m_treeFrame.result.selectedItemId, EventSource::Tree);
|
||||
RebuildPanelLayout(dispatchEntry.bounds);
|
||||
refreshBrowserLayout();
|
||||
}
|
||||
if (m_treeFrame.result.renameRequested &&
|
||||
!m_treeFrame.result.renameItemId.empty()) {
|
||||
@@ -1607,8 +1743,11 @@ void ProjectPanel::Update(
|
||||
EmitSelectionClearedEvent(EventSource::Tree);
|
||||
}
|
||||
RebuildPanelLayout(dispatchEntry.bounds);
|
||||
refreshBrowserLayout();
|
||||
}
|
||||
|
||||
updateBrowserScrollInteraction();
|
||||
|
||||
struct ProjectAssetDragCallbacks {
|
||||
::XCEngine::UI::Widgets::UISelectionModel& assetSelection;
|
||||
::XCEngine::UI::Widgets::UIExpansionModel& folderExpansion;
|
||||
@@ -1723,6 +1862,7 @@ void ProjectPanel::Update(
|
||||
}
|
||||
|
||||
RebuildPanelLayout(dispatchEntry.bounds);
|
||||
refreshBrowserLayout();
|
||||
}
|
||||
|
||||
const bool suppressPanelPointerEvents =
|
||||
@@ -1770,7 +1910,8 @@ void ProjectPanel::Update(
|
||||
ClampNavigationWidth(
|
||||
event.position.x - dispatchEntry.bounds.x,
|
||||
dispatchEntry.bounds.width);
|
||||
m_layout = BuildLayout(dispatchEntry.bounds);
|
||||
RebuildPanelLayout(dispatchEntry.bounds);
|
||||
refreshBrowserLayout();
|
||||
}
|
||||
|
||||
m_splitterHovered =
|
||||
@@ -1892,6 +2033,7 @@ void ProjectPanel::Update(
|
||||
if (item.clickable) {
|
||||
NavigateToFolder(item.targetFolderId, EventSource::Breadcrumb);
|
||||
RebuildPanelLayout(dispatchEntry.bounds);
|
||||
refreshBrowserLayout();
|
||||
}
|
||||
}
|
||||
m_pressedBreadcrumbIndex = kInvalidLayoutIndex;
|
||||
@@ -1904,7 +2046,10 @@ void ProjectPanel::Update(
|
||||
}
|
||||
}
|
||||
|
||||
ProjectPanel::Layout ProjectPanel::BuildLayout(const UIRect& bounds) const {
|
||||
ProjectPanel::Layout ProjectPanel::BuildLayout(
|
||||
const UIRect& bounds,
|
||||
const UIRect& browserContentRect,
|
||||
float browserVerticalOffset) const {
|
||||
Layout layout = {};
|
||||
const auto& assetEntries = GetBrowserModel().GetAssetEntries();
|
||||
const std::vector<ProjectBrowserModel::BreadcrumbSegment> breadcrumbSegments =
|
||||
@@ -1949,11 +2094,15 @@ ProjectPanel::Layout ProjectPanel::BuildLayout(const UIRect& bounds) const {
|
||||
layout.browserHeaderRect.y + layout.browserHeaderRect.height,
|
||||
layout.rightPaneRect.width,
|
||||
ClampNonNegative(layout.rightPaneRect.height - layout.browserHeaderRect.height));
|
||||
const UIRect effectiveBrowserContentRect =
|
||||
HasValidBounds(browserContentRect)
|
||||
? browserContentRect
|
||||
: layout.browserBodyRect;
|
||||
layout.gridRect = UIRect(
|
||||
layout.browserBodyRect.x + kGridInsetX,
|
||||
layout.browserBodyRect.y + kGridInsetY,
|
||||
ClampNonNegative(layout.browserBodyRect.width - kGridInsetX * 2.0f),
|
||||
ClampNonNegative(layout.browserBodyRect.height - kGridInsetY * 2.0f));
|
||||
effectiveBrowserContentRect.x + kGridInsetX,
|
||||
effectiveBrowserContentRect.y + kGridInsetY,
|
||||
ClampNonNegative(effectiveBrowserContentRect.width - kGridInsetX * 2.0f),
|
||||
ClampNonNegative(effectiveBrowserContentRect.height - kGridInsetY * 2.0f));
|
||||
|
||||
const float breadcrumbRowHeight = kHeaderFontSize + kBreadcrumbItemPaddingY * 2.0f;
|
||||
const float breadcrumbY =
|
||||
@@ -2004,20 +2153,16 @@ ProjectPanel::Layout ProjectPanel::BuildLayout(const UIRect& bounds) const {
|
||||
nextItemX += itemWidth + kBreadcrumbSpacing;
|
||||
}
|
||||
|
||||
const float effectiveTileWidth = kGridTileWidth + kGridTileGapX;
|
||||
int columnCount = effectiveTileWidth > 0.0f
|
||||
? static_cast<int>((layout.gridRect.width + kGridTileGapX) / effectiveTileWidth)
|
||||
: 1;
|
||||
if (columnCount < 1) {
|
||||
columnCount = 1;
|
||||
}
|
||||
const int columnCount = ResolveAssetGridColumnCount(layout.gridRect.width);
|
||||
|
||||
layout.assetTiles.reserve(assetEntries.size());
|
||||
for (std::size_t index = 0; index < assetEntries.size(); ++index) {
|
||||
const int column = static_cast<int>(index % static_cast<std::size_t>(columnCount));
|
||||
const int row = static_cast<int>(index / static_cast<std::size_t>(columnCount));
|
||||
const float tileX = layout.gridRect.x + static_cast<float>(column) * (kGridTileWidth + kGridTileGapX);
|
||||
const float tileY = layout.gridRect.y + static_cast<float>(row) * (kGridTileHeight + kGridTileGapY);
|
||||
const float tileY =
|
||||
layout.gridRect.y - browserVerticalOffset +
|
||||
static_cast<float>(row) * (kGridTileHeight + kGridTileGapY);
|
||||
|
||||
AssetTileLayout tile = {};
|
||||
tile.itemIndex = index;
|
||||
@@ -2183,6 +2328,16 @@ void ProjectPanel::Append(UIDrawList& drawList) const {
|
||||
}
|
||||
drawList.PopClipRect();
|
||||
|
||||
if (HasValidBounds(m_browserScrollFrame.layout.bounds)) {
|
||||
Widgets::AppendUIEditorScrollViewBackground(
|
||||
drawList,
|
||||
m_browserScrollFrame.layout,
|
||||
m_browserScrollInteractionState.scrollViewState,
|
||||
BuildProjectBrowserScrollPalette(),
|
||||
ResolveUIEditorScrollViewMetrics());
|
||||
}
|
||||
|
||||
drawList.PushClipRect(m_browserScrollFrame.layout.contentRect);
|
||||
for (const AssetTileLayout& tile : m_layout.assetTiles) {
|
||||
if (tile.itemIndex >= assetEntries.size()) {
|
||||
continue;
|
||||
@@ -2274,6 +2429,7 @@ void ProjectPanel::Append(UIDrawList& drawList) const {
|
||||
kTextMuted,
|
||||
kHeaderFontSize);
|
||||
}
|
||||
drawList.PopClipRect();
|
||||
|
||||
AppendContextMenu(drawList);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Commands/EditorEditCommandRoute.h"
|
||||
#include <XCEditor/Collections/UIEditorGridDragDrop.h>
|
||||
#include <XCEditor/Collections/UIEditorInlineRenameSession.h>
|
||||
#include <XCEditor/Collections/UIEditorScrollViewInteraction.h>
|
||||
#include <XCEditor/Collections/UIEditorTreeDragDrop.h>
|
||||
#include <XCEditor/Collections/UIEditorTreeViewInteraction.h>
|
||||
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
|
||||
@@ -176,7 +177,10 @@ private:
|
||||
std::optional<EditCommandTarget> ResolveEditCommandTarget(
|
||||
std::string_view explicitItemId = {},
|
||||
bool forceCurrentFolder = false) const;
|
||||
Layout BuildLayout(const ::XCEngine::UI::UIRect& bounds) const;
|
||||
Layout BuildLayout(
|
||||
const ::XCEngine::UI::UIRect& bounds,
|
||||
const ::XCEngine::UI::UIRect& browserContentRect,
|
||||
float browserVerticalOffset) const;
|
||||
std::size_t HitTestBreadcrumbItem(const ::XCEngine::UI::UIPoint& point) const;
|
||||
std::size_t HitTestAssetTile(const ::XCEngine::UI::UIPoint& point) const;
|
||||
std::string ResolveAssetDropTargetItemId(
|
||||
@@ -184,6 +188,9 @@ private:
|
||||
DropTargetSurface* surface = nullptr) const;
|
||||
void SyncCurrentFolderSelection();
|
||||
bool NavigateToFolder(std::string_view itemId, EventSource source = EventSource::None);
|
||||
float MeasureBrowserContentHeight(
|
||||
const ::XCEngine::UI::UIRect& browserContentRect) const;
|
||||
void RebuildBrowserScrollLayout();
|
||||
void EmitEvent(EventKind kind, EventSource source, const FolderEntry* folder);
|
||||
void EmitEvent(EventKind kind, EventSource source, const AssetEntry* asset);
|
||||
void EmitSelectionClearedEvent(EventSource source);
|
||||
@@ -247,6 +254,9 @@ private:
|
||||
::XCEngine::UI::Widgets::UISelectionModel m_assetSelection = {};
|
||||
Collections::GridDragDrop::State m_assetDragState = {};
|
||||
Collections::TreeDragDrop::State m_treeDragState = {};
|
||||
UIEditorScrollViewInteractionState m_browserScrollInteractionState = {};
|
||||
UIEditorScrollViewInteractionFrame m_browserScrollFrame = {};
|
||||
float m_browserVerticalOffset = 0.0f;
|
||||
UIEditorTreeViewInteractionState m_treeInteractionState = {};
|
||||
UIEditorTreeViewInteractionFrame m_treeFrame = {};
|
||||
UIEditorInlineRenameSessionState m_renameState = {};
|
||||
|
||||
Reference in New Issue
Block a user