Refine editor tree alignment and project panel events
This commit is contained in:
@@ -405,6 +405,10 @@ bool ProductProjectPanel::HasActivePointerCapture() const {
|
||||
return m_splitterDragging;
|
||||
}
|
||||
|
||||
const std::vector<ProductProjectPanel::Event>& ProductProjectPanel::GetFrameEvents() const {
|
||||
return m_frameEvents;
|
||||
}
|
||||
|
||||
const ProductProjectPanel::FolderEntry* ProductProjectPanel::FindFolderEntry(
|
||||
std::string_view itemId) const {
|
||||
for (const FolderEntry& entry : m_folderEntries) {
|
||||
@@ -416,6 +420,17 @@ const ProductProjectPanel::FolderEntry* ProductProjectPanel::FindFolderEntry(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ProductProjectPanel::AssetEntry* ProductProjectPanel::FindAssetEntry(
|
||||
std::string_view itemId) const {
|
||||
for (const AssetEntry& entry : m_assetEntries) {
|
||||
if (entry.itemId == itemId) {
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const UIEditorPanelContentHostPanelState* ProductProjectPanel::FindMountedProjectPanel(
|
||||
const UIEditorPanelContentHostFrame& contentHostFrame) const {
|
||||
for (const UIEditorPanelContentHostPanelState& panelState : contentHostFrame.panelStates) {
|
||||
@@ -656,9 +671,9 @@ void ProductProjectPanel::SyncCurrentFolderSelection() {
|
||||
m_folderSelection.SetSelection(m_currentFolderId);
|
||||
}
|
||||
|
||||
void ProductProjectPanel::NavigateToFolder(std::string_view itemId) {
|
||||
bool ProductProjectPanel::NavigateToFolder(std::string_view itemId, EventSource source) {
|
||||
if (itemId.empty() || FindFolderEntry(itemId) == nullptr || itemId == m_currentFolderId) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_currentFolderId = std::string(itemId);
|
||||
@@ -667,6 +682,53 @@ void ProductProjectPanel::NavigateToFolder(std::string_view itemId) {
|
||||
m_hoveredAssetItemId.clear();
|
||||
m_lastPrimaryClickedAssetId.clear();
|
||||
RefreshAssetList();
|
||||
EmitEvent(EventKind::FolderNavigated, source, FindFolderEntry(m_currentFolderId));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProductProjectPanel::EmitEvent(
|
||||
EventKind kind,
|
||||
EventSource source,
|
||||
const FolderEntry* folder) {
|
||||
if (kind == EventKind::None || folder == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Event event = {};
|
||||
event.kind = kind;
|
||||
event.source = source;
|
||||
event.itemId = folder->itemId;
|
||||
event.absolutePath = folder->absolutePath;
|
||||
event.displayName = PathToUtf8String(folder->absolutePath.filename());
|
||||
event.directory = true;
|
||||
m_frameEvents.push_back(std::move(event));
|
||||
}
|
||||
|
||||
void ProductProjectPanel::EmitEvent(
|
||||
EventKind kind,
|
||||
EventSource source,
|
||||
const AssetEntry* asset) {
|
||||
if (kind == EventKind::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
Event event = {};
|
||||
event.kind = kind;
|
||||
event.source = source;
|
||||
if (asset != nullptr) {
|
||||
event.itemId = asset->itemId;
|
||||
event.absolutePath = asset->absolutePath;
|
||||
event.displayName = asset->displayName;
|
||||
event.directory = asset->directory;
|
||||
}
|
||||
m_frameEvents.push_back(std::move(event));
|
||||
}
|
||||
|
||||
void ProductProjectPanel::EmitSelectionClearedEvent(EventSource source) {
|
||||
Event event = {};
|
||||
event.kind = EventKind::AssetSelectionCleared;
|
||||
event.source = source;
|
||||
m_frameEvents.push_back(std::move(event));
|
||||
}
|
||||
|
||||
void ProductProjectPanel::RefreshAssetList() {
|
||||
@@ -720,6 +782,7 @@ void ProductProjectPanel::RefreshAssetList() {
|
||||
|
||||
void ProductProjectPanel::ResetTransientFrames() {
|
||||
m_treeFrame = {};
|
||||
m_frameEvents.clear();
|
||||
m_layout = {};
|
||||
m_hoveredAssetItemId.clear();
|
||||
m_hoveredBreadcrumbIndex = kInvalidLayoutIndex;
|
||||
@@ -735,6 +798,7 @@ void ProductProjectPanel::Update(
|
||||
bool panelActive) {
|
||||
m_requestPointerCapture = false;
|
||||
m_requestPointerRelease = false;
|
||||
m_frameEvents.clear();
|
||||
|
||||
const UIEditorPanelContentHostPanelState* panelState =
|
||||
FindMountedProjectPanel(contentHostFrame);
|
||||
@@ -779,7 +843,7 @@ void ProductProjectPanel::Update(
|
||||
if (m_treeFrame.result.selectionChanged &&
|
||||
!m_treeFrame.result.selectedItemId.empty() &&
|
||||
m_treeFrame.result.selectedItemId != m_currentFolderId) {
|
||||
NavigateToFolder(m_treeFrame.result.selectedItemId);
|
||||
NavigateToFolder(m_treeFrame.result.selectedItemId, EventSource::Tree);
|
||||
m_layout = BuildLayout(panelState->bounds);
|
||||
}
|
||||
|
||||
@@ -823,39 +887,35 @@ void ProductProjectPanel::Update(
|
||||
break;
|
||||
|
||||
case UIInputEventType::PointerButtonDown:
|
||||
if (event.pointerButton != ::XCEngine::UI::UIPointerButton::Left) {
|
||||
break;
|
||||
}
|
||||
if (event.pointerButton == ::XCEngine::UI::UIPointerButton::Left) {
|
||||
if (ContainsPoint(m_layout.dividerRect, event.position)) {
|
||||
m_splitterDragging = true;
|
||||
m_splitterHovered = true;
|
||||
m_pressedBreadcrumbIndex = kInvalidLayoutIndex;
|
||||
m_requestPointerCapture = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ContainsPoint(m_layout.dividerRect, event.position)) {
|
||||
m_splitterDragging = true;
|
||||
m_splitterHovered = true;
|
||||
m_pressedBreadcrumbIndex = kInvalidLayoutIndex;
|
||||
m_requestPointerCapture = true;
|
||||
break;
|
||||
}
|
||||
m_pressedBreadcrumbIndex = HitTestBreadcrumbItem(event.position);
|
||||
|
||||
m_pressedBreadcrumbIndex = HitTestBreadcrumbItem(event.position);
|
||||
if (!ContainsPoint(m_layout.gridRect, event.position)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ContainsPoint(m_layout.gridRect, event.position)) {
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
const std::size_t hitIndex = HitTestAssetTile(event.position);
|
||||
if (hitIndex >= m_assetEntries.size()) {
|
||||
m_assetSelection.ClearSelection();
|
||||
if (m_assetSelection.HasSelection()) {
|
||||
m_assetSelection.ClearSelection();
|
||||
EmitSelectionClearedEvent(EventSource::Background);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const AssetEntry& assetEntry = m_assetEntries[hitIndex];
|
||||
const bool alreadySelected = m_assetSelection.IsSelected(assetEntry.itemId);
|
||||
m_assetSelection.SetSelection(assetEntry.itemId);
|
||||
|
||||
if (!assetEntry.directory) {
|
||||
m_lastPrimaryClickedAssetId = assetEntry.itemId;
|
||||
m_lastPrimaryClickTimeMs = GetTickCount64();
|
||||
break;
|
||||
const bool selectionChanged = m_assetSelection.SetSelection(assetEntry.itemId);
|
||||
if (selectionChanged) {
|
||||
EmitEvent(EventKind::AssetSelected, EventSource::GridPrimary, &assetEntry);
|
||||
}
|
||||
|
||||
const std::uint64_t nowMs = GetTickCount64();
|
||||
@@ -873,9 +933,30 @@ void ProductProjectPanel::Update(
|
||||
break;
|
||||
}
|
||||
|
||||
NavigateToFolder(assetEntry.itemId);
|
||||
m_layout = BuildLayout(panelState->bounds);
|
||||
m_hoveredAssetItemId.clear();
|
||||
if (assetEntry.directory) {
|
||||
NavigateToFolder(assetEntry.itemId, EventSource::GridDoubleClick);
|
||||
m_layout = BuildLayout(panelState->bounds);
|
||||
m_hoveredAssetItemId.clear();
|
||||
} else {
|
||||
EmitEvent(EventKind::AssetOpened, EventSource::GridDoubleClick, &assetEntry);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (event.pointerButton == ::XCEngine::UI::UIPointerButton::Right &&
|
||||
ContainsPoint(m_layout.gridRect, event.position)) {
|
||||
const std::size_t hitIndex = HitTestAssetTile(event.position);
|
||||
if (hitIndex >= m_assetEntries.size()) {
|
||||
EmitEvent(EventKind::ContextMenuRequested, EventSource::Background, static_cast<const AssetEntry*>(nullptr));
|
||||
break;
|
||||
}
|
||||
|
||||
const AssetEntry& assetEntry = m_assetEntries[hitIndex];
|
||||
if (!m_assetSelection.IsSelected(assetEntry.itemId)) {
|
||||
m_assetSelection.SetSelection(assetEntry.itemId);
|
||||
EmitEvent(EventKind::AssetSelected, EventSource::GridSecondary, &assetEntry);
|
||||
}
|
||||
EmitEvent(EventKind::ContextMenuRequested, EventSource::GridSecondary, &assetEntry);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -900,7 +981,7 @@ void ProductProjectPanel::Update(
|
||||
const BreadcrumbItemLayout& item =
|
||||
m_layout.breadcrumbItems[releasedBreadcrumbIndex];
|
||||
if (item.clickable) {
|
||||
NavigateToFolder(item.targetFolderId);
|
||||
NavigateToFolder(item.targetFolderId, EventSource::Breadcrumb);
|
||||
m_layout = BuildLayout(panelState->bounds);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user