ui: add vector4 editor field validation

This commit is contained in:
2026-04-08 03:23:15 +08:00
parent 2e961295bf
commit 7be3b2cc45
19 changed files with 2346 additions and 2 deletions

View File

@@ -7,6 +7,9 @@
#include <XCEditor/Widgets/UIEditorNumberField.h>
#include <XCEditor/Widgets/UIEditorTextField.h>
#include <XCEditor/Widgets/UIEditorTextLayout.h>
#include <XCEditor/Widgets/UIEditorVector2Field.h>
#include <XCEditor/Widgets/UIEditorVector3Field.h>
#include <XCEditor/Widgets/UIEditorVector4Field.h>
#include <XCEngine/UI/Widgets/UIPopupOverlayModel.h>
@@ -94,6 +97,48 @@ UIEditorTextFieldSpec BuildTextFieldSpec(const UIEditorPropertyGridField& field)
return spec;
}
UIEditorVector2FieldSpec BuildVector2FieldSpec(const UIEditorPropertyGridField& field) {
UIEditorVector2FieldSpec spec = {};
spec.fieldId = field.fieldId;
spec.label = field.label;
spec.values = field.vector2Value.values;
spec.componentLabels = field.vector2Value.componentLabels;
spec.step = field.vector2Value.step;
spec.minValue = field.vector2Value.minValue;
spec.maxValue = field.vector2Value.maxValue;
spec.integerMode = field.vector2Value.integerMode;
spec.readOnly = field.readOnly;
return spec;
}
UIEditorVector3FieldSpec BuildVector3FieldSpec(const UIEditorPropertyGridField& field) {
UIEditorVector3FieldSpec spec = {};
spec.fieldId = field.fieldId;
spec.label = field.label;
spec.values = field.vector3Value.values;
spec.componentLabels = field.vector3Value.componentLabels;
spec.step = field.vector3Value.step;
spec.minValue = field.vector3Value.minValue;
spec.maxValue = field.vector3Value.maxValue;
spec.integerMode = field.vector3Value.integerMode;
spec.readOnly = field.readOnly;
return spec;
}
UIEditorVector4FieldSpec BuildVector4FieldSpec(const UIEditorPropertyGridField& field) {
UIEditorVector4FieldSpec spec = {};
spec.fieldId = field.fieldId;
spec.label = field.label;
spec.values = field.vector4Value.values;
spec.componentLabels = field.vector4Value.componentLabels;
spec.step = field.vector4Value.step;
spec.minValue = field.vector4Value.minValue;
spec.maxValue = field.vector4Value.maxValue;
spec.integerMode = field.vector4Value.integerMode;
spec.readOnly = field.readOnly;
return spec;
}
struct UIEditorPropertyGridFieldRects {
UIRect labelRect = {};
UIRect valueRect = {};
@@ -128,6 +173,30 @@ UIEditorPropertyGridFieldRects ResolveFieldRects(
return { fieldLayout.labelRect, fieldLayout.valueRect };
}
case UIEditorPropertyGridFieldKind::Vector2: {
const UIEditorVector2FieldLayout fieldLayout = BuildUIEditorVector2FieldLayout(
rowRect,
BuildVector2FieldSpec(field),
::XCEngine::UI::Editor::BuildUIEditorHostedVector2FieldMetrics(metrics));
return { fieldLayout.labelRect, fieldLayout.controlRect };
}
case UIEditorPropertyGridFieldKind::Vector3: {
const UIEditorVector3FieldLayout fieldLayout = BuildUIEditorVector3FieldLayout(
rowRect,
BuildVector3FieldSpec(field),
::XCEngine::UI::Editor::BuildUIEditorHostedVector3FieldMetrics(metrics));
return { fieldLayout.labelRect, fieldLayout.controlRect };
}
case UIEditorPropertyGridFieldKind::Vector4: {
const UIEditorVector4FieldLayout fieldLayout = BuildUIEditorVector4FieldLayout(
rowRect,
BuildVector4FieldSpec(field),
::XCEngine::UI::Editor::BuildUIEditorHostedVector4FieldMetrics(metrics));
return { fieldLayout.labelRect, fieldLayout.controlRect };
}
case UIEditorPropertyGridFieldKind::Text:
default: {
const UIEditorTextFieldLayout fieldLayout = BuildUIEditorTextFieldLayout(
@@ -199,6 +268,36 @@ UIEditorTextFieldHitTargetKind ResolveTextHoveredTarget(
: UIEditorTextFieldHitTargetKind::Row;
}
UIEditorVector2FieldHitTargetKind ResolveVector2HoveredTarget(
const UIEditorPropertyGridState& state,
const UIEditorPropertyGridField& field) {
if (state.hoveredFieldId != field.fieldId) {
return UIEditorVector2FieldHitTargetKind::None;
}
return UIEditorVector2FieldHitTargetKind::Row;
}
UIEditorVector3FieldHitTargetKind ResolveVector3HoveredTarget(
const UIEditorPropertyGridState& state,
const UIEditorPropertyGridField& field) {
if (state.hoveredFieldId != field.fieldId) {
return UIEditorVector3FieldHitTargetKind::None;
}
return UIEditorVector3FieldHitTargetKind::Row;
}
UIEditorVector4FieldHitTargetKind ResolveVector4HoveredTarget(
const UIEditorPropertyGridState& state,
const UIEditorPropertyGridField& field) {
if (state.hoveredFieldId != field.fieldId) {
return UIEditorVector4FieldHitTargetKind::None;
}
return UIEditorVector4FieldHitTargetKind::Row;
}
std::vector<UIEditorMenuPopupItem> BuildEnumPopupItems(
const UIEditorPropertyGridField& field) {
std::vector<UIEditorMenuPopupItem> items = {};
@@ -280,6 +379,27 @@ bool BuildEnumPopupRuntime(
return true;
}
std::string FormatVector2ValueText(const UIEditorPropertyGridField& field) {
const UIEditorVector2FieldSpec spec = BuildVector2FieldSpec(field);
return FormatUIEditorVector2FieldComponentValue(spec, 0u) + ", " +
FormatUIEditorVector2FieldComponentValue(spec, 1u);
}
std::string FormatVector3ValueText(const UIEditorPropertyGridField& field) {
const UIEditorVector3FieldSpec spec = BuildVector3FieldSpec(field);
return FormatUIEditorVector3FieldComponentValue(spec, 0u) + ", " +
FormatUIEditorVector3FieldComponentValue(spec, 1u) + ", " +
FormatUIEditorVector3FieldComponentValue(spec, 2u);
}
std::string FormatVector4ValueText(const UIEditorPropertyGridField& field) {
const UIEditorVector4FieldSpec spec = BuildVector4FieldSpec(field);
return FormatUIEditorVector4FieldComponentValue(spec, 0u) + ", " +
FormatUIEditorVector4FieldComponentValue(spec, 1u) + ", " +
FormatUIEditorVector4FieldComponentValue(spec, 2u) + ", " +
FormatUIEditorVector4FieldComponentValue(spec, 3u);
}
} // namespace
bool IsUIEditorPropertyGridPointInside(
@@ -330,6 +450,15 @@ std::string ResolveUIEditorPropertyGridFieldValueText(
case UIEditorPropertyGridFieldKind::Enum:
return ResolveUIEditorEnumFieldValueText(BuildEnumFieldSpec(field));
case UIEditorPropertyGridFieldKind::Vector2:
return FormatVector2ValueText(field);
case UIEditorPropertyGridFieldKind::Vector3:
return FormatVector3ValueText(field);
case UIEditorPropertyGridFieldKind::Vector4:
return FormatVector4ValueText(field);
case UIEditorPropertyGridFieldKind::Text:
default:
return field.valueText;
@@ -571,6 +700,18 @@ void AppendUIEditorPropertyGridForeground(
::XCEngine::UI::Editor::BuildUIEditorHostedTextFieldMetrics(metrics);
const UIEditorTextFieldPalette textPalette =
::XCEngine::UI::Editor::BuildUIEditorHostedTextFieldPalette(palette);
const UIEditorVector2FieldMetrics vector2Metrics =
::XCEngine::UI::Editor::BuildUIEditorHostedVector2FieldMetrics(metrics);
const UIEditorVector2FieldPalette vector2Palette =
::XCEngine::UI::Editor::BuildUIEditorHostedVector2FieldPalette(palette);
const UIEditorVector3FieldMetrics vector3Metrics =
::XCEngine::UI::Editor::BuildUIEditorHostedVector3FieldMetrics(metrics);
const UIEditorVector3FieldPalette vector3Palette =
::XCEngine::UI::Editor::BuildUIEditorHostedVector3FieldPalette(palette);
const UIEditorVector4FieldMetrics vector4Metrics =
::XCEngine::UI::Editor::BuildUIEditorHostedVector4FieldMetrics(metrics);
const UIEditorVector4FieldPalette vector4Palette =
::XCEngine::UI::Editor::BuildUIEditorHostedVector4FieldPalette(palette);
const UIEditorEnumFieldMetrics enumMetrics =
::XCEngine::UI::Editor::BuildUIEditorHostedEnumFieldMetrics(metrics);
const UIEditorEnumFieldPalette enumPalette =
@@ -640,6 +781,60 @@ void AppendUIEditorPropertyGridForeground(
break;
}
case UIEditorPropertyGridFieldKind::Vector2: {
UIEditorVector2FieldState fieldState = {};
fieldState.hoveredTarget = ResolveVector2HoveredTarget(state, field);
fieldState.activeTarget =
state.pressedFieldId == field.fieldId
? UIEditorVector2FieldHitTargetKind::Row
: UIEditorVector2FieldHitTargetKind::None;
fieldState.focused = state.focused;
AppendUIEditorVector2Field(
drawList,
layout.fieldRowRects[visibleFieldIndex],
BuildVector2FieldSpec(field),
fieldState,
vector2Palette,
vector2Metrics);
break;
}
case UIEditorPropertyGridFieldKind::Vector3: {
UIEditorVector3FieldState fieldState = {};
fieldState.hoveredTarget = ResolveVector3HoveredTarget(state, field);
fieldState.activeTarget =
state.pressedFieldId == field.fieldId
? UIEditorVector3FieldHitTargetKind::Row
: UIEditorVector3FieldHitTargetKind::None;
fieldState.focused = state.focused;
AppendUIEditorVector3Field(
drawList,
layout.fieldRowRects[visibleFieldIndex],
BuildVector3FieldSpec(field),
fieldState,
vector3Palette,
vector3Metrics);
break;
}
case UIEditorPropertyGridFieldKind::Vector4: {
UIEditorVector4FieldState fieldState = {};
fieldState.hoveredTarget = ResolveVector4HoveredTarget(state, field);
fieldState.activeTarget =
state.pressedFieldId == field.fieldId
? UIEditorVector4FieldHitTargetKind::Row
: UIEditorVector4FieldHitTargetKind::None;
fieldState.focused = state.focused;
AppendUIEditorVector4Field(
drawList,
layout.fieldRowRects[visibleFieldIndex],
BuildVector4FieldSpec(field),
fieldState,
vector4Palette,
vector4Metrics);
break;
}
case UIEditorPropertyGridFieldKind::Text:
default: {
const std::string& displayedValue =