Skip to content

Commit 07d0d48

Browse files
authored
Merge branch 'develop' into effect-transform-optimizations
2 parents 6aab070 + 13b9ed7 commit 07d0d48

File tree

13 files changed

+266
-175
lines changed

13 files changed

+266
-175
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"minilog": "3.1.0",
5454
"raw-loader": "^0.5.1",
5555
"scratch-storage": "^1.0.0",
56-
"scratch-svg-renderer": "0.2.0-prerelease.20190523193400",
56+
"scratch-svg-renderer": "0.2.0-prerelease.20190822202608",
5757
"twgl.js": "4.4.0"
5858
}
5959
}

src/BitmapSkin.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ class BitmapSkin extends Skin {
2323

2424
/** @type {Array<int>} */
2525
this._textureSize = [0, 0];
26-
27-
/**
28-
* The "native" size, in texels, of this skin.
29-
* @type {Array<number>}
30-
*/
31-
this.size = [0, 0];
3226
}
3327

3428
/**
@@ -49,6 +43,13 @@ class BitmapSkin extends Skin {
4943
return true;
5044
}
5145

46+
/**
47+
* @return {Array<number>} the "native" size, in texels, of this skin.
48+
*/
49+
get size () {
50+
return [this._textureSize[0] / this._costumeResolution, this._textureSize[1] / this._costumeResolution];
51+
}
52+
5253
/**
5354
* @param {Array<number>} scale - The scaling factors to be used.
5455
* @return {WebGLTexture} The GL texture representation of this skin when drawing at the given scale.
@@ -109,7 +110,6 @@ class BitmapSkin extends Skin {
109110
// Do these last in case any of the above throws an exception
110111
this._costumeResolution = costumeResolution || 2;
111112
this._textureSize = BitmapSkin._getBitmapSize(bitmapData);
112-
this.size = [this._textureSize[0] / this._costumeResolution, this._textureSize[1] / this._costumeResolution];
113113

114114
if (typeof rotationCenter === 'undefined') rotationCenter = this.calculateRotationCenter();
115115
this.setRotationCenter.apply(this, rotationCenter);

src/Drawable.js

Lines changed: 98 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const twgl = require('twgl.js');
33
const Rectangle = require('./Rectangle');
44
const RenderConstants = require('./RenderConstants');
55
const ShaderManager = require('./ShaderManager');
6+
const Skin = require('./Skin');
67
const EffectTransform = require('./EffectTransform');
78

89
/**
@@ -108,6 +109,8 @@ class Drawable {
108109
/** @todo move convex hull functionality, maybe bounds functionality overall, to Skin classes */
109110
this._convexHullPoints = null;
110111
this._convexHullDirty = true;
112+
113+
this._skinWasAltered = this._skinWasAltered.bind(this);
111114
}
112115

113116
/**
@@ -146,7 +149,13 @@ class Drawable {
146149
*/
147150
set skin (newSkin) {
148151
if (this._skin !== newSkin) {
152+
if (this._skin) {
153+
this._skin.removeListener(Skin.Events.WasAltered, this._skinWasAltered);
154+
}
149155
this._skin = newSkin;
156+
if (this._skin) {
157+
this._skin.addListener(Skin.Events.WasAltered, this._skinWasAltered);
158+
}
150159
this._skinWasAltered();
151160
}
152161
}
@@ -176,55 +185,98 @@ class Drawable {
176185
}
177186

