From 062ffeab5ce108463a06793f7a6076056f6f6647 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Sat, 18 Jul 2026 06:03:11 +0200 Subject: [PATCH] Support scroll-rotate in Atlas Split mouse wheel scroll handling into horizontal and vertical. Keep vertical scroll for zooming and use horizontal to rotate around the y axis replicating the behaviour of the main game. Signed-off-by: Ralph Sennhauser --- .../AtlasUI/ScenarioEditor/ScenarioEditor.cpp | 12 ++++++-- source/tools/atlas/GameInterface/GameLoop.h | 5 ++-- .../Handlers/CameraCtrlHandlers.cpp | 8 +++++ .../atlas/GameInterface/InputProcessor.cpp | 29 +++++++++++++++++++ source/tools/atlas/GameInterface/Messages.h | 4 +++ 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp index 433ba4a683..ab6788a538 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp @@ -273,8 +273,16 @@ private: if (evt.GetWheelRotation()) { - float speed = 16.f * ScenarioEditor::GetSpeedModifier(); - POST_MESSAGE(SmoothZoom, (eRenderView::GAME, evt.GetWheelRotation() * speed / evt.GetWheelDelta())); + if (evt.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL) + { + float speed = 16.f * ScenarioEditor::GetSpeedModifier(); + POST_MESSAGE(SmoothZoom, (eRenderView::GAME, evt.GetWheelRotation() * speed / evt.GetWheelDelta())); + } + else + { + float speed = ScenarioEditor::GetSpeedModifier(); + POST_MESSAGE(RotateY, (evt.GetWheelRotation() * speed / evt.GetWheelDelta())); + } } else { diff --git a/source/tools/atlas/GameInterface/GameLoop.h b/source/tools/atlas/GameInterface/GameLoop.h index b1ccada183..b74418808c 100644 --- a/source/tools/atlas/GameInterface/GameLoop.h +++ b/source/tools/atlas/GameInterface/GameLoop.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -41,7 +41,8 @@ struct GameLoopState struct Input { float scrollSpeed[6]; // [fwd, bwd, left, right, cw-rotation, ccw-rotation]. 0.0f for disabled. - float zoomDelta; + float zoomDelta{0.f}; + float rotateDelta{0.f}; } input; }; diff --git a/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp index 47da436fc1..230002251f 100644 --- a/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/CameraCtrlHandlers.cpp @@ -199,6 +199,14 @@ MESSAGEHANDLER(RotateAround) } } +MESSAGEHANDLER(RotateY) +{ + if (!g_Game || g_Game->GetView()->GetCinema()->IsPlaying()) + return; + + g_AtlasGameLoop->input.rotateDelta = msg->angle; +} + MESSAGEHANDLER(LookAt) { // TODO: different camera depending on msg->view diff --git a/source/tools/atlas/GameInterface/InputProcessor.cpp b/source/tools/atlas/GameInterface/InputProcessor.cpp index 17f17a5dca..0e16836dbd 100644 --- a/source/tools/atlas/GameInterface/InputProcessor.cpp +++ b/source/tools/atlas/GameInterface/InputProcessor.cpp @@ -117,6 +117,35 @@ bool InputProcessor::ProcessInput(GameLoopState* state) moved = true; } + if (state->input.rotateDelta != 0.f) + { + float angle{4 * state->realFrameLength}; + if (input.rotateDelta > 0 ) + { + if (angle > input.rotateDelta) + { + angle = input.rotateDelta; + input.rotateDelta = 0.f; + } + else + input.rotateDelta -= angle; + } + else + { + angle *= -1; + if (angle < input.rotateDelta) + { + angle = input.rotateDelta; + input.rotateDelta = 0.f; + } + else + input.rotateDelta -= angle; + } + Rotate(camera, angle); + + moved = true; + } + if (moved) { camera.UpdateFrustum(); diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h index 9e381d7b38..624a817424 100644 --- a/source/tools/atlas/GameInterface/Messages.h +++ b/source/tools/atlas/GameInterface/Messages.h @@ -456,6 +456,10 @@ MESSAGE(RotateAround, ((Position, pos)) ); +MESSAGE(RotateY, + ((float, angle)) + ); + MESSAGE(LookAt, ((int, view)) // eRenderView ((Position, pos))