Builtin Library
README.md
camera_controls
Camera control utilities — fly and orbit controllers built on the entity
camera API (entity.find("camera").camera.*). Each controller activates an
input map and subscribes to the move, look, zoom and flyVertical
controls on it, so the same camera answers from a keyboard, a pad and a
touch surface. Each call returns an object with update(dt) plus
introspection methods; call :update(dt) once per frame from your
component update, and :release() when the controller goes away.
Deprecated: prefer @builtin::controller.* components on the
camera entity. This compatibility module remains for controllers that
need custom orbit logic (e.g. model_viewer auto-rotate) and will be
removed after full migration.
Exports
M.createFlyController(opts: FlyOpts?) -> FlyController— fly controller driven bymove,look,zoomandflyVertical.M.createOrbitController(opts: OrbitOpts?) -> OrbitController— orbit-around-center controller:lookorbits,movepans the center,zoomchanges the distance.
Types:
FlyOpts = { inputMap?, moveSpeed?, rotateSpeed?, zoomSpeed?, distance?, minDistance?, maxDistance?, logMouse? }OrbitOpts = { inputMap?, center?, distance?, yaw?, pitch?, minPitch?, maxPitch?, minDistance?, maxDistance?, invertPitchInput?, moveSpeed?, rotateSpeed?, zoomSpeed? }FlyController = { update, release, lastMousePos, distance }OrbitController = { update, release, setCenter, setDistance, setYawPitch, yawPitch, distance, lastMousePos }
Usage
local CameraControls = require("@builtin::modules.extras.camera_controls")
local ctrl = CameraControls.createOrbitController({
center = { x = 0, y = 0.8, z = 0 },
distance = 5,
moveSpeed = 5,
rotateSpeed = 0.005,
zoomSpeed = 0.1,
})
-- in update(dt):
ctrl:update(dt)
local mousePos = ctrl:lastMousePos() -- { x, y } or nil
-- when the controller goes away:
ctrl:release()
Notes
opts.inputMapnames the map;@builtin::inputMaps.editoris the default. Each controller holds its own activation, so two of them do not share one reading, and:release()is what takes the controls back out of the live set.- Each constructor calls
Zin.autoTick.start()so the controls keep dispatching across frames. - Vertical movement comes from the
flyVerticalcontrol, which a map is free to leave out — a map without it drives everything else. - The
lookcontrol carries its own gate, so a mouse steers only while the camera is being flown while a stick or a touch drag steers whenever it is pushed. - WASM-safe: no
string.formatnumeric formats, no Rust APIs.