Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Extension: MIDI #1637

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
07e686d
Update extensions.json
Brackets-Coder Jul 31, 2024
c1a3459
Create midi.js
Brackets-Coder Jul 31, 2024
5564b7a
Create midi.svg
Brackets-Coder Jul 31, 2024
551301d
Add midi.svg
Brackets-Coder Jul 31, 2024
4095018
Delete images/MasterMath/midi.svg
Brackets-Coder Jul 31, 2024
9b9ef60
Create midi.png
Brackets-Coder Jul 31, 2024
9d67ff5
Add midi.png
Brackets-Coder Jul 31, 2024
97d8cd5
Update midi.png
Brackets-Coder Jul 31, 2024
3cddad7
Update midi.js
Brackets-Coder Jul 31, 2024
5f438a9
Update midi.js
Brackets-Coder Jul 31, 2024
f28a68d
Update midi.js
Brackets-Coder Aug 1, 2024
44ad6f2
Lily/LooksPlus: Optimize restore content block (#1638)
GarboMuffin Aug 5, 2024
eafceab
encoding: Fix unicode base64 encode/decode (#1599)
Procybit Aug 5, 2024
3ce22a6
Skyhigh173/JSON: fix json_is_valid() (#1596)
Procybit Aug 5, 2024
ea67bd8
Update translations (#1641)
GarboMuffin Aug 5, 2024
532daff
Lily/Video: clamp volume, add screenshot at current time (#1595)
SharkPool-SP Aug 6, 2024
dfb5354
Lily/Video: playback rate (#1642)
GarboMuffin Aug 6, 2024
23e5c1a
Lily/Assets: fix addCostume corruption (#1643)
GarboMuffin Aug 6, 2024
5499be0
vercte/dictionaries: Always Cast Keys to Strings (#1644)
SharkPool-SP Aug 10, 2024
d228f60
mbw/xml: fix bugs, add inner HTML blocks (#1647)
mybearworld Aug 13, 2024
ba73df3
Attempt to fix prettier format
Brackets-Coder Aug 17, 2024
ee34483
build(deps-dev): bump eslint from 9.8.0 to 9.9.0 (#1646)
dependabot[bot] Aug 19, 2024
9edfed5
build(deps): bump adm-zip from 0.5.14 to 0.5.15 (#1645)
dependabot[bot] Aug 19, 2024
263033c
Xeltalliv/clippingblending: Fix compatibility with instanced pen rend…
Xeltalliv Aug 21, 2024
f0d4e9e
build(deps-dev): bump eslint from 9.9.0 to 9.9.1 (#1659)
dependabot[bot] Aug 26, 2024
2646607
build(deps): bump adm-zip from 0.5.15 to 0.5.16 (#1668)
dependabot[bot] Sep 2, 2024
8f81856
veggiecan/LongmanDictionary: fix all defs returning array instead of …
GarboMuffin Sep 7, 2024
2ad97a9
Fix format
Brackets-Coder Sep 14, 2024
f1f30a2
Fix format again?
Brackets-Coder Sep 14, 2024
a834058
Lily/Video: fix videos rendering as pure black (#1692)
GarboMuffin Sep 20, 2024
7e91056
build(deps-dev): bump eslint from 9.9.1 to 9.12.0 (#1713)
dependabot[bot] Oct 7, 2024
d689cbc
build(deps): bump express from 4.19.2 to 4.21.0 (#1687)
dependabot[bot] Oct 7, 2024
363e5fb
Lily/Skins: fix `delete all skins` not deleting the renderer skins (#…
CST1229 Oct 11, 2024
d21f029
build(deps): bump express from 4.21.0 to 4.21.1 (#1722)
dependabot[bot] Oct 14, 2024
b58a62e
Revert "fix: downloadBlob isn't working properly on some old browsers…
FurryR Oct 14, 2024
33afff0
Edit some paragraphs on the homepage (#1660)
DNin01 Oct 14, 2024
3cc3b2c
Update extensions.json
Brackets-Coder Jul 31, 2024
db0a95b
Create midi.js
Brackets-Coder Jul 31, 2024
b7a979e
Create midi.svg
Brackets-Coder Jul 31, 2024
b612c45
Add midi.svg
Brackets-Coder Jul 31, 2024
70fcbd7
Delete images/MasterMath/midi.svg
Brackets-Coder Jul 31, 2024
4bb421d
Create midi.png
Brackets-Coder Jul 31, 2024
73d77f8
Add midi.png
Brackets-Coder Jul 31, 2024
f07a7bb
Update midi.png
Brackets-Coder Jul 31, 2024
517f1dd
Update midi.js
Brackets-Coder Jul 31, 2024
2faa7c7
Update midi.js
Brackets-Coder Jul 31, 2024
f562dee
Update midi.js
Brackets-Coder Aug 1, 2024
b4f91c4
Attempt to fix prettier format
Brackets-Coder Aug 17, 2024
554ac50
Fix format
Brackets-Coder Sep 14, 2024
6b4d6c9
Fix format again?
Brackets-Coder Sep 14, 2024
79aa132
Merge branch 'master' of https://github.com/Brackets-Coder/extensions
Brackets-Coder Oct 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions development/homepage-template.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -258,21 +258,19 @@
<div>TurboWarp Extension Gallery</div>
</h1>

<p>Unlike custom extensions on other websites, these aren't limited by the extension sandbox, so they are a lot more powerful. All extensions are reviewed for safety.</p>
<p>
To use multiple of these extensions in TurboWarp, hover over the extension and press the button to copy its URL. Then go to the editor, open the extension chooser, then choose the "Custom Extension" option at the bottom, and enter the URL.
</p>
<p>This is the official extension gallery, where you can get extensions that aren't limited by the extension sandbox. All of the extensions here are reviewed for safety.</p>
<p>You can also find these extensions in TurboWarp's "Add Extension" menu.</p>

<div class="infobox infobox-warning">
<div class="infobox-title">These extensions are not compatible with Scratch.</div>
Projects that use these extensions can't be uploaded to the Scratch website.
They can, however, be used in <a href="https://packager.turbowarp.org/">the packager</a>.
Projects that use these extensions can't be opened in Scratch or uploaded to the Scratch website.
They can still be used in <a href="https://packager.turbowarp.org/">the TurboWarp packager</a>.
</div>

<div class="infobox">
<div class="infobox-title">Some extensions may not work in TurboWarp Desktop.</div>
For compatibility, security, and offline support, each <a href="https://desktop.turbowarp.org/">TurboWarp Desktop</a> update contains an offline copy of these extensions from its release date, so some extensions may be outdated or missing.
Use the latest update for best results.
To make sure extensions work offline, each release of <a href="https://desktop.turbowarp.org/">TurboWarp Desktop</a> comes with a copy of these extensions as of its release date, so some extensions may be outdated or missing.
Update to the latest version for the best results.
</div>
</div>

Expand Down
8 changes: 7 additions & 1 deletion extensions/Lily/Assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,14 @@
const assetType = this._typeIsBitmap(blob.type)
? runtime.storage.AssetType.ImageBitmap
: runtime.storage.AssetType.ImageVector;

// Bitmap data format is not actually enforced, but setting it to something that isn't in scratch-parser's
// known format list will throw an error when someone tries to load the project.
// (https://github.com/scratchfoundation/scratch-parser/blob/665f05d739a202d565a4af70a201909393d456b2/lib/sb3_definitions.json#L51)
const dataType =
blob.type === "image/svg+xml" ? "svg" : blob.type.split("/")[1];
blob.type === "image/svg+xml"
? runtime.storage.DataFormat.SVG
: runtime.storage.DataFormat.PNG;

const arrayBuffer = await new Promise((resolve, reject) => {
const fr = new FileReader();
Expand Down
48 changes: 31 additions & 17 deletions extensions/Lily/LooksPlus.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
return util.runtime.getSpriteTargetByName(nameString);
};

const renderer = Scratch.vm.runtime.renderer;

class LooksPlus {
getInfo() {
return {
Expand Down Expand Up @@ -380,7 +382,7 @@
const drawableID = target.drawableID;
const layerOrder = target.getLayerOrder();
const newLayer = args.LAYER - layerOrder;
target.renderer.setDrawableOrder(drawableID, newLayer, "sprite", true);
renderer.setDrawableOrder(drawableID, newLayer, "sprite", true);
}

spriteLayerNumber(args, util) {
Expand Down Expand Up @@ -442,7 +444,7 @@

snapshotStage(args, util) {
return new Promise((resolve) => {
Scratch.vm.runtime.renderer.requestSnapshot((uri) => {
renderer.requestSnapshot((uri) => {
resolve(uri);
});
});
Expand All @@ -467,15 +469,18 @@
const contentType = args.TYPE;
const content = args.CONTENT;
if (contentType === "SVG") {
Scratch.vm.runtime.renderer.updateSVGSkin(
costume.skinId,
Scratch.Cast.toString(content)
);
try {
renderer.updateSVGSkin(
costume.skinId,
Scratch.Cast.toString(content)
);
renderer._allSkins[costume.skinId].differsFromAsset = true;
} catch (e) {
console.error(e);
}
} else {
console.error("Options other than SVG are currently unavailable");
return;
}
Scratch.vm.emitTargetsUpdate();
}

restoreCostumeContent(args, util) {
Expand All @@ -490,21 +495,30 @@
return;
}

//This is here to ensure no changes are made to bitmap costumes, as changes are irreversible
//Check will be removed when it's possible to edit bitmap skins
// This is here to ensure no changes are made to bitmap costumes, as changes are irreversible
// Check will be removed when it's possible to edit bitmap skins
const format = costume.asset.assetType.runtimeFormat;
if (format !== "svg") {
console.error("Costume is not vector");
return;
}

const content = costume.asset.decodeText();
const rotationCenterX = costume.rotationCenterX;
const rotationCenterY = costume.rotationCenterY;
util.target.renderer.updateSVGSkin(costume.skinId, content, [
rotationCenterX,
rotationCenterY,
]);
if (!renderer._allSkins[costume.skinId].differsFromAsset) {
return;
}

try {
const content = costume.asset.decodeText();
const rotationCenterX = costume.rotationCenterX;
const rotationCenterY = costume.rotationCenterY;
renderer.updateSVGSkin(costume.skinId, content, [
rotationCenterX,
rotationCenterY,
]);
renderer._allSkins[costume.skinId].differsFromAsset = false;
} catch (e) {
console.error(e);
}
}

costumeContent(args, util) {
Expand Down
8 changes: 4 additions & 4 deletions extensions/Lily/Skins.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
const renderer = runtime.renderer;
const Cast = Scratch.Cast;

var createdSkins = [];
var createdSkins = {};

class Skins {
constructor() {
Expand Down Expand Up @@ -371,9 +371,9 @@

deleteAllSkins() {
this._refreshTargets();
for (let i = 0; i < createdSkins.length; i++)
renderer.destroySkin(createdSkins[i]);
createdSkins = [];
for (const skinName in createdSkins)
renderer.destroySkin(createdSkins[skinName]);
createdSkins = {};
}

restoreTargets(args) {
Expand Down
97 changes: 96 additions & 1 deletion extensions/Lily/Video.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// ID: lmsVideo
// Description: Play videos from URLs.
// By: LilyMakesThings <https://scratch.mit.edu/users/LilyMakesThings/>
// By: SharkPool
// License: MIT AND LGPL-3.0

// Attribution is not required, but greatly appreciated.
Expand All @@ -14,6 +15,21 @@
const renderer = vm.renderer;
const Cast = Scratch.Cast;

// In some versions of Chrome, it seems that trying to render a <video> returns pure black
// if it's not in the DOM in a place the browser thinks is visible. That means we can't
// use display: none.
// See https://github.com/TurboWarp/scratch-render/issues/12
const elementContainer = document.createElement("div");
elementContainer.className = "tw-extensions-lily-videos-container";
elementContainer.style.pointerEvents = "none";
elementContainer.style.position = "absolute";
elementContainer.style.opacity = "0";
elementContainer.style.width = "0";
elementContainer.style.height = "0";
elementContainer.style.visibility = "hidden";
elementContainer.ariaHidden = "true";
document.body.appendChild(elementContainer);

const BitmapSkin = runtime.renderer.exports.BitmapSkin;
class VideoSkin extends BitmapSkin {
constructor(id, renderer, videoName, videoSrc) {
Expand Down Expand Up @@ -49,6 +65,10 @@
this.videoElement.src = videoSrc;
this.videoElement.currentTime = 0;

// <video> must be in the DOM for it to render (see comments above)
elementContainer.appendChild(this.videoElement);
this.videoElement.tabIndex = -1;

this.videoDirty = true;

this.reuploadVideo();
Expand Down Expand Up @@ -105,6 +125,7 @@
dispose() {
super.dispose();
this.videoElement.pause();
this.videoElement.remove();
}
}

Expand Down Expand Up @@ -239,6 +260,19 @@
},
},
},
{
opcode: "getFrame",
blockType: Scratch.BlockType.REPORTER,
text: Scratch.translate(
"screenshot of video [NAME] at current time"
),
arguments: {
NAME: {
type: Scratch.ArgumentType.STRING,
defaultValue: "my video",
},
},
},
"---",
{
opcode: "pause",
Expand Down Expand Up @@ -293,6 +327,23 @@
},
},
},
{
opcode: "setPlaybackRate",
blockType: Scratch.BlockType.COMMAND,
text: Scratch.translate(
"set playback rate of video [NAME] to [RATE]"
),
arguments: {
NAME: {
type: Scratch.ArgumentType.STRING,
defaultValue: "my video",
},
RATE: {
type: Scratch.ArgumentType.NUMBER,
defaultValue: "2",
},
},
},
],
menus: {
targets: {
Expand Down Expand Up @@ -335,6 +386,10 @@
text: Scratch.translate("height"),
value: "height",
},
{
text: Scratch.translate("playback rate"),
value: "playback rate",
},
],
},
},
Expand Down Expand Up @@ -461,11 +516,36 @@
return videoSkin.size[0];
case "height":
return videoSkin.size[1];
case "playback rate":
return videoSkin.videoElement.playbackRate;
default:
return 0;
}
}

getFrame(args) {
const videoName = Cast.toString(args.NAME);
const videoSkin = this.videos[videoName];
if (!videoSkin) return "";

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
if (!ctx) {
console.warn("2D rendering context not available");
return "";
}

const videoElement = videoSkin.videoElement;
if (videoElement.videoWidth === 0 || videoElement.videoHeight === 0) {
return "";
}

canvas.width = videoElement.videoWidth;
canvas.height = videoElement.videoHeight;
ctx.drawImage(videoElement, 0, 0);
return canvas.toDataURL();
}

pause(args) {
const videoName = Cast.toString(args.NAME);
const videoSkin = this.videos[videoName];
Expand Down Expand Up @@ -496,11 +576,26 @@

setVolume(args) {
const videoName = Cast.toString(args.NAME);
const videoSkin = this.videos[videoName];
if (!videoSkin) return;

const value = Cast.toNumber(args.VALUE);
videoSkin.videoElement.volume = Math.min(1, Math.max(0, value / 100));
}

setPlaybackRate(args) {
const videoName = Cast.toString(args.NAME);
const videoSkin = this.videos[videoName];
if (!videoSkin) return;

videoSkin.videoElement.volume = value / 100;
try {
const value = Cast.toNumber(args.RATE);
// Supposedly negative values will work in Safari but people probably shouldn't rely
// on that since others don't.
videoSkin.videoElement.playbackRate = Math.max(0, value);
} catch (e) {
console.warn(e);
}
}

/** @returns {VM.Target|undefined} */
Expand Down
11 changes: 5 additions & 6 deletions extensions/Lily/lmsutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1356,14 +1356,13 @@

setSpriteSVG(args, util) {
try {
Scratch.vm.runtime.renderer.updateSVGSkin(
util.target.sprite.costumes[args.INPUTA - 1].skinId,
args.INPUTB
);
const skinId = util.target.sprite.costumes[args.INPUTA - 1].skinId;
const renderer = Scratch.vm.runtime.renderer;
renderer.updateSVGSkin(skinId, Scratch.Cast.toString(args.INPUTB));
renderer._allSkins[skinId].differsFromAsset = true;
} catch (error) {
return;
console.error(error);
}
Scratch.vm.emitTargetsUpdate();
}

alertBlock(args) {
Expand Down
Loading
Loading