feat(new_editor): add standalone add-component utility window
This commit is contained in:
@@ -22,7 +22,9 @@ using ::XCEngine::UI::UIColor;
|
||||
using ::XCEngine::UI::UIDrawList;
|
||||
using ::XCEngine::UI::UIInputEvent;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
using ::XCEngine::UI::UIPointerButton;
|
||||
using ::XCEngine::UI::UIRect;
|
||||
using ::XCEngine::UI::UIInputEventType;
|
||||
|
||||
constexpr float kPanelPadding = 10.0f;
|
||||
constexpr float kTitleHeight = 18.0f;
|
||||
@@ -30,6 +32,9 @@ constexpr float kSubtitleHeight = 16.0f;
|
||||
constexpr float kHeaderGap = 10.0f;
|
||||
constexpr float kTitleFontSize = 13.0f;
|
||||
constexpr float kSubtitleFontSize = 11.0f;
|
||||
constexpr float kAddComponentButtonHeight = 24.0f;
|
||||
constexpr float kAddComponentButtonTopGap = 10.0f;
|
||||
constexpr float kAddComponentButtonFontSize = 12.0f;
|
||||
constexpr UIColor kTitleColor(0.930f, 0.930f, 0.930f, 1.0f);
|
||||
constexpr UIColor kSubtitleColor(0.660f, 0.660f, 0.660f, 1.0f);
|
||||
constexpr UIColor kSurfaceColor(0.10f, 0.10f, 0.10f, 1.0f);
|
||||
@@ -68,6 +73,27 @@ float ResolveTextTop(float rectY, float rectHeight, float fontSize) {
|
||||
return rectY + std::floor((rectHeight - lineHeight) * 0.5f);
|
||||
}
|
||||
|
||||
float ResolveCenteredTextX(
|
||||
const UIRect& rect,
|
||||
std::string_view text,
|
||||
float fontSize) {
|
||||
const float estimatedTextWidth =
|
||||
static_cast<float>(text.size()) * fontSize * 0.56f;
|
||||
return rect.x + std::floor((std::max)(rect.width - estimatedTextWidth, 0.0f) * 0.5f);
|
||||
}
|
||||
|
||||
UIColor ResolveAddComponentButtonFillColor(bool hovered, bool pressed) {
|
||||
const Widgets::UIEditorPropertyGridPalette& palette =
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridPalette();
|
||||
if (pressed) {
|
||||
return palette.valueBoxEditingColor;
|
||||
}
|
||||
if (hovered) {
|
||||
return palette.valueBoxHoverColor;
|
||||
}
|
||||
return palette.valueBoxColor;
|
||||
}
|
||||
|
||||
UIEditorHostCommandEvaluationResult BuildEvaluationResult(
|
||||
bool executable,
|
||||
std::string message) {
|
||||
@@ -115,6 +141,7 @@ void InspectorPanel::ResetInteractionState() {
|
||||
m_interactionState = {};
|
||||
m_gridFrame = {};
|
||||
m_lastAppliedColorPickerRevision = 0u;
|
||||
ResetAddComponentButtonState();
|
||||
}
|
||||
|
||||
void InspectorPanel::SyncExpansionState(bool subjectChanged) {
|
||||
@@ -182,6 +209,10 @@ float InspectorPanel::ResolveHeaderHeight() const {
|
||||
return kTitleHeight + kSubtitleHeight + kHeaderGap;
|
||||
}
|
||||
|
||||
bool InspectorPanel::ShouldShowAddComponentButton() const {
|
||||
return m_subject.kind == InspectorSubjectKind::SceneObject;
|
||||
}
|
||||
|
||||
UIRect InspectorPanel::BuildGridBounds() const {
|
||||
const float horizontalPadding =
|
||||
ResolveInspectorHorizontalPadding(m_presentation);
|
||||
@@ -196,6 +227,33 @@ UIRect InspectorPanel::BuildGridBounds() const {
|
||||
return UIRect(x, y, width, height);
|
||||
}
|
||||
|
||||
UIRect InspectorPanel::BuildAddComponentButtonRect() const {
|
||||
if (!ShouldShowAddComponentButton()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const float horizontalPadding =
|
||||
ResolveInspectorHorizontalPadding(m_presentation);
|
||||
const float bottomPadding = ResolveInspectorBottomPadding(m_presentation);
|
||||
float buttonTop = BuildGridBounds().y;
|
||||
if (!m_gridFrame.layout.fieldRowRects.empty()) {
|
||||
const UIRect& lastFieldRect = m_gridFrame.layout.fieldRowRects.back();
|
||||
buttonTop = lastFieldRect.y + lastFieldRect.height + kAddComponentButtonTopGap;
|
||||
} else if (!m_gridFrame.layout.sectionHeaderRects.empty()) {
|
||||
const UIRect& lastSectionRect = m_gridFrame.layout.sectionHeaderRects.back();
|
||||
buttonTop = lastSectionRect.y + lastSectionRect.height + kAddComponentButtonTopGap;
|
||||
}
|
||||
|
||||
const float maxVisibleTop =
|
||||
m_bounds.y + m_bounds.height - bottomPadding - kAddComponentButtonHeight;
|
||||
buttonTop = (std::min)(buttonTop, maxVisibleTop);
|
||||
return UIRect(
|
||||
m_bounds.x + horizontalPadding,
|
||||
buttonTop,
|
||||
(std::max)(m_bounds.width - horizontalPadding * 2.0f, 0.0f),
|
||||
kAddComponentButtonHeight);
|
||||
}
|
||||
|
||||
const InspectorPresentationComponentBinding* InspectorPanel::FindSelectedComponentBinding() const {
|
||||
if (!m_fieldSelection.HasSelection()) {
|
||||
return nullptr;
|
||||
@@ -399,6 +457,66 @@ void InspectorPanel::RequestColorPicker(
|
||||
field->fieldId,
|
||||
field->colorValue.value,
|
||||
field->colorValue.showAlpha);
|
||||
context.RequestOpenUtilityWindow(EditorUtilityWindowKind::ColorPicker);
|
||||
}
|
||||
|
||||
void InspectorPanel::ResetAddComponentButtonState() {
|
||||
m_addComponentButtonHovered = false;
|
||||
m_addComponentButtonPressed = false;
|
||||
}
|
||||
|
||||
void InspectorPanel::UpdateAddComponentButton(
|
||||
EditorContext& context,
|
||||
const std::vector<UIInputEvent>& inputEvents) {
|
||||
if (!ShouldShowAddComponentButton()) {
|
||||
ResetAddComponentButtonState();
|
||||
return;
|
||||
}
|
||||
|
||||
const UIRect buttonRect = BuildAddComponentButtonRect();
|
||||
if (buttonRect.width <= 0.0f || buttonRect.height <= 0.0f) {
|
||||
ResetAddComponentButtonState();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const UIInputEvent& event : inputEvents) {
|
||||
switch (event.type) {
|
||||
case UIInputEventType::PointerMove:
|
||||
m_addComponentButtonHovered = ContainsPoint(buttonRect, event.position);
|
||||
break;
|
||||
|
||||
case UIInputEventType::PointerLeave:
|
||||
case UIInputEventType::FocusLost:
|
||||
ResetAddComponentButtonState();
|
||||
break;
|
||||
|
||||
case UIInputEventType::PointerButtonDown:
|
||||
if (event.pointerButton != UIPointerButton::Left) {
|
||||
break;
|
||||
}
|
||||
|
||||
m_addComponentButtonHovered = ContainsPoint(buttonRect, event.position);
|
||||
m_addComponentButtonPressed = m_addComponentButtonHovered;
|
||||
break;
|
||||
|
||||
case UIInputEventType::PointerButtonUp:
|
||||
if (event.pointerButton != UIPointerButton::Left) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_addComponentButtonPressed &&
|
||||
ContainsPoint(buttonRect, event.position)) {
|
||||
context.RequestOpenUtilityWindow(EditorUtilityWindowKind::AddComponent);
|
||||
}
|
||||
|
||||
m_addComponentButtonHovered = ContainsPoint(buttonRect, event.position);
|
||||
m_addComponentButtonPressed = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InspectorPanel::ApplyChangedField(std::string_view fieldId) {
|
||||
@@ -479,11 +597,6 @@ void InspectorPanel::Update(
|
||||
RefreshPresentation(context, subjectChanged);
|
||||
ApplyColorPickerToolValue(context);
|
||||
|
||||
if (m_presentation.sections.empty()) {
|
||||
m_gridFrame = {};
|
||||
return;
|
||||
}
|
||||
|
||||
const std::vector<UIInputEvent> filteredEvents =
|
||||
BuildUIEditorPanelInputEvents(
|
||||
m_bounds,
|
||||
@@ -507,28 +620,32 @@ void InspectorPanel::Update(
|
||||
filteredEvents,
|
||||
m_bounds,
|
||||
dispatchEntry.allowInteraction);
|
||||
m_gridFrame = UpdateUIEditorPropertyGridInteraction(
|
||||
m_interactionState,
|
||||
m_fieldSelection,
|
||||
m_sectionExpansion,
|
||||
m_propertyEditModel,
|
||||
BuildGridBounds(),
|
||||
m_presentation.sections,
|
||||
filteredEvents,
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridMetrics());
|
||||
if (m_gridFrame.result.pickerRequested &&
|
||||
!m_gridFrame.result.requestedFieldId.empty()) {
|
||||
RequestColorPicker(context, m_gridFrame.result.requestedFieldId);
|
||||
}
|
||||
m_gridFrame = {};
|
||||
if (!m_presentation.sections.empty()) {
|
||||
m_gridFrame = UpdateUIEditorPropertyGridInteraction(
|
||||
m_interactionState,
|
||||
m_fieldSelection,
|
||||
m_sectionExpansion,
|
||||
m_propertyEditModel,
|
||||
BuildGridBounds(),
|
||||
m_presentation.sections,
|
||||
filteredEvents,
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridMetrics());
|
||||
if (m_gridFrame.result.pickerRequested &&
|
||||
!m_gridFrame.result.requestedFieldId.empty()) {
|
||||
RequestColorPicker(context, m_gridFrame.result.requestedFieldId);
|
||||
}
|
||||
|
||||
if (m_gridFrame.result.fieldValueChanged &&
|
||||
!m_gridFrame.result.changedFieldId.empty()) {
|
||||
if (ApplyChangedField(m_gridFrame.result.changedFieldId)) {
|
||||
RefreshPresentation(context, false);
|
||||
} else {
|
||||
ForceResyncPresentation(context);
|
||||
if (m_gridFrame.result.fieldValueChanged &&
|
||||
!m_gridFrame.result.changedFieldId.empty()) {
|
||||
if (ApplyChangedField(m_gridFrame.result.changedFieldId)) {
|
||||
RefreshPresentation(context, false);
|
||||
} else {
|
||||
ForceResyncPresentation(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateAddComponentButton(context, filteredEvents);
|
||||
}
|
||||
|
||||
void InspectorPanel::Append(UIDrawList& drawList) const {
|
||||
@@ -565,20 +682,50 @@ void InspectorPanel::Append(UIDrawList& drawList) const {
|
||||
kSubtitleFontSize);
|
||||
}
|
||||
|
||||
if (m_presentation.sections.empty()) {
|
||||
if (!m_presentation.sections.empty()) {
|
||||
Widgets::AppendUIEditorPropertyGrid(
|
||||
drawList,
|
||||
BuildGridBounds(),
|
||||
m_presentation.sections,
|
||||
m_fieldSelection,
|
||||
m_sectionExpansion,
|
||||
m_propertyEditModel,
|
||||
m_interactionState.propertyGridState,
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridPalette(),
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridMetrics());
|
||||
}
|
||||
|
||||
if (!ShouldShowAddComponentButton()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Widgets::AppendUIEditorPropertyGrid(
|
||||
drawList,
|
||||
BuildGridBounds(),
|
||||
m_presentation.sections,
|
||||
m_fieldSelection,
|
||||
m_sectionExpansion,
|
||||
m_propertyEditModel,
|
||||
m_interactionState.propertyGridState,
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridPalette(),
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridMetrics());
|
||||
const UIRect buttonRect = BuildAddComponentButtonRect();
|
||||
if (buttonRect.width <= 0.0f || buttonRect.height <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Widgets::UIEditorPropertyGridPalette& palette =
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridPalette();
|
||||
const Widgets::UIEditorPropertyGridMetrics& metrics =
|
||||
::XCEngine::UI::Editor::GetUIEditorFixedPropertyGridMetrics();
|
||||
drawList.AddFilledRect(
|
||||
buttonRect,
|
||||
ResolveAddComponentButtonFillColor(
|
||||
m_addComponentButtonHovered,
|
||||
m_addComponentButtonPressed),
|
||||
metrics.valueBoxRounding);
|
||||
drawList.AddRectOutline(
|
||||
buttonRect,
|
||||
palette.valueBoxBorderColor,
|
||||
metrics.borderThickness,
|
||||
metrics.valueBoxRounding);
|
||||
drawList.AddText(
|
||||
UIPoint(
|
||||
ResolveCenteredTextX(buttonRect, "Add Component", kAddComponentButtonFontSize),
|
||||
ResolveTextTop(buttonRect.y, buttonRect.height, kAddComponentButtonFontSize)),
|
||||
"Add Component",
|
||||
palette.valueTextColor,
|
||||
kAddComponentButtonFontSize);
|
||||
}
|
||||
|
||||
UIEditorHostCommandEvaluationResult InspectorPanel::EvaluateEditCommand(
|
||||
|
||||
Reference in New Issue
Block a user