New Engine/Core/Input.h/.cpp: static input facade with a Key/MouseButton
enum (values map to GLFW key codes internally) so scripts and game logic
no longer touch GLFW directly - window backend becomes swappable and the
facade is the surface to expose when embedding scripting later. Wired up
in Application's constructor; Camera (editor camera WASD/RMB/MMB), the
WASDMove script and SandboxApp key handling now query Input only.
Ctrl+P hotkey fix: the !m_Playing guard made the hotkey dead exactly
when it was needed - after pressing Play. Now toggles both ways.
Toolbar Pause button now reads "Resume" while paused (tooltip follows).
User pointed out the real gap: UE Details shows rotation in [0,360)
(-90 reads 270); our readback exposed [-180,180] with negative zeros.
GetRotation now wraps each axis to [0,360) via fmod -- strictly
equivalent math (each axis has 360-degree period), so matrix-rebuild
consumers like Camera::EulerRotMat are unaffected. The one consumer
needing a continuous domain is the free-look pitch clamp [-89,89] in
Camera::Update, which wraps back to [-180,180) before applying deltas.
Key conflict fix (UE semantics): while RMB is held the keyboard belongs
to the camera, so WASD no longer collides with the gizmo W/E/R tool
hotkeys. Editor mode gates fly movement behind RMB; game mode keeps
always-on WASD. Viewport tool hotkeys (W/E/R/T/F) are suppressed while
RMB is held.
Focus orbit (pivot): MMB drag rotates the camera around a pivot keeping
distance; first orbit picks a pivot 5m ahead on the view ray. Shift+MMB
pans in screen plane (camera and pivot move together). Mouse wheel
dollies toward/away from the pivot with exponential steps (no pivot:
move along view ray). F focuses the selected entity (frame-selection):
pivot set to its position, camera slides along the view ray; orbit
distance persists.
Window gains a polled scroll-delta channel (ConsumeScrollDelta) that
respects ImGui mouse capture; Camera::Update mutates orbit state (no
longer const).