Formalize scene viewport navigation input helpers
This commit is contained in:
@@ -1,5 +1,28 @@
|
|||||||
# SceneViewport Overlay/Gizmo Rework Checkpoint
|
# SceneViewport Overlay/Gizmo Rework Checkpoint
|
||||||
|
|
||||||
|
## Update 2026-04-04 Phase 5E
|
||||||
|
|
||||||
|
### Navigation/Input State Formalization Completed
|
||||||
|
|
||||||
|
- Added `SceneViewportEditorModes.h` to move shared scene viewport editor mode enums out of `SceneViewPanel.h`.
|
||||||
|
- Added `SceneViewportNavigation.h` as the formal navigation/input helper layer for:
|
||||||
|
- tool shortcut resolution
|
||||||
|
- look/pan drag state transitions
|
||||||
|
- mouse/keyboard capture requests
|
||||||
|
- `SceneViewportInput` assembly
|
||||||
|
- interaction-resolution gating
|
||||||
|
- `SceneViewPanel` now owns one `SceneViewportNavigationState` instead of multiple raw drag booleans and no longer assembles scene viewport input inline.
|
||||||
|
- Removed the dead `m_loggedLookDelta` / `m_loggedPanDelta` panel state that no longer influenced runtime behavior.
|
||||||
|
- Added focused editor tests for shortcut mapping, drag transitions, capture flags, input assembly, and interaction gating.
|
||||||
|
|
||||||
|
### Verification
|
||||||
|
|
||||||
|
- `cmake --build build --config Debug --target editor_tests -- /p:BuildProjectReferences=false`
|
||||||
|
- `build/tests/Editor/Debug/editor_tests.exe --gtest_filter=SceneViewportNavigationTest.*:SceneViewportInteractionActionsTest.*:SceneViewportInteractionResolverTest.*:SceneViewportTransformGizmoCoordinatorTest.*:SceneViewportOverlayRenderer_Test.*:SceneViewportOverlayProviderRegistryTest.*:ViewportRenderFlowUtilsTest.*`
|
||||||
|
- `cmake --build build --config Debug --target XCEditor`
|
||||||
|
|
||||||
|
All commands completed successfully in `Debug`.
|
||||||
|
|
||||||
## Update 2026-04-04 Phase 5D
|
## Update 2026-04-04 Phase 5D
|
||||||
|
|
||||||
### Stage-Oriented Gizmo Frame API Completed
|
### Stage-Oriented Gizmo Frame API Completed
|
||||||
|
|||||||
27
editor/src/Viewport/SceneViewportEditorModes.h
Normal file
27
editor/src/Viewport/SceneViewportEditorModes.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Editor {
|
||||||
|
|
||||||
|
enum class SceneViewportToolMode : uint8_t {
|
||||||
|
ViewMove = 0,
|
||||||
|
Move,
|
||||||
|
Rotate,
|
||||||
|
Scale,
|
||||||
|
Transform
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SceneViewportPivotMode : uint8_t {
|
||||||
|
Pivot = 0,
|
||||||
|
Center
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SceneViewportTransformSpaceMode : uint8_t {
|
||||||
|
Global = 0,
|
||||||
|
Local
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Editor
|
||||||
|
} // namespace XCEngine
|
||||||
279
editor/src/Viewport/SceneViewportNavigation.h
Normal file
279
editor/src/Viewport/SceneViewportNavigation.h
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IViewportHostService.h"
|
||||||
|
#include "SceneViewportEditorModes.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace Editor {
|
||||||
|
|
||||||
|
struct SceneViewportToolShortcutRequest {
|
||||||
|
bool wantTextInput = false;
|
||||||
|
bool lookDragging = false;
|
||||||
|
bool panDragging = false;
|
||||||
|
bool pressedViewMove = false;
|
||||||
|
bool pressedMove = false;
|
||||||
|
bool pressedRotate = false;
|
||||||
|
bool pressedScale = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SceneViewportToolShortcutAction {
|
||||||
|
SceneViewportToolMode targetTool = SceneViewportToolMode::Move;
|
||||||
|
bool triggered = false;
|
||||||
|
bool cancelMoveGizmo = false;
|
||||||
|
bool cancelRotateGizmo = false;
|
||||||
|
bool cancelScaleGizmo = false;
|
||||||
|
|
||||||
|
bool HasAction() const {
|
||||||
|
return triggered;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool CanUseSceneViewportToolShortcut(const SceneViewportToolShortcutRequest& request) {
|
||||||
|
return !request.wantTextInput && !request.lookDragging && !request.panDragging;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SceneViewportToolShortcutAction BuildSceneViewportToolShortcutAction(
|
||||||
|
const SceneViewportToolShortcutRequest& request) {
|
||||||
|
SceneViewportToolShortcutAction action = {};
|
||||||
|
if (!CanUseSceneViewportToolShortcut(request)) {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.pressedViewMove) {
|
||||||
|
action.targetTool = SceneViewportToolMode::ViewMove;
|
||||||
|
action.triggered = true;
|
||||||
|
action.cancelMoveGizmo = true;
|
||||||
|
action.cancelRotateGizmo = true;
|
||||||
|
action.cancelScaleGizmo = true;
|
||||||
|
} else if (request.pressedMove) {
|
||||||
|
action.targetTool = SceneViewportToolMode::Move;
|
||||||
|
action.triggered = true;
|
||||||
|
action.cancelRotateGizmo = true;
|
||||||
|
action.cancelScaleGizmo = true;
|
||||||
|
} else if (request.pressedRotate) {
|
||||||
|
action.targetTool = SceneViewportToolMode::Rotate;
|
||||||
|
action.triggered = true;
|
||||||
|
action.cancelMoveGizmo = true;
|
||||||
|
action.cancelScaleGizmo = true;
|
||||||
|
} else if (request.pressedScale) {
|
||||||
|
action.targetTool = SceneViewportToolMode::Scale;
|
||||||
|
action.triggered = true;
|
||||||
|
action.cancelMoveGizmo = true;
|
||||||
|
action.cancelRotateGizmo = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SceneViewportNavigationState {
|
||||||
|
bool lookDragging = false;
|
||||||
|
bool panDragging = false;
|
||||||
|
int panDragButton = ImGuiMouseButton_Middle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SceneViewportNavigationRequest {
|
||||||
|
SceneViewportNavigationState state = {};
|
||||||
|
bool hasInteractiveViewport = false;
|
||||||
|
bool viewportHovered = false;
|
||||||
|
bool usingViewMoveTool = false;
|
||||||
|
bool gizmoActive = false;
|
||||||
|
bool clickedLeft = false;
|
||||||
|
bool clickedRight = false;
|
||||||
|
bool clickedMiddle = false;
|
||||||
|
bool leftMouseDown = false;
|
||||||
|
bool rightMouseDown = false;
|
||||||
|
bool middleMouseDown = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SceneViewportNavigationUpdate {
|
||||||
|
SceneViewportNavigationState state = {};
|
||||||
|
bool beginLookDrag = false;
|
||||||
|
bool beginPanDrag = false;
|
||||||
|
bool beginLeftPanDrag = false;
|
||||||
|
bool beginMiddlePanDrag = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool ShouldBeginSceneViewportNavigationDrag(
|
||||||
|
bool hasInteractiveViewport,
|
||||||
|
bool hovered,
|
||||||
|
bool activeDrag,
|
||||||
|
bool otherDrag,
|
||||||
|
bool gizmoActive,
|
||||||
|
bool clicked) {
|
||||||
|
return hasInteractiveViewport && hovered && !activeDrag && !otherDrag && !gizmoActive && clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsSceneViewportPanDragButtonDown(
|
||||||
|
const SceneViewportNavigationRequest& request,
|
||||||
|
int button) {
|
||||||
|
switch (button) {
|
||||||
|
case ImGuiMouseButton_Left:
|
||||||
|
return request.leftMouseDown;
|
||||||
|
case ImGuiMouseButton_Right:
|
||||||
|
return request.rightMouseDown;
|
||||||
|
case ImGuiMouseButton_Middle:
|
||||||
|
default:
|
||||||
|
return request.middleMouseDown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline SceneViewportNavigationUpdate UpdateSceneViewportNavigationState(
|
||||||
|
const SceneViewportNavigationRequest& request) {
|
||||||
|
SceneViewportNavigationUpdate update = {};
|
||||||
|
update.state = request.state;
|
||||||
|
update.beginLeftPanDrag = request.usingViewMoveTool
|
||||||
|
? ShouldBeginSceneViewportNavigationDrag(
|
||||||
|
request.hasInteractiveViewport,
|
||||||
|
request.viewportHovered,
|
||||||
|
request.state.panDragging,
|
||||||
|
request.state.lookDragging,
|
||||||
|
request.gizmoActive,
|
||||||
|
request.clickedLeft)
|
||||||
|
: false;
|
||||||
|
update.beginLookDrag = ShouldBeginSceneViewportNavigationDrag(
|
||||||
|
request.hasInteractiveViewport,
|
||||||
|
request.viewportHovered,
|
||||||
|
request.state.lookDragging,
|
||||||
|
request.state.panDragging,
|
||||||
|
request.gizmoActive,
|
||||||
|
request.clickedRight);
|
||||||
|
update.beginMiddlePanDrag = ShouldBeginSceneViewportNavigationDrag(
|
||||||
|
request.hasInteractiveViewport,
|
||||||
|
request.viewportHovered,
|
||||||
|
request.state.panDragging,
|
||||||
|
request.state.lookDragging,
|
||||||
|
request.gizmoActive,
|
||||||
|
request.clickedMiddle);
|
||||||
|
update.beginPanDrag = update.beginLeftPanDrag || update.beginMiddlePanDrag;
|
||||||
|
|
||||||
|
if (update.beginLookDrag) {
|
||||||
|
update.state.lookDragging = true;
|
||||||
|
update.state.panDragging = false;
|
||||||
|
}
|
||||||
|
if (update.beginPanDrag) {
|
||||||
|
update.state.panDragging = true;
|
||||||
|
update.state.lookDragging = false;
|
||||||
|
update.state.panDragButton = update.beginLeftPanDrag
|
||||||
|
? ImGuiMouseButton_Left
|
||||||
|
: ImGuiMouseButton_Middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update.state.lookDragging && !request.rightMouseDown) {
|
||||||
|
update.state.lookDragging = false;
|
||||||
|
}
|
||||||
|
if (update.state.panDragging &&
|
||||||
|
!IsSceneViewportPanDragButtonDown(request, update.state.panDragButton)) {
|
||||||
|
update.state.panDragging = false;
|
||||||
|
update.state.panDragButton = ImGuiMouseButton_Middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SceneViewportCaptureRequest {
|
||||||
|
SceneViewportNavigationState state = {};
|
||||||
|
bool moveGizmoActive = false;
|
||||||
|
bool rotateGizmoActive = false;
|
||||||
|
bool scaleGizmoActive = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SceneViewportCaptureFlags {
|
||||||
|
bool captureMouse = false;
|
||||||
|
bool captureKeyboard = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline SceneViewportCaptureFlags BuildSceneViewportCaptureFlags(
|
||||||
|
const SceneViewportCaptureRequest& request) {
|
||||||
|
SceneViewportCaptureFlags flags = {};
|
||||||
|
flags.captureMouse =
|
||||||
|
request.state.lookDragging ||
|
||||||
|
request.state.panDragging ||
|
||||||
|
request.moveGizmoActive ||
|
||||||
|
request.rotateGizmoActive ||
|
||||||
|
request.scaleGizmoActive;
|
||||||
|
flags.captureKeyboard = request.state.lookDragging;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CanResolveSceneViewportInteraction(
|
||||||
|
bool hasInteractiveViewport,
|
||||||
|
bool viewportHovered,
|
||||||
|
bool usingViewMoveTool,
|
||||||
|
const SceneViewportNavigationState& navigationState,
|
||||||
|
bool gizmoActive) {
|
||||||
|
return hasInteractiveViewport &&
|
||||||
|
viewportHovered &&
|
||||||
|
!usingViewMoveTool &&
|
||||||
|
!navigationState.lookDragging &&
|
||||||
|
!navigationState.panDragging &&
|
||||||
|
!gizmoActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SceneViewportInputBuildRequest {
|
||||||
|
SceneViewportNavigationState state = {};
|
||||||
|
ImVec2 viewportSize = ImVec2(0.0f, 0.0f);
|
||||||
|
ImVec2 mouseDelta = ImVec2(0.0f, 0.0f);
|
||||||
|
float mouseWheel = 0.0f;
|
||||||
|
float deltaTime = 0.0f;
|
||||||
|
bool viewportHovered = false;
|
||||||
|
bool viewportFocused = false;
|
||||||
|
bool wantTextInput = false;
|
||||||
|
bool fastMove = false;
|
||||||
|
bool focusSelectionKeyPressed = false;
|
||||||
|
bool moveForwardKeyDown = false;
|
||||||
|
bool moveBackwardKeyDown = false;
|
||||||
|
bool moveRightKeyDown = false;
|
||||||
|
bool moveLeftKeyDown = false;
|
||||||
|
bool moveUpKeyDown = false;
|
||||||
|
bool moveDownKeyDown = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline SceneViewportInput BuildSceneViewportInput(const SceneViewportInputBuildRequest& request) {
|
||||||
|
SceneViewportInput input = {};
|
||||||
|
input.viewportSize = request.viewportSize;
|
||||||
|
input.deltaTime = request.deltaTime;
|
||||||
|
input.hovered = request.viewportHovered;
|
||||||
|
input.focused =
|
||||||
|
request.viewportFocused ||
|
||||||
|
request.state.lookDragging ||
|
||||||
|
request.state.panDragging;
|
||||||
|
input.mouseWheel =
|
||||||
|
(request.viewportHovered && !request.state.lookDragging)
|
||||||
|
? request.mouseWheel
|
||||||
|
: 0.0f;
|
||||||
|
input.flySpeedDelta =
|
||||||
|
(request.viewportHovered && request.state.lookDragging)
|
||||||
|
? request.mouseWheel
|
||||||
|
: 0.0f;
|
||||||
|
input.looking = request.state.lookDragging;
|
||||||
|
input.orbiting = false;
|
||||||
|
input.panning = request.state.panDragging;
|
||||||
|
input.fastMove = request.fastMove;
|
||||||
|
input.focusSelectionRequested =
|
||||||
|
input.focused &&
|
||||||
|
!request.wantTextInput &&
|
||||||
|
request.focusSelectionKeyPressed;
|
||||||
|
|
||||||
|
if (request.state.lookDragging && !request.wantTextInput) {
|
||||||
|
input.moveForward =
|
||||||
|
(request.moveForwardKeyDown ? 1.0f : 0.0f) -
|
||||||
|
(request.moveBackwardKeyDown ? 1.0f : 0.0f);
|
||||||
|
input.moveRight =
|
||||||
|
(request.moveRightKeyDown ? 1.0f : 0.0f) -
|
||||||
|
(request.moveLeftKeyDown ? 1.0f : 0.0f);
|
||||||
|
input.moveUp =
|
||||||
|
(request.moveUpKeyDown ? 1.0f : 0.0f) -
|
||||||
|
(request.moveDownKeyDown ? 1.0f : 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.state.lookDragging || request.state.panDragging) {
|
||||||
|
input.mouseDelta = request.mouseDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Editor
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "Viewport/SceneViewportInteractionActions.h"
|
#include "Viewport/SceneViewportInteractionActions.h"
|
||||||
#include "Viewport/SceneViewportInteractionResolver.h"
|
#include "Viewport/SceneViewportInteractionResolver.h"
|
||||||
#include "Viewport/SceneViewportMath.h"
|
#include "Viewport/SceneViewportMath.h"
|
||||||
|
#include "Viewport/SceneViewportNavigation.h"
|
||||||
#include "Viewport/SceneViewportTransformGizmoCoordinator.h"
|
#include "Viewport/SceneViewportTransformGizmoCoordinator.h"
|
||||||
#include "ViewportPanelContent.h"
|
#include "ViewportPanelContent.h"
|
||||||
#include "Platform/Win32Utf8.h"
|
#include "Platform/Win32Utf8.h"
|
||||||
@@ -243,21 +244,6 @@ SceneViewportToolOverlayResult RenderSceneViewportToolOverlay(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShouldBeginSceneViewportNavigationDrag(
|
|
||||||
bool hasInteractiveViewport,
|
|
||||||
bool hovered,
|
|
||||||
bool activeDrag,
|
|
||||||
bool otherDrag,
|
|
||||||
bool gizmoActive,
|
|
||||||
ImGuiMouseButton button) {
|
|
||||||
return hasInteractiveViewport &&
|
|
||||||
hovered &&
|
|
||||||
!activeDrag &&
|
|
||||||
!otherDrag &&
|
|
||||||
!gizmoActive &&
|
|
||||||
ImGui::IsMouseClicked(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
SceneViewPanel::SceneViewPanel() : Panel("Scene") {}
|
SceneViewPanel::SceneViewPanel() : Panel("Scene") {}
|
||||||
@@ -279,56 +265,31 @@ void SceneViewPanel::Render() {
|
|||||||
const bool viewportContentHovered = content.hovered && !toolOverlay.hovered;
|
const bool viewportContentHovered = content.hovered && !toolOverlay.hovered;
|
||||||
|
|
||||||
if (toolOverlay.clicked) {
|
if (toolOverlay.clicked) {
|
||||||
if (m_moveGizmo.IsActive()) {
|
CancelSceneViewportTransformGizmoFrame(*m_context, m_moveGizmo, m_rotateGizmo, m_scaleGizmo);
|
||||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
if (m_rotateGizmo.IsActive()) {
|
|
||||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
if (m_scaleGizmo.IsActive()) {
|
|
||||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
m_toolMode = toolOverlay.clickedTool;
|
m_toolMode = toolOverlay.clickedTool;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool allowToolShortcut = !io.WantTextInput && !m_lookDragging && !m_panDragging;
|
SceneViewportToolShortcutRequest toolShortcutRequest = {};
|
||||||
if (allowToolShortcut) {
|
toolShortcutRequest.wantTextInput = io.WantTextInput;
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_Q, false)) {
|
toolShortcutRequest.lookDragging = m_navigationState.lookDragging;
|
||||||
if (m_moveGizmo.IsActive()) {
|
toolShortcutRequest.panDragging = m_navigationState.panDragging;
|
||||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
toolShortcutRequest.pressedViewMove = ImGui::IsKeyPressed(ImGuiKey_Q, false);
|
||||||
}
|
toolShortcutRequest.pressedMove = ImGui::IsKeyPressed(ImGuiKey_W, false);
|
||||||
if (m_rotateGizmo.IsActive()) {
|
toolShortcutRequest.pressedRotate = ImGui::IsKeyPressed(ImGuiKey_E, false);
|
||||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
toolShortcutRequest.pressedScale = ImGui::IsKeyPressed(ImGuiKey_R, false);
|
||||||
}
|
const SceneViewportToolShortcutAction toolShortcutAction =
|
||||||
if (m_scaleGizmo.IsActive()) {
|
BuildSceneViewportToolShortcutAction(toolShortcutRequest);
|
||||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
if (toolShortcutAction.HasAction()) {
|
||||||
}
|
if (toolShortcutAction.cancelMoveGizmo && m_moveGizmo.IsActive()) {
|
||||||
m_toolMode = SceneViewportToolMode::ViewMove;
|
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||||
} else if (ImGui::IsKeyPressed(ImGuiKey_W, false)) {
|
|
||||||
if (m_rotateGizmo.IsActive()) {
|
|
||||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
if (m_scaleGizmo.IsActive()) {
|
|
||||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
m_toolMode = SceneViewportToolMode::Move;
|
|
||||||
} else if (ImGui::IsKeyPressed(ImGuiKey_E, false)) {
|
|
||||||
if (m_moveGizmo.IsActive()) {
|
|
||||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
if (m_scaleGizmo.IsActive()) {
|
|
||||||
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
m_toolMode = SceneViewportToolMode::Rotate;
|
|
||||||
} else if (ImGui::IsKeyPressed(ImGuiKey_R, false)) {
|
|
||||||
if (m_moveGizmo.IsActive()) {
|
|
||||||
m_moveGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
if (m_rotateGizmo.IsActive()) {
|
|
||||||
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
|
||||||
}
|
|
||||||
m_toolMode = SceneViewportToolMode::Scale;
|
|
||||||
}
|
}
|
||||||
|
if (toolShortcutAction.cancelRotateGizmo && m_rotateGizmo.IsActive()) {
|
||||||
|
m_rotateGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||||
|
}
|
||||||
|
if (toolShortcutAction.cancelScaleGizmo && m_scaleGizmo.IsActive()) {
|
||||||
|
m_scaleGizmo.CancelDrag(&m_context->GetUndoManager());
|
||||||
|
}
|
||||||
|
m_toolMode = toolShortcutAction.targetTool;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool usingViewMoveTool = m_toolMode == SceneViewportToolMode::ViewMove;
|
const bool usingViewMoveTool = m_toolMode == SceneViewportToolMode::ViewMove;
|
||||||
@@ -390,14 +351,12 @@ void SceneViewPanel::Render() {
|
|||||||
const SceneViewportHudOverlayData interactionHudOverlay =
|
const SceneViewportHudOverlayData interactionHudOverlay =
|
||||||
BuildSceneViewportHudOverlayData(overlay);
|
BuildSceneViewportHudOverlayData(overlay);
|
||||||
SceneViewportInteractionResult hoveredInteraction = {};
|
SceneViewportInteractionResult hoveredInteraction = {};
|
||||||
const bool canResolveViewportInteraction =
|
const bool canResolveViewportInteraction = CanResolveSceneViewportInteraction(
|
||||||
hasInteractiveViewport &&
|
hasInteractiveViewport,
|
||||||
viewportContentHovered &&
|
viewportContentHovered,
|
||||||
!usingViewMoveTool &&
|
usingViewMoveTool,
|
||||||
!m_lookDragging &&
|
m_navigationState,
|
||||||
!m_panDragging &&
|
gizmoActive);
|
||||||
!toolOverlay.hovered &&
|
|
||||||
!gizmoActive;
|
|
||||||
if (canResolveViewportInteraction) {
|
if (canResolveViewportInteraction) {
|
||||||
SceneViewportInteractionResolveRequest interactionRequest = {};
|
SceneViewportInteractionResolveRequest interactionRequest = {};
|
||||||
interactionRequest.overlayFrameData = &interactionOverlayFrameData;
|
interactionRequest.overlayFrameData = &interactionOverlayFrameData;
|
||||||
@@ -426,33 +385,24 @@ void SceneViewPanel::Render() {
|
|||||||
hasInteractiveViewport,
|
hasInteractiveViewport,
|
||||||
content.clickedLeft,
|
content.clickedLeft,
|
||||||
canResolveViewportInteraction);
|
canResolveViewportInteraction);
|
||||||
const bool beginLeftPanDrag = usingViewMoveTool
|
SceneViewportNavigationRequest navigationRequest = {};
|
||||||
? ShouldBeginSceneViewportNavigationDrag(
|
navigationRequest.state = m_navigationState;
|
||||||
hasInteractiveViewport,
|
navigationRequest.hasInteractiveViewport = hasInteractiveViewport;
|
||||||
viewportContentHovered,
|
navigationRequest.viewportHovered = viewportContentHovered;
|
||||||
m_panDragging,
|
navigationRequest.usingViewMoveTool = usingViewMoveTool;
|
||||||
m_lookDragging,
|
navigationRequest.gizmoActive = gizmoActive;
|
||||||
gizmoActive,
|
navigationRequest.clickedLeft = content.clickedLeft;
|
||||||
ImGuiMouseButton_Left)
|
navigationRequest.clickedRight = content.clickedRight;
|
||||||
: false;
|
navigationRequest.clickedMiddle = content.clickedMiddle;
|
||||||
const bool beginLookDrag = ShouldBeginSceneViewportNavigationDrag(
|
navigationRequest.leftMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left);
|
||||||
hasInteractiveViewport,
|
navigationRequest.rightMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Right);
|
||||||
viewportContentHovered,
|
navigationRequest.middleMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle);
|
||||||
m_lookDragging,
|
const SceneViewportNavigationUpdate navigationUpdate =
|
||||||
m_panDragging,
|
UpdateSceneViewportNavigationState(navigationRequest);
|
||||||
gizmoActive,
|
m_navigationState = navigationUpdate.state;
|
||||||
ImGuiMouseButton_Right);
|
|
||||||
const bool beginMiddlePanDrag = ShouldBeginSceneViewportNavigationDrag(
|
|
||||||
hasInteractiveViewport,
|
|
||||||
viewportContentHovered,
|
|
||||||
m_panDragging,
|
|
||||||
m_lookDragging,
|
|
||||||
gizmoActive,
|
|
||||||
ImGuiMouseButton_Middle);
|
|
||||||
const bool beginPanDrag = beginLeftPanDrag || beginMiddlePanDrag;
|
|
||||||
|
|
||||||
if (toolOverlay.clicked || interactionActions.HasClickAction() || beginLookDrag ||
|
if (toolOverlay.clicked || interactionActions.HasClickAction() || navigationUpdate.beginLookDrag ||
|
||||||
beginPanDrag) {
|
navigationUpdate.beginPanDrag) {
|
||||||
ImGui::SetWindowFocus();
|
ImGui::SetWindowFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,81 +431,37 @@ void SceneViewPanel::Render() {
|
|||||||
m_rotateGizmo,
|
m_rotateGizmo,
|
||||||
m_scaleGizmo);
|
m_scaleGizmo);
|
||||||
|
|
||||||
if (beginLookDrag) {
|
const SceneViewportCaptureFlags captureFlags = BuildSceneViewportCaptureFlags(
|
||||||
m_lookDragging = true;
|
SceneViewportCaptureRequest{
|
||||||
m_panDragging = false;
|
m_navigationState,
|
||||||
m_loggedLookDelta = false;
|
m_moveGizmo.IsActive(),
|
||||||
m_loggedPanDelta = false;
|
m_rotateGizmo.IsActive(),
|
||||||
}
|
m_scaleGizmo.IsActive()});
|
||||||
if (beginPanDrag) {
|
if (captureFlags.captureMouse) {
|
||||||
m_panDragging = true;
|
|
||||||
m_lookDragging = false;
|
|
||||||
m_panDragButton = beginLeftPanDrag ? ImGuiMouseButton_Left : ImGuiMouseButton_Middle;
|
|
||||||
m_loggedPanDelta = false;
|
|
||||||
m_loggedLookDelta = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_lookDragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
|
|
||||||
m_lookDragging = false;
|
|
||||||
m_loggedLookDelta = false;
|
|
||||||
}
|
|
||||||
if (m_panDragging && !ImGui::IsMouseDown(m_panDragButton)) {
|
|
||||||
m_panDragging = false;
|
|
||||||
m_panDragButton = ImGuiMouseButton_Middle;
|
|
||||||
m_loggedPanDelta = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_lookDragging || m_panDragging || m_moveGizmo.IsActive() || m_rotateGizmo.IsActive() ||
|
|
||||||
m_scaleGizmo.IsActive()) {
|
|
||||||
ImGui::SetNextFrameWantCaptureMouse(true);
|
ImGui::SetNextFrameWantCaptureMouse(true);
|
||||||
}
|
}
|
||||||
if (m_lookDragging) {
|
if (captureFlags.captureKeyboard) {
|
||||||
ImGui::SetNextFrameWantCaptureKeyboard(true);
|
ImGui::SetNextFrameWantCaptureKeyboard(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneViewportInput input = {};
|
SceneViewportInputBuildRequest inputRequest = {};
|
||||||
input.viewportSize = content.availableSize;
|
inputRequest.state = m_navigationState;
|
||||||
input.deltaTime = io.DeltaTime;
|
inputRequest.viewportSize = content.availableSize;
|
||||||
input.hovered = viewportContentHovered;
|
inputRequest.mouseDelta = io.MouseDelta;
|
||||||
input.focused = content.focused || m_lookDragging || m_panDragging;
|
inputRequest.mouseWheel = io.MouseWheel;
|
||||||
input.mouseWheel = (viewportContentHovered && !m_lookDragging) ? io.MouseWheel : 0.0f;
|
inputRequest.deltaTime = io.DeltaTime;
|
||||||
input.flySpeedDelta = (viewportContentHovered && m_lookDragging) ? io.MouseWheel : 0.0f;
|
inputRequest.viewportHovered = viewportContentHovered;
|
||||||
input.looking = m_lookDragging;
|
inputRequest.viewportFocused = content.focused;
|
||||||
input.orbiting = false;
|
inputRequest.wantTextInput = io.WantTextInput;
|
||||||
input.panning = m_panDragging;
|
inputRequest.fastMove = io.KeyShift;
|
||||||
input.fastMove = io.KeyShift;
|
inputRequest.focusSelectionKeyPressed = ImGui::IsKeyPressed(ImGuiKey_F, false);
|
||||||
input.focusSelectionRequested =
|
inputRequest.moveForwardKeyDown = ImGui::IsKeyDown(ImGuiKey_W);
|
||||||
input.focused && !io.WantTextInput && ImGui::IsKeyPressed(ImGuiKey_F, false);
|
inputRequest.moveBackwardKeyDown = ImGui::IsKeyDown(ImGuiKey_S);
|
||||||
|
inputRequest.moveRightKeyDown = ImGui::IsKeyDown(ImGuiKey_D);
|
||||||
if (m_lookDragging && !io.WantTextInput) {
|
inputRequest.moveLeftKeyDown = ImGui::IsKeyDown(ImGuiKey_A);
|
||||||
input.moveForward =
|
inputRequest.moveUpKeyDown = ImGui::IsKeyDown(ImGuiKey_E);
|
||||||
(ImGui::IsKeyDown(ImGuiKey_W) ? 1.0f : 0.0f) -
|
inputRequest.moveDownKeyDown = ImGui::IsKeyDown(ImGuiKey_Q);
|
||||||
(ImGui::IsKeyDown(ImGuiKey_S) ? 1.0f : 0.0f);
|
const SceneViewportInput input = BuildSceneViewportInput(inputRequest);
|
||||||
input.moveRight =
|
|
||||||
(ImGui::IsKeyDown(ImGuiKey_D) ? 1.0f : 0.0f) -
|
|
||||||
(ImGui::IsKeyDown(ImGuiKey_A) ? 1.0f : 0.0f);
|
|
||||||
input.moveUp =
|
|
||||||
(ImGui::IsKeyDown(ImGuiKey_E) ? 1.0f : 0.0f) -
|
|
||||||
(ImGui::IsKeyDown(ImGuiKey_Q) ? 1.0f : 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_lookDragging || m_panDragging) {
|
|
||||||
if (m_lookDragging) {
|
|
||||||
input.mouseDelta = io.MouseDelta;
|
|
||||||
if (!m_loggedLookDelta &&
|
|
||||||
(input.mouseDelta.x != 0.0f || input.mouseDelta.y != 0.0f)) {
|
|
||||||
m_loggedLookDelta = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_panDragging) {
|
|
||||||
input.mouseDelta = io.MouseDelta;
|
|
||||||
if (!m_loggedPanDelta &&
|
|
||||||
(input.mouseDelta.x != 0.0f || input.mouseDelta.y != 0.0f)) {
|
|
||||||
m_loggedPanDelta = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewportHostService->UpdateSceneViewInput(*m_context, input);
|
viewportHostService->UpdateSceneViewInput(*m_context, input);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Panel.h"
|
#include "Panel.h"
|
||||||
|
#include "Viewport/SceneViewportEditorModes.h"
|
||||||
#include "Viewport/SceneViewportMoveGizmo.h"
|
#include "Viewport/SceneViewportMoveGizmo.h"
|
||||||
|
#include "Viewport/SceneViewportNavigation.h"
|
||||||
#include "Viewport/SceneViewportRotateGizmo.h"
|
#include "Viewport/SceneViewportRotateGizmo.h"
|
||||||
#include "Viewport/SceneViewportScaleGizmo.h"
|
#include "Viewport/SceneViewportScaleGizmo.h"
|
||||||
|
|
||||||
@@ -10,24 +12,6 @@
|
|||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace Editor {
|
namespace Editor {
|
||||||
|
|
||||||
enum class SceneViewportToolMode : uint8_t {
|
|
||||||
ViewMove = 0,
|
|
||||||
Move,
|
|
||||||
Rotate,
|
|
||||||
Scale,
|
|
||||||
Transform
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SceneViewportPivotMode : uint8_t {
|
|
||||||
Pivot = 0,
|
|
||||||
Center
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SceneViewportTransformSpaceMode : uint8_t {
|
|
||||||
Global = 0,
|
|
||||||
Local
|
|
||||||
};
|
|
||||||
|
|
||||||
class SceneViewPanel : public Panel {
|
class SceneViewPanel : public Panel {
|
||||||
public:
|
public:
|
||||||
SceneViewPanel();
|
SceneViewPanel();
|
||||||
@@ -37,11 +21,7 @@ private:
|
|||||||
SceneViewportToolMode m_toolMode = SceneViewportToolMode::Move;
|
SceneViewportToolMode m_toolMode = SceneViewportToolMode::Move;
|
||||||
SceneViewportPivotMode m_pivotMode = SceneViewportPivotMode::Pivot;
|
SceneViewportPivotMode m_pivotMode = SceneViewportPivotMode::Pivot;
|
||||||
SceneViewportTransformSpaceMode m_transformSpaceMode = SceneViewportTransformSpaceMode::Global;
|
SceneViewportTransformSpaceMode m_transformSpaceMode = SceneViewportTransformSpaceMode::Global;
|
||||||
bool m_lookDragging = false;
|
SceneViewportNavigationState m_navigationState = {};
|
||||||
bool m_panDragging = false;
|
|
||||||
int m_panDragButton = ImGuiMouseButton_Middle;
|
|
||||||
bool m_loggedLookDelta = false;
|
|
||||||
bool m_loggedPanDelta = false;
|
|
||||||
SceneViewportMoveGizmo m_moveGizmo;
|
SceneViewportMoveGizmo m_moveGizmo;
|
||||||
SceneViewportRotateGizmo m_rotateGizmo;
|
SceneViewportRotateGizmo m_rotateGizmo;
|
||||||
SceneViewportScaleGizmo m_scaleGizmo;
|
SceneViewportScaleGizmo m_scaleGizmo;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ set(EDITOR_TEST_SOURCES
|
|||||||
test_application_asset_cache_stub.cpp
|
test_application_asset_cache_stub.cpp
|
||||||
test_play_session_controller.cpp
|
test_play_session_controller.cpp
|
||||||
test_scene_viewport_camera_controller.cpp
|
test_scene_viewport_camera_controller.cpp
|
||||||
|
test_scene_viewport_navigation.cpp
|
||||||
test_scene_viewport_move_gizmo.cpp
|
test_scene_viewport_move_gizmo.cpp
|
||||||
test_scene_viewport_rotate_gizmo.cpp
|
test_scene_viewport_rotate_gizmo.cpp
|
||||||
test_scene_viewport_scale_gizmo.cpp
|
test_scene_viewport_scale_gizmo.cpp
|
||||||
|
|||||||
154
tests/editor/test_scene_viewport_navigation.cpp
Normal file
154
tests/editor/test_scene_viewport_navigation.cpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "Viewport/SceneViewportNavigation.h"
|
||||||
|
|
||||||
|
using XCEngine::Editor::BuildSceneViewportCaptureFlags;
|
||||||
|
using XCEngine::Editor::BuildSceneViewportInput;
|
||||||
|
using XCEngine::Editor::BuildSceneViewportToolShortcutAction;
|
||||||
|
using XCEngine::Editor::CanResolveSceneViewportInteraction;
|
||||||
|
using XCEngine::Editor::SceneViewportCaptureRequest;
|
||||||
|
using XCEngine::Editor::SceneViewportInputBuildRequest;
|
||||||
|
using XCEngine::Editor::SceneViewportNavigationRequest;
|
||||||
|
using XCEngine::Editor::SceneViewportNavigationState;
|
||||||
|
using XCEngine::Editor::SceneViewportToolMode;
|
||||||
|
using XCEngine::Editor::SceneViewportToolShortcutRequest;
|
||||||
|
using XCEngine::Editor::UpdateSceneViewportNavigationState;
|
||||||
|
|
||||||
|
TEST(SceneViewportNavigationTest, ToolShortcutActionIgnoresShortcutsDuringTextInputOrDrag) {
|
||||||
|
SceneViewportToolShortcutRequest request = {};
|
||||||
|
request.pressedMove = true;
|
||||||
|
request.wantTextInput = true;
|
||||||
|
EXPECT_FALSE(BuildSceneViewportToolShortcutAction(request).HasAction());
|
||||||
|
|
||||||
|
request.wantTextInput = false;
|
||||||
|
request.lookDragging = true;
|
||||||
|
EXPECT_FALSE(BuildSceneViewportToolShortcutAction(request).HasAction());
|
||||||
|
|
||||||
|
request.lookDragging = false;
|
||||||
|
request.panDragging = true;
|
||||||
|
EXPECT_FALSE(BuildSceneViewportToolShortcutAction(request).HasAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SceneViewportNavigationTest, ToolShortcutActionMapsShortcutTargetsAndCancelFlags) {
|
||||||
|
SceneViewportToolShortcutRequest request = {};
|
||||||
|
request.pressedViewMove = true;
|
||||||
|
const auto viewMoveAction = BuildSceneViewportToolShortcutAction(request);
|
||||||
|
EXPECT_TRUE(viewMoveAction.HasAction());
|
||||||
|
EXPECT_EQ(viewMoveAction.targetTool, SceneViewportToolMode::ViewMove);
|
||||||
|
EXPECT_TRUE(viewMoveAction.cancelMoveGizmo);
|
||||||
|
EXPECT_TRUE(viewMoveAction.cancelRotateGizmo);
|
||||||
|
EXPECT_TRUE(viewMoveAction.cancelScaleGizmo);
|
||||||
|
|
||||||
|
request = {};
|
||||||
|
request.pressedRotate = true;
|
||||||
|
const auto rotateAction = BuildSceneViewportToolShortcutAction(request);
|
||||||
|
EXPECT_TRUE(rotateAction.HasAction());
|
||||||
|
EXPECT_EQ(rotateAction.targetTool, SceneViewportToolMode::Rotate);
|
||||||
|
EXPECT_TRUE(rotateAction.cancelMoveGizmo);
|
||||||
|
EXPECT_FALSE(rotateAction.cancelRotateGizmo);
|
||||||
|
EXPECT_TRUE(rotateAction.cancelScaleGizmo);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SceneViewportNavigationTest, NavigationUpdateBeginsLookAndPanDrags) {
|
||||||
|
SceneViewportNavigationRequest lookRequest = {};
|
||||||
|
lookRequest.hasInteractiveViewport = true;
|
||||||
|
lookRequest.viewportHovered = true;
|
||||||
|
lookRequest.clickedRight = true;
|
||||||
|
lookRequest.rightMouseDown = true;
|
||||||
|
const auto lookUpdate = UpdateSceneViewportNavigationState(lookRequest);
|
||||||
|
EXPECT_TRUE(lookUpdate.beginLookDrag);
|
||||||
|
EXPECT_FALSE(lookUpdate.beginPanDrag);
|
||||||
|
EXPECT_TRUE(lookUpdate.state.lookDragging);
|
||||||
|
EXPECT_FALSE(lookUpdate.state.panDragging);
|
||||||
|
|
||||||
|
SceneViewportNavigationRequest panRequest = {};
|
||||||
|
panRequest.hasInteractiveViewport = true;
|
||||||
|
panRequest.viewportHovered = true;
|
||||||
|
panRequest.usingViewMoveTool = true;
|
||||||
|
panRequest.clickedLeft = true;
|
||||||
|
panRequest.leftMouseDown = true;
|
||||||
|
const auto panUpdate = UpdateSceneViewportNavigationState(panRequest);
|
||||||
|
EXPECT_FALSE(panUpdate.beginLookDrag);
|
||||||
|
EXPECT_TRUE(panUpdate.beginPanDrag);
|
||||||
|
EXPECT_TRUE(panUpdate.beginLeftPanDrag);
|
||||||
|
EXPECT_TRUE(panUpdate.state.panDragging);
|
||||||
|
EXPECT_EQ(panUpdate.state.panDragButton, ImGuiMouseButton_Left);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SceneViewportNavigationTest, NavigationUpdateEndsDragsWhenButtonsRelease) {
|
||||||
|
SceneViewportNavigationRequest lookRequest = {};
|
||||||
|
lookRequest.state.lookDragging = true;
|
||||||
|
const auto lookUpdate = UpdateSceneViewportNavigationState(lookRequest);
|
||||||
|
EXPECT_FALSE(lookUpdate.state.lookDragging);
|
||||||
|
|
||||||
|
SceneViewportNavigationRequest panRequest = {};
|
||||||
|
panRequest.state.panDragging = true;
|
||||||
|
panRequest.state.panDragButton = ImGuiMouseButton_Left;
|
||||||
|
const auto panUpdate = UpdateSceneViewportNavigationState(panRequest);
|
||||||
|
EXPECT_FALSE(panUpdate.state.panDragging);
|
||||||
|
EXPECT_EQ(panUpdate.state.panDragButton, ImGuiMouseButton_Middle);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SceneViewportNavigationTest, CaptureFlagsTrackNavigationAndActiveGizmos) {
|
||||||
|
SceneViewportCaptureRequest request = {};
|
||||||
|
request.state.lookDragging = true;
|
||||||
|
const auto lookFlags = BuildSceneViewportCaptureFlags(request);
|
||||||
|
EXPECT_TRUE(lookFlags.captureMouse);
|
||||||
|
EXPECT_TRUE(lookFlags.captureKeyboard);
|
||||||
|
|
||||||
|
request = {};
|
||||||
|
request.rotateGizmoActive = true;
|
||||||
|
const auto gizmoFlags = BuildSceneViewportCaptureFlags(request);
|
||||||
|
EXPECT_TRUE(gizmoFlags.captureMouse);
|
||||||
|
EXPECT_FALSE(gizmoFlags.captureKeyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SceneViewportNavigationTest, BuildInputRoutesWheelFocusMovementAndMouseDelta) {
|
||||||
|
SceneViewportInputBuildRequest request = {};
|
||||||
|
request.viewportSize = ImVec2(640.0f, 360.0f);
|
||||||
|
request.viewportHovered = true;
|
||||||
|
request.viewportFocused = true;
|
||||||
|
request.mouseWheel = 2.0f;
|
||||||
|
const auto zoomInput = BuildSceneViewportInput(request);
|
||||||
|
EXPECT_FLOAT_EQ(zoomInput.mouseWheel, 2.0f);
|
||||||
|
EXPECT_FLOAT_EQ(zoomInput.flySpeedDelta, 0.0f);
|
||||||
|
EXPECT_FALSE(zoomInput.looking);
|
||||||
|
EXPECT_TRUE(zoomInput.focused);
|
||||||
|
|
||||||
|
request = {};
|
||||||
|
request.state.lookDragging = true;
|
||||||
|
request.viewportSize = ImVec2(640.0f, 360.0f);
|
||||||
|
request.viewportHovered = true;
|
||||||
|
request.mouseWheel = 1.5f;
|
||||||
|
request.mouseDelta = ImVec2(5.0f, -3.0f);
|
||||||
|
request.fastMove = true;
|
||||||
|
request.focusSelectionKeyPressed = true;
|
||||||
|
request.moveForwardKeyDown = true;
|
||||||
|
request.moveRightKeyDown = true;
|
||||||
|
request.moveUpKeyDown = true;
|
||||||
|
const auto flyInput = BuildSceneViewportInput(request);
|
||||||
|
EXPECT_FLOAT_EQ(flyInput.mouseWheel, 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(flyInput.flySpeedDelta, 1.5f);
|
||||||
|
EXPECT_TRUE(flyInput.looking);
|
||||||
|
EXPECT_TRUE(flyInput.fastMove);
|
||||||
|
EXPECT_TRUE(flyInput.focused);
|
||||||
|
EXPECT_TRUE(flyInput.focusSelectionRequested);
|
||||||
|
EXPECT_FLOAT_EQ(flyInput.moveForward, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(flyInput.moveRight, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(flyInput.moveUp, 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(flyInput.mouseDelta.x, 5.0f);
|
||||||
|
EXPECT_FLOAT_EQ(flyInput.mouseDelta.y, -3.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SceneViewportNavigationTest, CanResolveInteractionRequiresHoverWithoutNavigationOrActiveGizmo) {
|
||||||
|
SceneViewportNavigationState state = {};
|
||||||
|
EXPECT_TRUE(CanResolveSceneViewportInteraction(true, true, false, state, false));
|
||||||
|
|
||||||
|
state.lookDragging = true;
|
||||||
|
EXPECT_FALSE(CanResolveSceneViewportInteraction(true, true, false, state, false));
|
||||||
|
|
||||||
|
state = {};
|
||||||
|
EXPECT_FALSE(CanResolveSceneViewportInteraction(true, true, true, state, false));
|
||||||
|
EXPECT_FALSE(CanResolveSceneViewportInteraction(true, true, false, state, true));
|
||||||
|
EXPECT_FALSE(CanResolveSceneViewportInteraction(false, true, false, state, false));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user