#include #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)); }