Pivot Crosshair - #28
drakeraz09 wants to merge 3 commits into
Conversation
The bounding box already drew a crosshair in the middle of the selection, but it did nothing. Everything rotated and scaled around the center of the bounds no matter what, so swinging an arm around its elbow meant moving the art, rotating it, and moving it back. Every single time. Now you can drag it. It snaps to the corners, edge midpoints and center of the selection, and to the costume's rotation center. Drop it back on the center, or double click, and it goes away. The anchor sits on paper's own `item.pivot`, which already transforms with the item and gets serialized into the project JSON so undo works. It belongs to the selection rather than one item. A group is a single item and answers for itself, and a loose multi-selection only counts as having an anchor while every member agrees on it. Grouping moves the anchor onto the new group and clears it off the members so there is one answer instead of five. The old static glyph and the selectionAnchor bookkeeping ScaleTool did to keep it upright are gone, since the crosshair is drawn on the guide layer now and rebuilt on every update. Also fixes the hover outline landing in the wrong spot once an item has an anchor. It was placed with `item.position`, which IS the anchor as soon as you set one. Uses the matrix instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
RotateTool always span the selection about the center of its bounds. Now that the selection can carry an anchor, spin around that when everyone agrees on one, and fall back to the bounds center otherwise. This also kills a jolt that was there before any of this existed. `prevRot` got initialized to 90 degrees on mouse down, which assumes the rotation handle sits directly below whatever you are spinning around. Only true when that happens to be the bounds center. So the first drag event applied the gap between the real angle and the assumed one as a rotation, and the drawing jumped the instant you touched the handle. With an anchor set it was bad enough to throw the art off screen. Just use where the handle actually was. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`item.pivot` survives undo because paper serializes it into the project JSON, but it does not survive the SVG round trip a costume goes through on save. An anchor that quietly vanishes when you reopen the project is worse than no anchor at all. It goes on the item's own element as `data-pivot`. The element is the key, so there is no id to hand out and nothing to clean up later, and copying a subtree brings the anchor along for free. DOMPurify's svg profile keeps `data-*` attributes, so it survives the round trip scratch-vm puts costumes through. It crosses the SVG boundary as an inert copy on `item.data`, written before the export scales the layer, read back on import, and applied only once initializeSvg has finished shoving everything around. That is what stops it getting mangled. Stored relative to the art board center rather than in SVG coordinates, because the SVG export origin depends on the current content bounds and moves whenever the art does. An anchor written in SVG space would drift every time you nudged the drawing. Bitmap mode gets the crosshair as a plain marker. A bitmap costume has nowhere to save an anchor, and setting one would change what `position` means on the raster the bitmap tools move around. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
I FORGOT TO SAY: all the commits are very new Because i'm a lazy sack of shit that cant use git for anything so i had to do it all just now |
|
did you test it |
8mb.video-EOu-JbRcSzSP.mp4Im pretty sure it should work on PenguinMod-Paint This is it working on my pm fork so |
|
how is the pivot stored in the project.json? |
|
Pivot is stored using the svg itself using attribute "data-pivot", rather than project.json serialization... so the pivot is put in the svg itself (survives sanitization since the sanitizer will spare data-* tags on svgs) |
|
is there a way to reset the pivot perhaps
Sent from my phone :D
…________________________________
From: draker ***@***.***>
Sent: Monday, 21 September 2026 23:00:41
To: PenguinMod/PenguinMod-Paint ***@***.***>
Cc: Kyle Vaillancourt ***@***.***>; Comment ***@***.***>
Subject: Re: [PenguinMod/PenguinMod-Paint] Pivot Crosshair (PR #28)
[https://avatars.githubusercontent.com/u/228128273?s=20&v=4]drakeraz09 left a comment (PenguinMod/PenguinMod-Paint#28)<#28 (comment)>
Pivot is stored using the svg itself using attribute "data-pivot", rather than project.json serialization... so the pivot is put in the svg itself
—
Reply to this email directly, view it on GitHub<#28?email_source=notifications&email_token=AT7TNOTOUVJBZICAG5JOGLL5QHMMTA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKNZXGAYTMMJUGQ22M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5770161445>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AT7TNOXI63M4S5V6CBVKF7D5QHMMTAVCNFSNUABFKJSXA33TNF2G64TZHM3DENJYGE2DKOJSHNEXG43VMU5TKNJSG42TEMRVGE4KC5QC>.
You are receiving this because you commented.Message ID: ***@***.***>
|
yesss You can just double click the crosshair or hover it over the center |
|
TO CLARIFY ON THE PROJECT JSON THING I meant the PAPER.JS LIVE PROJECT JSON that tracks state and what not. i realize now that that is very easily mistaken with an sb3 project json |
|
reimplemented without ai, the feature itself is added to port though |
very kind :) |
Pivot!!!!!
The bounding box already drew a crosshair in the middle of your selection, but it did literally nothing. Everything rotated and scaled around the center of the bounds no matter what.
So now the crosshair actually does something:
(Bitmap mode gets the crosshair as a plain marker. Bitmap costumes have nowhere to put an anchor because they are foolish and ephemeral).
Its
Paper.js handles the heavy lifting via
item.pivot, serializing it into PAPER PROJECT JSON so undo/redo works.data-pivoton the item's element. DOMPurify keepsdata-*attributes safe, so it survives scratch-vm's round-trip sanitizer.item.data, stored relative to the artboard center so it doesn't get killed and ljkadgsfjlkgdlreffd when the svg export origin shifts.Bugs we befriended along the way
RotateToolused to assume the rotation handle was always directly below the center, causing the drawing to JOOOLTTTT the instant you started dragging. Now it uses where the handle actually is.item.position.Files changed
New:
src/helper/pivot.js(Anchor logic, agreement, & snapping)src/helper/pivot-data.js(svg saving and loading)src/helper/selection-tools/pivot-tool.js(Crosshair rendering & dragging)Modified:
bounding-box-tool.js,rotate-tool.js,scale-tool.js,select-tool.js,guides.js,group.js,paper-canvas.jsx, andupdate-image-hoc.jsx.Tests
26 unit tests included. I don't wanna write documentation about them. Just take them.