Skip to documentation
CranberryClock.Ideas / Systems / Design

INDEPENDENT TOOL / v0.1.0

LatchAPI reference

The public Latch API: inputs, outputs, behavior, and constraints.

API

new Latch(options?)

Option Default Meaning
reach 3 Default maximum actor-to-hit surface distance, world units; finite and nonnegative.
aimFar Infinity Maximum intersection distance from the aim origin; nonnegative. This is separate from actor reach.
focusTolerance 0.015 Keep current focus when its nearest eligible surface is within this many world units of the nearest aim hit. Finite and nonnegative.

options is a read-only normalized snapshot. size is the current target count.

register(options): Target

Field Default Meaning
id required Unique nonempty string.
root required Three.Object3D; an individual root can be registered once.
label id Prompt text.
mode 'press' 'press' or 'hold'.
holdDuration 1 Duration in seconds; finite and at least 0.000001. Used for hold targets.
reach controller reach Per-target finite nonnegative world-space reach.
condition always available Pure synchronous predicate, described below.

The returned frozen Target has the normalized fields above, including condition when supplied. Configuration is copied; scene objects remain host-owned references. To change registration settings, remove and register the target again. Re-registering the same id creates a new target and cancels an old hold on the next update.

condition({ context, actorPosition, target, hit }) returns true to permit activation, false for a generic “Unavailable” reason, or a string describing the block. An empty string also produces “Unavailable”. The predicate receives a copy of actor position and a shallow intersection copy with a copied hit point. Treat all referenced host objects as read-only. Conditions may run multiple times per update, including immediately before completion. Do not consume inventory, change scene state, register/remove targets, or call update() from a condition. Reentrant controller mutation throws; predicate exceptions propagate to the host. If an update throws, Latch restores its prior interaction state, so a retry does not consume a press or silently lose a cancellation. Host-side predicate or custom-raycast side effects cannot be rolled back.

Target and occluder lifecycle

Method Result
remove(id) Returns whether a target was removed. Pending cancel/blur events are returned at the next update.
clear() Unregisters all targets; cancellation/blur appears at the next update. Occluders and input history remain.
setOccluders(roots = []) Copies and deduplicates an array of Object3D roots; returns the controller. An empty array disables explicit occlusion.

Removing a target never removes, hides, or disposes the corresponding scene object. Merely detaching an object from its scene does not unregister it: call remove, hide it, or clear its registration. To dispose a controller, stop sending updates and release it; it owns no GPU resources or DOM listeners. Release host geometry, materials, and listeners separately.

update(frame): InteractionResult

Frame field Requirement
dt Finite, nonnegative elapsed seconds since the previous update.
aimRay Three.Ray with finite origin and nonzero Vector3 direction. Direction is copied and normalized.
actorPosition Finite Three.Vector3 in world coordinates.
pressed Boolean current button state; a press means a false-to-true transition.
suspended Optional boolean, default false. Cancels work and clears focus.
context Optional host data for conditions; not copied or modified.
camera Optional Three.Camera for view-dependent raycasting.
Result field Meaning
focus Focus snapshot or null.
progress Hold fraction from 0 to 1; resets to 0 after activation or cancellation.
holding Whether a hold is currently in progress.
requiresRelease A held input cannot start another action until an update observes pressed: false.
events Fresh ordered, frozen array of interaction events. Process after the update returns.

Focus includes id, root, label, mode, holdDuration, point, distance, available, and reason. point is a copy in world space; distance is actor-to-hit distance. reason is null when available. Snapshot objects are shallow-frozen; Three vectors and host object references are not deep-frozen. Changing a snapshot's point does not change raycast geometry or the controller's hit point, but may change other references to that same snapshot.

Events

Every event includes type and a target: Focus snapshot.

Type Additional data When returned
focus A new reachable target is selected.
blur reason Previous focus is lost, removed, or suspended.
start A fresh press begins a hold.
cancel reason An in-progress hold is interrupted.
activate A press or a completed hold passes its final availability check.
blocked reason A fresh press attempts an unavailable target, or a press fails its completion check.

Cancellation reasons are 'focus-lost', 'removed', 'suspended', 'released', and 'unavailable'. Blur uses the first three. A target switch returns cancel if holding, then blur, then focus. A new hold returns start; a successful press returns activate. A hold that loses availability returns cancel, with the current blocked reason also available on result.focus.reason. No progress events are emitted; read the result once per frame.

View versioned source on GitHub ↗