178187
/**
179-
* Update the position, direction, scale, or effect properties of this Drawable.
180-
* @param {object.<string,*>} properties The new property values to set.
188+
* Update the position if it is different. Marks the transform as dirty.
189+
* @param {Array.<number>} position A new position.
181190
*/
182-
updateProperties (properties) {
183-
let dirty = false;
184-
if ('position' in properties && (
185-
this._position[0] !== properties.position[0] ||
186-
this._position[1] !== properties.position[1])) {
187-
this._position[0] = Math.round(properties.position[0]);
188-
this._position[1] = Math.round(properties.position[1]);
189-
dirty = true;
190-
}
191-
if ('direction' in properties && this._direction !== properties.direction) {
192-
this._direction = properties.direction;
191+
updatePosition (position) {
192+
if (this._position[0] !== position[0] ||
193+
this._position[1] !== position[1]) {
194+
this._position[0] = Math.round(position[0]);
195+
this._position[1] = Math.round(position[1]);
196+
this.setTransformDirty();
197+
}
198+
}
199+
200+
/**
201+
* Update the direction if it is different. Marks the transform as dirty.
202+
* @param {number} direction A new direction.
203+
*/
204+
updateDirection (direction) {
205+
if (this._direction !== direction) {
206+
this._direction = direction;
193207
this._rotationTransformDirty = true;
194-
dirty = true;
208+
this.setTransformDirty();
195209
}
196-
if ('scale' in properties && (
197-
this._scale[0] !== properties.scale[0] ||
198-
this._scale[1] !== properties.scale[1])) {
199-
this._scale[0] = properties.scale[0];
200-
this._scale[1] = properties.scale[1];
210+
}
211+
212+
/**
213+
* Update the scale if it is different. Marks the transform as dirty.
214+
* @param {Array.<number>} scale A new scale.
215+
*/
216+
updateScale (scale) {
217+
if (this._scale[0] !== scale[0] ||
218+
this._scale[1] !== scale[1]) {
219+
this._scale[0] = scale[0];
220+
this._scale[1] = scale[1];
201221
this._rotationCenterDirty = true;
202222
this._skinScaleDirty = true;
203-
dirty = true;
223+
this.setTransformDirty();
204224
}
205-
if ('visible' in properties) {
206-
this._visible = properties.visible;
225+
}
226+
227+
/**
228+
* Update visibility if it is different. Marks the convex hull as dirty.
229+
* @param {boolean} visible A new visibility state.
230+
*/
231+
updateVisible (visible) {
232+
if (this._visible !== visible) {
233+
this._visible = visible;
207234
this.setConvexHullDirty();
208235
}
209-
if (dirty) {
210-
this.setTransformDirty();
236+
}
237+
238+
/**
239+
* Update an effect. Marks the convex hull as dirty if the effect changes shape.
240+
* @param {string} effectName The name of the effect.
241+
* @param {number} rawValue A new effect value.
242+
*/
243+
updateEffect (effectName, rawValue) {
244+
const effectInfo = ShaderManager.EFFECT_INFO[effectName];
245+
if (rawValue) {
246+
this.enabledEffects |= effectInfo.mask;
247+
} else {
248+
this.enabledEffects &= ~effectInfo.mask;
249+
}
250+
const converter = effectInfo.converter;
251+
this._uniforms[effectInfo.uniformName] = converter(rawValue);
252+
if (effectInfo.shapeChanges) {
253+
this.setConvexHullDirty();
254+
}
255+
}
256+
257+
/**
258+
* Update the position, direction, scale, or effect properties of this Drawable.
259+
* @deprecated Use specific update* methods instead.
260+
* @param {object.<string,*>} properties The new property values to set.
261+
*/
262+
updateProperties (properties) {
263+
if ('position' in properties) {
264+
this.updatePosition(properties.position);
265+
}
266+
if ('direction' in properties) {
267+
this.updateDirection(properties.direction);
268+
}
269+
if ('scale' in properties) {
270+
this.updateScale(properties.scale);
271+
}
272+
if ('visible' in properties) {
273+
this.updateVisible(properties.visible);
211274
}
212275
const numEffects = ShaderManager.EFFECTS.length;
213276
for (let index = 0; index < numEffects; ++index) {
214277
const effectName = ShaderManager.EFFECTS[index];
215278
if (effectName in properties) {
216-
const rawValue = properties[effectName];
217-
const effectInfo = ShaderManager.EFFECT_INFO[effectName];
218-
if (rawValue) {
219-
this.enabledEffects |= effectInfo.mask;
220-
} else {
221-
this.enabledEffects &= ~effectInfo.mask;
222-
}
223-
const converter = effectInfo.converter;
224-
this._uniforms[effectInfo.uniformName] = converter(rawValue);
225-
if (effectInfo.shapeChanges) {
226-
this.setConvexHullDirty();
227-
}
279+
this.updateEffect(effectName, properties[effectName]);
228280
}
229281
}
230282
}
@@ -425,6 +477,16 @@ class Drawable {
425477
return true;
426478
}
427479

480+
// If the effect bits for mosaic, pixelate, whirl, or fisheye are set, use linear
481+
if ((this._effectBits & (
482+
ShaderManager.EFFECT_INFO.fisheye.mask |
483+
ShaderManager.EFFECT_INFO.whirl.mask |
484+
ShaderManager.EFFECT_INFO.pixelate.mask |
485+
ShaderManager.EFFECT_INFO.mosaic.mask
486+
)) !== 0) {
487+
return false;
488+
}
489+
428490
// We can't use nearest neighbor unless we are a multiple of 90 rotation
429491
if (this._direction % 90 !== 0) {
430492
return false;
@@ -512,7 +574,6 @@ class Drawable {
512574
* @return {!Rectangle} Bounds for the Drawable.
513575
*/
514576
getFastBounds (result) {
515-
this.updateMatrix();
516577
if (!this.needsConvexHullPoints()) {
517578
return this.getBounds(result);
518579
}

src/PenSkin.js

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ class PenSkin extends Skin {
8888
/** @type {HTMLCanvasElement} */
8989
this._canvas = document.createElement('canvas');
9090

91-
/** @type {Array<number>} */
92-
this._canvasSize = twgl.v3.create();
93-
9491
/** @type {WebGLTexture} */
9592
this._texture = null;
9693

@@ -168,7 +165,7 @@ class PenSkin extends Skin {
168165
* @return {Array<number>} the "native" size, in texels, of this skin. [width, height]
169166
*/
170167
get size () {
171-
return this._canvasSize;
168+
return [this._canvas.width, this._canvas.height];
172169
}
173170

174171
/**
@@ -191,13 +188,13 @@ class PenSkin extends Skin {
191188
clear () {
192189
const gl = this._renderer.gl;
193190
twgl.bindFramebufferInfo(gl, this._framebuffer);
194-
191+
195192
/* Reset framebuffer to transparent black */
196193
gl.clearColor(0, 0, 0, 0);
197194
gl.clear(gl.COLOR_BUFFER_BIT);
198195

199196
const ctx = this._canvas.getContext('2d');
200-
ctx.clearRect(0, 0, this._canvasSize[0], this._canvasSize[1]);
197+
ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
201198

202199
this._silhouetteDirty = true;
203200
}
@@ -335,8 +332,7 @@ class PenSkin extends Skin {
335332

336333
const uniforms = {
337334
u_skin: this._texture,
338-
u_projectionMatrix: projection,
339-
u_fudge: 0
335+
u_projectionMatrix: projection
340336
};
341337

342338
twgl.setUniforms(currentShader, uniforms);
@@ -454,7 +450,7 @@ class PenSkin extends Skin {
454450
* @param {number} x - centered at x
455451
* @param {number} y - centered at y
456452
*/
457-
_drawRectangle (currentShader, texture, bounds, x = -this._canvasSize[0] / 2, y = this._canvasSize[1] / 2) {
453+
_drawRectangle (currentShader, texture, bounds, x = -this._canvas.width / 2, y = this._canvas.height / 2) {
458454
const gl = this._renderer.gl;
459455

460456
const projection = twgl.m4.ortho(
@@ -477,8 +473,7 @@ class PenSkin extends Skin {
477473
0
478474
), __modelScalingMatrix),
479475
__modelMatrix
480-
),
481-
u_fudge: 0
476+
)
482477
};
483478

484479
twgl.setTextureParameters(gl, texture, {minMag: gl.NEAREST});
@@ -517,7 +512,7 @@ class PenSkin extends Skin {
517512
* @param {number} x - texture centered at x
518513
* @param {number} y - texture centered at y
519514
*/
520-
_drawToBuffer (texture = this._texture, x = -this._canvasSize[0] / 2, y = this._canvasSize[1] / 2) {
515+
_drawToBuffer (texture = this._texture, x = -this._canvas.width / 2, y = this._canvas.height / 2) {
521516
if (texture !== this._texture && this._canvasDirty) {
522517
this._drawToBuffer();
523518
}
@@ -531,7 +526,7 @@ class PenSkin extends Skin {
531526
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._canvas);
532527

533528
const ctx = this._canvas.getContext('2d');
534-
ctx.clearRect(0, 0, this._canvasSize[0], this._canvasSize[1]);
529+
ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
535530

536531
this._canvasDirty = false;
537532
}
@@ -567,8 +562,8 @@ class PenSkin extends Skin {
567562
this._bounds = new Rectangle();
568563
this._bounds.initFromBounds(width / 2, width / -2, height / 2, height / -2);
569564

570-
this._canvas.width = this._canvasSize[0] = width;
571-
this._canvas.height = this._canvasSize[1] = height;
565+
this._canvas.width = width;
566+
this._canvas.height = height;
572567
this._rotationCenter[0] = width / 2;
573568
this._rotationCenter[1] = height / 2;
574569

@@ -654,8 +649,8 @@ class PenSkin extends Skin {
654649
this._renderer.enterDrawRegion(this._toBufferDrawRegionId);
655650

656651
// Sample the framebuffer's pixels into the silhouette instance
657-
const skinPixels = new Uint8Array(Math.floor(this._canvasSize[0] * this._canvasSize[1] * 4));
658-
gl.readPixels(0, 0, this._canvasSize[0], this._canvasSize[1], gl.RGBA, gl.UNSIGNED_BYTE, skinPixels);
652+
const skinPixels = new Uint8Array(Math.floor(this._canvas.width * this._canvas.height * 4));
653+
gl.readPixels(0, 0, this._canvas.width, this._canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, skinPixels);
659654

660655
const skinCanvas = this._canvas;
661656
skinCanvas.width = bounds.width;

src/Rectangle.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,11 @@ class Rectangle {
123123
this.right = Math.min(this.right, right);
124124
this.bottom = Math.max(this.bottom, bottom);
125125
this.top = Math.min(this.top, top);
126-
// Ensure rectangle coordinates in order.
127-
this.left = Math.min(this.left, this.right);
128-
this.right = Math.max(this.right, this.left);
129-
this.bottom = Math.min(this.bottom, this.top);
130-
this.top = Math.max(this.top, this.bottom);
126+
127+
this.left = Math.min(this.left, right);
128+
this.right = Math.max(this.right, left);
129+
this.bottom = Math.min(this.bottom, top);
130+
this.top = Math.max(this.top, bottom);
131131
}
132132

133133
/**

0 commit comments

Comments
 (0)