fix: correct scene view fly and pan controls

This commit is contained in:
2026-03-28 18:37:18 +08:00
parent 569f8ef725
commit a519fdab7d
4 changed files with 21 additions and 16 deletions

View File

@@ -94,8 +94,10 @@ public:
const Math::Vector3 right = GetRight();
const Math::Vector3 up = GetUp();
const float worldUnitsPerPixel = ComputeWorldUnitsPerPixel(input.viewportHeight);
m_focalPoint += ((right * -input.panDeltaX) + (up * input.panDeltaY)) * worldUnitsPerPixel;
m_position += ((right * -input.panDeltaX) + (up * input.panDeltaY)) * worldUnitsPerPixel;
const Math::Vector3 delta =
((right * input.panDeltaX) + (up * -input.panDeltaY)) * worldUnitsPerPixel;
m_focalPoint += delta;
m_position += delta;
}
if (input.deltaTime > 0.0f &&
@@ -103,8 +105,8 @@ public:
std::abs(input.moveRight) > Math::EPSILON ||
std::abs(input.moveUp) > Math::EPSILON)) {
const Math::Vector3 movement =
GetForward() * input.moveForward +
GetRight() * input.moveRight +
GetForward() * -input.moveForward +
GetRight() * -input.moveRight +
Math::Vector3::Up() * input.moveUp;
if (movement.SqrMagnitude() > Math::EPSILON) {
const float speedMultiplier = input.fastMove ? 4.0f : 1.0f;

View File

@@ -239,24 +239,17 @@ void SceneViewPanel::Render() {
const ViewportPanelContentResult content = RenderViewportPanelContent(*m_context, EditorViewportKind::Scene);
if (IViewportHostService* viewportHostService = m_context->GetViewportHostService()) {
const ImGuiIO& io = ImGui::GetIO();
const bool altDown = io.KeyAlt;
if (!m_lookDragging && content.hovered && !altDown && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
if (!m_lookDragging && content.hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
m_lookDragging = true;
}
if (!m_orbitDragging && content.hovered && altDown && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
m_orbitDragging = true;
}
if (!m_panDragging && content.hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Middle)) {
m_panDragging = true;
}
if (m_lookDragging && (!ImGui::IsMouseDown(ImGuiMouseButton_Right) || altDown)) {
if (m_lookDragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
m_lookDragging = false;
}
if (m_orbitDragging && (!ImGui::IsMouseDown(ImGuiMouseButton_Left) || !altDown)) {
m_orbitDragging = false;
}
if (m_panDragging && !ImGui::IsMouseDown(ImGuiMouseButton_Middle)) {
m_panDragging = false;
}
@@ -268,7 +261,7 @@ void SceneViewPanel::Render() {
input.focused = content.focused;
input.mouseWheel = content.hovered ? -io.MouseWheel : 0.0f;
input.looking = m_lookDragging;
input.orbiting = m_orbitDragging;
input.orbiting = false;
input.panning = m_panDragging;
input.fastMove = io.KeyShift;
input.focusSelectionRequested =
@@ -286,7 +279,7 @@ void SceneViewPanel::Render() {
(ImGui::IsKeyDown(ImGuiKey_Q) ? 1.0f : 0.0f);
}
if (m_lookDragging || m_orbitDragging || m_panDragging) {
if (m_lookDragging || m_panDragging) {
input.mouseDelta = io.MouseDelta;
}

View File

@@ -12,7 +12,6 @@ public:
private:
bool m_lookDragging = false;
bool m_orbitDragging = false;
bool m_panDragging = false;
};

View File

@@ -92,6 +92,8 @@ TEST(SceneViewportCameraController_Test, PanAndZoomUpdateCameraStateConsistently
const Vector3 initialPosition = controller.GetPosition();
const Vector3 initialFocus = controller.GetFocalPoint();
const float initialDistance = controller.GetDistance();
const Vector3 right = Vector3::Normalize(Vector3::Cross(Vector3::Up(), controller.GetForward()));
const Vector3 up = Vector3::Normalize(Vector3::Cross(controller.GetForward(), right));
SceneViewportCameraInputState input = {};
input.viewportHeight = 720.0f;
@@ -103,6 +105,10 @@ TEST(SceneViewportCameraController_Test, PanAndZoomUpdateCameraStateConsistently
EXPECT_FALSE(NearlyEqual(controller.GetPosition(), initialPosition));
EXPECT_FALSE(NearlyEqual(controller.GetFocalPoint(), initialFocus));
EXPECT_LT(controller.GetDistance(), initialDistance);
const Vector3 panDelta = controller.GetFocalPoint() - initialFocus;
EXPECT_NEAR(Vector3::Dot(panDelta, controller.GetForward()), 0.0f, 1e-3f);
EXPECT_GT(std::abs(Vector3::Dot(panDelta, right)), 0.0f);
EXPECT_GT(std::abs(Vector3::Dot(panDelta, up)), 0.0f);
EXPECT_TRUE(NearlyEqual(
controller.GetFocalPoint(),
controller.GetPosition() + controller.GetForward() * controller.GetDistance(),
@@ -116,6 +122,8 @@ TEST(SceneViewportCameraController_Test, FlyInputMovesCameraAndFocalPointTogethe
const Vector3 initialPosition = controller.GetPosition();
const Vector3 initialFocus = controller.GetFocalPoint();
const Vector3 initialOffset = initialFocus - initialPosition;
const Vector3 forward = controller.GetForward();
const Vector3 right = Vector3::Normalize(Vector3::Cross(Vector3::Up(), forward));
SceneViewportCameraInputState input = {};
input.viewportHeight = 720.0f;
@@ -126,6 +134,9 @@ TEST(SceneViewportCameraController_Test, FlyInputMovesCameraAndFocalPointTogethe
EXPECT_FALSE(NearlyEqual(controller.GetPosition(), initialPosition));
EXPECT_FALSE(NearlyEqual(controller.GetFocalPoint(), initialFocus));
const Vector3 positionDelta = controller.GetPosition() - initialPosition;
EXPECT_GT(std::abs(Vector3::Dot(positionDelta, forward)), 0.0f);
EXPECT_GT(std::abs(Vector3::Dot(positionDelta, right)), 0.0f);
EXPECT_TRUE(NearlyEqual(controller.GetFocalPoint() - controller.GetPosition(), initialOffset, 1e-3f));
}