Files
XCEngine/new_editor/src/Fields/UIEditorObjectFieldInteraction.cpp

175 lines
7.0 KiB
C++

#include <XCEditor/Fields/UIEditorObjectFieldInteraction.h>
#include <XCEngine/Input/InputTypes.h>
namespace XCEngine::UI::Editor {
namespace {
using ::XCEngine::Input::KeyCode;
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
using ::XCEngine::UI::UIPointerButton;
using Widgets::BuildUIEditorObjectFieldLayout;
using Widgets::HitTestUIEditorObjectField;
using Widgets::UIEditorObjectFieldHitTargetKind;
bool ShouldUsePointerPosition(const UIInputEvent& event) {
switch (event.type) {
case UIInputEventType::PointerMove:
case UIInputEventType::PointerEnter:
case UIInputEventType::PointerButtonDown:
case UIInputEventType::PointerButtonUp:
return true;
default:
return false;
}
}
bool CanActivate(const Widgets::UIEditorObjectFieldSpec& spec) {
return !spec.readOnly;
}
bool CanClear(const Widgets::UIEditorObjectFieldSpec& spec) {
return !spec.readOnly && spec.hasValue && spec.showClearButton;
}
} // namespace
UIEditorObjectFieldInteractionFrame UpdateUIEditorObjectFieldInteraction(
UIEditorObjectFieldInteractionState& state,
const Widgets::UIEditorObjectFieldSpec& spec,
const ::XCEngine::UI::UIRect& bounds,
const std::vector<UIInputEvent>& inputEvents,
const Widgets::UIEditorObjectFieldMetrics& metrics) {
Widgets::UIEditorObjectFieldLayout layout =
BuildUIEditorObjectFieldLayout(bounds, spec, metrics);
if (state.hasPointerPosition) {
state.fieldState.hoveredTarget = HitTestUIEditorObjectField(layout, state.pointerPosition).kind;
} else {
state.fieldState.hoveredTarget = UIEditorObjectFieldHitTargetKind::None;
}
UIEditorObjectFieldInteractionResult interactionResult = {};
for (const UIInputEvent& event : inputEvents) {
if (ShouldUsePointerPosition(event)) {
state.pointerPosition = event.position;
state.hasPointerPosition = true;
} else if (event.type == UIInputEventType::PointerLeave) {
state.hasPointerPosition = false;
}
UIEditorObjectFieldInteractionResult eventResult = {};
switch (event.type) {
case UIInputEventType::FocusGained:
eventResult.focusChanged = !state.fieldState.focused;
state.fieldState.focused = true;
break;
case UIInputEventType::FocusLost:
eventResult.focusChanged = state.fieldState.focused;
state.fieldState.focused = false;
state.fieldState.activeTarget = UIEditorObjectFieldHitTargetKind::None;
state.hasPointerPosition = false;
state.fieldState.hoveredTarget = UIEditorObjectFieldHitTargetKind::None;
break;
case UIInputEventType::PointerMove:
case UIInputEventType::PointerEnter:
case UIInputEventType::PointerLeave:
break;
case UIInputEventType::PointerButtonDown:
eventResult.hitTarget = state.hasPointerPosition
? HitTestUIEditorObjectField(layout, state.pointerPosition)
: Widgets::UIEditorObjectFieldHitTarget {};
if (event.pointerButton == UIPointerButton::Left &&
eventResult.hitTarget.kind != UIEditorObjectFieldHitTargetKind::None) {
eventResult.focusChanged = !state.fieldState.focused;
state.fieldState.focused = true;
state.fieldState.activeTarget = eventResult.hitTarget.kind;
eventResult.consumed = true;
} else if (event.pointerButton == UIPointerButton::Left) {
eventResult.focusChanged = state.fieldState.focused;
state.fieldState.focused = false;
state.fieldState.activeTarget = UIEditorObjectFieldHitTargetKind::None;
}
break;
case UIInputEventType::PointerButtonUp:
eventResult.hitTarget = state.hasPointerPosition
? HitTestUIEditorObjectField(layout, state.pointerPosition)
: Widgets::UIEditorObjectFieldHitTarget {};
if (event.pointerButton == UIPointerButton::Left) {
const UIEditorObjectFieldHitTargetKind activeTarget = state.fieldState.activeTarget;
state.fieldState.activeTarget = UIEditorObjectFieldHitTargetKind::None;
if (eventResult.hitTarget.kind == activeTarget) {
if ((activeTarget == UIEditorObjectFieldHitTargetKind::ValueBox ||
activeTarget == UIEditorObjectFieldHitTargetKind::PickerButton) &&
CanActivate(spec)) {
eventResult.activateRequested = true;
eventResult.consumed = true;
} else if (activeTarget == UIEditorObjectFieldHitTargetKind::ClearButton &&
CanClear(spec)) {
eventResult.clearRequested = true;
eventResult.consumed = true;
} else if (activeTarget == UIEditorObjectFieldHitTargetKind::Row) {
eventResult.consumed = true;
}
}
}
break;
case UIInputEventType::KeyDown:
if (!state.fieldState.focused) {
break;
}
if ((static_cast<KeyCode>(event.keyCode) == KeyCode::Enter ||
static_cast<KeyCode>(event.keyCode) == KeyCode::Space) &&
CanActivate(spec)) {
eventResult.activateRequested = true;
eventResult.consumed = true;
} else if ((static_cast<KeyCode>(event.keyCode) == KeyCode::Delete ||
static_cast<KeyCode>(event.keyCode) == KeyCode::Backspace) &&
CanClear(spec)) {
eventResult.clearRequested = true;
eventResult.consumed = true;
}
break;
default:
break;
}
layout = BuildUIEditorObjectFieldLayout(bounds, spec, metrics);
if (state.hasPointerPosition) {
state.fieldState.hoveredTarget = HitTestUIEditorObjectField(layout, state.pointerPosition).kind;
} else {
state.fieldState.hoveredTarget = UIEditorObjectFieldHitTargetKind::None;
}
if (eventResult.consumed ||
eventResult.focusChanged ||
eventResult.activateRequested ||
eventResult.clearRequested ||
eventResult.hitTarget.kind != UIEditorObjectFieldHitTargetKind::None) {
interactionResult = eventResult;
}
}
layout = BuildUIEditorObjectFieldLayout(bounds, spec, metrics);
if (state.hasPointerPosition) {
state.fieldState.hoveredTarget = HitTestUIEditorObjectField(layout, state.pointerPosition).kind;
if (interactionResult.hitTarget.kind == UIEditorObjectFieldHitTargetKind::None) {
interactionResult.hitTarget = HitTestUIEditorObjectField(layout, state.pointerPosition);
}
} else {
state.fieldState.hoveredTarget = UIEditorObjectFieldHitTargetKind::None;
}
return { layout, interactionResult };
}
} // namespace XCEngine::UI::Editor