220 lines
7.4 KiB
C++
220 lines
7.4 KiB
C++
#pragma once
|
|
|
|
#include "ProjectPanel.h"
|
|
|
|
#include "Rendering/Assets/BuiltInIcons.h"
|
|
#include "UI/Styles/EditorTreeViewStyle.h"
|
|
|
|
#include <XCEditor/Collections/UIEditorTreeView.h>
|
|
#include <XCEditor/Foundation/UIEditorTheme.h>
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <string_view>
|
|
|
|
namespace XCEngine::UI::Editor::App::ProjectPanelSupport {
|
|
|
|
using ::XCEngine::UI::Editor::UIEditorTextMeasureRequest;
|
|
using ::XCEngine::UI::Editor::UIEditorTextMeasurer;
|
|
using ::XCEngine::UI::UIColor;
|
|
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;
|
|
|
|
inline constexpr std::string_view kProjectPanelId = "project";
|
|
inline constexpr std::size_t kInvalidLayoutIndex = static_cast<std::size_t>(-1);
|
|
|
|
inline constexpr float kBrowserHeaderHeight = 24.0f;
|
|
inline constexpr float kNavigationMinWidth = 180.0f;
|
|
inline constexpr float kBrowserMinWidth = 260.0f;
|
|
inline constexpr float kHeaderHorizontalPadding = 10.0f;
|
|
inline constexpr float kHeaderBottomBorderThickness = 1.0f;
|
|
inline constexpr float kBreadcrumbItemPaddingX = 4.0f;
|
|
inline constexpr float kBreadcrumbItemPaddingY = 1.0f;
|
|
inline constexpr float kBreadcrumbSpacing = 3.0f;
|
|
inline constexpr float kTreeTopPadding = 0.0f;
|
|
inline constexpr float kGridInsetX = 16.0f;
|
|
inline constexpr float kGridInsetY = 12.0f;
|
|
inline constexpr float kGridTileWidth = 92.0f;
|
|
inline constexpr float kGridTileHeight = 92.0f;
|
|
inline constexpr float kGridTileGapX = 12.0f;
|
|
inline constexpr float kGridTileGapY = 12.0f;
|
|
inline constexpr float kGridPreviewWidth = 68.0f;
|
|
inline constexpr float kGridPreviewHeight = 54.0f;
|
|
inline constexpr float kHeaderFontSize = 12.0f;
|
|
inline constexpr float kTileLabelFontSize = 11.0f;
|
|
|
|
inline constexpr UIColor kSurfaceColor(0.10f, 0.10f, 0.10f, 1.0f);
|
|
inline constexpr UIColor kPaneColor(0.10f, 0.10f, 0.10f, 1.0f);
|
|
inline constexpr UIColor kHeaderColor(0.11f, 0.11f, 0.11f, 1.0f);
|
|
inline constexpr UIColor kTextPrimary(0.880f, 0.880f, 0.880f, 1.0f);
|
|
inline constexpr UIColor kTextStrong(0.930f, 0.930f, 0.930f, 1.0f);
|
|
inline constexpr UIColor kTextMuted(0.640f, 0.640f, 0.640f, 1.0f);
|
|
inline constexpr UIColor kTileHoverColor(0.14f, 0.14f, 0.14f, 1.0f);
|
|
inline constexpr UIColor kTileSelectedColor(0.18f, 0.18f, 0.18f, 1.0f);
|
|
inline constexpr UIColor kTilePreviewFillColor(0.15f, 0.15f, 0.15f, 1.0f);
|
|
inline constexpr UIColor kTilePreviewShadeColor(0.12f, 0.12f, 0.12f, 1.0f);
|
|
inline constexpr UIColor kTilePreviewOutlineColor(0.920f, 0.920f, 0.920f, 0.20f);
|
|
|
|
inline 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;
|
|
}
|
|
|
|
inline float ClampNonNegative(float value) {
|
|
return (std::max)(value, 0.0f);
|
|
}
|
|
|
|
inline float ResolveTextTop(float rectY, float rectHeight, float fontSize) {
|
|
const float lineHeight = fontSize * 1.6f;
|
|
return rectY + std::floor((rectHeight - lineHeight) * 0.5f);
|
|
}
|
|
|
|
inline float MeasureTextWidth(
|
|
const UIEditorTextMeasurer* textMeasurer,
|
|
std::string_view text,
|
|
float fontSize) {
|
|
if (text.empty()) {
|
|
return 0.0f;
|
|
}
|
|
|
|
if (textMeasurer != nullptr) {
|
|
const float measuredWidth =
|
|
textMeasurer->MeasureTextWidth(UIEditorTextMeasureRequest{ text, fontSize });
|
|
if (measuredWidth > 0.0f) {
|
|
return measuredWidth;
|
|
}
|
|
}
|
|
|
|
return static_cast<float>(text.size()) * fontSize * 0.56f;
|
|
}
|
|
|
|
inline std::vector<UIInputEvent> FilterProjectPanelInputEvents(
|
|
const UIRect& bounds,
|
|
const std::vector<UIInputEvent>& inputEvents,
|
|
bool allowInteraction,
|
|
bool panelActive,
|
|
bool captureActive) {
|
|
if (!allowInteraction && !captureActive) {
|
|
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 (captureActive || ContainsPoint(bounds, event.position)) {
|
|
filteredEvents.push_back(event);
|
|
}
|
|
break;
|
|
case UIInputEventType::PointerLeave:
|
|
filteredEvents.push_back(event);
|
|
break;
|
|
case UIInputEventType::FocusGained:
|
|
case UIInputEventType::FocusLost:
|
|
if (panelActive || captureActive) {
|
|
filteredEvents.push_back(event);
|
|
}
|
|
break;
|
|
case UIInputEventType::KeyDown:
|
|
case UIInputEventType::KeyUp:
|
|
case UIInputEventType::Character:
|
|
if (panelActive) {
|
|
filteredEvents.push_back(event);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return filteredEvents;
|
|
}
|
|
|
|
inline std::vector<UIInputEvent> FilterTreeInputEvents(
|
|
const std::vector<UIInputEvent>& inputEvents,
|
|
bool suppressPointerInput) {
|
|
if (!suppressPointerInput) {
|
|
return inputEvents;
|
|
}
|
|
|
|
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:
|
|
case UIInputEventType::PointerEnter:
|
|
break;
|
|
default:
|
|
filteredEvents.push_back(event);
|
|
break;
|
|
}
|
|
}
|
|
return filteredEvents;
|
|
}
|
|
|
|
inline ::XCEngine::UI::UITextureHandle ResolveFolderIcon(const BuiltInIcons* icons) {
|
|
return icons != nullptr
|
|
? icons->Resolve(BuiltInIconKind::Folder)
|
|
: ::XCEngine::UI::UITextureHandle {};
|
|
}
|
|
|
|
inline float ClampNavigationWidth(float value, float totalWidth) {
|
|
const float maxWidth =
|
|
(std::max)(
|
|
kNavigationMinWidth,
|
|
totalWidth - kBrowserMinWidth - ResolveUIEditorDockHostMetrics().splitterMetrics.thickness);
|
|
return std::clamp(value, kNavigationMinWidth, maxWidth);
|
|
}
|
|
|
|
inline void AppendTilePreview(
|
|
UIDrawList& drawList,
|
|
const UIRect& previewRect,
|
|
bool directory) {
|
|
if (directory) {
|
|
const UIRect tabRect(
|
|
previewRect.x + 8.0f,
|
|
previewRect.y + 7.0f,
|
|
22.0f,
|
|
7.0f);
|
|
const UIRect bodyRect(
|
|
previewRect.x + 4.0f,
|
|
previewRect.y + 13.0f,
|
|
previewRect.width - 8.0f,
|
|
previewRect.height - 18.0f);
|
|
drawList.AddFilledRect(tabRect, kTilePreviewShadeColor, 1.0f);
|
|
drawList.AddFilledRect(bodyRect, kTilePreviewFillColor, 1.0f);
|
|
drawList.AddRectOutline(bodyRect, kTilePreviewOutlineColor, 1.0f, 1.0f);
|
|
return;
|
|
}
|
|
|
|
const UIRect sheetRect(
|
|
previewRect.x + 10.0f,
|
|
previewRect.y + 4.0f,
|
|
previewRect.width - 20.0f,
|
|
previewRect.height - 8.0f);
|
|
const UIRect accentRect(
|
|
sheetRect.x,
|
|
sheetRect.y,
|
|
sheetRect.width,
|
|
7.0f);
|
|
drawList.AddFilledRect(sheetRect, kTilePreviewFillColor, 1.0f);
|
|
drawList.AddFilledRect(accentRect, kTilePreviewShadeColor, 1.0f);
|
|
drawList.AddRectOutline(sheetRect, kTilePreviewOutlineColor, 1.0f, 1.0f);
|
|
}
|
|
|
|
} // namespace XCEngine::UI::Editor::App::ProjectPanelSupport
|