Refine new_editor scene viewport flow
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
@@ -22,10 +21,6 @@ using ::XCEngine::Input::KeyCode;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
using ::XCEngine::UI::UIPointerButton;
|
||||
using ::XCEngine::UI::UIRect;
|
||||
using ::XCEngine::UI::Editor::Widgets::HitTestUIEditorViewportSlot;
|
||||
using ::XCEngine::UI::Editor::Widgets::UIEditorViewportSlotHitTarget;
|
||||
using ::XCEngine::UI::Editor::Widgets::UIEditorViewportSlotHitTargetKind;
|
||||
|
||||
constexpr float kWheelDeltaPerStep = 120.0f;
|
||||
|
||||
bool ContainsPoint(const UIRect& rect, const UIPoint& point) {
|
||||
@@ -69,6 +64,17 @@ float NormalizeWheelDelta(float wheelDelta) {
|
||||
return wheelDelta / kWheelDeltaPerStep;
|
||||
}
|
||||
|
||||
bool IsViewMoveTool(SceneToolMode mode) {
|
||||
return mode == SceneToolMode::View;
|
||||
}
|
||||
|
||||
bool IsPanDragButtonDown(
|
||||
const UIEditorViewportInputBridgeState& state,
|
||||
UIPointerButton button) {
|
||||
return button != UIPointerButton::None &&
|
||||
IsUIEditorViewportInputBridgePointerButtonDown(state, button);
|
||||
}
|
||||
|
||||
bool TryResolveToolModeShortcut(
|
||||
const UIEditorViewportInputBridgeFrame& inputFrame,
|
||||
SceneToolMode& outMode) {
|
||||
@@ -98,29 +104,6 @@ bool TryResolveToolModeShortcut(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ApplySceneToolbarCommand(
|
||||
std::string_view itemId,
|
||||
EditorSceneRuntime& sceneRuntime) {
|
||||
if (itemId == "scene.pivot.pivot") {
|
||||
sceneRuntime.SetToolPivotMode(SceneToolPivotMode::Pivot);
|
||||
return true;
|
||||
}
|
||||
if (itemId == "scene.pivot.center") {
|
||||
sceneRuntime.SetToolPivotMode(SceneToolPivotMode::Center);
|
||||
return true;
|
||||
}
|
||||
if (itemId == "scene.space.world") {
|
||||
sceneRuntime.SetToolSpaceMode(SceneToolSpaceMode::World);
|
||||
return true;
|
||||
}
|
||||
if (itemId == "scene.space.local") {
|
||||
sceneRuntime.SetToolSpaceMode(SceneToolSpaceMode::Local);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ApplySceneToolMode(
|
||||
SceneToolMode mode,
|
||||
EditorSceneRuntime& sceneRuntime,
|
||||
@@ -166,7 +149,6 @@ void SceneViewportController::Update(
|
||||
if (m_legacyGizmo.IsActive()) {
|
||||
m_legacyGizmo.CancelDrag(sceneRuntime);
|
||||
}
|
||||
sceneRuntime.ClearToolbarInteraction();
|
||||
sceneRuntime.SetHoveredToolHandle(SceneToolHandle::None);
|
||||
ResetInteractionState();
|
||||
return;
|
||||
@@ -175,7 +157,6 @@ void SceneViewportController::Update(
|
||||
const auto& inputFrame = viewportFrame->viewportShellFrame.inputFrame;
|
||||
const auto& inputState = panelState->viewportShellState.inputBridgeState;
|
||||
const auto& slotLayout = viewportFrame->viewportShellFrame.slotLayout;
|
||||
const auto& toolItems = viewportFrame->viewportShellModel.spec.toolItems;
|
||||
const bool leftMouseDown = IsUIEditorViewportInputBridgePointerButtonDown(
|
||||
inputState,
|
||||
UIPointerButton::Left);
|
||||
@@ -196,55 +177,8 @@ void SceneViewportController::Update(
|
||||
if (m_legacyGizmo.IsActive()) {
|
||||
m_legacyGizmo.CancelDrag(sceneRuntime);
|
||||
}
|
||||
sceneRuntime.ClearToolbarInteraction();
|
||||
}
|
||||
|
||||
std::size_t hoveredToolbarIndex = kSceneToolInvalidToolbarIndex;
|
||||
if (!toolItems.empty() && inputState.hasPointerPosition) {
|
||||
const UIEditorViewportSlotHitTarget toolbarHit =
|
||||
HitTestUIEditorViewportSlot(slotLayout, pointerScreen);
|
||||
if (toolbarHit.kind == UIEditorViewportSlotHitTargetKind::ToolItem &&
|
||||
toolbarHit.index < toolItems.size() &&
|
||||
toolItems[toolbarHit.index].enabled) {
|
||||
hoveredToolbarIndex = toolbarHit.index;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_legacyGizmo.IsActive()) {
|
||||
sceneRuntime.ClearToolbarInteraction();
|
||||
} else {
|
||||
sceneRuntime.SetToolbarHoveredIndex(hoveredToolbarIndex);
|
||||
if (inputFrame.changedPointerButton == UIPointerButton::Left &&
|
||||
leftMouseDown &&
|
||||
hoveredToolbarIndex != kSceneToolInvalidToolbarIndex) {
|
||||
sceneRuntime.SetToolbarActiveIndex(hoveredToolbarIndex);
|
||||
sceneRuntime.SetToolInteractionLock(SceneToolInteractionLock::Toolbar);
|
||||
} else if (inputFrame.changedPointerButton == UIPointerButton::Left &&
|
||||
!leftMouseDown) {
|
||||
const std::size_t activeToolbarIndex =
|
||||
sceneRuntime.GetToolState().toolbarActiveIndex;
|
||||
const bool applyCommand =
|
||||
activeToolbarIndex != kSceneToolInvalidToolbarIndex &&
|
||||
activeToolbarIndex == hoveredToolbarIndex &&
|
||||
activeToolbarIndex < toolItems.size() &&
|
||||
toolItems[activeToolbarIndex].enabled;
|
||||
sceneRuntime.ClearToolbarInteraction();
|
||||
if (applyCommand) {
|
||||
ApplySceneToolbarCommand(
|
||||
toolItems[activeToolbarIndex].itemId,
|
||||
sceneRuntime);
|
||||
}
|
||||
} else if (!leftMouseDown &&
|
||||
sceneRuntime.GetToolState().interactionLock ==
|
||||
SceneToolInteractionLock::Toolbar) {
|
||||
sceneRuntime.ClearToolbarInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
const bool toolbarInteractionActive =
|
||||
sceneRuntime.GetToolState().interactionLock ==
|
||||
SceneToolInteractionLock::Toolbar;
|
||||
|
||||
m_toolOverlay.BuildFrame(
|
||||
slotLayout.inputRect,
|
||||
sceneRuntime.GetToolMode(),
|
||||
@@ -258,24 +192,30 @@ void SceneViewportController::Update(
|
||||
? m_toolOverlay.HitTest(pointerScreen)
|
||||
: kSceneViewportToolOverlayInvalidIndex;
|
||||
|
||||
if (inputFrame.changedPointerButton == UIPointerButton::Left &&
|
||||
leftMouseDown &&
|
||||
hoveredToolOverlayIndex != kSceneViewportToolOverlayInvalidIndex &&
|
||||
!toolbarInteractionActive &&
|
||||
!m_legacyGizmo.IsActive()) {
|
||||
m_activeToolOverlayIndex = hoveredToolOverlayIndex;
|
||||
} else if (inputFrame.changedPointerButton == UIPointerButton::Left &&
|
||||
!leftMouseDown) {
|
||||
if (m_activeToolOverlayIndex != kSceneViewportToolOverlayInvalidIndex &&
|
||||
m_activeToolOverlayIndex == hoveredToolOverlayIndex &&
|
||||
m_activeToolOverlayIndex < m_toolOverlay.GetFrame().buttons.size()) {
|
||||
ApplySceneToolMode(
|
||||
m_toolOverlay.GetFrame().buttons[m_activeToolOverlayIndex].mode,
|
||||
sceneRuntime,
|
||||
m_legacyGizmo);
|
||||
for (const auto& transition : inputFrame.pointerButtonTransitions) {
|
||||
if (transition.button != UIPointerButton::Left) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::size_t transitionHoveredToolOverlayIndex =
|
||||
m_toolOverlay.HitTest(transition.screenPosition);
|
||||
if (transition.pressed &&
|
||||
transitionHoveredToolOverlayIndex !=
|
||||
kSceneViewportToolOverlayInvalidIndex &&
|
||||
!m_legacyGizmo.IsActive()) {
|
||||
m_activeToolOverlayIndex = transitionHoveredToolOverlayIndex;
|
||||
if (m_activeToolOverlayIndex < m_toolOverlay.GetFrame().buttons.size()) {
|
||||
ApplySceneToolMode(
|
||||
m_toolOverlay.GetFrame().buttons[m_activeToolOverlayIndex].mode,
|
||||
sceneRuntime,
|
||||
m_legacyGizmo);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
m_activeToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
} else if (!leftMouseDown) {
|
||||
}
|
||||
if (!leftMouseDown) {
|
||||
m_activeToolOverlayIndex = kSceneViewportToolOverlayInvalidIndex;
|
||||
}
|
||||
m_hoveredToolOverlayIndex = hoveredToolOverlayIndex;
|
||||
@@ -289,43 +229,55 @@ void SceneViewportController::Update(
|
||||
const bool toolOverlayInteractionActive =
|
||||
m_activeToolOverlayIndex != kSceneViewportToolOverlayInvalidIndex;
|
||||
|
||||
if (!toolbarInteractionActive &&
|
||||
!toolOverlayInteractionActive &&
|
||||
!m_legacyGizmo.IsActive()) {
|
||||
if (inputFrame.pointerPressedInside &&
|
||||
inputFrame.changedPointerButton == UIPointerButton::Right &&
|
||||
!pointerOverToolOverlay) {
|
||||
m_navigationState.lookDragging = true;
|
||||
m_navigationState.panDragging = false;
|
||||
}
|
||||
if (inputFrame.pointerPressedInside &&
|
||||
inputFrame.changedPointerButton == UIPointerButton::Middle &&
|
||||
!pointerOverToolOverlay) {
|
||||
m_navigationState.panDragging = true;
|
||||
m_navigationState.lookDragging = false;
|
||||
const bool usingViewMoveTool = IsViewMoveTool(sceneRuntime.GetToolMode());
|
||||
|
||||
if (!m_legacyGizmo.IsActive()) {
|
||||
for (const auto& transition : inputFrame.pointerButtonTransitions) {
|
||||
if (!transition.pressed ||
|
||||
!ContainsPoint(slotLayout.inputRect, transition.screenPosition) ||
|
||||
m_toolOverlay.Contains(transition.screenPosition)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (usingViewMoveTool &&
|
||||
transition.button == UIPointerButton::Left) {
|
||||
m_navigationState.panDragging = true;
|
||||
m_navigationState.lookDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::Left;
|
||||
} else if (transition.button == UIPointerButton::Right) {
|
||||
m_navigationState.lookDragging = true;
|
||||
m_navigationState.panDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::None;
|
||||
} else if (transition.button == UIPointerButton::Middle) {
|
||||
m_navigationState.panDragging = true;
|
||||
m_navigationState.lookDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::Middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_navigationState.lookDragging && !rightMouseDown) {
|
||||
m_navigationState.lookDragging = false;
|
||||
}
|
||||
if (m_navigationState.panDragging && !middleMouseDown) {
|
||||
if (m_navigationState.panDragging &&
|
||||
!IsPanDragButtonDown(inputState, m_navigationState.panDragButton)) {
|
||||
m_navigationState.panDragging = false;
|
||||
m_navigationState.panDragButton = UIPointerButton::None;
|
||||
}
|
||||
|
||||
const bool viewportHoverEligible =
|
||||
inputState.hasPointerPosition &&
|
||||
ContainsPoint(slotLayout.inputRect, pointerScreen) &&
|
||||
!pointerOverToolOverlay &&
|
||||
!toolbarInteractionActive &&
|
||||
!toolOverlayInteractionActive &&
|
||||
!m_navigationState.lookDragging &&
|
||||
!m_navigationState.panDragging;
|
||||
|
||||
if (!m_legacyGizmo.IsActive() &&
|
||||
!toolbarInteractionActive &&
|
||||
!toolOverlayInteractionActive &&
|
||||
inputFrame.focused) {
|
||||
inputFrame.focused &&
|
||||
!m_navigationState.lookDragging &&
|
||||
!m_navigationState.panDragging) {
|
||||
SceneToolMode shortcutMode = SceneToolMode::View;
|
||||
if (TryResolveToolModeShortcut(inputFrame, shortcutMode)) {
|
||||
ApplySceneToolMode(shortcutMode, sceneRuntime, m_legacyGizmo);
|
||||
@@ -356,8 +308,7 @@ void SceneViewportController::Update(
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputFrame.changedPointerButton == UIPointerButton::Left &&
|
||||
!leftMouseDown) {
|
||||
if (!leftMouseDown) {
|
||||
m_legacyGizmo.EndDrag(sceneRuntime);
|
||||
m_legacyGizmo.Refresh(
|
||||
sceneRuntime,
|
||||
@@ -376,48 +327,52 @@ void SceneViewportController::Update(
|
||||
return;
|
||||
}
|
||||
|
||||
const bool shouldStartTransformDrag =
|
||||
inputFrame.pointerPressedInside &&
|
||||
inputFrame.changedPointerButton == UIPointerButton::Left &&
|
||||
viewportHoverEligible &&
|
||||
m_legacyGizmo.IsHoveringHandle();
|
||||
if (shouldStartTransformDrag &&
|
||||
m_legacyGizmo.TryBeginDrag(sceneRuntime)) {
|
||||
m_navigationState = {};
|
||||
m_legacyGizmo.Refresh(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
return;
|
||||
}
|
||||
|
||||
const bool shouldPickSelection =
|
||||
inputFrame.pointerPressedInside &&
|
||||
inputFrame.changedPointerButton == UIPointerButton::Left &&
|
||||
viewportHoverEligible &&
|
||||
!m_legacyGizmo.IsHoveringHandle();
|
||||
if (shouldPickSelection) {
|
||||
const ViewportObjectIdPickResult pickResult =
|
||||
viewportHostService.PickSceneViewportObject(
|
||||
viewportFrame->viewportShellFrame.requestedViewportSize,
|
||||
inputFrame.localPointerPosition);
|
||||
if (pickResult.status == ViewportObjectIdPickStatus::Success) {
|
||||
if (pickResult.entityId != 0u) {
|
||||
sceneRuntime.SetSelection(pickResult.entityId);
|
||||
} else {
|
||||
sceneRuntime.ClearSelection();
|
||||
if (!usingViewMoveTool) {
|
||||
for (const auto& transition : inputFrame.pointerButtonTransitions) {
|
||||
if (!transition.pressed ||
|
||||
transition.button != UIPointerButton::Left ||
|
||||
!ContainsPoint(slotLayout.inputRect, transition.screenPosition) ||
|
||||
m_toolOverlay.Contains(transition.screenPosition)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
m_legacyGizmo.Refresh(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
m_legacyGizmo.Refresh(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
transition.screenPosition,
|
||||
true);
|
||||
if (m_legacyGizmo.IsHoveringHandle() &&
|
||||
m_legacyGizmo.TryBeginDrag(sceneRuntime)) {
|
||||
m_navigationState = {};
|
||||
m_legacyGizmo.Refresh(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
return;
|
||||
}
|
||||
|
||||
const ViewportObjectIdPickResult pickResult =
|
||||
viewportHostService.PickSceneViewportObject(
|
||||
viewportFrame->viewportShellFrame.requestedViewportSize,
|
||||
transition.localPointerPosition);
|
||||
if (pickResult.status == ViewportObjectIdPickStatus::Success) {
|
||||
if (pickResult.entityId != 0u) {
|
||||
sceneRuntime.SetSelection(pickResult.entityId);
|
||||
} else {
|
||||
sceneRuntime.ClearSelection();
|
||||
}
|
||||
}
|
||||
|
||||
m_legacyGizmo.Refresh(
|
||||
sceneRuntime,
|
||||
slotLayout.inputRect,
|
||||
pointerScreen,
|
||||
viewportHoverEligible);
|
||||
}
|
||||
}
|
||||
|
||||
if (toolbarInteractionActive || toolOverlayInteractionActive) {
|
||||
if (toolOverlayInteractionActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -443,7 +398,7 @@ void SceneViewportController::Update(
|
||||
} else if (m_navigationState.panDragging) {
|
||||
input.panDeltaX = inputFrame.pointerDelta.x;
|
||||
input.panDeltaY = inputFrame.pointerDelta.y;
|
||||
} else if (inputFrame.hovered && !pointerOverToolOverlay) {
|
||||
} else if (ContainsPoint(slotLayout.inputRect, pointerScreen) && !pointerOverToolOverlay) {
|
||||
input.zoomDelta = NormalizeWheelDelta(inputFrame.wheelDelta);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user