Files
XCEngine/new_editor/app/Panels/ProductHierarchyPanel.cpp

190 lines
5.8 KiB
C++

#include "ProductHierarchyPanel.h"
#include "Icons/ProductBuiltInIcons.h"
#include "Panels/ProductTreeViewStyle.h"
#include <XCEditor/Collections/UIEditorTreeView.h>
#include <string>
#include <string_view>
namespace XCEngine::UI::Editor::App {
namespace {
using ::XCEngine::UI::UIDrawList;
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
using ::XCEngine::UI::UIPoint;
using ::XCEngine::UI::UIRect;
using Widgets::AppendUIEditorTreeViewBackground;
using Widgets::AppendUIEditorTreeViewForeground;
constexpr std::string_view kHierarchyPanelId = "hierarchy";
bool ContainsPoint(const UIRect& rect, const UIPoint& point) {
return point.x >= rect.x &&
point.x <= rect.x + rect.width &&
point.y >= rect.y &&
point.y <= rect.y + rect.height;
}
std::vector<UIInputEvent> FilterHierarchyInputEvents(
const UIRect& bounds,
const std::vector<UIInputEvent>& inputEvents,
bool allowInteraction,
bool panelActive) {
if (!allowInteraction) {
return {};
}
std::vector<UIInputEvent> filteredEvents = {};
filteredEvents.reserve(inputEvents.size());
for (const UIInputEvent& event : inputEvents) {
switch (event.type) {
case UIInputEventType::PointerMove:
case UIInputEventType::PointerButtonDown:
case UIInputEventType::PointerButtonUp:
case UIInputEventType::PointerWheel:
if (ContainsPoint(bounds, event.position)) {
filteredEvents.push_back(event);
}
break;
case UIInputEventType::PointerLeave:
filteredEvents.push_back(event);
break;
case UIInputEventType::FocusGained:
case UIInputEventType::FocusLost:
case UIInputEventType::KeyDown:
case UIInputEventType::KeyUp:
case UIInputEventType::Character:
if (panelActive) {
filteredEvents.push_back(event);
}
break;
default:
break;
}
}
return filteredEvents;
}
::XCEngine::UI::UITextureHandle ResolveGameObjectIcon(
const ProductBuiltInIcons* icons) {
return icons != nullptr
? icons->Resolve(ProductBuiltInIconKind::GameObject)
: ::XCEngine::UI::UITextureHandle {};
}
} // namespace
void ProductHierarchyPanel::Initialize() {
RebuildItems();
}
void ProductHierarchyPanel::SetBuiltInIcons(const ProductBuiltInIcons* icons) {
m_icons = icons;
RebuildItems();
}
const UIEditorPanelContentHostPanelState* ProductHierarchyPanel::FindMountedHierarchyPanel(
const UIEditorPanelContentHostFrame& contentHostFrame) const {
for (const UIEditorPanelContentHostPanelState& panelState : contentHostFrame.panelStates) {
if (panelState.panelId == kHierarchyPanelId && panelState.mounted) {
return &panelState;
}
}
return nullptr;
}
void ProductHierarchyPanel::RebuildItems() {
const auto icon = ResolveGameObjectIcon(m_icons);
const std::string previousSelection =
m_selection.HasSelection() ? m_selection.GetSelectedId() : std::string();
m_treeItems = {
{ "main-camera", "Main Camera", 0u, true, 0.0f, icon },
{ "directional-light", "Directional Light", 0u, true, 0.0f, icon },
{ "player", "Player", 0u, false, 0.0f, icon },
{ "player/camera-pivot", "Camera Pivot", 1u, true, 0.0f, icon },
{ "player/mesh", "Mesh", 1u, true, 0.0f, icon },
{ "environment", "Environment", 0u, false, 0.0f, icon },
{ "environment/ground", "Ground", 1u, true, 0.0f, icon },
{ "environment/props", "Props", 1u, false, 0.0f, icon },
{ "environment/props/crate-01", "Crate_01", 2u, true, 0.0f, icon },
{ "environment/props/barrel-01", "Barrel_01", 2u, true, 0.0f, icon }
};
m_expansion.Expand("player");
m_expansion.Expand("environment");
m_expansion.Expand("environment/props");
if (!previousSelection.empty()) {
for (const Widgets::UIEditorTreeViewItem& item : m_treeItems) {
if (item.itemId == previousSelection) {
m_selection.SetSelection(previousSelection);
return;
}
}
}
if (!m_treeItems.empty()) {
m_selection.SetSelection(m_treeItems.front().itemId);
}
}
void ProductHierarchyPanel::Update(
const UIEditorPanelContentHostFrame& contentHostFrame,
const std::vector<UIInputEvent>& inputEvents,
bool allowInteraction,
bool panelActive) {
const UIEditorPanelContentHostPanelState* panelState =
FindMountedHierarchyPanel(contentHostFrame);
if (panelState == nullptr) {
m_visible = false;
m_treeFrame = {};
return;
}
if (m_treeItems.empty()) {
RebuildItems();
}
m_visible = true;
m_treeFrame = UpdateUIEditorTreeViewInteraction(
m_treeInteractionState,
m_selection,
m_expansion,
panelState->bounds,
m_treeItems,
FilterHierarchyInputEvents(panelState->bounds, inputEvents, allowInteraction, panelActive),
BuildProductTreeViewMetrics());
}
void ProductHierarchyPanel::Append(UIDrawList& drawList) const {
if (!m_visible || m_treeFrame.layout.bounds.width <= 0.0f || m_treeFrame.layout.bounds.height <= 0.0f) {
return;
}
const Widgets::UIEditorTreeViewPalette palette = BuildProductTreeViewPalette();
const Widgets::UIEditorTreeViewMetrics metrics = BuildProductTreeViewMetrics();
AppendUIEditorTreeViewBackground(
drawList,
m_treeFrame.layout,
m_treeItems,
m_selection,
m_treeInteractionState.treeViewState,
palette,
metrics);
AppendUIEditorTreeViewForeground(
drawList,
m_treeFrame.layout,
m_treeItems,
palette,
metrics);
}
} // namespace XCEngine::UI::Editor::App