From da04df9546c525b23c29b43adce9a255801b1437 Mon Sep 17 00:00:00 2001
From: BonesYT <63462200+BonesYT@users.noreply.github.com>
Date: Sat, 11 Jan 2025 11:11:44 -0300
Subject: [PATCH 1/5] add scratch complex
---
extensions/BonesYT/ScratchComplex.js | 466 +++++++++++++++++++++++++++
extensions/extensions.json | 201 ++++++------
images/BonesYT/ScratchComplex.svg | 1 +
3 files changed, 568 insertions(+), 100 deletions(-)
create mode 100644 extensions/BonesYT/ScratchComplex.js
create mode 100644 images/BonesYT/ScratchComplex.svg
diff --git a/extensions/BonesYT/ScratchComplex.js b/extensions/BonesYT/ScratchComplex.js
new file mode 100644
index 0000000000..bbca552dc4
--- /dev/null
+++ b/extensions/BonesYT/ScratchComplex.js
@@ -0,0 +1,466 @@
+// Name: Complex Numbers
+// ID: bonesytcomplex
+// Description: Mathematical functions for complex numbers. Has all the operations from the Operators category, and a few extra ones.
+// By: Bones2
+// License: MPL-2.0
+(function (Scratch) {
+ /* Version 1.0 - 01/10/2025 MM/DD/YYYY */
+ "use strict";
+ if (!Scratch.extensions.unsandboxed) {
+ throw new Error("You're running an unsandboxed extension as sandboxed.");
+ }
+
+ class ScratchComplex {
+ constructor() {}
+
+ advancedSyntax = true;
+
+ complex({ r, i }) {
+ (r = +r), (i = +i);
+ if (isNaN(r) || isNaN(i)) return "NaN";
+ if (this.advancedSyntax) {
+ const a = (x) =>
+ (x < 0 ? "-" : "") + (Math.abs(x) == 1 ? "" : Math.abs(x)) + "i";
+ return r == 0 && i != 0
+ ? a(i)
+ : r < 0 && i > 0
+ ? a(i) + r
+ : r + (i == 0 ? "" : (i > 0 ? "+" : "") + a(i));
+ } else {
+ return i == 0 ? "" + +r : +r + "," + +i;
+ }
+ }
+
+ parse(input) {
+ input = "" + input;
+ if (!input) return { r: 0, i: 0 };
+ if (!input.includes(",") && this.advancedSyntax) {
+ input = input
+ .replace(/\s/g, "")
+ .replace(/[eE]\+/g, "p")
+ .replace(/[eE]-/g, "m");
+ let parts = input.split(/(? v.replace("p", "e+").replace("m", "e-"));
+ return { r: +parts[0], i: +parts[1] * sign };
+ }
+ } else {
+ const parts = input.split(",");
+ return { r: +parts[0], i: parts[1] == undefined ? 0 : +parts[1] };
+ }
+ }
+
+ getReal({ x }) {
+ return this.parse(x).r;
+ }
+ getImag({ x }) {
+ return this.parse(x).i;
+ }
+ isReal({ x }) {
+ return this.parse(x).i == 0;
+ }
+
+ add(x, y) {
+ if (x.i == 0 && y.i == 0) return { r: x.r + y.r, i: 0 };
+ const r = x.r + y.r;
+ const i = x.i + y.i;
+ return { r, i };
+ }
+ complexAdd({ x, y }) {
+ (x = this.parse(x)), (y = this.parse(y));
+ const v = this.add(x, y);
+ return this.complex(v);
+ }
+ sub(x, y) {
+ if (x.i == 0 && y.i == 0) return { r: x.r - y.r, i: 0 };
+ const r = x.r - y.r;
+ const i = x.i - y.i;
+ return { r, i };
+ }
+ complexSub({ x, y }) {
+ (x = this.parse(x)), (y = this.parse(y));
+ const v = this.sub(x, y);
+ return this.complex(v);
+ }
+ mul(x, y) {
+ if (x.i == 0 && y.i == 0) return { r: x.r * y.r, i: 0 };
+ const r = x.r * y.r - x.i * y.i;
+ const i = x.r * y.i + x.i * y.r;
+ return { r, i };
+ }
+ complexMul({ x, y }) {
+ (x = this.parse(x)), (y = this.parse(y));
+ const mul = this.mul(x, y);
+ return this.complex(mul);
+ }
+ div(x, y) {
+ if (x.i == 0 && y.i == 0) return { r: x.r / y.r, i: 0 };
+ if (y.r == 0 && y.i == 0) return { r: 1 / (y.r * x.r), i: 0 };
+ const a = y.r ** 2 + y.i ** 2;
+ const r = (x.r * y.r + x.i * y.i) / a;
+ const i = (x.i * y.r - x.r * y.i) / a;
+ return { r, i };
+ }
+ complexDiv({ x, y }) {
+ (x = this.parse(x)), (y = this.parse(y));
+ const div = this.div(x, y);
+ return this.complex(div);
+ }
+ pow(x, y) {
+ if (x.i == 0 && y.i == 0) {
+ const r = x.r ** y.r;
+ if (!isNaN(r)) return { r, i: 0 };
+ }
+ const R = Math.sqrt(x.r ** 2 + x.i ** 2);
+ const T = Math.atan2(x.i, x.r);
+ const e = Math.E ** (y.r * Math.log(R) - y.i * T);
+ const a = y.r * T + y.i * Math.log(R);
+ const r = e * Math.cos(a);
+ const i = e * Math.sin(a);
+ return { r, i };
+ }
+ complexPow({ x, y }) {
+ (x = this.parse(x)), (y = this.parse(y));
+ const pow = this.pow(x, y);
+ return this.complex(pow);
+ }
+ ln(x) {
+ if (x.i == 0 && x.r >= 0) return { r: Math.log(x.r), i: 0 };
+ const r = Math.log(x.r ** 2 + x.i ** 2) / 2;
+ const i = Math.atan2(x.i, x.r);
+ return { r, i };
+ }
+ complexOperation({ oper, z }) {
+ z = this.parse(z);
+ let r = z.r,
+ i = z.i;
+ if (["sin", "cos", "tan"].includes(oper))
+ (r /= 180 / Math.PI), (i /= 180 / Math.PI);
+ let out, alt;
+
+ switch (oper) {
+ case "abs":
+ out = [Math.sqrt(r ** 2 + i ** 2), 0];
+ break;
+ case "conjugate":
+ out = [r, -i];
+ break;
+ case "flip":
+ out = [i, r];
+ break;
+ case "floor":
+ out = [Math.floor(r), Math.floor(i)];
+ break;
+ case "ceiling":
+ out = [Math.ceil(r), Math.ceil(i)];
+ break;
+ case "round":
+ out = [Math.round(r), Math.round(i)];
+ break;
+ case "sqrt":
+ out = this.pow(z, { r: 0.5, i: 0 });
+ break;
+ case "atan2":
+ out = [Math.atan2(i, r), 0];
+ break;
+ case "e^":
+ out = this.pow({ r: Math.E, i: 0 }, z);
+ break;
+ case "10^":
+ out = this.pow({ r: 10, i: 0 }, z);
+ break;
+ case "sign":
+ out = [Math.sign(r), Math.sign(i)];
+ break;
+ case "sin":
+ out =
+ i == 0
+ ? [Math.sin(r), 0]
+ : [Math.sin(r) * Math.cosh(i), Math.cos(r) * Math.sinh(i)];
+ break;
+ case "cos":
+ out =
+ i == 0
+ ? [Math.cos(r), 0]
+ : [Math.cos(r) * Math.cosh(i), Math.sin(r) * Math.sinh(i)];
+ break;
+ case "tan":
+ i == 0
+ ? (out = [Math.tan(r), 0])
+ : ((alt = Math.cos(r * 2) + Math.cosh(i * 2)),
+ (out = [Math.sin(r * 2) / alt, Math.sinh(i * 2) / alt]));
+ break;
+ case "asin":
+ if (i == 0 && Math.abs(r) <= 1)
+ out = [(Math.asin(r) * 180) / Math.PI, 0];
+ else {
+ alt = this.mul(
+ this.ln(
+ this.add(
+ this.pow(
+ this.sub({ r: 1, i: 0 }, this.pow(z, { r: 2, i: 0 })),
+ { r: 0.5, i: 0 }
+ ),
+ this.mul(z, { r: 0, i: 1 })
+ )
+ ),
+ { r: 0, i: -1 }
+ );
+ out = [(alt.r * 180) / Math.PI, (alt.i * 180) / Math.PI];
+ }
+ break;
+ case "acos":
+ if (i == 0 && Math.abs(r) <= 1)
+ out = [(Math.acos(r) * 180) / Math.PI, 0];
+ else {
+ alt = this.mul(
+ this.ln(
+ this.add(
+ this.mul(
+ this.pow(
+ this.sub({ r: 1, i: 0 }, this.pow(z, { r: 2, i: 0 })),
+ { r: 0.5, i: 0 }
+ ),
+ { r: 0, i: 1 }
+ ),
+ z
+ )
+ ),
+ { r: 0, i: -1 }
+ );
+ out = [(alt.r * 180) / Math.PI, (alt.i * 180) / Math.PI];
+ }
+ break;
+ case "atan":
+ if (i == 0) out = [(Math.atan(r) * 180) / Math.PI, 0];
+ else {
+ alt = this.mul(
+ this.ln(
+ this.div(
+ this.sub({ r: 1, i: 0 }, this.mul(z, { r: 0, i: 1 })),
+ this.add({ r: 1, i: 0 }, this.mul(z, { r: 0, i: 1 }))
+ )
+ ),
+ { r: 0, i: 0.5 }
+ );
+ out = [(alt.r * 180) / Math.PI, (alt.i * 180) / Math.PI];
+ }
+ break;
+ case "ln":
+ (alt = this.ln(z)), (out = [alt.r, alt.i]);
+ break;
+ }
+
+ return this.complex({ r: out[0], i: out[1] });
+ }
+ complexLog({ n, z }) {
+ (n = this.parse(n)), (z = this.parse(z));
+ if (n.i == 0 && z.i == 0) return Math.log(z.r) / Math.log(n.r);
+ const N = {
+ r: Math.log(n.r ** 2 + n.i ** 2) / 2,
+ i: Math.atan2(n.i, n.r),
+ };
+ const Z = {
+ r: Math.log(z.r ** 2 + z.i ** 2) / 2,
+ i: Math.atan2(z.i, z.r),
+ };
+ const out = this.div(Z, N);
+ return this.complex(out);
+ }
+ toggleComplexAdvSyntax({ mode }) {
+ this.advancedSyntax = mode == "advanced (slower)";
+ }
+ getComplexAdvSyntax() {
+ return this.advancedSyntax;
+ }
+ complexMod({ x, y }) {
+ (x = this.parse(x)), (y = this.parse(y));
+ const a = this.div(x, y);
+ a.r -= Math.floor(a.r);
+ a.i -= Math.floor(a.i);
+ const out = this.mul(a, y);
+ return this.complex(out);
+ }
+
+ getInfo() {
+ return {
+ id: "bonesytcomplex",
+ name: Scratch.translate("Complex Numbers"),
+ color1: "#51CCAB",
+ color2: "#42BC9B",
+ color3: "#2FA887",
+ menuIconURI:
+ "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSI2My4yNSIgaGVpZ2h0PSI2My4yNSIgdmlld0JveD0iMCwwLDYzLjI1LDYzLjI1Ij48ZGVmcz48bGluZWFyR3JhZGllbnQgeDE9IjI0MCIgeTE9IjE3MS44MDk2OSIgeDI9IjI0MCIgeTI9IjIwMS43Nzc3OCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGlkPSJjb2xvci0xIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM5OWZmZGYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM4N2ZmZjEiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCB4MT0iMjQwIiB5MT0iMTcxLjgwOTY5IiB4Mj0iMjQwIiB5Mj0iMjAxLjc3Nzc4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImNvbG9yLTIiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2Q1ZmZmMiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2I2ZmZmNyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMDguMzc1LC0xNDguMzc1KSI+PGcgZGF0YS1wYXBlci1kYXRhPSJ7JnF1b3Q7aXNQYWludGluZ0xheWVyJnF1b3Q7OnRydWV9IiBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZS1saW5lY2FwPSJidXR0IiBzdHJva2UtbGluZWpvaW49Im1pdGVyIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS1kYXNoYXJyYXk9IiIgc3Ryb2tlLWRhc2hvZmZzZXQ9IjAiIHN0eWxlPSJtaXgtYmxlbmQtbW9kZTogbm9ybWFsIj48cGF0aCBkPSJNMjEwLDE4MGMwLC0xNi41Njg1NCAxMy40MzE0NiwtMzAgMzAsLTMwYzE2LjU2ODU0LDAgMzAsMTMuNDMxNDYgMzAsMzBjMCwxNi41Njg1NCAtMTMuNDMxNDYsMzAgLTMwLDMwYy0xNi41Njg1NCwwIC0zMCwtMTMuNDMxNDYgLTMwLC0zMHoiIGZpbGw9IiM1MWNjYWIiIHN0cm9rZT0iIzJmYTg4NyIgc3Ryb2tlLXdpZHRoPSIzLjI1Ii8+PGcgc3Ryb2tlPSIjMDA0NjRmIiBzdHJva2Utd2lkdGg9IjQiPjxwYXRoIGQ9Ik0yMzcuMjA0MDEsMTYzLjQwMDQ3YzAsLTIuODU5ODcgMi4zMTgzOCwtNS4xNzgyNSA1LjE3ODI1LC01LjE3ODI1YzIuODU5ODcsMCA1LjE3ODI1LDIuMzE4MzggNS4xNzgyNSw1LjE3ODI1YzAsMi44NTk4NyAtMi4zMTgzOCw1LjE3ODI1IC01LjE3ODI1LDUuMTc4MjVjLTIuODU5ODcsMCAtNS4xNzgyNSwtMi4zMTgzOCAtNS4xNzgyNSwtNS4xNzgyNXoiIGZpbGw9IiM5OWZmZGYiLz48cGF0aCBkPSJNMjMxLjI0NTc3LDE3NC43OTAwOGwwLjc4NDMxLC0yLjk4MDM5aDE0LjYxMDY0YzAsMCAtNC43Mjk2OSwyMS4wNTExIC0zLjk4Mjg5LDI0LjEwNjVjMC42NzEwNywyLjczMTI2IDUuNjI3OTcsMC4yMzk1OCA1LjYyNzk3LDAuMjM5NThsMC40Njg0MiwzLjMwOTE5YzAsMCAtMy40NTczMywyLjI3MDUyIC03LjQ0NzczLDIuMzEyMzhjLTMuNTQ4OTUsMC4wMzcyMiAtNiwtMi4yNTIwNCAtNi41MDAxMywtNC42MDEwNWMtMS42Mzk1OSwtNy43MDA5NSAyLjc4MjY3LC0yMi4zODYxOSAyLjc4MjY3LC0yMi4zODYxOXoiIGZpbGw9InVybCgjY29sb3ItMSkiLz48L2c+PHBhdGggZD0iTTIzNy4yMDQwMSwxNjMuNDAwNDdjMCwtMi44NTk4NyAyLjMxODM4LC01LjE3ODI1IDUuMTc4MjUsLTUuMTc4MjVjMi44NTk4NywwIDUuMTc4MjUsMi4zMTgzOCA1LjE3ODI1LDUuMTc4MjVjMCwyLjg1OTg3IC0yLjMxODM4LDUuMTc4MjUgLTUuMTc4MjUsNS4xNzgyNWMtMi44NTk4NywwIC01LjE3ODI1LC0yLjMxODM4IC01LjE3ODI1LC01LjE3ODI1eiIgZmlsbD0iI2RhZmZmMyIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjAiLz48cGF0aCBkPSJNMjMxLjI0NTc3LDE3NC43OTAwOGwwLjc4NDMxLC0yLjk4MDM5aDE0LjYxMDY0YzAsMCAtNC43Mjk2OSwyMS4wNTExIC0zLjk4Mjg5LDI0LjEwNjVjMC42NzEwNywyLjczMTI2IDUuNjI3OTcsMC4yMzk1OCA1LjYyNzk3LDAuMjM5NThsMC40Njg0MiwzLjMwOTE5YzAsMCAtMy40NTczMywyLjI3MDUyIC03LjQ0NzczLDIuMzEyMzhjLTMuNTQ4OTUsMC4wMzcyMiAtNiwtMi4yNTIwNCAtNi41MDAxMywtNC42MDEwNWMtMS42Mzk1OSwtNy43MDA5NSAyLjc4MjY3LC0yMi4zODYxOSAyLjc4MjY3LC0yMi4zODYxOXoiIGZpbGw9InVybCgjY29sb3ItMikiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIwIi8+PC9nPjwvZz48L3N2Zz48IS0tcm90YXRpb25DZW50ZXI6MzEuNjI1OjMxLjYyNS0tPg==",
+ /** @type {('---'|Scratch.Block)[]} */
+ blocks: [
+ {
+ opcode: "complex",
+ blockType: "reporter",
+ text: Scratch.translate("[r] + [i]i"),
+ arguments: {
+ r: { type: "number", defaultValue: 0 },
+ i: { type: "number", defaultValue: 1 },
+ },
+ },
+ {
+ opcode: "getReal",
+ blockType: "reporter",
+ text: Scratch.translate("real of [x]"),
+ arguments: {
+ x: { type: "string", defaultValue: "1 + 2i" },
+ },
+ },
+ {
+ opcode: "getImag",
+ blockType: "reporter",
+ text: Scratch.translate("imaginary of [x]"),
+ arguments: {
+ x: { type: "string", defaultValue: "1 + 2i" },
+ },
+ },
+ {
+ opcode: "isReal",
+ blockType: "Boolean",
+ text: Scratch.translate("is [x] a real number?"),
+ arguments: {
+ x: { type: "string", defaultValue: "i" },
+ },
+ },
+ "---",
+ {
+ opcode: "complexAdd",
+ blockType: "reporter",
+ text: Scratch.translate("[x] + [y]"),
+ arguments: {
+ x: { type: "string", defaultValue: " " },
+ y: { type: "string", defaultValue: " " },
+ },
+ },
+ {
+ opcode: "complexSub",
+ blockType: "reporter",
+ text: Scratch.translate("[x] - [y]"),
+ arguments: {
+ x: { type: "string", defaultValue: " " },
+ y: { type: "string", defaultValue: " " },
+ },
+ },
+ {
+ opcode: "complexMul",
+ blockType: "reporter",
+ text: Scratch.translate("[x] * [y]"),
+ arguments: {
+ x: { type: "string", defaultValue: " " },
+ y: { type: "string", defaultValue: " " },
+ },
+ },
+ {
+ opcode: "complexDiv",
+ blockType: "reporter",
+ text: Scratch.translate("[x] / [y]"),
+ arguments: {
+ x: { type: "string", defaultValue: " " },
+ y: { type: "string", defaultValue: " " },
+ },
+ },
+ {
+ opcode: "complexPow",
+ blockType: "reporter",
+ text: Scratch.translate("[x] ^ [y]"),
+ arguments: {
+ x: { type: "string", defaultValue: " " },
+ y: { type: "string", defaultValue: " " },
+ },
+ },
+ "---",
+ {
+ opcode: "complexOperation",
+ blockType: "reporter",
+ text: Scratch.translate("[oper] of [z]"),
+ arguments: {
+ oper: { type: "string", menu: "complexOper" },
+ z: { type: "string", defaultValue: "i + 1" },
+ },
+ },
+ {
+ opcode: "complexLog",
+ blockType: "reporter",
+ text: Scratch.translate("log base [n] of [z]"),
+ arguments: {
+ n: { type: "string", defaultValue: "10" },
+ z: { type: "string", defaultValue: "100" },
+ },
+ },
+ {
+ opcode: "complexMod",
+ blockType: "reporter",
+ text: Scratch.translate("[x] mod [y]"),
+ arguments: {
+ x: { type: "string", defaultValue: " " },
+ y: { type: "string", defaultValue: " " },
+ },
+ },
+ "---",
+ {
+ opcode: "toggleComplexAdvSyntax",
+ blockType: "command",
+ text: Scratch.translate("set syntax mode to [mode]"),
+ arguments: { mode: { type: "string", menu: "complexSyntaxMode" } },
+ },
+ {
+ opcode: "getComplexAdvSyntax",
+ blockType: "Boolean",
+ text: Scratch.translate("using advanced syntax?"),
+ },
+ ],
+ menus: {
+ complexOper: {
+ acceptReporters: false,
+ items: [
+ "abs",
+ "conjugate",
+ "flip",
+ "floor",
+ "ceiling",
+ "round",
+ "sqrt",
+ "sin",
+ "cos",
+ "tan",
+ "asin",
+ "acos",
+ "atan",
+ "atan2",
+ "ln",
+ "e^",
+ "10^",
+ "sign",
+ ],
+ },
+ complexSyntaxMode: {
+ acceptReporters: false,
+ items: ["simple (faster)", "advanced (slower)"],
+ },
+ },
+ };
+ }
+
+ /* add methods for blocks */
+ }
+ Scratch.extensions.register(new ScratchComplex());
+})(Scratch);
diff --git a/extensions/extensions.json b/extensions/extensions.json
index 9027c00ac9..51d948267c 100644
--- a/extensions/extensions.json
+++ b/extensions/extensions.json
@@ -1,100 +1,101 @@
-[
- // This file supports comments
- "lab/text",
- "stretch",
- "gamepad",
- "box2d",
- "files",
- "pointerlock",
- "cursor",
- "runtime-options",
- "fetch",
- "text",
- "local-storage",
- "true-fantom/base",
- "bitwise",
- "Skyhigh173/bigint",
- "utilities",
- "sound",
- "Lily/Video",
- "iframe",
- "Clay/htmlEncode",
- "Xeltalliv/clippingblending",
- "clipboard",
- "obviousAlexC/penPlus",
- "penplus",
- "Xeltalliv/simple3D",
- "Lily/Skins",
- "obviousAlexC/SensingPlus",
- "CubesterYT/KeySimulation",
- "Lily/ClonesPlus",
- "Lily/LooksPlus",
- "Lily/MoreEvents",
- "Lily/ListTools",
- "veggiecan/mobilekeyboard",
- "NexusKitten/moremotion",
- "CubesterYT/WindowControls",
- "veggiecan/browserfullscreen",
- "shreder95ua/resolution",
- "XmerOriginals/closecontrol",
- "navigator",
- "battery",
- "PwLDev/vibration",
- "TheShovel/CustomStyles",
- "TheShovel/ColorPicker",
- "NexusKitten/controlcontrols",
- "mdwalters/notifications",
- "XeroName/Deltatime",
- "ar",
- "encoding",
- "Lily/SoundExpanded",
- "Lily/TempVariables2",
- "Lily/MoreTimers",
- "clouddata-ping",
- "cloudlink",
- "true-fantom/network",
- "true-fantom/math",
- "true-fantom/regexp",
- "true-fantom/couplers",
- "Lily/AllMenus",
- "Lily/HackedBlocks",
- "Lily/Cast",
- "-SIPC-/time",
- "-SIPC-/consoles",
- "ZXMushroom63/searchApi",
- "TheShovel/ShovelUtils",
- "Lily/Assets",
- "SharkPool/Font-Manager",
- "DNin/wake-lock",
- "Skyhigh173/json",
- "mbw/xml",
- "numerical-encoding-2",
- "cs2627883/numericalencoding",
- "DT/cameracontrols",
- "TheShovel/CanvasEffects",
- "Longboost/color_channels",
- "CST1229/zip",
- "CST1229/images",
- "TheShovel/LZ-String",
- "0832/rxFS2",
- "NexusKitten/sgrab",
- "NOname-awa/graphics2d",
- "NOname-awa/more-comparisons",
- "JeremyGamer13/tween",
- "rixxyx",
- "Lily/lmsutils",
- "qxsck/data-analysis",
- "qxsck/var-and-list",
- "vercte/dictionaries",
- "godslayerakp/http",
- "godslayerakp/ws",
- "Lily/CommentBlocks",
- "veggiecan/LongmanDictionary",
- "CubesterYT/TurboHook",
- "Alestore/nfcwarp",
- "steamworks",
- "itchio",
- "gamejolt",
- "obviousAlexC/newgroundsIO",
- "Lily/McUtils" // McUtils should always be the last item.
-]
+[
+ // This file supports comments
+ "lab/text",
+ "stretch",
+ "gamepad",
+ "box2d",
+ "files",
+ "pointerlock",
+ "cursor",
+ "runtime-options",
+ "fetch",
+ "text",
+ "local-storage",
+ "true-fantom/base",
+ "bitwise",
+ "Skyhigh173/bigint",
+ "utilities",
+ "sound",
+ "Lily/Video",
+ "iframe",
+ "Clay/htmlEncode",
+ "Xeltalliv/clippingblending",
+ "clipboard",
+ "obviousAlexC/penPlus",
+ "penplus",
+ "Xeltalliv/simple3D",
+ "Lily/Skins",
+ "obviousAlexC/SensingPlus",
+ "CubesterYT/KeySimulation",
+ "Lily/ClonesPlus",
+ "Lily/LooksPlus",
+ "Lily/MoreEvents",
+ "Lily/ListTools",
+ "veggiecan/mobilekeyboard",
+ "NexusKitten/moremotion",
+ "CubesterYT/WindowControls",
+ "veggiecan/browserfullscreen",
+ "shreder95ua/resolution",
+ "XmerOriginals/closecontrol",
+ "navigator",
+ "battery",
+ "PwLDev/vibration",
+ "TheShovel/CustomStyles",
+ "TheShovel/ColorPicker",
+ "NexusKitten/controlcontrols",
+ "mdwalters/notifications",
+ "XeroName/Deltatime",
+ "ar",
+ "encoding",
+ "Lily/SoundExpanded",
+ "Lily/TempVariables2",
+ "Lily/MoreTimers",
+ "clouddata-ping",
+ "cloudlink",
+ "true-fantom/network",
+ "true-fantom/math",
+ "true-fantom/regexp",
+ "true-fantom/couplers",
+ "Lily/AllMenus",
+ "Lily/HackedBlocks",
+ "Lily/Cast",
+ "-SIPC-/time",
+ "-SIPC-/consoles",
+ "ZXMushroom63/searchApi",
+ "TheShovel/ShovelUtils",
+ "Lily/Assets",
+ "SharkPool/Font-Manager",
+ "DNin/wake-lock",
+ "Skyhigh173/json",
+ "mbw/xml",
+ "numerical-encoding-2",
+ "cs2627883/numericalencoding",
+ "DT/cameracontrols",
+ "TheShovel/CanvasEffects",
+ "Longboost/color_channels",
+ "CST1229/zip",
+ "CST1229/images",
+ "TheShovel/LZ-String",
+ "0832/rxFS2",
+ "NexusKitten/sgrab",
+ "NOname-awa/graphics2d",
+ "NOname-awa/more-comparisons",
+ "JeremyGamer13/tween",
+ "rixxyx",
+ "Lily/lmsutils",
+ "qxsck/data-analysis",
+ "qxsck/var-and-list",
+ "vercte/dictionaries",
+ "godslayerakp/http",
+ "godslayerakp/ws",
+ "Lily/CommentBlocks",
+ "veggiecan/LongmanDictionary",
+ "CubesterYT/TurboHook",
+ "Alestore/nfcwarp",
+ "steamworks",
+ "itchio",
+ "gamejolt",
+ "obviousAlexC/newgroundsIO",
+ "BonesYT/ScratchComplex",
+ "Lily/McUtils" // McUtils should always be the last item.
+]
diff --git a/images/BonesYT/ScratchComplex.svg b/images/BonesYT/ScratchComplex.svg
new file mode 100644
index 0000000000..b2ad18753a
--- /dev/null
+++ b/images/BonesYT/ScratchComplex.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
From a0cc35f79e1e376d0dc1df7e9b19404040154208 Mon Sep 17 00:00:00 2001
From: BonesYT <63462200+BonesYT@users.noreply.github.com>
Date: Sat, 11 Jan 2025 12:40:03 -0300
Subject: [PATCH 2/5] add scratch complex
---
extensions/BonesYT/ScratchComplex.js | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/extensions/BonesYT/ScratchComplex.js b/extensions/BonesYT/ScratchComplex.js
index bbca552dc4..617f6371c3 100644
--- a/extensions/BonesYT/ScratchComplex.js
+++ b/extensions/BonesYT/ScratchComplex.js
@@ -52,12 +52,13 @@
: { r: +part, i: 0 };
} else {
const sign = input.match(/(? v.replace("p", "e+").replace("m", "e-"));
- return { r: +parts[0], i: +parts[1] * sign };
+ return { r: +parts[0] * (reversed ? sign : 1), i: +parts[1] * (reversed ? 1 : sign) };
}
} else {
const parts = input.split(",");
From 14dc0ad26f5e32ce08405d08fcc94d22d59c73c5 Mon Sep 17 00:00:00 2001
From: BonesYT <63462200+BonesYT@users.noreply.github.com>
Date: Sat, 11 Jan 2025 16:11:25 -0300
Subject: [PATCH 3/5] fixed a tiny bug
---
extensions/BonesYT/ScratchComplex.js | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/extensions/BonesYT/ScratchComplex.js b/extensions/BonesYT/ScratchComplex.js
index 617f6371c3..480e70719a 100644
--- a/extensions/BonesYT/ScratchComplex.js
+++ b/extensions/BonesYT/ScratchComplex.js
@@ -52,13 +52,16 @@
: { r: +part, i: 0 };
} else {
const sign = input.match(/(? v.replace("p", "e+").replace("m", "e-"));
- return { r: +parts[0] * (reversed ? sign : 1), i: +parts[1] * (reversed ? 1 : sign) };
+ return {
+ r: +parts[0] * (reversed ? sign : 1),
+ i: +parts[1] * (reversed ? 1 : sign),
+ };
}
} else {
const parts = input.split(",");
@@ -464,4 +467,4 @@
/* add methods for blocks */
}
Scratch.extensions.register(new ScratchComplex());
-})(Scratch);
+})(Scratch);
\ No newline at end of file
From ca7c3492bdeae805438672157b8da34e41f4e7e6 Mon Sep 17 00:00:00 2001
From: BonesYT <63462200+BonesYT@users.noreply.github.com>
Date: Sat, 11 Jan 2025 16:16:41 -0300
Subject: [PATCH 4/5] fixed a tiny bug
---
extensions/BonesYT/ScratchComplex.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/extensions/BonesYT/ScratchComplex.js b/extensions/BonesYT/ScratchComplex.js
index 480e70719a..92b22f7686 100644
--- a/extensions/BonesYT/ScratchComplex.js
+++ b/extensions/BonesYT/ScratchComplex.js
@@ -467,4 +467,4 @@
/* add methods for blocks */
}
Scratch.extensions.register(new ScratchComplex());
-})(Scratch);
\ No newline at end of file
+})(Scratch);
From 0c38071cde1f6f1a2912b231951b1cb1a49a3d12 Mon Sep 17 00:00:00 2001
From: BonesYT <63462200+BonesYT@users.noreply.github.com>
Date: Sun, 12 Jan 2025 13:58:51 -0300
Subject: [PATCH 5/5] solved e^, 10^ and sqrt returning only NaN
---
extensions/BonesYT/ScratchComplex.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/extensions/BonesYT/ScratchComplex.js b/extensions/BonesYT/ScratchComplex.js
index 92b22f7686..db7ef2c607 100644
--- a/extensions/BonesYT/ScratchComplex.js
+++ b/extensions/BonesYT/ScratchComplex.js
@@ -177,16 +177,19 @@
out = [Math.round(r), Math.round(i)];
break;
case "sqrt":
- out = this.pow(z, { r: 0.5, i: 0 });
+ alt = this.pow(z, { r: 0.5, i: 0 });
+ out = [alt.r, alt.i];
break;
case "atan2":
out = [Math.atan2(i, r), 0];
break;
case "e^":
- out = this.pow({ r: Math.E, i: 0 }, z);
+ alt = this.pow({ r: Math.E, i: 0 }, z);
+ out = [alt.r, alt.i];
break;
case "10^":
- out = this.pow({ r: 10, i: 0 }, z);
+ alt = this.pow({ r: 10, i: 0 }, z);
+ out = [alt.r, alt.i];
break;
case "sign":
out = [Math.sign(r), Math.sign(i)];