Skip to content
Merged
Changes from all commits
Commits
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
73 changes: 33 additions & 40 deletions extensions/lab/video-sprites.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Name: Video sprites
// Name: Video Sprites
// ID: videoSprites
// Description: Replace sprites with a live video feed. Compatible with Scratch Lab's Animated Text experiment.
// By: Staevski_G <https://scratch.mit.edu/users/Staevski_G/>
Expand Down Expand Up @@ -115,7 +115,7 @@
* @returns {boolean} true if a frame was drawn
*/
const sampleVideoToWorkCanvas = (width, height, zoom) => {
const videoCanvas = videoDevice.getFrame({

Check warning on line 118 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Property 'getFrame' does not exist on type 'Video'.
format: "canvas",
});

Expand All @@ -125,8 +125,7 @@

const videoWidth = videoCanvas.width;
const videoHeight = videoCanvas.height;
const upscaleFactor =
width > height ? videoWidth / width : videoHeight / height;
const upscaleFactor = Math.min(videoWidth / width, videoHeight / height);
const zoomFactor = zoom / 100;
const cropWidth = (width * upscaleFactor) / zoomFactor;
const cropHeight = (height * upscaleFactor) / zoomFactor;
Expand Down Expand Up @@ -186,8 +185,11 @@
/** @type {import('scratch-vm').Target} */
this.target = target;

/** @type {boolean} */
this._useParentTexture = false;
/**
* Cached image data to reduce unnecessary allocations
* @type {Uint8ClampedArray|null}
*/
this._outData = null;
}

dispose() {
Expand All @@ -206,11 +208,7 @@
return renderer._allSkins[costume.skinId] || null;
}

_renderAsParent() {
this._useParentTexture = true;
}

get size() {

Check warning on line 211 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Property 'size' in type 'VideoSpriteSkin' is not assignable to the same property in base type 'Skin'. Type 'number[]' is not assignable to type '[number, number]'. Target requires 2 element(s) but source may have fewer.
const parent = this._getParentSkin();
return parent ? parent.size : [0, 0];
}
Expand All @@ -228,47 +226,35 @@
updateSilhouette(scale) {
const parent = this._getParentSkin();
if (parent) {
parent.updateSilhouette(scale);

Check warning on line 229 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Expected 0 arguments, but got 1.
this._silhouette = parent._silhouette;
}
}

_getParentTexture(scale) {
return (
this._getParentSkin()?.getTexture(scale) || super.getTexture(scale)
);
}

getTexture(scale) {
// Re-render the parent at current scale so that we can get the most accurate silhouette
const parentTexture = this._getParentTexture(scale);
const parent = this._getParentSkin();
const parentTexture = parent?.getTexture(scale);

this._render();

if (parent && this._useParentTexture) {
return parentTexture;
}
return this._texture || super.getTexture(scale);
}

_render() {
const state = getState(this.target);
if (!state) {
this._renderAsParent();
return;
}

const parent = this._getParentSkin();
if (!parent) {
this._renderAsParent();
return;
if (!state || !parent) {
return parentTexture;
}

parent.updateSilhouette();
parent.updateSilhouette(scale);

Check warning on line 249 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Expected 0 arguments, but got 1.
const silhouette = parent._silhouette;
this._silhouette = silhouette;

const silhouetteData = silhouette._colorData;
const width = silhouette._width;
const height = silhouette._height;
const silhouetteData = silhouette?._colorData;
const width = silhouette?._width;
const height = silhouette?._height;
if (!width || !height || !silhouetteData) {
this._renderAsParent();
return;
return parentTexture;
}

if (workCanvas.width !== width || workCanvas.height !== height) {
Expand All @@ -277,26 +263,31 @@
}

if (!sampleVideoToWorkCanvas(width, height, state.zoom)) {
this._useParentTexture = true;
return;
return parentTexture;
}

this._useParentTexture = false;

const sampledVideoData = workContext.getImageData(
0,
0,
width,
height
).data;
const outData = new Uint8ClampedArray(silhouetteData.length);

if (!this._outData || this._outData.length !== silhouetteData.length) {
this._outData = new Uint8ClampedArray(silhouetteData.length);
}
const outData = this._outData;

const isMask = state.mode === "mask";
const maskColor = state.maskColor;

for (let i = 0; i < silhouetteData.length; i += 4) {
const parentA = silhouetteData[i + 3];
if (parentA === 0) {
outData[i] = 0;
outData[i + 1] = 0;
outData[i + 2] = 0;
outData[i + 3] = 0;
continue;
}

Expand Down Expand Up @@ -329,7 +320,7 @@
}

if (!this._texture) {
this._texture = twgl.createTexture(gl, {

Check warning on line 323 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Property 'createTexture' does not exist on type 'object'.
auto: false,
wrap: gl.CLAMP_TO_EDGE,
});
Expand All @@ -344,9 +335,11 @@
gl.RGBA,
gl.RGBA,
gl.UNSIGNED_BYTE,
new ImageData(outData, width, height)

Check warning on line 338 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

No overload matches this call. Overload 1 of 2, '(sw: number, sh: number, settings?: ImageDataSettings): ImageData', gave the following error. Argument of type 'Uint8ClampedArray<ArrayBufferLike>' is not assignable to parameter of type 'number'. Overload 2 of 2, '(data: ImageDataArray, sw: number, sh?: number, settings?: ImageDataSettings): ImageData', gave the following error. Argument of type 'Uint8ClampedArray<ArrayBufferLike>' is not assignable to parameter of type 'ImageDataArray'. Type 'ArrayBufferLike' is not assignable to type 'ArrayBuffer'. Type 'SharedArrayBuffer' is not assignable to type 'ArrayBuffer'. Types of property '[Symbol.toStringTag]' are incompatible. Type '"SharedArrayBuffer"' is not assignable to type '"ArrayBuffer"'.
);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);

return this._texture;
}
}

Expand All @@ -358,7 +351,7 @@
if (!state.skin) {
const id = renderer._nextSkinId++;
state.skin = new VideoSpriteSkin(id, target);
renderer._allSkins[id] = state.skin;

Check warning on line 354 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Type 'VideoSpriteSkin' is not assignable to type 'Skin'. Types of property 'size' are incompatible. Type 'number[]' is not assignable to type '[number, number]'. Target requires 2 element(s) but source may have fewer.
}

renderer.updateDrawableSkinId(target.drawableID, state.skin.id);
Expand Down Expand Up @@ -401,10 +394,10 @@
let hidPreview = false;
const ensureCamera = async () => {
try {
await videoDevice.enableVideo();

Check warning on line 397 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Property 'enableVideo' does not exist on type 'Video'.
if (!hidPreview) {
hidPreview = true;
videoDevice.setPreviewGhost(100);

Check warning on line 400 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

Property 'setPreviewGhost' does not exist on type 'Video'.
}
return true;
} catch (error) {
Expand All @@ -425,7 +418,7 @@

// If another script override the costume, switch it back to the video sprite one.
const drawable = renderer._allDrawables[target.drawableID];
if (drawable && drawable.skin !== skin) {

Check warning on line 421 in extensions/lab/video-sprites.js

View workflow job for this annotation

GitHub Actions / type-warnings

Type warning - may indicate a bug - ignore if no bug

This comparison appears to be unintentional because the types 'Skin' and 'VideoSpriteSkin' have no overlap.
renderer.updateDrawableSkinId(target.drawableID, skin.id);
}

Expand Down
Loading