tricker than I thought: making sure that pasted shapes don't end up on top of each other
Normally we'd like to place a pasted shape in the middle of the editor. You can think of this as an offset of [0,0] from the center.
But there are two circumstances where we'd want to offset this position. First, if the shapes that we copied happen to also be perfectly centered in the window, then we'd increase our offset (e.g. to [16, 16]).
Second, we would need to increase the offset if the viewport's center is still at the same place as the last time we pasted a shape.
Moving the viewport should reset this offset; and so should copying a new shape.
Undos will break this system though, because we aren't reversing that offset on undo. I could store the offset in our state, which would get undone... but I might leave it here for now.
Creative apps have really complicated logic around where things are pasted—some of which can be very hard to predict, especially as we get into groups! So I'm sure I'll be back to this feature again soon.
Anyway, here's what I actually sat down to implement
The regular @croquet/react bindings have a lot of boilerplate that's available from their context object (e.g. a viewId) so these bindings folds that stuff in.
It’s still a lot of boilerplate though. Most of the “subscriptions” I’m writing are manually syncing these two data sources (the data published from the model and the React state).
Ever wonder why regular pencil tools wait until after you finish drawing to smooth out your line? It's usually because the app using a line-simplification algorithm—and these sorts of algorithms aren't "stable" as a line is changing. 🧵
Here's the algorithm at work, picking new points on almost every frame. Each solution is "correct" for each set of points, but it is overall "incorrect" in the sense that the solutions keep changing! codesandbox.io/s/simplified-t…
Why simplify at all? The "raw" input points are often very jerky and noisy.
Introducing rko, a three-letter state management library for #reactjs with built-in undo, redo, and local persistence. Built on @pmndrs zustand. github.com/steveruizok/rko.
The idea here is to update state either with a "patch", or a deep partial of the state containing only the changes that you want to make...
...or else a "command" made up of two patches, before and after. Only commands become part of the undo/redo stack.
Live cursors are interesting. You don't really want to be constantly sending updates but you do want the cursors to move smoothly and naturally like this. What's the trick?
Here's what it looks like without any animations.
Regular tweens/duration-based animations won't work here because each new update will "redirect" the animation. While the cursor is moving from A to B, a new update may come in that means it should move instead from its current point (C) to point D instead.
perf breakthru on ios, panning and zooming back to 60 FPS
I was over here staring at the performance tab, all signs green, no dropped frames reported—while also watching things obviously skip around at <30 fps. Super frustrating, couldn't figure it out.
Finally I think, maybe I'm not actually updating the state on every frame? Of course I was, but somehow in a way that didn't quite count for Safari.