Spaces:
Runtime error
Runtime error
Update src/addons/addons/paint-tool-panel/userscript.js
Browse files
src/addons/addons/paint-tool-panel/userscript.js
CHANGED
@@ -8,6 +8,8 @@ export default async function () {
|
|
8 |
const valueObserverObj = { r: 0, sx: 1, sy: 1, kx: 0, ky: 0, outlineRatio: 1 };
|
9 |
const panelID = "costume-editor-panel";
|
10 |
const epsilon = 1e-8;
|
|
|
|
|
11 |
|
12 |
const guiIMGS = {
|
13 |
"panel": `<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><rect x="10.796" y="6.222" width="4.813" height="2.174" rx=".5" ry=".5" fill="#fff" fill-rule="evenodd" stroke="#575e75" stroke-width=".75"/><path fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75" style="paint-order:markers stroke fill" d="M3 3h14v14H3z"/><g fill="#fff" fill-rule="evenodd" stroke-width=".75"><path stroke="red" stroke-linecap="round" stroke-linejoin="round" style="paint-order:markers fill stroke" d="M3 3h14v1.896H3z"/><rect x="10.796" y="9.722" width="4.813" height="2.174" rx=".5" ry=".5" stroke="#575e75"/><rect x="10.796" y="13.222" width="4.813" height="2.174" rx=".5" ry=".5" stroke="#575e75"/></g><path d="M9.563 7.309H4.242m5.321 6.978H4.242m5.321-3.478H4.242" style="paint-order:markers stroke fill" fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75"/></svg>`,
|
@@ -50,6 +52,10 @@ export default async function () {
|
|
50 |
items: [
|
51 |
{ title: "x", input: "number", params: "sx" },
|
52 |
{ title: "y", input: "number", params: "sy" },
|
|
|
|
|
|
|
|
|
53 |
{ title: "Group Scaling", id: "groupScale", input: "toggler" },
|
54 |
"br",
|
55 |
{ title: "Scale Outlines", id: "strokeScale", input: "toggler" },
|
@@ -59,7 +65,8 @@ export default async function () {
|
|
59 |
title: "Skewing",
|
60 |
items: [
|
61 |
{ title: "x", input: "number", params: "sx" },
|
62 |
-
{ title: "y", input: "number", params: "sy" }
|
|
|
63 |
]
|
64 |
},
|
65 |
{
|
@@ -110,16 +117,16 @@ export default async function () {
|
|
110 |
return ogScale.call(this, ...args);
|
111 |
};
|
112 |
|
113 |
-
const
|
114 |
-
paper.Item.prototype.
|
115 |
const kx = typeof args[0] === "number" ? args[0] : 1;
|
116 |
const ky = typeof args[1] === "number" ? args[1] : kx;
|
117 |
for (const child of this._children ?? [this]) {
|
118 |
if (!child[panelTag]) child[panelTag] = structuredClone(valueObserverObj);
|
119 |
-
child[panelTag].kx += kx;
|
120 |
-
child[panelTag].ky += ky;
|
121 |
}
|
122 |
-
return
|
123 |
};
|
124 |
}
|
125 |
|
@@ -138,8 +145,9 @@ export default async function () {
|
|
138 |
for (const item of selectedItems) func(item, value);
|
139 |
|
140 |
queueMicrotask(() => {
|
|
|
141 |
if (sessionCenterNeedsUpdate) {
|
142 |
-
//
|
143 |
modalStorage.sessionStore = { center: getCenter(selectedItems) };
|
144 |
sessionCenterNeedsUpdate = false;
|
145 |
}
|
@@ -228,6 +236,16 @@ export default async function () {
|
|
228 |
}
|
229 |
}
|
230 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
/* GUI Utils */
|
232 |
function getButtonURI(name, dontCompile) {
|
233 |
const themeHex = isPM ? "#00c3ff" : document.documentElement.style.getPropertyValue("--looks-secondary") || "#ff4c4c";
|
@@ -271,6 +289,18 @@ export default async function () {
|
|
271 |
value: (item1[panelTag] ? isX ? item1[panelTag].sx : item1[panelTag].sy : 1) * 100
|
272 |
};
|
273 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
case "Skewing/x":
|
275 |
case "Skewing/y": {
|
276 |
if (selectedItems.length > 1) return { value: "", placeholder: "mixed" };
|
@@ -350,10 +380,10 @@ export default async function () {
|
|
350 |
case "Skewing/y": return (item, value) => {
|
351 |
if (isX) {
|
352 |
value -= item[panelTag]?.kx ?? 0;
|
353 |
-
item
|
354 |
} else {
|
355 |
value -= item[panelTag]?.ky ?? 0;
|
356 |
-
item
|
357 |
}
|
358 |
}
|
359 |
case "Layering/order": return (item, value) => {
|
@@ -381,6 +411,7 @@ export default async function () {
|
|
381 |
const inputStyle = `text-align: center; font-size: 13px; width: 60px; height: 25px; margin: 5px; border: solid 2px var(--ui-black-transparent, hsla(0, 0%, 0%, 0.15)); border-radius: 15px;`;
|
382 |
const selectStyle = `text-align: center; font-size: 13px; height: 25px; margin: 5px; border: solid 2px var(--ui-black-transparent, hsla(0, 0%, 0%, 0.15)); border-radius: 5px;`;
|
383 |
const togglerStyle = `background: transparent; border: none; margin-left: 3px; padding: 5px 0 0 0;`;
|
|
|
384 |
|
385 |
const selectedItems = getRealSelection();
|
386 |
const center = getCenter(selectedItems);
|
@@ -411,7 +442,15 @@ export default async function () {
|
|
411 |
|
412 |
const id = `${tool.title}/${item.title}`;
|
413 |
let input;
|
414 |
-
if (item.input === "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
415 |
input = document.createElement("select");
|
416 |
input.setAttribute("style", selectStyle);
|
417 |
input.id = id;
|
@@ -481,15 +520,30 @@ export default async function () {
|
|
481 |
if (item === "br") continue;
|
482 |
|
483 |
const id = `${tool.title}/${item.title}`;
|
484 |
-
const input = toolDiv.querySelector(`input[id="${id}"], select[id="${id}"`);
|
485 |
if (input) {
|
486 |
const params = getToolParams(id, selectedItems);
|
487 |
-
if (params.value !== "")
|
|
|
|
|
|
|
488 |
}
|
489 |
}
|
490 |
}
|
491 |
}
|
492 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
493 |
function closeToolModal() {
|
494 |
const existingModal = document.querySelector(`div[class="costume-tool-modal"]`);
|
495 |
if (existingModal) existingModal.remove();
|
|
|
8 |
const valueObserverObj = { r: 0, sx: 1, sy: 1, kx: 0, ky: 0, outlineRatio: 1 };
|
9 |
const panelID = "costume-editor-panel";
|
10 |
const epsilon = 1e-8;
|
11 |
+
const toRad = Math.PI / 180;
|
12 |
+
const toDeg = 180 / Math.PI;
|
13 |
|
14 |
const guiIMGS = {
|
15 |
"panel": `<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><rect x="10.796" y="6.222" width="4.813" height="2.174" rx=".5" ry=".5" fill="#fff" fill-rule="evenodd" stroke="#575e75" stroke-width=".75"/><path fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75" style="paint-order:markers stroke fill" d="M3 3h14v14H3z"/><g fill="#fff" fill-rule="evenodd" stroke-width=".75"><path stroke="red" stroke-linecap="round" stroke-linejoin="round" style="paint-order:markers fill stroke" d="M3 3h14v1.896H3z"/><rect x="10.796" y="9.722" width="4.813" height="2.174" rx=".5" ry=".5" stroke="#575e75"/><rect x="10.796" y="13.222" width="4.813" height="2.174" rx=".5" ry=".5" stroke="#575e75"/></g><path d="M9.563 7.309H4.242m5.321 6.978H4.242m5.321-3.478H4.242" style="paint-order:markers stroke fill" fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75"/></svg>`,
|
|
|
52 |
items: [
|
53 |
{ title: "x", input: "number", params: "sx" },
|
54 |
{ title: "y", input: "number", params: "sy" },
|
55 |
+
"br",
|
56 |
+
{ title: "width", input: "monitor", params: "width" },
|
57 |
+
{ title: "height", input: "monitor", params: "height" },
|
58 |
+
"br",
|
59 |
{ title: "Group Scaling", id: "groupScale", input: "toggler" },
|
60 |
"br",
|
61 |
{ title: "Scale Outlines", id: "strokeScale", input: "toggler" },
|
|
|
65 |
title: "Skewing",
|
66 |
items: [
|
67 |
{ title: "x", input: "number", params: "sx" },
|
68 |
+
{ title: "y", input: "number", params: "sy" },
|
69 |
+
{ title: "Group Skewing", id: "groupSkew", input: "toggler" },
|
70 |
]
|
71 |
},
|
72 |
{
|
|
|
117 |
return ogScale.call(this, ...args);
|
118 |
};
|
119 |
|
120 |
+
const ogShear = paper.Item.prototype.shear;
|
121 |
+
paper.Item.prototype.shear = function(...args) {
|
122 |
const kx = typeof args[0] === "number" ? args[0] : 1;
|
123 |
const ky = typeof args[1] === "number" ? args[1] : kx;
|
124 |
for (const child of this._children ?? [this]) {
|
125 |
if (!child[panelTag]) child[panelTag] = structuredClone(valueObserverObj);
|
126 |
+
child[panelTag].kx += Math.atan(kx) * toDeg;
|
127 |
+
child[panelTag].ky += Math.atan(ky) * toDeg;
|
128 |
}
|
129 |
+
return ogShear.call(this, ...args);
|
130 |
};
|
131 |
}
|
132 |
|
|
|
145 |
for (const item of selectedItems) func(item, value);
|
146 |
|
147 |
queueMicrotask(() => {
|
148 |
+
updateMonitors();
|
149 |
if (sessionCenterNeedsUpdate) {
|
150 |
+
// perform tasks for bounding box updates
|
151 |
modalStorage.sessionStore = { center: getCenter(selectedItems) };
|
152 |
sessionCenterNeedsUpdate = false;
|
153 |
}
|
|
|
236 |
}
|
237 |
}
|
238 |
|
239 |
+
function skewItem(item, x, y, isLocked) {
|
240 |
+
let pivot = isLocked ? new paper.Point(modalStorage.sessionStore.center) : item.bounds.center;
|
241 |
+
|
242 |
+
item.translate(pivot.multiply(-1));
|
243 |
+
item.shear(Math.tan(x * toRad), Math.tan(y * toRad));
|
244 |
+
item.translate(pivot);
|
245 |
+
|
246 |
+
sessionCenterNeedsUpdate = true;
|
247 |
+
}
|
248 |
+
|
249 |
/* GUI Utils */
|
250 |
function getButtonURI(name, dontCompile) {
|
251 |
const themeHex = isPM ? "#00c3ff" : document.documentElement.style.getPropertyValue("--looks-secondary") || "#ff4c4c";
|
|
|
289 |
value: (item1[panelTag] ? isX ? item1[panelTag].sx : item1[panelTag].sy : 1) * 100
|
290 |
};
|
291 |
}
|
292 |
+
case "Scaling/width":
|
293 |
+
case "Scaling/height": {
|
294 |
+
if (selectedItems.length > 1) {
|
295 |
+
const groupBounds = paper.Rectangle.create(selectedItems.map(i => i.bounds))
|
296 |
+
.reduce((a, b) => a.unite(b));
|
297 |
+
return {
|
298 |
+
value: (groupBounds[name.endsWith("width") ? "width" : "height"] / 2).toFixed(2)
|
299 |
+
};
|
300 |
+
} else return {
|
301 |
+
value: (item1.getBounds()[name.endsWith("width") ? "width" : "height"] / 2).toFixed(2)
|
302 |
+
};
|
303 |
+
}
|
304 |
case "Skewing/x":
|
305 |
case "Skewing/y": {
|
306 |
if (selectedItems.length > 1) return { value: "", placeholder: "mixed" };
|
|
|
380 |
case "Skewing/y": return (item, value) => {
|
381 |
if (isX) {
|
382 |
value -= item[panelTag]?.kx ?? 0;
|
383 |
+
skewItem(item, value, 0, modalStorage["groupSkew"]);
|
384 |
} else {
|
385 |
value -= item[panelTag]?.ky ?? 0;
|
386 |
+
skewItem(item, 0, value, modalStorage["groupSkew"]);
|
387 |
}
|
388 |
}
|
389 |
case "Layering/order": return (item, value) => {
|
|
|
411 |
const inputStyle = `text-align: center; font-size: 13px; width: 60px; height: 25px; margin: 5px; border: solid 2px var(--ui-black-transparent, hsla(0, 0%, 0%, 0.15)); border-radius: 15px;`;
|
412 |
const selectStyle = `text-align: center; font-size: 13px; height: 25px; margin: 5px; border: solid 2px var(--ui-black-transparent, hsla(0, 0%, 0%, 0.15)); border-radius: 5px;`;
|
413 |
const togglerStyle = `background: transparent; border: none; margin-left: 3px; padding: 5px 0 0 0;`;
|
414 |
+
const monitorStyle = `text-align: center; font-size: 13px; margin: 5px; padding: 5px; border: solid 2px var(--ui-black-transparent, hsla(0, 0%, 0%, 0.15)); border-radius: 5px;`;
|
415 |
|
416 |
const selectedItems = getRealSelection();
|
417 |
const center = getCenter(selectedItems);
|
|
|
442 |
|
443 |
const id = `${tool.title}/${item.title}`;
|
444 |
let input;
|
445 |
+
if (item.input === "monitor") {
|
446 |
+
input = document.createElement("div");
|
447 |
+
input.setAttribute("style", monitorStyle);
|
448 |
+
input.classList.add("monitor");
|
449 |
+
input.id = id;
|
450 |
+
|
451 |
+
const param = getToolParams(id, selectedItems);
|
452 |
+
input.textContent = param.value;
|
453 |
+
} else if (item.input === "select") {
|
454 |
input = document.createElement("select");
|
455 |
input.setAttribute("style", selectStyle);
|
456 |
input.id = id;
|
|
|
520 |
if (item === "br") continue;
|
521 |
|
522 |
const id = `${tool.title}/${item.title}`;
|
523 |
+
const input = toolDiv.querySelector(`input[id="${id}"], select[id="${id}"], div[id="${id}"]`);
|
524 |
if (input) {
|
525 |
const params = getToolParams(id, selectedItems);
|
526 |
+
if (params.value !== "") {
|
527 |
+
if (item.input === "monitor") input.textContent = params.value;
|
528 |
+
else input.value = params.value;
|
529 |
+
}
|
530 |
}
|
531 |
}
|
532 |
}
|
533 |
}
|
534 |
|
535 |
+
function updateMonitors() {
|
536 |
+
const selectedItems = getRealSelection();
|
537 |
+
const toolDiv = modalStorage.toolDiv;
|
538 |
+
if (!toolDiv) return;
|
539 |
+
|
540 |
+
const monitors = modalStorage.toolDiv.querySelectorAll(`[class="monitor"]`);
|
541 |
+
for (const monitor of monitors) {
|
542 |
+
const params = getToolParams(monitor.id, selectedItems);
|
543 |
+
if (params.value !== "") monitor.textContent = params.value;
|
544 |
+
}
|
545 |
+
}
|
546 |
+
|
547 |
function closeToolModal() {
|
548 |
const existingModal = document.querySelector(`div[class="costume-tool-modal"]`);
|
549 |
if (existingModal) existingModal.remove();
|