Synesthesia hands your script.js the mouse position (_muvc) and the button
states (_click), but not the thing you actually want for dragging: how far the
mouse moved since the last frame. That’s a delta, and a delta needs memory.
LastClick is that memory — three lines, and it’s the foundation of every
click-and-drag interaction in a scene.
function LastClick() { this.x = -100; this.y = -100; }
LastClick.prototype.click = function () { this.x = _muvc.x; this.y = _muvc.y; };
LastClick.prototype.release = function () { this.x = -100; this.y = -100; };
The -100 matters more than it looks. It’s a sentinel meaning “not currently
dragging”, parked far outside the coordinate range _muvc can ever return. Without
it, the first frame of a drag would diff the current position against whatever was
left over from the last drag — and the camera would snap by the full distance
between them before settling.
So the rule is: always gate the diff on the sentinel.
Usage
var lastL = new LastClick();
function setup() {
onOffToOn('_click', 'onDown');
onOnToOff('_click', 'onUp');
}
function onDown() { lastL.click(); }
function onUp() { lastL.release(); }
function update(dt) {
var deltaX = 0, deltaY = 0;
if (lastL.x > -50) { // -50, not -100: see notes
deltaX = _muvc.x - lastL.x;
deltaY = _muvc.y - lastL.y;
lastL.click(); // re-anchor for the next frame
}
cam_rd.smooth(cam_rd.goal_x + deltaX * 2.0,
cam_rd.goal_y + deltaY * 2.0,
cam_rd.goal_z);
}
Note the lastL.click() inside the drag branch — you re-anchor every frame, so
the delta stays per-frame rather than accumulating from where the drag started.
Notes
- Test against
-50, not-100. Comparing to the exact sentinel is fragile; any value below-50is unreachable for a real cursor, so the loose threshold is both safer and self-documenting. _clickis a vec3 — left, right, and middle button states. Track a separateLastClickper button if you want them to do different things (orbit on left, pan on middle, dolly on right is the usual mapping).- Event callbacks are passed as string names, not function references:
onOffToOn('_click', 'onDown'). Passing the function itself fails quietly. _muvcis the centered mouse UV._muvis the 0–1 version — pick whichever matches the space you’re working in and don’t mix them.- To get inertia for free, feed the delta into a
Smooth3goal rather than into the camera value directly, and multiply the delta by0.95each frame after release so the motion coasts to a stop.