diff --git a/README.md b/README.md deleted file mode 100644 index 8b750b5a4b..0000000000 --- a/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# TurboWarp Extension Gallery - -User-contributed unsandboxed extension gallery for TurboWarp. - -https://extensions.turbowarp.org/ - -## Contributing - -See [CONTRIBUTING.md](CONTRIBUTING.md). - -## License - -Extensions (in the `extensions` folder) will have a comment at the top of the file describing the license for the code. In the past [MIT](./licenses/MIT.txt) was the default, however now [MPL-2.0](./licenses/MPL-2.0.txt) is recommended. Some extensions may contain a mix of several. - -Sample projects (in the `samples` folder) are licensed under [CC-BY 4.0](./licenses/CC-BY-4.0.txt). - -Everything else, such as the extension images, development server, and website are licensed under the [GNU General Public License version 3](licenses/GPL-3.0.txt). - -See [images/README.md](images/README.md) for attribution information for each image. diff --git a/extensions/NexusKitten/moremotion.js b/extensions/NexusKitten/moremotion.js index b1324ec0a8..a6e597ed68 100644 --- a/extensions/NexusKitten/moremotion.js +++ b/extensions/NexusKitten/moremotion.js @@ -242,6 +242,177 @@ }, extensions: ["colours_motion"], }, + "---", + { + filter: [Scratch.TargetType.SPRITE], + opcode: "turnRight", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("turn right [SPRITE] [DEG] degrees [MODE]"), + arguments: { + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + DEG: { type: Scratch.ArgumentType.NUMBER, defaultValue: 15 }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "turnLeft", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("turn left [SPRITE] [DEG] degrees [MODE]"), + arguments: { + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + DEG: { type: Scratch.ArgumentType.NUMBER, defaultValue: 15 }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "goToXY", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("go to x [X] y [Y] for [SPRITE] [MODE]"), + arguments: { + X: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }, + Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }, + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "changeX", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("change x by [DX] for [SPRITE] [MODE]"), + arguments: { + DX: { type: Scratch.ArgumentType.NUMBER, defaultValue: 10 }, + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "changeY", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("change y by [DY] for [SPRITE] [MODE]"), + arguments: { + DY: { type: Scratch.ArgumentType.NUMBER, defaultValue: 10 }, + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "setX", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("set x to [X] for [SPRITE] [MODE]"), + arguments: { + X: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }, + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "setY", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("set y to [Y] for [SPRITE] [MODE]"), + arguments: { + Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 }, + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "pointDirection", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate( + "point in direction [DIR] for [SPRITE] [MODE]" + ), + arguments: { + DIR: { type: Scratch.ArgumentType.ANGLE, defaultValue: 90 }, + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, + { + filter: [Scratch.TargetType.SPRITE], + opcode: "rotationStylePlus", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate( + "set rotation style [STYLE] for [SPRITE] [MODE]" + ), + arguments: { + STYLE: { + type: Scratch.ArgumentType.STRING, + menu: "menuRotation", + }, + SPRITE: { + type: Scratch.ArgumentType.STRING, + menu: "menuSprites", + }, + MODE: { + type: Scratch.ArgumentType.STRING, + menu: "menuCloneMode", + }, + }, + extensions: ["colours_motion"], + }, ], menus: { WHAT: { @@ -265,6 +436,18 @@ }, ], }, + menuSprites: { + acceptReporters: false, + items: "getSpriteNames", + }, + menuCloneMode: { + acceptReporters: false, + items: "getCloneModes", + }, + menuRotation: { + acceptReporters: false, + items: ["left-right", "don't rotate", "all around"], + }, }, }; } @@ -444,6 +627,81 @@ } } } + + // Motion++ helper methods + getSpriteNames() { + return Scratch.vm.runtime.targets + .filter((t) => t.isSprite && !t.isStage) + .map((t) => t.sprite.name); + } + + getCloneModes() { + return ["sprite only", "clone included"]; + } + + _getTargets(name, mode) { + const runtime = Scratch.vm.runtime; + return runtime.targets.filter( + (t) => + t.isSprite && + !t.isStage && + t.sprite.name === name && + (mode === "clone included" || !t.isClone) + ); + } + + turnRight(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) t.setDirection(t.direction + args.DEG); + } + + turnLeft(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) t.setDirection(t.direction - args.DEG); + } + + goToXY(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) t.setXY(args.X, args.Y); + } + + changeX(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) { + const newX = t.x + args.DX; + const newY = t.y; + t.setXY(newX, newY); + } + } + + changeY(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) { + const newX = t.x; + const newY = t.y + args.DY; + t.setXY(newX, newY); + } + } + + setX(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) t.setXY(args.X, t.y); + } + + setY(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) t.setXY(t.x, args.Y); + } + + pointDirection(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) t.setDirection(args.DIR); + } + + rotationStylePlus(args) { + const targets = this._getTargets(args.SPRITE, args.MODE); + for (const t of targets) t.setRotationStyle(args.STYLE); + } } Scratch.extensions.register(new nkmoremotion());