Skip to content

Commit 0f3a8aa

Browse files
authored
Merge pull request #957 from rgantzos/main
More Paint Functions
2 parents 8225a0c + 5914db3 commit 0f3a8aa

File tree

9 files changed

+259
-0
lines changed

9 files changed

+259
-0
lines changed

features/features.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
[
2+
{
3+
"version": 2,
4+
"id": "more-paint-functions",
5+
"versionAdded": "v4.0.0"
6+
},
27
{
38
"version": 2,
49
"id": "asset-size",

features/more-editor-fonts/script.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default async function ({ feature, console }) {
99
feature.page.waitForElements(
1010
"div[class^='asset-panel_wrapper_'] div[class^='action-menu_more-buttons_']",
1111
function (menu) {
12+
if (feature.traps.gui().editorTab.activeTabIndex !== 1) return;
1213
if (menu.querySelector(".ste-more-fonts")) return;
1314

1415
let div = document.createElement("div");
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"title": "More Paint Functions",
3+
"description": "Adds new functions to the paint editor. The new functions include unite (combining them into one), subtract (removing one shape from another), exclude (removing the overlap of 2 items), and intersect (removing everything but the overlap of 2 items). Each function only works with 2 items.",
4+
"credits": [
5+
{ "username": "rgantzos", "url": "https://scratch.mit.edu/users/rgantzos/" }
6+
],
7+
"type": ["Editor"],
8+
"tags": ["New", "Featured"],
9+
"dynamic": true,
10+
"scripts": [{ "file": "script.js", "runOn": "/projects/*" }],
11+
"styles": [{ "file": "style.css", "runOn": "/projects/*" }],
12+
"resources": [
13+
{ "name": "function-exclude", "path": "/icons/exclude.svg" },
14+
{ "name": "function-intersect", "path": "/icons/intersect.svg" },
15+
{ "name": "function-subtract", "path": "/icons/subtract.svg" },
16+
{ "name": "function-unite", "path": "/icons/unite.svg" }
17+
],
18+
"components": [{
19+
"type": "warning",
20+
"content": "In order to avoid clutter in the paint editor, this feature replaces the Copy, Paste and Delete buttons. However, hotkeys still work."
21+
}]
22+
}
Lines changed: 13 additions & 0 deletions
Loading
Lines changed: 20 additions & 0 deletions
Loading
Lines changed: 17 additions & 0 deletions
Loading
Lines changed: 13 additions & 0 deletions
Loading
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
export default async function ({ feature, console }) {
2+
function unite() {
3+
let paper = feature.traps.getPaper();
4+
let items = paper.project.selectedItems;
5+
6+
if (items.length !== 2) return;
7+
8+
for (var i in items) {
9+
if (i > 0) {
10+
items[0].unite(items[i]);
11+
}
12+
}
13+
14+
for (var i in items) {
15+
items[i].remove();
16+
}
17+
18+
paper.tool.onUpdateImage();
19+
}
20+
21+
function subtract() {
22+
let paper = feature.traps.getPaper();
23+
let items = paper.project.selectedItems;
24+
25+
if (items.length !== 2) return;
26+
27+
for (var i in items) {
28+
if (i > 0) {
29+
items[0].subtract(items[i]);
30+
}
31+
}
32+
33+
for (var i in items) {
34+
items[i].remove();
35+
}
36+
37+
paper.tool.onUpdateImage();
38+
}
39+
40+
function exclude() {
41+
let paper = feature.traps.getPaper();
42+
let items = paper.project.selectedItems;
43+
44+
if (items.length !== 2) return;
45+
46+
for (var i in items) {
47+
if (i > 0) {
48+
items[0].exclude(items[i]);
49+
}
50+
}
51+
52+
for (var i in items) {
53+
items[i].remove();
54+
}
55+
56+
paper.tool.onUpdateImage();
57+
}
58+
59+
function intersect() {
60+
let paper = feature.traps.getPaper();
61+
let items = paper.project.selectedItems;
62+
63+
if (items.length !== 2) return;
64+
65+
for (var i in items) {
66+
if (i > 0) {
67+
items[0].intersect(items[i]);
68+
}
69+
}
70+
71+
for (var i in items) {
72+
items[i].remove();
73+
}
74+
75+
paper.tool.onUpdateImage();
76+
}
77+
78+
ScratchTools.waitForElements(
79+
"div[class^='mode-tools_mod-labeled-icon-height_']",
80+
async function (row) {
81+
if (row.querySelector(".ste-more-functions")) return;
82+
83+
let functions = [
84+
{
85+
name: "Unite",
86+
icon: "function-unite",
87+
callback: unite,
88+
},
89+
{
90+
name: "Subtract",
91+
icon: "function-subtract",
92+
callback: subtract,
93+
},
94+
{
95+
name: "Exclude",
96+
icon: "function-exclude",
97+
callback: exclude,
98+
},
99+
{
100+
name: "Intersect",
101+
icon: "function-intersect",
102+
callback: intersect,
103+
},
104+
];
105+
106+
for (var i in functions) {
107+
row.appendChild(makeButton(functions[i]));
108+
}
109+
110+
let align = await ScratchTools.waitForElement(".ste-align-items");
111+
row.appendChild(align);
112+
}
113+
);
114+
115+
feature.redux.subscribe(function () {
116+
if (document.querySelector(".ste-more-functions")) {
117+
let span = document.querySelector(".ste-more-functions");
118+
if (
119+
feature.traps.paint().format === "BITMAP" ||
120+
feature.traps.paint().selectedItems?.length < 2
121+
) {
122+
document.querySelectorAll(".ste-more-functions").forEach(function (el) {
123+
el.classList.add("button_mod-disabled_1rf31");
124+
});
125+
} else {
126+
document.querySelectorAll(".ste-more-functions").forEach(function (el) {
127+
el.classList.remove("button_mod-disabled_1rf31");
128+
});
129+
}
130+
}
131+
});
132+
133+
function makeButton({ name, icon, callback }) {
134+
let span = document.createElement("span");
135+
span.className =
136+
"button_button_u6SE2 labeled-icon-button_mod-edit-field_1bXYC ste-more-functions";
137+
span.role = "button";
138+
139+
let img = document.createElement("img");
140+
img.src = feature.self.getResource(icon);
141+
img.className = "labeled-icon-button_edit-field-icon_3j-Pf";
142+
img.alt = name;
143+
img.title = name;
144+
img.draggable = false;
145+
span.appendChild(img);
146+
147+
let label = document.createElement("span");
148+
label.textContent = name;
149+
label.className = "labeled-icon-button_edit-field-title_1ZoEV";
150+
span.appendChild(label);
151+
152+
span.addEventListener("click", function (e) {
153+
if (span.className.includes("disabled")) return;
154+
callback();
155+
});
156+
157+
feature.self.hideOnDisable(span);
158+
159+
return span;
160+
}
161+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
div[class*='mode-tools_mode-tools_'] > div[class*='mode-tools_mod-dashed-border_']:nth-child(1), div[class*='mode-tools_mode-tools_'] > div[class*='mode-tools_mod-dashed-border_']:nth-child(2) {
2+
display: none;
3+
}
4+
5+
div[class*='mode-tools_mode-tools_'] > div[class*='mode-tools_mod-labeled-icon-height_']:nth-child(3) {
6+
margin-left: 0px !important;
7+
}

0 commit comments

Comments
 (0)