refactor(new_editor): snapshot hosted editor restructuring

This commit is contained in:
2026-04-21 00:57:14 +08:00
parent e123e584c8
commit 9b7b369007
248 changed files with 21152 additions and 14397 deletions

View File

@@ -2,8 +2,11 @@
#include "Ports/TexturePort.h"
#include <XCEditor/Widgets/UIEditorTextLayout.h>
#include <algorithm>
#include <array>
#include <cmath>
namespace XCEngine::UI::Editor::App {
@@ -13,6 +16,9 @@ using ::XCEngine::UI::UIColor;
using ::XCEngine::UI::UIDrawList;
using ::XCEngine::UI::UIPoint;
using ::XCEngine::UI::UIRect;
using Widgets::MeasureUIEditorTextWidth;
using Widgets::ResolveUIEditorTextClipRect;
using Widgets::ResolveUIEditorTextTop;
constexpr float kButtonExtent = 26.0f;
constexpr float kButtonSpacing = 4.0f;
@@ -22,6 +28,13 @@ constexpr float kIconInset = 3.0f;
constexpr float kPanelCornerRounding = 6.0f;
constexpr float kButtonCornerRounding = 4.0f;
constexpr float kFallbackFontSize = 10.0f;
constexpr float kToggleFontSize = 13.0f;
constexpr float kToggleHorizontalPadding = 8.0f;
constexpr float kTopBarButtonInsetX = 0.0f;
constexpr float kTopBarButtonInsetY = 3.0f;
constexpr float kToggleButtonSpacing = 6.0f;
constexpr float kToggleButtonCornerRounding = 5.0f;
constexpr float kToggleMinWidth = 60.0f;
struct ToolButtonSpec {
SceneToolMode mode = SceneToolMode::View;
@@ -45,6 +58,45 @@ bool ContainsPoint(const UIRect& rect, const UIPoint& point) {
point.y <= rect.y + rect.height;
}
std::string_view ResolveToggleLabel(
SceneViewportToggleButtonKind kind,
SceneToolPivotMode pivotMode,
SceneToolSpaceMode spaceMode) {
switch (kind) {
case SceneViewportToggleButtonKind::Pivot:
return pivotMode == SceneToolPivotMode::Center
? std::string_view("Center")
: std::string_view("Pivot");
case SceneViewportToggleButtonKind::Space:
return spaceMode == SceneToolSpaceMode::Local
? std::string_view("Local")
: std::string_view("Global");
default:
return {};
}
}
float ResolveToggleWidth(std::string_view firstLabel, std::string_view secondLabel) {
const float firstWidth =
MeasureUIEditorTextWidth(std::string(firstLabel), kToggleFontSize);
const float secondWidth =
MeasureUIEditorTextWidth(std::string(secondLabel), kToggleFontSize);
return (std::max)(
kToggleMinWidth,
std::ceil((std::max)(firstWidth, secondWidth) + kToggleHorizontalPadding * 2.0f));
}
float ResolveToggleWidth(SceneViewportToggleButtonKind kind) {
switch (kind) {
case SceneViewportToggleButtonKind::Pivot:
return ResolveToggleWidth("Pivot", "Center");
case SceneViewportToggleButtonKind::Space:
return ResolveToggleWidth("Global", "Local");
default:
return kToggleMinWidth;
}
}
UIRect BuildButtonRect(const UIRect& panelRect, std::size_t index) {
return UIRect(
panelRect.x + kPanelPadding,
@@ -53,6 +105,99 @@ UIRect BuildButtonRect(const UIRect& panelRect, std::size_t index) {
kButtonExtent);
}
UIRect BuildToggleButtonRect(
const UIRect& topBarRect,
std::size_t index,
float width) {
const float buttonHeight =
(std::max)(topBarRect.height - kTopBarButtonInsetY * 2.0f, 0.0f);
return UIRect(
topBarRect.x + kTopBarButtonInsetX + static_cast<float>(index) * (width + kToggleButtonSpacing),
topBarRect.y + kTopBarButtonInsetY,
width,
buttonHeight);
}
::XCEngine::UI::UIColor ResolveToolButtonFill(
bool active,
bool hovered,
bool pressed) {
constexpr UIColor kButtonIdle(
44.0f / 255.0f,
44.0f / 255.0f,
44.0f / 255.0f,
230.0f / 255.0f);
constexpr UIColor kButtonHover(
66.0f / 255.0f,
66.0f / 255.0f,
66.0f / 255.0f,
240.0f / 255.0f);
constexpr UIColor kButtonPressed(
92.0f / 255.0f,
92.0f / 255.0f,
92.0f / 255.0f,
245.0f / 255.0f);
constexpr UIColor kButtonActive(
84.0f / 255.0f,
84.0f / 255.0f,
84.0f / 255.0f,
245.0f / 255.0f);
if (pressed) {
return kButtonPressed;
}
if (hovered) {
return active ? kButtonActive : kButtonHover;
}
return active ? kButtonActive : kButtonIdle;
}
::XCEngine::UI::UIColor ResolveToolIconTint(
bool active,
bool hovered,
bool pressed) {
if (pressed) {
return UIColor(1.0f, 1.0f, 1.0f, 1.0f);
}
if (active) {
return hovered
? UIColor(1.0f, 1.0f, 1.0f, 1.0f)
: UIColor(0.98f, 0.98f, 0.98f, 1.0f);
}
if (hovered) {
return UIColor(0.90f, 0.90f, 0.90f, 1.0f);
}
return UIColor(0.80f, 0.80f, 0.80f, 1.0f);
}
::XCEngine::UI::UIColor ResolveToggleButtonFill(
bool hovered,
bool pressed) {
constexpr UIColor kToggleIdle(
38.0f / 255.0f,
38.0f / 255.0f,
38.0f / 255.0f,
1.0f);
constexpr UIColor kToggleHover(
47.0f / 255.0f,
47.0f / 255.0f,
47.0f / 255.0f,
1.0f);
constexpr UIColor kTogglePressed(
56.0f / 255.0f,
56.0f / 255.0f,
56.0f / 255.0f,
1.0f);
if (pressed) {
return kTogglePressed;
}
if (hovered) {
return kToggleHover;
}
return kToggleIdle;
}
} // namespace
bool SceneViewportToolOverlay::Initialize(
@@ -61,7 +206,7 @@ bool SceneViewportToolOverlay::Initialize(
Shutdown(renderer);
const std::filesystem::path iconRoot =
(repoRoot / "editor" / "resources" / "Icons").lexically_normal();
(repoRoot / "new_editor" / "resources" / "Icons").lexically_normal();
bool loadedAnyTexture = false;
for (std::size_t index = 0; index < kToolButtonSpecs.size(); ++index) {
const ToolButtonSpec& path = kToolButtonSpecs[index];
@@ -103,16 +248,53 @@ void SceneViewportToolOverlay::ResetFrame() {
void SceneViewportToolOverlay::BuildFrame(
const UIRect& viewportRect,
const UIRect& topBarRect,
const UIRect& clipRect,
SceneToolMode activeMode,
SceneToolPivotMode pivotMode,
SceneToolSpaceMode spaceMode,
std::size_t hoveredIndex,
std::size_t pressedIndex) {
std::size_t pressedIndex,
std::size_t hoveredToggleIndex,
std::size_t pressedToggleIndex) {
m_frame = {};
if (viewportRect.width <= 1.0f || viewportRect.height <= 1.0f) {
return;
}
m_frame.visible = true;
m_frame.clipRect = viewportRect;
m_frame.clipRect = clipRect;
m_frame.toggleFrame.visible =
topBarRect.width > 1.0f && topBarRect.height > 1.0f;
const float pivotToggleWidth =
ResolveToggleWidth(SceneViewportToggleButtonKind::Pivot);
const float spaceToggleWidth =
ResolveToggleWidth(SceneViewportToggleButtonKind::Space);
m_frame.toggleFrame.panelRect = UIRect(
topBarRect.x + kTopBarButtonInsetX,
topBarRect.y,
pivotToggleWidth +
spaceToggleWidth +
kToggleButtonSpacing,
topBarRect.height);
for (std::size_t index = 0; index < m_frame.toggleFrame.buttons.size(); ++index) {
SceneViewportToggleButtonFrame& button =
m_frame.toggleFrame.buttons[index];
button = {};
button.kind = index == 0u
? SceneViewportToggleButtonKind::Pivot
: SceneViewportToggleButtonKind::Space;
button.label = std::string(
ResolveToggleLabel(button.kind, pivotMode, spaceMode));
button.rect = BuildToggleButtonRect(
topBarRect,
index,
index == 0u ? pivotToggleWidth : spaceToggleWidth);
button.active = true;
button.hovered = index == hoveredToggleIndex;
button.pressed = index == pressedToggleIndex;
}
m_frame.panelRect = UIRect(
viewportRect.x + kViewportInset,
viewportRect.y + kViewportInset,
@@ -132,14 +314,14 @@ void SceneViewportToolOverlay::BuildFrame(
button.active = spec.mode == activeMode;
button.hovered = index == hoveredIndex;
button.pressed = index == pressedIndex;
button.texture = button.active
button.texture = spec.mode == activeMode
? textureSet.activeTexture
: textureSet.inactiveTexture;
}
}
std::size_t SceneViewportToolOverlay::HitTest(const UIPoint& point) const {
if (!m_frame.visible || !Contains(point)) {
if (!m_frame.visible || !ContainsPoint(m_frame.panelRect, point)) {
return kSceneViewportToolOverlayInvalidIndex;
}
@@ -152,8 +334,27 @@ std::size_t SceneViewportToolOverlay::HitTest(const UIPoint& point) const {
return kSceneViewportToolOverlayInvalidIndex;
}
std::size_t SceneViewportToolOverlay::HitTestToggle(const UIPoint& point) const {
if (!m_frame.visible ||
!m_frame.toggleFrame.visible ||
!ContainsPoint(m_frame.toggleFrame.panelRect, point)) {
return kSceneViewportToolOverlayInvalidIndex;
}
for (std::size_t index = 0; index < m_frame.toggleFrame.buttons.size(); ++index) {
if (ContainsPoint(m_frame.toggleFrame.buttons[index].rect, point)) {
return index;
}
}
return kSceneViewportToolOverlayInvalidIndex;
}
bool SceneViewportToolOverlay::Contains(const UIPoint& point) const {
return m_frame.visible && ContainsPoint(m_frame.panelRect, point);
return m_frame.visible &&
(ContainsPoint(m_frame.panelRect, point) ||
(m_frame.toggleFrame.visible &&
ContainsPoint(m_frame.toggleFrame.panelRect, point)));
}
const SceneViewportToolOverlayFrame& SceneViewportToolOverlay::GetFrame() const {
@@ -169,31 +370,46 @@ void AppendSceneViewportToolOverlay(
constexpr UIColor kPanelFill(24.0f / 255.0f, 26.0f / 255.0f, 29.0f / 255.0f, 220.0f / 255.0f);
constexpr UIColor kPanelOutline(1.0f, 1.0f, 1.0f, 28.0f / 255.0f);
constexpr UIColor kButtonIdle(44.0f / 255.0f, 47.0f / 255.0f, 54.0f / 255.0f, 230.0f / 255.0f);
constexpr UIColor kButtonHover(68.0f / 255.0f, 74.0f / 255.0f, 84.0f / 255.0f, 240.0f / 255.0f);
constexpr UIColor kButtonPressed(86.0f / 255.0f, 96.0f / 255.0f, 109.0f / 255.0f, 245.0f / 255.0f);
constexpr UIColor kButtonActive(78.0f / 255.0f, 102.0f / 255.0f, 126.0f / 255.0f, 245.0f / 255.0f);
constexpr UIColor kButtonOutline(1.0f, 1.0f, 1.0f, 24.0f / 255.0f);
constexpr UIColor kButtonActiveOutline(1.0f, 1.0f, 1.0f, 48.0f / 255.0f);
constexpr UIColor kButtonActiveOutline(1.0f, 1.0f, 1.0f, 64.0f / 255.0f);
constexpr UIColor kToggleOutline(1.0f, 1.0f, 1.0f, 24.0f / 255.0f);
constexpr UIColor kToggleHoverOutline(1.0f, 1.0f, 1.0f, 40.0f / 255.0f);
constexpr UIColor kFallbackText(230.0f / 255.0f, 230.0f / 255.0f, 230.0f / 255.0f, 1.0f);
drawList.PushClipRect(frame.clipRect);
if (frame.toggleFrame.visible) {
for (const SceneViewportToggleButtonFrame& button : frame.toggleFrame.buttons) {
drawList.AddFilledRect(
button.rect,
ResolveToggleButtonFill(button.hovered, button.pressed),
kToggleButtonCornerRounding);
drawList.AddRectOutline(
button.rect,
button.hovered || button.pressed
? kToggleHoverOutline
: kToggleOutline,
1.0f,
kToggleButtonCornerRounding);
const float textWidth =
MeasureUIEditorTextWidth(button.label, kToggleFontSize);
const float textLeft = button.rect.x +
(std::max)(0.0f, std::floor((button.rect.width - textWidth) * 0.5f));
drawList.AddText(
UIPoint(textLeft, ResolveUIEditorTextTop(button.rect, kToggleFontSize)),
button.label,
kFallbackText,
kToggleFontSize);
}
}
drawList.AddFilledRect(frame.panelRect, kPanelFill, kPanelCornerRounding);
drawList.AddRectOutline(frame.panelRect, kPanelOutline, 1.0f, kPanelCornerRounding);
for (const SceneViewportToolOverlayButtonFrame& button : frame.buttons) {
UIColor fill = kButtonIdle;
if (button.active) {
fill = kButtonActive;
}
if (button.hovered) {
fill = button.active ? kButtonActive : kButtonHover;
}
if (button.pressed) {
fill = kButtonPressed;
}
drawList.AddFilledRect(button.rect, fill, kButtonCornerRounding);
drawList.AddFilledRect(
button.rect,
ResolveToolButtonFill(button.active, button.hovered, button.pressed),
kButtonCornerRounding);
drawList.AddRectOutline(
button.rect,
button.active ? kButtonActiveOutline : kButtonOutline,
@@ -206,7 +422,10 @@ void AppendSceneViewportToolOverlay(
button.rect.y + kIconInset,
button.rect.width - kIconInset * 2.0f,
button.rect.height - kIconInset * 2.0f);
drawList.AddImage(iconRect, button.texture);
drawList.AddImage(
iconRect,
button.texture,
ResolveToolIconTint(button.active, button.hovered, button.pressed));
continue;
}