Handle changing the stage's native size, tell pen
The `setStageSize` wasn't working correctly. This change fixes that and also notifies active `PenDrawable` instances about the resize. This was implemented by making the renderer an `EventEmitter`.
This commit is contained in:
parent
2a64c1dd18
commit
e3a05743b0
@ -71,7 +71,7 @@ class Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispose of this Drawable. Do not use it after calling this method.
|
* Dispose of this object. Do not use it after calling this method.
|
||||||
*/
|
*/
|
||||||
dispose () {
|
dispose () {
|
||||||
if (this._id >= 0) {
|
if (this._id >= 0) {
|
||||||
|
@ -1,29 +1,57 @@
|
|||||||
const twgl = require('twgl.js');
|
const twgl = require('twgl.js');
|
||||||
|
|
||||||
const Drawable = require('./Drawable');
|
const Drawable = require('./Drawable');
|
||||||
|
const RenderEvent = require('./RenderEvent');
|
||||||
|
|
||||||
|
|
||||||
class PenDrawable extends Drawable {
|
class PenDrawable extends Drawable {
|
||||||
/**
|
/**
|
||||||
* Create a Pen Layer.
|
* Create a Pen Layer.
|
||||||
|
* @param {RenderWebGL} renderer - The renderer which will draw this object.
|
||||||
* @param {WebGLRenderingContext} gl - The WebGL rendering context to use.
|
* @param {WebGLRenderingContext} gl - The WebGL rendering context to use.
|
||||||
*/
|
*/
|
||||||
constructor (gl) {
|
constructor (renderer, gl) {
|
||||||
super(gl);
|
super(gl);
|
||||||
|
|
||||||
|
/** @type {RenderWebGL} */
|
||||||
|
this._renderer = renderer;
|
||||||
|
|
||||||
/** @type {HTMLCanvasElement} */
|
/** @type {HTMLCanvasElement} */
|
||||||
this._canvas = document.createElement('canvas');
|
this._canvas = document.createElement('canvas');
|
||||||
|
|
||||||
/** @type {boolean} */
|
/** @type {boolean} */
|
||||||
this._canvasDirty = false;
|
this._canvasDirty = false;
|
||||||
|
|
||||||
|
this.onNativeSizeChanged = this.onNativeSizeChanged.bind(this);
|
||||||
|
this._renderer.on(RenderEvent.NativeSizeChanged, this.onNativeSizeChanged);
|
||||||
|
|
||||||
|
this._setCanvasSize(renderer.getNativeSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resize the pen layer's working area.
|
* Dispose of this object. Do not use it after calling this method.
|
||||||
* @param {int} width - The new width of the working area.
|
|
||||||
* @param {int} height - The new height of the working area.
|
|
||||||
*/
|
*/
|
||||||
resize (width, height) {
|
dispose () {
|
||||||
|
this._renderer.removeListener(RenderEvent.NativeSizeChanged, this.onNativeSizeChanged);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React to a change in the renderer's native size.
|
||||||
|
* @param {object} event - The change event.
|
||||||
|
*/
|
||||||
|
onNativeSizeChanged (event) {
|
||||||
|
this._setCanvasSize(event.newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the size of the pen canvas.
|
||||||
|
* @param {[int,int]} canvasSize - the new width and height for the canvas.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_setCanvasSize (canvasSize) {
|
||||||
|
const [width, height] = canvasSize;
|
||||||
|
|
||||||
const gl = this._gl;
|
const gl = this._gl;
|
||||||
this._canvas.width = width;
|
this._canvas.width = width;
|
||||||
this._canvas.height = height;
|
this._canvas.height = height;
|
||||||
|
5
src/RenderEvent.js
Normal file
5
src/RenderEvent.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const RenderEvent = {
|
||||||
|
NativeSizeChanged: 'NativeSizeChanged'
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = RenderEvent;
|
@ -1,8 +1,11 @@
|
|||||||
|
const EventEmitter = require('events');
|
||||||
|
|
||||||
const hull = require('hull.js');
|
const hull = require('hull.js');
|
||||||
const twgl = require('twgl.js');
|
const twgl = require('twgl.js');
|
||||||
|
|
||||||
const Drawable = require('./Drawable');
|
const Drawable = require('./Drawable');
|
||||||
const PenDrawable = require('./PenDrawable');
|
const PenDrawable = require('./PenDrawable');
|
||||||
|
const RenderEvent = require('./RenderEvent');
|
||||||
const ShaderManager = require('./ShaderManager');
|
const ShaderManager = require('./ShaderManager');
|
||||||
const SkinnedDrawable = require('./SkinnedDrawable');
|
const SkinnedDrawable = require('./SkinnedDrawable');
|
||||||
|
|
||||||
@ -28,7 +31,7 @@ const MAX_TOUCH_SIZE = [3, 3];
|
|||||||
const TOLERANCE_TOUCHING_COLOR = 2;
|
const TOLERANCE_TOUCHING_COLOR = 2;
|
||||||
|
|
||||||
|
|
||||||
class RenderWebGL {
|
class RenderWebGL extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* Create a renderer for drawing Scratch sprites to a canvas using WebGL.
|
* Create a renderer for drawing Scratch sprites to a canvas using WebGL.
|
||||||
* Coordinates will default to Scratch 2.0 values if unspecified.
|
* Coordinates will default to Scratch 2.0 values if unspecified.
|
||||||
@ -45,6 +48,8 @@ class RenderWebGL {
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
constructor (canvas, xLeft, xRight, yBottom, yTop) {
|
constructor (canvas, xLeft, xRight, yBottom, yTop) {
|
||||||
|
super();
|
||||||
|
|
||||||
// TODO: remove?
|
// TODO: remove?
|
||||||
twgl.setDefaults({crossOrigin: true});
|
twgl.setDefaults({crossOrigin: true});
|
||||||
|
|
||||||
@ -60,10 +65,11 @@ class RenderWebGL {
|
|||||||
|
|
||||||
this._createGeometry();
|
this._createGeometry();
|
||||||
|
|
||||||
|
this.on(RenderEvent.NativeSizeChanged, this.onNativeSizeChanged);
|
||||||
|
|
||||||
this.setBackgroundColor(1, 1, 1);
|
this.setBackgroundColor(1, 1, 1);
|
||||||
this.setStageSize(xLeft || -240, xRight || 240, yBottom || -180, yTop || 180);
|
this.setStageSize(xLeft || -240, xRight || 240, yBottom || -180, yTop || 180);
|
||||||
this.resize(this._nativeSize[0], this._nativeSize[1]);
|
this.resize(this._nativeSize[0], this._nativeSize[1]);
|
||||||
this._createFixedBuffers();
|
|
||||||
|
|
||||||
gl.disable(gl.DEPTH_TEST);
|
gl.disable(gl.DEPTH_TEST);
|
||||||
gl.enable(gl.BLEND); // TODO: disable when no partial transparency?
|
gl.enable(gl.BLEND); // TODO: disable when no partial transparency?
|
||||||
@ -114,8 +120,27 @@ class RenderWebGL {
|
|||||||
this._xRight = xRight;
|
this._xRight = xRight;
|
||||||
this._yBottom = yBottom;
|
this._yBottom = yBottom;
|
||||||
this._yTop = yTop;
|
this._yTop = yTop;
|
||||||
this._nativeSize = [Math.abs(xRight - xLeft), Math.abs(yBottom - yTop)];
|
|
||||||
this._projection = twgl.m4.ortho(xLeft, xRight, yBottom, yTop, -1, 1);
|
this._projection = twgl.m4.ortho(xLeft, xRight, yBottom, yTop, -1, 1);
|
||||||
|
|
||||||
|
this._setNativeSize(Math.abs(xRight - xLeft), Math.abs(yBottom - yTop));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {[int,int]} the "native" size of the stage, which is used for pen, query renders, etc.
|
||||||
|
*/
|
||||||
|
getNativeSize () {
|
||||||
|
return [this._nativeSize[0], this._nativeSize[1]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the "native" size of the stage, which is used for pen, query renders, etc.
|
||||||
|
* @param {int} width - the new width to set.
|
||||||
|
* @param {int} height - the new height to set.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_setNativeSize (width, height) {
|
||||||
|
this._nativeSize = [width, height];
|
||||||
|
this.emit(RenderEvent.NativeSizeChanged, {newSize: this._nativeSize});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,8 +159,7 @@ class RenderWebGL {
|
|||||||
* @returns {int} The ID of the new PenDrawable.
|
* @returns {int} The ID of the new PenDrawable.
|
||||||
*/
|
*/
|
||||||
createPenDrawable () {
|
createPenDrawable () {
|
||||||
const drawable = new PenDrawable(this._gl);
|
const drawable = new PenDrawable(this, this._gl);
|
||||||
drawable.resize(this._nativeSize[0], this._nativeSize[1]);
|
|
||||||
const drawableID = drawable.id;
|
const drawableID = drawable.id;
|
||||||
this._drawables.push(drawableID);
|
this._drawables.push(drawableID);
|
||||||
return drawableID;
|
return drawableID;
|
||||||
@ -599,23 +623,32 @@ class RenderWebGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create those frame buffers which are fixed in size regardless of the size of the main render target. This
|
* Respond to a change in the "native" rendering size. The native size is used by buffers which are fixed in size
|
||||||
* includes the buffers used for queries such as picking and color-touching. The fixed size allows (more)
|
* regardless of the size of the main render target. This includes the buffers used for queries such as picking and
|
||||||
* consistent behavior across devices and presentation modes.
|
* color-touching. The fixed size allows (more) consistent behavior across devices and presentation modes.
|
||||||
|
* @param {object} event - The change event.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_createFixedBuffers () {
|
onNativeSizeChanged (event) {
|
||||||
|
const [width, height] = event.newSize;
|
||||||
|
|
||||||
const gl = this._gl;
|
const gl = this._gl;
|
||||||
const attachments = [
|
const attachments = [
|
||||||
{format: gl.RGBA},
|
{format: gl.RGBA},
|
||||||
{format: gl.DEPTH_STENCIL}
|
{format: gl.DEPTH_STENCIL}
|
||||||
];
|
];
|
||||||
|
|
||||||
this._pickBufferInfo = twgl.createFramebufferInfo(gl, attachments, MAX_TOUCH_SIZE[0], MAX_TOUCH_SIZE[1]);
|
if (!this._pickBufferInfo) {
|
||||||
|
this._pickBufferInfo = twgl.createFramebufferInfo(gl, attachments, MAX_TOUCH_SIZE[0], MAX_TOUCH_SIZE[1]);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: should we create this on demand to save memory?
|
// TODO: should we create this on demand to save memory?
|
||||||
// A 480x360 32-bpp buffer is 675 KiB.
|
// A 480x360 32-bpp buffer is 675 KiB.
|
||||||
this._queryBufferInfo = twgl.createFramebufferInfo(gl, attachments, this._nativeSize[0], this._nativeSize[1]);
|
if (this._queryBufferInfo) {
|
||||||
|
twgl.resizeFramebufferInfo(gl, this._queryBufferInfo, attachments, width, height);
|
||||||
|
} else {
|
||||||
|
this._queryBufferInfo = twgl.createFramebufferInfo(gl, attachments, width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user