ui: add typed editor field foundations

This commit is contained in:
2026-04-08 02:52:28 +08:00
parent 805e07bf90
commit 0a392e1311
69 changed files with 11676 additions and 1169 deletions

View File

@@ -1,9 +1,12 @@
#pragma once
#include <XCEditor/Widgets/UIEditorMenuPopup.h>
#include <XCEditor/Widgets/UIEditorEnumField.h>
#include <XCEngine/UI/Types.h>
#include <cstddef>
#include <string>
#include <vector>
namespace XCEngine::UI::Editor {
@@ -11,19 +14,29 @@ namespace XCEngine::UI::Editor {
struct UIEditorEnumFieldInteractionState {
Widgets::UIEditorEnumFieldState fieldState = {};
::XCEngine::UI::UIPoint pointerPosition = {};
std::size_t highlightedIndex = Widgets::UIEditorMenuPopupInvalidIndex;
std::size_t pressedPopupIndex = Widgets::UIEditorMenuPopupInvalidIndex;
bool hasPointerPosition = false;
bool popupOpen = false;
};
struct UIEditorEnumFieldInteractionResult {
bool consumed = false;
bool selectionChanged = false;
bool focusedChanged = false;
bool popupOpened = false;
bool popupClosed = false;
std::size_t selectedIndex = 0u;
Widgets::UIEditorEnumFieldHitTarget hitTarget = {};
std::size_t popupItemIndex = Widgets::UIEditorMenuPopupInvalidIndex;
};
struct UIEditorEnumFieldInteractionFrame {
Widgets::UIEditorEnumFieldLayout layout = {};
Widgets::UIEditorMenuPopupLayout popupLayout = {};
Widgets::UIEditorMenuPopupState popupState = {};
std::vector<Widgets::UIEditorMenuPopupItem> popupItems = {};
bool popupOpen = false;
UIEditorEnumFieldInteractionResult result = {};
};
@@ -33,6 +46,8 @@ UIEditorEnumFieldInteractionFrame UpdateUIEditorEnumFieldInteraction(
const ::XCEngine::UI::UIRect& bounds,
const Widgets::UIEditorEnumFieldSpec& spec,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorEnumFieldMetrics& metrics = {});
const Widgets::UIEditorEnumFieldMetrics& metrics = {},
const Widgets::UIEditorMenuPopupMetrics& popupMetrics = {},
const ::XCEngine::UI::UIRect& viewportRect = {});
} // namespace XCEngine::UI::Editor

View File

