Camera and Xbox controller controls

Model Studio mouse and keyboard

The Camera panel selects what a left-mouse drag does: Orbit model, Pan camera, or Free look. Orbit moves around the current target. Pan translates the camera and its target together. Free look changes the target and pointing direction while keeping the camera position fixed. Switching modes does not jump the view.

Camera movement is independent of the model's Rotation and Scale controls. Scaling a model now changes its visible size without automatically moving the camera; use Frame selected afterward if needed.

Connect and activate

Use the Xbox controller already paired with the computer. Open the workshop through localhost or HTTPS, focus the browser tab, and press/release a controller button so the browser exposes the device. The Xbox Controller panel reports detection and readiness. Click Focus 3D view for control when returning from a form field. Release sticks, triggers and buttons after reconnecting or changing focus; neutral controls re-arm input.

The implementation uses the browser's W3C standard gamepad layout. It does not pair Bluetooth devices or assume raw axis/button indices for unrecognized layouts. The Xbox system/Guide button remains managed by the browser/operating system. Controller controls & settings lists all assigned controls, live input values, sensitivity and deadzone settings. The default radial stick deadzone is 15%; a small trigger deadzone also removes noise. Settings persist between scenes for the current page session.

InputModel StudioFlight
Left stickPan cameraBank; pull back to raise nose
Right stickOrbit, or free look in Free look modeLook around pilot/chase view
LT / RTZoom out / inDecrease / increase throttle
LB / RBRotate selected modelLeft / right rudder
D-pad left / rightSelect previous / next existing modelToggle navigation / landing lights
D-pad up / downIncrease / decrease model scaleRetract / extend flaps
A / BFirst / second model action, when availableSwitch view / center look
XFrame selectedToggle gear
YToggle orbit/free lookToggle guided/manual
Hold left-stick clickPrecision camera/model movementClick levels wings
Right-stick clickFrame selectedCenter look
MenuPause / resumePause / resume
ViewShow / hide controller guideShow / hide controller guide

In flight, moving flight axes or throttle takes manual control from the guided tour. Right-stick looking alone does not. Reverse flight pitch direction is available in controller settings. During landscape inspection, the sticks pan/orbit and triggers zoom; A returns to flight. See FLIGHT_CONTROLLER.md for exact flight integration.

Model loading and arbitrary model-specific property editing remain in the library/inspector panel. Controller A/B invoke actions supplied by the selected package; no action is invented for a package that exposes none. Camera/model transforms remain available for every compatible model.

Reuse in another application

OrbitControls remains in the engine with default keyboard input disabled. Enable {keyboard:true} for a focused viewport and call tick(realDt) from the consumer's input loop. Public methods are setMode(mode), orbitBy(yawRadians, pitchRadians), lookBy(yawRadians, pitchRadians), panBy(right, up, forward=0) in world units relative to the camera, and zoomBy(logAmount) (positive out). Positive look yaw turns left; positive look pitch aims upward. Movement methods return whether they changed the view and invoke onChange. Disposal clears keys, captures and listeners.

GamepadInput is a separate reusable engine module. It supplies neutral, deadzone-filtered left, right, lt, rt, down, and rising-edge pressed values. poll({active}) returns connection/mapping/arming metadata plus input state. Unsupported mappings and inactive input return neutral commands. select(index) supports explicit device selection in other consumers; the workshop automatically retains its current controller or chooses a standard-mapped one. Injecting a provider is supported for deterministic tests.

The shell owns the mappings and a lightweight input animation loop separate from simulation time. This permits Menu to resume a paused renderer and permits paused camera movement. Blur, hidden-page and disconnect events clear stored commands immediately, even when animation-frame polling is suspended. The next active input requires a neutral pose. Editing input/select fields suspends controller actions. Aircraft simulation time and commands remain paused during camera inspection.

Verification scope

tests/gamepad-input.test.mjs, camera-controls.test.mjs and flight-controls.test.mjs cover 22 focused cases. tests/controller.html exercises 13 integration checks with actual rendered Studio/Flight scenes and synthetic controller snapshots, including the UI polling loop while paused. These are not physical wireless-controller tests. See VERIFICATION.md and verification/controller-v022.json for the final device status and packaged scope.