From 689173c08f5353cee3070323628e02534b76a109 Mon Sep 17 00:00:00 2001 From: Jazza-231 Date: Mon, 8 Jan 2024 14:25:49 +0800 Subject: [PATCH] initial commmit --- addons/addons.json | 1 + addons/anchor-point/addon.json | 18 +++++++ addons/anchor-point/userscript.js | 79 +++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 addons/anchor-point/addon.json create mode 100644 addons/anchor-point/userscript.js diff --git a/addons/addons.json b/addons/addons.json index e8cefbc313..6daf4650dd 100644 --- a/addons/addons.json +++ b/addons/addons.json @@ -150,6 +150,7 @@ "paint-skew", "preview-project-description", "collapse-footer", + "anchor-point", "// NEW ADDONS ABOVE THIS ↑↑", "// Note: these themes need this exact order to work properly,", diff --git a/addons/anchor-point/addon.json b/addons/anchor-point/addon.json new file mode 100644 index 0000000000..6664ee27c9 --- /dev/null +++ b/addons/anchor-point/addon.json @@ -0,0 +1,18 @@ +{ + "name": "Shiftable anchor point", + "description": "Allows you to rotate the selection around a point other than the center.", + "credits": [ + { + "name": "Jazza", + "link": "https://scratch.mit.edu/users/greeny--231" + } + ], + "userscripts": [ + { + "url": "userscript.js", + "matches": ["projects"] + } + ], + "tags": ["editor", "costumeEditor", "featured", "recommended"], + "versionAdded": "1.35.0" +} diff --git a/addons/anchor-point/userscript.js b/addons/anchor-point/userscript.js new file mode 100644 index 0000000000..119c2c743c --- /dev/null +++ b/addons/anchor-point/userscript.js @@ -0,0 +1,79 @@ +import { loadModules } from "../paint-snap/helpers.js"; + +export default async function ({ addon, console }) { + window.addon = addon; + const paper = await addon.tab.traps.getPaper(); + + /** + * Selection must be a single item or a group + * When you have something selected, a custom pivot point will show, and when you drag it, + * that is the point on the canvas which it rotates around (you can not rotate relative to the + * item, because its center changes on rotation). + * When you move the item/group, the pivot point is moved too, so that it's not rotating on the same canvas point, but + * acts like it is relative to the item. + * Make sure to keep all original scratch features (shift to snap to 45 degrees), and think about compat with new addon idea + * customising the value that it snaps to when you hold shift. + * Add an option to lock it the canvas no matter where you move the object - hexagonal + * Pivot point, when dragged, snaps to the center of the object + */ + + // updateSelectTool.js line 114 is the selection anchor, this should be made draggable and displays new pivot point + // Snapping addon snaps from pivot point, not center. + + // Local storage structure (don't forget localStorage only allows strings, use JSON.stringify) + // In order to do .clone() etc on the pivots, after reading, use new paper.Point([x, y]) + const data = [ + { + spriteId: "|f}2;)JrF-0wS)ZPxtgL", + costumeId: "592bae6f8bb9c8d88401b54ac431f7b6", + itemId: 10, + pivot: { + x: 530, + y: 310, + }, + locked: true, // If locked is false, pivot is changed when dragged + // (IMPORTANT: you cant do anything relative to the object, you just have to pretend it is) + }, + ]; + + const { + layer: { getLayer }, + } = loadModules(paper); + + const rotateTool = paper.tool.boundingBoxTool._modeMap.ROTATE; + + rotateTool.constructor.prototype.onMouseDrag = function (e) { + // rotGroupPivot gets set to null on mouse up, thus the changed property is falsy + // Do it this way so that we don't have to worry about changing the onMouseDown function + if (!this.rotGroupPivot.changed) { + this.realPivot = this.rotGroupPivot.clone(); + this.rotGroupPivot.x = data[0].pivot.x; + this.rotGroupPivot.y = data[0].pivot.y; + this.rotGroupPivot.changed = true; + + let v1 = e.point.subtract(this.rotGroupPivot); + let v2 = e.point.subtract(this.realPivot); + let angle = Math.acos(v1.dot(v2) / (v1.length * v2.length)) * (180 / Math.PI); + angle *= e.point.x < this.rotGroupPivot.x ? -1 : 1; + this.modifierAngle = angle; + } + + let rotAngle = e.point.subtract(this.rotGroupPivot).angle + this.modifierAngle; + if (e.modifiers.shift) { + rotAngle = Math.round(rotAngle / 45) * 45; + } + + this.rotItems.forEach((item) => { + item.rotate(rotAngle - this.prevRot, this.rotGroupPivot); + }); + + this.prevRot = rotAngle; + }; + + const oldSetSelectionBounds = paper.tool.boundingBoxTool.setSelectionBounds; + paper.tool.boundingBoxTool.setSelectionBounds = function () { + oldSetSelectionBounds.call(this); + + this.boundsPath.selectionAnchor.position = new paper.Point(data[0].pivot); + }; +}