@@ -19,6 +19,7 @@ struct UIEditorPropertyGridInteractionState {
::XCEngine::UI::Widgets::UIKeyboardNavigationModel keyboardNavigation = {};
::XCEngine::UI::Text::UITextInputState textInputState = {};
::XCEngine::UI::UIPoint pointerPosition = {};
std::size_t pressedPopupIndex = Widgets::UIEditorPropertyGridInvalidIndex;
bool hasPointerPosition = false;
};
@@ -30,7 +31,11 @@ struct UIEditorPropertyGridInteractionResult {
bool editStarted = false;
bool editValueChanged = false;
bool editCommitted = false;
bool editCommitRejected = false;
bool editCanceled = false;
bool popupOpened = false;
bool popupClosed = false;
bool fieldValueChanged = false;
bool secondaryClicked = false;
Widgets::UIEditorPropertyGridHitTarget hitTarget = {};
std::string toggledSectionId = {};
@@ -38,6 +43,8 @@ struct UIEditorPropertyGridInteractionResult {
std::string activeFieldId = {};
std::string committedFieldId = {};
std::string committedValue = {};
std::string changedFieldId = {};
std::string changedValue = {};
};
struct UIEditorPropertyGridInteractionFrame {
@@ -51,8 +58,9 @@ UIEditorPropertyGridInteractionFrame UpdateUIEditorPropertyGridInteraction(
::XCEngine::UI::Widgets::UIExpansionModel& expansionModel,
::XCEngine::UI::Widgets::UIPropertyEditModel& propertyEditModel,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<Widgets::UIEditorPropertyGridSection>& sections,
std::vector<Widgets::UIEditorPropertyGridSection>& sections,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorPropertyGridMetrics& metrics = {});
const Widgets::UIEditorPropertyGridMetrics& metrics = {},
const Widgets::UIEditorMenuPopupMetrics& popupMetrics = {});
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,47 @@
#pragma once
#include <XCEditor/Widgets/UIEditorTextField.h>
#include <XCEngine/UI/Text/UITextInputController.h>
#include <XCEngine/UI/Types.h>
#include <XCEngine/UI/Widgets/UIPropertyEditModel.h>
#include <string>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorTextFieldInteractionState {
Widgets::UIEditorTextFieldState textFieldState = {};
::XCEngine::UI::Text::UITextInputState textInputState = {};
::XCEngine::UI::Widgets::UIPropertyEditModel editModel = {};
::XCEngine::UI::UIPoint pointerPosition = {};
bool hasPointerPosition = false;
};
struct UIEditorTextFieldInteractionResult {
bool consumed = false;
bool focusChanged = false;
bool valueChanged = false;
bool editStarted = false;
bool editCommitted = false;
bool editCanceled = false;
Widgets::UIEditorTextFieldHitTarget hitTarget = {};
std::string valueBefore = {};
std::string valueAfter = {};
std::string committedText = {};
};
struct UIEditorTextFieldInteractionFrame {
Widgets::UIEditorTextFieldLayout layout = {};
UIEditorTextFieldInteractionResult result = {};
};
UIEditorTextFieldInteractionFrame UpdateUIEditorTextFieldInteraction(
UIEditorTextFieldInteractionState& state,
Widgets::UIEditorTextFieldSpec& spec,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorTextFieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,140 @@
#pragma once
#include <XCEditor/Widgets/UIEditorBoolField.h>
#include <XCEditor/Widgets/UIEditorEnumField.h>
#include <XCEditor/Widgets/UIEditorMenuPopup.h>
#include <XCEditor/Widgets/UIEditorNumberField.h>
#include <XCEditor/Widgets/UIEditorPropertyGrid.h>
#include <XCEditor/Widgets/UIEditorTextField.h>
#include <XCEditor/Widgets/UIEditorVector2Field.h>
#include <XCEditor/Widgets/UIEditorVector3Field.h>
#include <XCEngine/UI/Style/Theme.h>
#include <string_view>
namespace XCEngine::UI::Editor {
float ResolveUIEditorThemeFloat(
const ::XCEngine::UI::Style::UITheme& theme,
std::string_view tokenName,
float fallbackValue);
::XCEngine::UI::UIColor ResolveUIEditorThemeColor(
const ::XCEngine::UI::Style::UITheme& theme,
std::string_view tokenName,
const ::XCEngine::UI::UIColor& fallbackValue);
Widgets::UIEditorBoolFieldMetrics ResolveUIEditorBoolFieldMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorBoolFieldMetrics& fallback = {});
Widgets::UIEditorBoolFieldPalette ResolveUIEditorBoolFieldPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorBoolFieldPalette& fallback = {});
Widgets::UIEditorNumberFieldMetrics ResolveUIEditorNumberFieldMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorNumberFieldMetrics& fallback = {});
Widgets::UIEditorNumberFieldPalette ResolveUIEditorNumberFieldPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorNumberFieldPalette& fallback = {});
Widgets::UIEditorTextFieldMetrics ResolveUIEditorTextFieldMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorTextFieldMetrics& fallback = {});
Widgets::UIEditorTextFieldPalette ResolveUIEditorTextFieldPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorTextFieldPalette& fallback = {});
Widgets::UIEditorVector2FieldMetrics ResolveUIEditorVector2FieldMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorVector2FieldMetrics& fallback = {});
Widgets::UIEditorVector2FieldPalette ResolveUIEditorVector2FieldPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorVector2FieldPalette& fallback = {});
Widgets::UIEditorVector3FieldMetrics ResolveUIEditorVector3FieldMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorVector3FieldMetrics& fallback = {});
Widgets::UIEditorVector3FieldPalette ResolveUIEditorVector3FieldPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorVector3FieldPalette& fallback = {});
Widgets::UIEditorEnumFieldMetrics ResolveUIEditorEnumFieldMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorEnumFieldMetrics& fallback = {});
Widgets::UIEditorEnumFieldPalette ResolveUIEditorEnumFieldPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorEnumFieldPalette& fallback = {});
Widgets::UIEditorMenuPopupMetrics ResolveUIEditorMenuPopupMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorMenuPopupMetrics& fallback = {});
Widgets::UIEditorMenuPopupPalette ResolveUIEditorMenuPopupPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorMenuPopupPalette& fallback = {});
Widgets::UIEditorPropertyGridMetrics ResolveUIEditorPropertyGridMetrics(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorPropertyGridMetrics& fallback = {});
Widgets::UIEditorPropertyGridPalette ResolveUIEditorPropertyGridPalette(
const ::XCEngine::UI::Style::UITheme& theme,
const Widgets::UIEditorPropertyGridPalette& fallback = {});
Widgets::UIEditorBoolFieldMetrics BuildUIEditorHostedBoolFieldMetrics(
const Widgets::UIEditorPropertyGridMetrics& propertyGridMetrics,
const Widgets::UIEditorBoolFieldMetrics& fallback = {});
Widgets::UIEditorBoolFieldPalette BuildUIEditorHostedBoolFieldPalette(
const Widgets::UIEditorPropertyGridPalette& propertyGridPalette,
const Widgets::UIEditorBoolFieldPalette& fallback = {});
Widgets::UIEditorNumberFieldMetrics BuildUIEditorHostedNumberFieldMetrics(
const Widgets::UIEditorPropertyGridMetrics& propertyGridMetrics,
const Widgets::UIEditorNumberFieldMetrics& fallback = {});
Widgets::UIEditorNumberFieldPalette BuildUIEditorHostedNumberFieldPalette(
const Widgets::UIEditorPropertyGridPalette& propertyGridPalette,
const Widgets::UIEditorNumberFieldPalette& fallback = {});
Widgets::UIEditorTextFieldMetrics BuildUIEditorHostedTextFieldMetrics(
const Widgets::UIEditorPropertyGridMetrics& propertyGridMetrics,
const Widgets::UIEditorTextFieldMetrics& fallback = {});
Widgets::UIEditorTextFieldPalette BuildUIEditorHostedTextFieldPalette(
const Widgets::UIEditorPropertyGridPalette& propertyGridPalette,
const Widgets::UIEditorTextFieldPalette& fallback = {});
Widgets::UIEditorVector2FieldMetrics BuildUIEditorHostedVector2FieldMetrics(
const Widgets::UIEditorPropertyGridMetrics& propertyGridMetrics,
const Widgets::UIEditorVector2FieldMetrics& fallback = {});
Widgets::UIEditorVector2FieldPalette BuildUIEditorHostedVector2FieldPalette(
const Widgets::UIEditorPropertyGridPalette& propertyGridPalette,
const Widgets::UIEditorVector2FieldPalette& fallback = {});
Widgets::UIEditorVector3FieldMetrics BuildUIEditorHostedVector3FieldMetrics(
const Widgets::UIEditorPropertyGridMetrics& propertyGridMetrics,
const Widgets::UIEditorVector3FieldMetrics& fallback = {});
Widgets::UIEditorVector3FieldPalette BuildUIEditorHostedVector3FieldPalette(
const Widgets::UIEditorPropertyGridPalette& propertyGridPalette,
const Widgets::UIEditorVector3FieldPalette& fallback = {});
Widgets::UIEditorEnumFieldMetrics BuildUIEditorHostedEnumFieldMetrics(
const Widgets::UIEditorPropertyGridMetrics& propertyGridMetrics,
const Widgets::UIEditorEnumFieldMetrics& fallback = {});
Widgets::UIEditorEnumFieldPalette BuildUIEditorHostedEnumFieldPalette(
const Widgets::UIEditorPropertyGridPalette& propertyGridPalette,
const Widgets::UIEditorEnumFieldPalette& fallback = {});
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,53 @@
#pragma once
#include <XCEditor/Widgets/UIEditorVector2Field.h>
#include <XCEngine/UI/Text/UITextInputController.h>
#include <XCEngine/UI/Types.h>
#include <XCEngine/UI/Widgets/UIPropertyEditModel.h>
#include <array>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorVector2FieldInteractionState {
Widgets::UIEditorVector2FieldState vector2FieldState = {};
::XCEngine::UI::Text::UITextInputState textInputState = {};
::XCEngine::UI::Widgets::UIPropertyEditModel editModel = {};
::XCEngine::UI::UIPoint pointerPosition = {};
bool hasPointerPosition = false;
};
struct UIEditorVector2FieldInteractionResult {
bool consumed = false;
bool focusChanged = false;
bool valueChanged = false;
bool stepApplied = false;
bool selectionChanged = false;
bool editStarted = false;
bool editCommitted = false;
bool editCommitRejected = false;
bool editCanceled = false;
Widgets::UIEditorVector2FieldHitTarget hitTarget = {};
std::size_t selectedComponentIndex = Widgets::UIEditorVector2FieldInvalidComponentIndex;
std::size_t changedComponentIndex = Widgets::UIEditorVector2FieldInvalidComponentIndex;
std::array<double, 2u> valuesBefore = { 0.0, 0.0 };
std::array<double, 2u> valuesAfter = { 0.0, 0.0 };
double stepDelta = 0.0;
std::string committedText = {};
};
struct UIEditorVector2FieldInteractionFrame {
Widgets::UIEditorVector2FieldLayout layout = {};
UIEditorVector2FieldInteractionResult result = {};
};
UIEditorVector2FieldInteractionFrame UpdateUIEditorVector2FieldInteraction(
UIEditorVector2FieldInteractionState& state,
Widgets::UIEditorVector2FieldSpec& spec,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorVector2FieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor

View File

@@ -0,0 +1,53 @@
#pragma once
#include <XCEditor/Widgets/UIEditorVector3Field.h>
#include <XCEngine/UI/Text/UITextInputController.h>
#include <XCEngine/UI/Types.h>
#include <XCEngine/UI/Widgets/UIPropertyEditModel.h>
#include <array>
#include <vector>
namespace XCEngine::UI::Editor {
struct UIEditorVector3FieldInteractionState {
Widgets::UIEditorVector3FieldState vector3FieldState = {};
::XCEngine::UI::Text::UITextInputState textInputState = {};
::XCEngine::UI::Widgets::UIPropertyEditModel editModel = {};
::XCEngine::UI::UIPoint pointerPosition = {};
bool hasPointerPosition = false;
};
struct UIEditorVector3FieldInteractionResult {
bool consumed = false;
bool focusChanged = false;
bool valueChanged = false;
bool stepApplied = false;
bool selectionChanged = false;
bool editStarted = false;
bool editCommitted = false;
bool editCommitRejected = false;
bool editCanceled = false;
Widgets::UIEditorVector3FieldHitTarget hitTarget = {};
std::size_t selectedComponentIndex = Widgets::UIEditorVector3FieldInvalidComponentIndex;
std::size_t changedComponentIndex = Widgets::UIEditorVector3FieldInvalidComponentIndex;
std::array<double, 3u> valuesBefore = { 0.0, 0.0, 0.0 };
std::array<double, 3u> valuesAfter = { 0.0, 0.0, 0.0 };
double stepDelta = 0.0;
std::string committedText = {};
};
struct UIEditorVector3FieldInteractionFrame {
Widgets::UIEditorVector3FieldLayout layout = {};
UIEditorVector3FieldInteractionResult result = {};
};
UIEditorVector3FieldInteractionFrame UpdateUIEditorVector3FieldInteraction(
UIEditorVector3FieldInteractionState& state,
Widgets::UIEditorVector3FieldSpec& spec,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<::XCEngine::UI::UIInputEvent>& inputEvents,
const Widgets::UIEditorVector3FieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor

View File

@@ -10,7 +10,7 @@ namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorBoolFieldHitTargetKind : std::uint8_t {
None = 0,
Row,
Toggle
Checkbox
};
struct UIEditorBoolFieldSpec {
@@ -27,51 +27,54 @@ struct UIEditorBoolFieldState {
};
struct UIEditorBoolFieldMetrics {
float rowHeight = 32.0f;
float rowHeight = 22.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 controlTrailingInset = 8.0f;
float checkboxSize = 18.0f;
float labelTextInsetY = 0.0f;
float labelFontSize = 11.0f;
float checkboxGlyphInsetX = 2.0f;
float checkboxGlyphInsetY = -1.0f;
float checkboxGlyphFontSize = 10.0f;
float cornerRounding = 0.0f;
float checkboxRounding = 2.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 2.0f;
float focusedBorderThickness = 1.0f;
};
struct UIEditorBoolFieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.22f, 0.22f, 0.22f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.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.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor checkboxColor =
::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 checkboxHoverColor =
::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 1.0f);
::XCEngine::UI::UIColor checkboxReadOnlyColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor checkboxBorderColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor checkboxMarkColor =
::XCEngine::UI::UIColor(0.72f, 0.72f, 0.72f, 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);
::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f);
};
struct UIEditorBoolFieldLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect toggleRect = {};
::XCEngine::UI::UIRect knobRect = {};
::XCEngine::UI::UIRect controlRect = {};
::XCEngine::UI::UIRect checkboxRect = {};
::XCEngine::UI::UIRect checkmarkRect = {};
};
struct UIEditorBoolFieldHitTarget {

View File

@@ -12,9 +12,8 @@ namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorEnumFieldHitTargetKind : std::uint8_t {
None = 0,
Row,
PreviousButton,
NextButton,
ValueBox
ValueBox,
DropdownArrow
};
struct UIEditorEnumFieldSpec {
@@ -29,52 +28,57 @@ struct UIEditorEnumFieldState {
UIEditorEnumFieldHitTargetKind hoveredTarget = UIEditorEnumFieldHitTargetKind::None;
bool focused = false;
bool active = false;
bool popupOpen = false;
};
struct UIEditorEnumFieldMetrics {
float rowHeight = 32.0f;
float rowHeight = 22.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float buttonWidth = 24.0f;
float controlGap = 4.0f;
float controlTrailingInset = 8.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 controlInsetY = 1.0f;
float labelTextInsetY = 0.0f;
float labelFontSize = 11.0f;
float valueTextInsetX = 3.0f;
float valueTextInsetY = 0.0f;
float valueFontSize = 12.0f;
float dropdownArrowWidth = 20.0f;
float dropdownArrowInsetX = 0.0f;
float dropdownArrowInsetY = -1.0f;
float dropdownArrowFontSize = 10.0f;
float cornerRounding = 0.0f;
float valueBoxRounding = 2.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 2.0f;
float focusedBorderThickness = 1.0f;
};
struct UIEditorEnumFieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.22f, 0.22f, 0.22f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.28f, 0.28f, 0.28f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.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 valueBoxHoverColor =
::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 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(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f);
::XCEngine::UI::UIColor valueColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f);
::XCEngine::UI::UIColor arrowColor =
::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f);
};
struct UIEditorEnumFieldLayout {
@@ -82,8 +86,7 @@ struct UIEditorEnumFieldLayout {
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
::XCEngine::UI::UIRect valueRect = {};
::XCEngine::UI::UIRect previousRect = {};
::XCEngine::UI::UIRect nextRect = {};
::XCEngine::UI::UIRect arrowRect = {};
};
struct UIEditorEnumFieldHitTarget {

View File

@@ -0,0 +1,27 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
namespace XCEngine::UI::Editor::Widgets {
struct UIEditorFieldRowLayoutMetrics {
float rowHeight = 22.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float controlTrailingInset = 8.0f;
float controlInsetY = 1.0f;
};
struct UIEditorFieldRowLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
};
UIEditorFieldRowLayout BuildUIEditorFieldRowLayout(
const ::XCEngine::UI::UIRect& bounds,
float minimumControlWidth,
const UIEditorFieldRowLayoutMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -45,8 +45,10 @@ struct UIEditorMenuPopupMetrics {
float popupCornerRounding = 8.0f;
float labelInsetX = 14.0f;
float labelInsetY = -1.0f;
float labelFontSize = 13.0f;
float shortcutInsetRight = 24.0f;
float estimatedGlyphWidth = 7.0f;
float glyphFontSize = 12.0f;
float separatorThickness = 1.0f;
float borderThickness = 1.0f;
};

View File

@@ -5,14 +5,13 @@
#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>
namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorNumberFieldHitTargetKind : std::uint8_t {
None = 0,
Row,
DecrementButton,
IncrementButton,
ValueBox
};
@@ -36,60 +35,53 @@ struct UIEditorNumberFieldState {
};
struct UIEditorNumberFieldMetrics {
float rowHeight = 32.0f;
float rowHeight = 22.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 controlTrailingInset = 8.0f;
float valueBoxMinWidth = 96.0f;
float controlInsetY = 1.0f;
float labelTextInsetY = 0.0f;
float labelFontSize = 11.0f;
float valueTextInsetX = 5.0f;
float valueTextInsetY = 0.0f;
float valueFontSize = 12.0f;
float cornerRounding = 0.0f;
float valueBoxRounding = 2.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 2.0f;
float focusedBorderThickness = 1.0f;
};
struct UIEditorNumberFieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.29f, 0.29f, 0.29f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.84f, 0.84f, 0.84f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.22f, 0.22f, 0.22f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.28f, 0.28f, 0.28f, 1.0f);
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.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(0.21f, 0.21f, 0.21f, 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(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor controlFocusedBorderColor =
::XCEngine::UI::UIColor(0.46f, 0.46f, 0.46f, 1.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor(0.80f, 0.80f, 0.80f, 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 {
@@ -97,8 +89,6 @@ struct UIEditorNumberFieldLayout {
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
::XCEngine::UI::UIRect valueRect = {};
::XCEngine::UI::UIRect decrementRect = {};
::XCEngine::UI::UIRect incrementRect = {};
};
struct UIEditorNumberFieldHitTarget {
@@ -109,6 +99,15 @@ bool IsUIEditorNumberFieldPointInside(
const ::XCEngine::UI::UIRect& rect,
const ::XCEngine::UI::UIPoint& point);
double NormalizeUIEditorNumberFieldValue(
const UIEditorNumberFieldSpec& spec,
double value);
bool TryParseUIEditorNumberFieldValue(
const UIEditorNumberFieldSpec& spec,
std::string_view text,
double& outValue);
std::string FormatUIEditorNumberFieldValue(const UIEditorNumberFieldSpec& spec);
UIEditorNumberFieldLayout BuildUIEditorNumberFieldLayout(
@@ -132,6 +131,7 @@ void AppendUIEditorNumberFieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorNumberFieldLayout& layout,
const UIEditorNumberFieldSpec& spec,
const UIEditorNumberFieldState& state,
const UIEditorNumberFieldPalette& palette = {},
const UIEditorNumberFieldMetrics& metrics = {});

View File

@@ -5,6 +5,8 @@
#include <XCEngine/UI/Widgets/UIPropertyEditModel.h>
#include <XCEngine/UI/Widgets/UISelectionModel.h>
#include <XCEditor/Widgets/UIEditorMenuPopup.h>
#include <cstddef>
#include <cstdint>
#include <string>
@@ -15,6 +17,13 @@ namespace XCEngine::UI::Editor::Widgets {
inline constexpr std::size_t UIEditorPropertyGridInvalidIndex = static_cast<std::size_t>(-1);
enum class UIEditorPropertyGridFieldKind : std::uint8_t {
Text = 0,
Bool,
Number,
Enum
};
enum class UIEditorPropertyGridHitTargetKind : std::uint8_t {
None = 0,
SectionHeader,
@@ -32,12 +41,29 @@ struct UIEditorPropertyGridFieldLocation {
}
};
struct UIEditorPropertyGridNumberFieldValue {
double value = 0.0;
double step = 1.0;
double minValue = 0.0;
double maxValue = 100.0;
bool integerMode = true;
};
struct UIEditorPropertyGridEnumFieldValue {
std::vector<std::string> options = {};
std::size_t selectedIndex = 0u;
};
struct UIEditorPropertyGridField {
std::string fieldId = {};
std::string label = {};
std::string valueText = {};
bool readOnly = false;
float desiredHeight = 0.0f;
UIEditorPropertyGridFieldKind kind = UIEditorPropertyGridFieldKind::Text;
bool boolValue = false;
UIEditorPropertyGridNumberFieldValue numberValue = {};
UIEditorPropertyGridEnumFieldValue enumValue = {};
};
struct UIEditorPropertyGridSection {
@@ -50,7 +76,11 @@ struct UIEditorPropertyGridSection {
struct UIEditorPropertyGridState {
std::string hoveredSectionId = {};
std::string hoveredFieldId = {};
UIEditorPropertyGridHitTargetKind hoveredHitTarget = UIEditorPropertyGridHitTargetKind::None;
bool focused = false;
std::string pressedFieldId = {};
std::string popupFieldId = {};
std::size_t popupHighlightedIndex = UIEditorPropertyGridInvalidIndex;
};
struct UIEditorPropertyGridMetrics {
@@ -65,10 +95,17 @@ struct UIEditorPropertyGridMetrics {
float disclosureExtent = 12.0f;
float disclosureLabelGap = 8.0f;
float sectionTextInsetY = 8.0f;
float sectionFontSize = 12.0f;
float disclosureGlyphInsetX = 2.0f;
float disclosureGlyphInsetY = -1.0f;
float disclosureGlyphFontSize = 12.0f;
float labelTextInsetY = 8.0f;
float labelFontSize = 12.0f;
float valueTextInsetY = 8.0f;
float valueFontSize = 12.0f;
float valueBoxInsetY = 4.0f;
float valueBoxInsetX = 8.0f;
float tagFontSize = 11.0f;
float cornerRounding = 6.0f;
float valueBoxRounding = 5.0f;
float borderThickness = 1.0f;
@@ -153,6 +190,9 @@ UIEditorPropertyGridFieldLocation FindUIEditorPropertyGridFieldLocation(
const std::vector<UIEditorPropertyGridSection>& sections,
std::string_view fieldId);
std::string ResolveUIEditorPropertyGridFieldValueText(
const UIEditorPropertyGridField& field);
std::size_t FindUIEditorPropertyGridVisibleFieldIndex(
const UIEditorPropertyGridLayout& layout,
std::string_view fieldId,
@@ -182,9 +222,12 @@ void AppendUIEditorPropertyGridForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorPropertyGridLayout& layout,
const std::vector<UIEditorPropertyGridSection>& sections,
const UIEditorPropertyGridState& state,
const ::XCEngine::UI::Widgets::UIPropertyEditModel& propertyEditModel,
const UIEditorPropertyGridPalette& palette = {},
const UIEditorPropertyGridMetrics& metrics = {});
const UIEditorPropertyGridMetrics& metrics = {},
const UIEditorMenuPopupPalette& popupPalette = {},
const UIEditorMenuPopupMetrics& popupMetrics = {});
void AppendUIEditorPropertyGrid(
::XCEngine::UI::UIDrawList& drawList,
@@ -195,6 +238,8 @@ void AppendUIEditorPropertyGrid(
const ::XCEngine::UI::Widgets::UIPropertyEditModel& propertyEditModel,
const UIEditorPropertyGridState& state,
const UIEditorPropertyGridPalette& palette = {},
const UIEditorPropertyGridMetrics& metrics = {});
const UIEditorPropertyGridMetrics& metrics = {},
const UIEditorMenuPopupPalette& popupPalette = {},
const UIEditorMenuPopupMetrics& popupMetrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,130 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <cstdint>
#include <string>
#include <string_view>
namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorTextFieldHitTargetKind : std::uint8_t {
None = 0,
Row,
ValueBox
};
struct UIEditorTextFieldSpec {
std::string fieldId = {};
std::string label = {};
std::string value = {};
bool readOnly = false;
};
struct UIEditorTextFieldState {
UIEditorTextFieldHitTargetKind hoveredTarget = UIEditorTextFieldHitTargetKind::None;
UIEditorTextFieldHitTargetKind activeTarget = UIEditorTextFieldHitTargetKind::None;
bool focused = false;
bool editing = false;
std::string displayText = {};
};
struct UIEditorTextFieldMetrics {
float rowHeight = 22.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float controlTrailingInset = 8.0f;
float valueBoxMinWidth = 96.0f;
float controlInsetY = 1.0f;
float labelTextInsetY = 0.0f;
float labelFontSize = 11.0f;
float valueTextInsetX = 5.0f;
float valueTextInsetY = 0.0f;
float valueFontSize = 12.0f;
float cornerRounding = 0.0f;
float valueBoxRounding = 2.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 1.0f;
};
struct UIEditorTextFieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor valueBoxColor =
::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
::XCEngine::UI::UIColor valueBoxHoverColor =
::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 1.0f);
::XCEngine::UI::UIColor valueBoxEditingColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 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.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor controlFocusedBorderColor =
::XCEngine::UI::UIColor(0.46f, 0.46f, 0.46f, 1.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.80f, 0.80f, 0.80f, 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);
};
struct UIEditorTextFieldLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
::XCEngine::UI::UIRect valueRect = {};
};
struct UIEditorTextFieldHitTarget {
UIEditorTextFieldHitTargetKind kind = UIEditorTextFieldHitTargetKind::None;
};
bool IsUIEditorTextFieldPointInside(
const ::XCEngine::UI::UIRect& rect,
const ::XCEngine::UI::UIPoint& point);
UIEditorTextFieldLayout BuildUIEditorTextFieldLayout(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorTextFieldSpec& spec,
const UIEditorTextFieldMetrics& metrics = {});
UIEditorTextFieldHitTarget HitTestUIEditorTextField(
const UIEditorTextFieldLayout& layout,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorTextFieldBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorTextFieldLayout& layout,
const UIEditorTextFieldSpec& spec,
const UIEditorTextFieldState& state,
const UIEditorTextFieldPalette& palette = {},
const UIEditorTextFieldMetrics& metrics = {});
void AppendUIEditorTextFieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorTextFieldLayout& layout,
const UIEditorTextFieldSpec& spec,
const UIEditorTextFieldState& state,
const UIEditorTextFieldPalette& palette = {},
const UIEditorTextFieldMetrics& metrics = {});
void AppendUIEditorTextField(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorTextFieldSpec& spec,
const UIEditorTextFieldState& state,
const UIEditorTextFieldPalette& palette = {},
const UIEditorTextFieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,35 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <algorithm>
#include <cmath>
namespace XCEngine::UI::Editor::Widgets {
inline float MeasureUIEditorTextLayoutHeight(float fontSize) {
return (std::max)(0.0f, fontSize * 1.35f);
}
inline float ResolveUIEditorTextTop(
const ::XCEngine::UI::UIRect& rect,
float fontSize,
float offsetY = 0.0f) {
const float textHeight = MeasureUIEditorTextLayoutHeight(fontSize);
const float centeredTop =
rect.y + (std::max)(0.0f, std::floor((rect.height - textHeight) * 0.5f));
return centeredTop - 1.0f + offsetY;
}
inline ::XCEngine::UI::UIRect ResolveUIEditorTextClipRect(
const ::XCEngine::UI::UIRect& rect,
float fontSize) {
const float extraPadding = (std::max)(2.0f, std::ceil(fontSize * 0.35f));
return ::XCEngine::UI::UIRect(
rect.x,
rect.y - 1.0f,
rect.width,
rect.height + extraPadding + 1.0f);
}
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,171 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
namespace XCEngine::UI::Editor::Widgets {
inline constexpr std::size_t UIEditorVector2FieldInvalidComponentIndex = static_cast<std::size_t>(-1);
enum class UIEditorVector2FieldHitTargetKind : std::uint8_t {
None = 0,
Row,
Component
};
struct UIEditorVector2FieldSpec {
std::string fieldId = {};
std::string label = {};
std::array<double, 2u> values = { 0.0, 0.0 };
std::array<std::string, 2u> componentLabels = { std::string("X"), std::string("Y") };
double step = 0.1;
double minValue = -1000000.0;
double maxValue = 1000000.0;
bool integerMode = false;
bool readOnly = false;
};
struct UIEditorVector2FieldState {
UIEditorVector2FieldHitTargetKind hoveredTarget = UIEditorVector2FieldHitTargetKind::None;
UIEditorVector2FieldHitTargetKind activeTarget = UIEditorVector2FieldHitTargetKind::None;
std::size_t hoveredComponentIndex = UIEditorVector2FieldInvalidComponentIndex;
std::size_t activeComponentIndex = UIEditorVector2FieldInvalidComponentIndex;
std::size_t selectedComponentIndex = UIEditorVector2FieldInvalidComponentIndex;
bool focused = false;
bool editing = false;
std::array<std::string, 2u> displayTexts = { std::string(), std::string() };
};
struct UIEditorVector2FieldMetrics {
float rowHeight = 22.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float controlTrailingInset = 8.0f;
float controlInsetY = 1.0f;
float componentGap = 6.0f;
float componentMinWidth = 72.0f;
float componentPrefixWidth = 9.0f;
float componentLabelGap = 4.0f;
float labelTextInsetY = 0.0f;
float labelFontSize = 11.0f;
float valueTextInsetX = 5.0f;
float valueTextInsetY = 0.0f;
float valueFontSize = 12.0f;
float prefixTextInsetX = 0.0f;
float prefixTextInsetY = -1.0f;
float prefixFontSize = 11.0f;
float cornerRounding = 0.0f;
float componentRounding = 2.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 1.0f;
};
struct UIEditorVector2FieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor componentColor =
::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
::XCEngine::UI::UIColor componentHoverColor =
::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 1.0f);
::XCEngine::UI::UIColor componentEditingColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
::XCEngine::UI::UIColor readOnlyColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor componentBorderColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor componentFocusedBorderColor =
::XCEngine::UI::UIColor(0.20f, 0.20f, 0.20f, 1.0f);
::XCEngine::UI::UIColor prefixColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor prefixBorderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.80f, 0.80f, 0.80f, 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 axisXColor =
::XCEngine::UI::UIColor(0.67f, 0.67f, 0.67f, 1.0f);
::XCEngine::UI::UIColor axisYColor =
::XCEngine::UI::UIColor(0.67f, 0.67f, 0.67f, 1.0f);
};
struct UIEditorVector2FieldLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
std::array<::XCEngine::UI::UIRect, 2u> componentRects = {};
std::array<::XCEngine::UI::UIRect, 2u> componentPrefixRects = {};
std::array<::XCEngine::UI::UIRect, 2u> componentValueRects = {};
};
struct UIEditorVector2FieldHitTarget {
UIEditorVector2FieldHitTargetKind kind = UIEditorVector2FieldHitTargetKind::None;
std::size_t componentIndex = UIEditorVector2FieldInvalidComponentIndex;
};
bool IsUIEditorVector2FieldPointInside(
const ::XCEngine::UI::UIRect& rect,
const ::XCEngine::UI::UIPoint& point);
double NormalizeUIEditorVector2FieldComponentValue(
const UIEditorVector2FieldSpec& spec,
double value);
bool TryParseUIEditorVector2FieldComponentValue(
const UIEditorVector2FieldSpec& spec,
std::string_view text,
double& outValue);
std::string FormatUIEditorVector2FieldComponentValue(
const UIEditorVector2FieldSpec& spec,
std::size_t componentIndex);
UIEditorVector2FieldLayout BuildUIEditorVector2FieldLayout(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorVector2FieldSpec& spec,
const UIEditorVector2FieldMetrics& metrics = {});
UIEditorVector2FieldHitTarget HitTestUIEditorVector2Field(
const UIEditorVector2FieldLayout& layout,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorVector2FieldBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorVector2FieldLayout& layout,
const UIEditorVector2FieldSpec& spec,
const UIEditorVector2FieldState& state,
const UIEditorVector2FieldPalette& palette = {},
const UIEditorVector2FieldMetrics& metrics = {});
void AppendUIEditorVector2FieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorVector2FieldLayout& layout,
const UIEditorVector2FieldSpec& spec,
const UIEditorVector2FieldState& state,
const UIEditorVector2FieldPalette& palette = {},
const UIEditorVector2FieldMetrics& metrics = {});
void AppendUIEditorVector2Field(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorVector2FieldSpec& spec,
const UIEditorVector2FieldState& state,
const UIEditorVector2FieldPalette& palette = {},
const UIEditorVector2FieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,173 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
namespace XCEngine::UI::Editor::Widgets {
inline constexpr std::size_t UIEditorVector3FieldInvalidComponentIndex = static_cast<std::size_t>(-1);
enum class UIEditorVector3FieldHitTargetKind : std::uint8_t {
None = 0,
Row,
Component
};
struct UIEditorVector3FieldSpec {
std::string fieldId = {};
std::string label = {};
std::array<double, 3u> values = { 0.0, 0.0, 0.0 };
std::array<std::string, 3u> componentLabels = { std::string("X"), std::string("Y"), std::string("Z") };
double step = 0.1;
double minValue = -1000000.0;
double maxValue = 1000000.0;
bool integerMode = false;
bool readOnly = false;
};
struct UIEditorVector3FieldState {
UIEditorVector3FieldHitTargetKind hoveredTarget = UIEditorVector3FieldHitTargetKind::None;
UIEditorVector3FieldHitTargetKind activeTarget = UIEditorVector3FieldHitTargetKind::None;
std::size_t hoveredComponentIndex = UIEditorVector3FieldInvalidComponentIndex;
std::size_t activeComponentIndex = UIEditorVector3FieldInvalidComponentIndex;
std::size_t selectedComponentIndex = UIEditorVector3FieldInvalidComponentIndex;
bool focused = false;
bool editing = false;
std::array<std::string, 3u> displayTexts = { std::string(), std::string(), std::string() };
};
struct UIEditorVector3FieldMetrics {
float rowHeight = 22.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float controlTrailingInset = 8.0f;
float controlInsetY = 1.0f;
float componentGap = 6.0f;
float componentMinWidth = 72.0f;
float componentPrefixWidth = 9.0f;
float componentLabelGap = 4.0f;
float labelTextInsetY = 0.0f;
float labelFontSize = 11.0f;
float valueTextInsetX = 5.0f;
float valueTextInsetY = 0.0f;
float valueFontSize = 12.0f;
float prefixTextInsetX = 0.0f;
float prefixTextInsetY = -1.0f;
float prefixFontSize = 11.0f;
float cornerRounding = 0.0f;
float componentRounding = 2.0f;
float borderThickness = 1.0f;
float focusedBorderThickness = 1.0f;
};
struct UIEditorVector3FieldPalette {
::XCEngine::UI::UIColor surfaceColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor borderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor focusedBorderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor componentColor =
::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
::XCEngine::UI::UIColor componentHoverColor =
::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 1.0f);
::XCEngine::UI::UIColor componentEditingColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
::XCEngine::UI::UIColor readOnlyColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor componentBorderColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor componentFocusedBorderColor =
::XCEngine::UI::UIColor(0.20f, 0.20f, 0.20f, 1.0f);
::XCEngine::UI::UIColor prefixColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor prefixBorderColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.80f, 0.80f, 0.80f, 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 axisXColor =
::XCEngine::UI::UIColor(0.67f, 0.67f, 0.67f, 1.0f);
::XCEngine::UI::UIColor axisYColor =
::XCEngine::UI::UIColor(0.67f, 0.67f, 0.67f, 1.0f);
::XCEngine::UI::UIColor axisZColor =
::XCEngine::UI::UIColor(0.67f, 0.67f, 0.67f, 1.0f);
};
struct UIEditorVector3FieldLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
std::array<::XCEngine::UI::UIRect, 3u> componentRects = {};
std::array<::XCEngine::UI::UIRect, 3u> componentPrefixRects = {};
std::array<::XCEngine::UI::UIRect, 3u> componentValueRects = {};
};
struct UIEditorVector3FieldHitTarget {
UIEditorVector3FieldHitTargetKind kind = UIEditorVector3FieldHitTargetKind::None;
std::size_t componentIndex = UIEditorVector3FieldInvalidComponentIndex;
};
bool IsUIEditorVector3FieldPointInside(
const ::XCEngine::UI::UIRect& rect,
const ::XCEngine::UI::UIPoint& point);
double NormalizeUIEditorVector3FieldComponentValue(
const UIEditorVector3FieldSpec& spec,
double value);
bool TryParseUIEditorVector3FieldComponentValue(
const UIEditorVector3FieldSpec& spec,
std::string_view text,
double& outValue);
std::string FormatUIEditorVector3FieldComponentValue(
const UIEditorVector3FieldSpec& spec,
std::size_t componentIndex);
UIEditorVector3FieldLayout BuildUIEditorVector3FieldLayout(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorVector3FieldSpec& spec,
const UIEditorVector3FieldMetrics& metrics = {});
UIEditorVector3FieldHitTarget HitTestUIEditorVector3Field(
const UIEditorVector3FieldLayout& layout,
const ::XCEngine::UI::UIPoint& point);
void AppendUIEditorVector3FieldBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorVector3FieldLayout& layout,
const UIEditorVector3FieldSpec& spec,
const UIEditorVector3FieldState& state,
const UIEditorVector3FieldPalette& palette = {},
const UIEditorVector3FieldMetrics& metrics = {});
void AppendUIEditorVector3FieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorVector3FieldLayout& layout,
const UIEditorVector3FieldSpec& spec,
const UIEditorVector3FieldState& state,
const UIEditorVector3FieldPalette& palette = {},
const UIEditorVector3FieldMetrics& metrics = {});
void AppendUIEditorVector3Field(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorVector3FieldSpec& spec,
const UIEditorVector3FieldState& state,
const UIEditorVector3FieldPalette& palette = {},
const UIEditorVector3FieldMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets