Add editor typed field widgets and validation scenarios

This commit is contained in:
2026-04-07 17:55:42 +08:00
parent e22ce763c2
commit 5a3232c099
32 changed files with 4635 additions and 1 deletions

View File

@@ -0,0 +1,113 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <cstdint>
#include <string>
namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorBoolFieldHitTargetKind : std::uint8_t {
None = 0,
Row,
Toggle
};
struct UIEditorBoolFieldSpec {
std::string fieldId = {};
std::string label = {};
bool value = false;
bool readOnly = false;
};
struct UIEditorBoolFieldState {
UIEditorBoolFieldHitTargetKind hoveredTarget = UIEditorBoolFieldHitTargetKind::None;
bool focused = false;
bool active = false;
};
struct UIEditorBoolFieldMetrics {
float rowHeight = 32.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float toggleWidth = 42.0f;
float toggleHeight = 20.0f;
float toggleKnobInset = 3.0f;
float textInsetY = 8.0f;
float cornerRounding = 6.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 2.0f;
};
struct UIEditorBoolFieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.22f, 0.22f, 0.22f, 1.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.28f, 0.28f, 0.28f, 1.0f);
::XCEngine::UI::UIColor toggleOffColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
::XCEngine::UI::UIColor toggleOnColor =
::XCEngine::UI::UIColor(0.78f, 0.78f, 0.78f, 1.0f);
::XCEngine::UI::UIColor toggleReadOnlyColor =
::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
::XCEngine::UI::UIColor toggleBorderColor =
::XCEngine::UI::UIColor(0.36f, 0.36f, 0.36f, 1.0f);
::XCEngine::UI::UIColor knobColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor valueColor =
::XCEngine::UI::UIColor(0.70f, 0.70f, 0.70f, 1.0f);
};
struct UIEditorBoolFieldLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect toggleRect = {};
::XCEngine::UI::UIRect knobRect = {};
};
struct UIEditorBoolFieldHitTarget {
UIEditorBoolFieldHitTargetKind kind = UIEditorBoolFieldHitTargetKind::None;
};
UIEditorBoolFieldLayout BuildUIEditorBoolFieldLayout(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorBoolFieldSpec& spec,
const UIEditorBoolFieldMetrics& metrics = {});
UIEditorBoolFieldHitTarget HitTestUIEditorBoolField(
const UIEditorBoolFieldLayout& layout,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorBoolFieldBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorBoolFieldLayout& layout,
const UIEditorBoolFieldSpec& spec,
const UIEditorBoolFieldState& state,
const UIEditorBoolFieldPalette& palette = {},
const UIEditorBoolFieldMetrics& metrics = {});
void AppendUIEditorBoolFieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorBoolFieldLayout& layout,
const UIEditorBoolFieldSpec& spec,
const UIEditorBoolFieldPalette& palette = {},
const UIEditorBoolFieldMetrics& metrics = {});
void AppendUIEditorBoolField(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorBoolFieldSpec& spec,
const UIEditorBoolFieldState& state,
const UIEditorBoolFieldPalette& palette = {},
const UIEditorBoolFieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,127 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorEnumFieldHitTargetKind : std::uint8_t {
None = 0,
Row,
PreviousButton,
NextButton,
ValueBox
};
struct UIEditorEnumFieldSpec {
std::string fieldId = {};
std::string label = {};
std::vector<std::string> options = {};
std::size_t selectedIndex = 0u;
bool readOnly = false;
};
struct UIEditorEnumFieldState {
UIEditorEnumFieldHitTargetKind hoveredTarget = UIEditorEnumFieldHitTargetKind::None;
bool focused = false;
bool active = false;
};
struct UIEditorEnumFieldMetrics {
float rowHeight = 32.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float buttonWidth = 24.0f;
float controlGap = 4.0f;
float valueBoxMinWidth = 96.0f;
float valueBoxHeight = 24.0f;
float labelTextInsetY = 8.0f;
float valueTextInsetX = 8.0f;
float valueTextInsetY = 6.0f;
float buttonTextInsetX = 8.0f;
float buttonTextInsetY = 6.0f;
float cornerRounding = 6.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 2.0f;
};
struct UIEditorEnumFieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.22f, 0.22f, 0.22f, 1.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.28f, 0.28f, 0.28f, 1.0f);
::XCEngine::UI::UIColor valueBoxColor =
::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
::XCEngine::UI::UIColor buttonColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
::XCEngine::UI::UIColor buttonHoverColor =
::XCEngine::UI::UIColor(0.30f, 0.30f, 0.30f, 1.0f);
::XCEngine::UI::UIColor readOnlyColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor controlBorderColor =
::XCEngine::UI::UIColor(0.36f, 0.36f, 0.36f, 1.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor valueColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
};
struct UIEditorEnumFieldLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
::XCEngine::UI::UIRect valueRect = {};
::XCEngine::UI::UIRect previousRect = {};
::XCEngine::UI::UIRect nextRect = {};
};
struct UIEditorEnumFieldHitTarget {
UIEditorEnumFieldHitTargetKind kind = UIEditorEnumFieldHitTargetKind::None;
};
std::string ResolveUIEditorEnumFieldValueText(const UIEditorEnumFieldSpec& spec);
UIEditorEnumFieldLayout BuildUIEditorEnumFieldLayout(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorEnumFieldSpec& spec,
const UIEditorEnumFieldMetrics& metrics = {});
UIEditorEnumFieldHitTarget HitTestUIEditorEnumField(
const UIEditorEnumFieldLayout& layout,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorEnumFieldBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorEnumFieldLayout& layout,
const UIEditorEnumFieldSpec& spec,
const UIEditorEnumFieldState& state,
const UIEditorEnumFieldPalette& palette = {},
const UIEditorEnumFieldMetrics& metrics = {});
void AppendUIEditorEnumFieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorEnumFieldLayout& layout,
const UIEditorEnumFieldSpec& spec,
const UIEditorEnumFieldPalette& palette = {},
const UIEditorEnumFieldMetrics& metrics = {});
void AppendUIEditorEnumField(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorEnumFieldSpec& spec,
const UIEditorEnumFieldState& state,
const UIEditorEnumFieldPalette& palette = {},
const UIEditorEnumFieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,146 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <cstddef>
#include <cstdint>
#include <string>
namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorNumberFieldHitTargetKind : std::uint8_t {
None = 0,
Row,
DecrementButton,
IncrementButton,
ValueBox
};
struct UIEditorNumberFieldSpec {
std::string fieldId = {};
std::string label = {};
double value = 0.0;
double step = 1.0;
double minValue = 0.0;
double maxValue = 100.0;
bool integerMode = true;
bool readOnly = false;
};
struct UIEditorNumberFieldState {
UIEditorNumberFieldHitTargetKind hoveredTarget = UIEditorNumberFieldHitTargetKind::None;
UIEditorNumberFieldHitTargetKind activeTarget = UIEditorNumberFieldHitTargetKind::None;
bool focused = false;
bool editing = false;
std::string displayText = {};
};
struct UIEditorNumberFieldMetrics {
float rowHeight = 32.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float buttonWidth = 22.0f;
float buttonGap = 4.0f;
float valueBoxMinWidth = 72.0f;
float controlInsetY = 4.0f;
float labelTextInsetY = 8.0f;
float valueTextInsetX = 8.0f;
float valueTextInsetY = 8.0f;
float buttonTextInsetY = 8.0f;
float cornerRounding = 6.0f;
float valueBoxRounding = 5.0f;
float buttonRounding = 4.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 2.0f;
};
struct UIEditorNumberFieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.22f, 0.22f, 0.22f, 1.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.28f, 0.28f, 0.28f, 1.0f);
::XCEngine::UI::UIColor valueBoxColor =
::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
::XCEngine::UI::UIColor valueBoxHoverColor =
::XCEngine::UI::UIColor(0.22f, 0.22f, 0.22f, 1.0f);
::XCEngine::UI::UIColor valueBoxEditingColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
::XCEngine::UI::UIColor buttonColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
::XCEngine::UI::UIColor buttonHoverColor =
::XCEngine::UI::UIColor(0.30f, 0.30f, 0.30f, 1.0f);
::XCEngine::UI::UIColor buttonActiveColor =
::XCEngine::UI::UIColor(0.36f, 0.36f, 0.36f, 1.0f);
::XCEngine::UI::UIColor readOnlyColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor controlBorderColor =
::XCEngine::UI::UIColor(0.36f, 0.36f, 0.36f, 1.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor valueColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor readOnlyValueColor =
::XCEngine::UI::UIColor(0.62f, 0.62f, 0.62f, 1.0f);
::XCEngine::UI::UIColor stepTextColor =
::XCEngine::UI::UIColor(0.90f, 0.90f, 0.90f, 1.0f);
};
struct UIEditorNumberFieldLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
::XCEngine::UI::UIRect valueRect = {};
::XCEngine::UI::UIRect decrementRect = {};
::XCEngine::UI::UIRect incrementRect = {};
};
struct UIEditorNumberFieldHitTarget {
UIEditorNumberFieldHitTargetKind kind = UIEditorNumberFieldHitTargetKind::None;
};
bool IsUIEditorNumberFieldPointInside(
const ::XCEngine::UI::UIRect& rect,
const ::XCEngine::UI::UIPoint& point);
std::string FormatUIEditorNumberFieldValue(const UIEditorNumberFieldSpec& spec);
UIEditorNumberFieldLayout BuildUIEditorNumberFieldLayout(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorNumberFieldSpec& spec,
const UIEditorNumberFieldMetrics& metrics = {});
UIEditorNumberFieldHitTarget HitTestUIEditorNumberField(
const UIEditorNumberFieldLayout& layout,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorNumberFieldBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorNumberFieldLayout& layout,
const UIEditorNumberFieldSpec& spec,
const UIEditorNumberFieldState& state,
const UIEditorNumberFieldPalette& palette = {},
const UIEditorNumberFieldMetrics& metrics = {});
void AppendUIEditorNumberFieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorNumberFieldLayout& layout,
const UIEditorNumberFieldSpec& spec,
const UIEditorNumberFieldPalette& palette = {},
const UIEditorNumberFieldMetrics& metrics = {});
void AppendUIEditorNumberField(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorNumberFieldSpec& spec,
const UIEditorNumberFieldState& state,
const UIEditorNumberFieldPalette& palette = {},
const UIEditorNumberFieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets