Remove worker support (#36)

* Remove WebWorker support

* Recompile Sept. 14
This commit is contained in:
Tim Mickel 2016-09-15 19:01:44 -04:00 committed by GitHub
parent a5fb65ebeb
commit fb3f677e2c
14 changed files with 111 additions and 9229 deletions

View File

@ -17,7 +17,20 @@
<script src="../render.js"></script>
<script>
var canvas = document.getElementById('scratch-stage');
var renderer = new RenderWebGLLocal(canvas);
var fudge = 90;
var renderer = new RenderWebGL(canvas);
var drawableID = renderer.createDrawable();
renderer.updateDrawableProperties(drawableID, {
position: [0, 0],
scale: [100, 100],
direction: 90
});
var drawableID2 = renderer.createDrawable();
renderer.updateDrawableProperties(drawableID2, {
skin: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' +
'09dc888b0b7df19f70d81588ae73420e.svg/get/'
});
var fudgeInput = document.getElementById('fudge');
function onFudgeMinChanged(newValue) {
@ -27,7 +40,13 @@
fudgeInput.max = newValue;
}
function onFudgeChanged(newValue) {
demoWorker.postMessage({fudge: newValue});
fudge = newValue;
var props = {};
//props.position = [posX, posY];
//props.direction = fudge;
//props.pixelate = fudge;
props.scale = [fudge, 100];
renderer.updateDrawableProperties(drawableID, props);
}
// Adapted from code by Simon Sarris: http://stackoverflow.com/a/10450761
@ -67,10 +86,8 @@
canvas.onclick = function(event) {
var mousePos = getMousePos(event, canvas);
var pickPromise = renderer.pick(mousePos.x, mousePos.y);
pickPromise.then(function(pickID) {
console.log('You clicked on ' + (pickID < 0 ? 'nothing' : 'ID# ' + pickID));
});
var pickID = renderer.pick(mousePos.x, mousePos.y);
console.log('You clicked on ' + (pickID < 0 ? 'nothing' : 'ID# ' + pickID));
};
function drawStep() {
@ -80,9 +97,6 @@
drawStep();
renderer.setDebugCanvas(document.getElementById('debug-canvas'));
var demoWorker = new Worker('worker.js');
renderer.connectWorker(demoWorker);
</script>
</body>
</html>

View File

@ -1,58 +0,0 @@
importScripts('../render-worker.js');
var renderer;
var drawableID;
var drawableID2;
var fudge = 90;
onmessage = function(message) {
if (message.data.fudge != undefined) {
fudge = message.data.fudge;
}
else {
if (message.data.id == 'RendererConnected') {
initWorker();
}
renderer.onmessage(message);
}
};
function initWorker() {
renderer = new self.RenderWebGLWorker();
var create1 = renderer.createDrawable();
var create2 = renderer.createDrawable();
create1.then(function (id) {
drawableID = id;
renderer.updateDrawableProperties(drawableID, {
position: [0, 0],
scale: [100, 100],
direction: 90
});
});
create2.then(function (id) {
drawableID2 = id;
renderer.updateDrawableProperties(drawableID2, {
skin: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' +
'09dc888b0b7df19f70d81588ae73420e.svg/get/'
});
});
Promise.all([create1, create2]).then(function () {
setInterval(thinkStep, 1 / 60);
});
}
function thinkStep() {
//direction += 0.1;
var props = {};
//props.position = [posX, posY];
//props.direction = fudge;
//props.pixelate = fudge;
props.scale = [fudge, 100];
renderer.updateDrawableProperties(drawableID, props);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

351
render.js

File diff suppressed because one or more lines are too long

16
render.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,6 @@
var twgl = require('twgl.js');
var Drawable = require('./Drawable');
var WorkerMessages = require('./WorkerMessages');
var ShaderManager = require('./ShaderManager');
@ -116,15 +115,11 @@ RenderWebGL.prototype.setStageSize = function (xLeft, xRight, yBottom, yTop) {
};
/********
* Functions supporting RenderWebGL{Local,Worker}: access from those classes.
********/
/**
* Create a new Drawable and add it to the scene.
* @returns {int} The ID of the new Drawable.
*/
RenderWebGL.prototype._createDrawable = function () {
RenderWebGL.prototype.createDrawable = function () {
var drawable = new Drawable(this._gl);
var drawableID = drawable.getID();
this._drawables.push(drawableID);
@ -136,7 +131,7 @@ RenderWebGL.prototype._createDrawable = function () {
* @param {int} drawableID The ID of the Drawable to remove.
* @returns {Boolean} True iff the drawable was found and removed.
*/
RenderWebGL.prototype._destroyDrawable = function (drawableID) {
RenderWebGL.prototype.destroyDrawable = function (drawableID) {
var index = this._drawables.indexOf(drawableID);
if (index >= 0) {
Drawable.getDrawableByID(drawableID).dispose();
@ -149,7 +144,7 @@ RenderWebGL.prototype._destroyDrawable = function (drawableID) {
/**
* Draw all current drawables and present the frame on the canvas.
*/
RenderWebGL.prototype._draw = function () {
RenderWebGL.prototype.draw = function () {
var gl = this._gl;
twgl.bindFramebufferInfo(gl, null);
@ -168,7 +163,7 @@ RenderWebGL.prototype._draw = function () {
* @param {int[]} [mask3b] Optionally mask the check to this part of Drawable.
* @returns {Boolean} True iff the Drawable is touching the color.
*/
RenderWebGL.prototype._isTouchingColor = function(drawableID, color3b, mask3b) {
RenderWebGL.prototype.isTouchingColor = function(drawableID, color3b, mask3b) {
var gl = this._gl;
@ -264,7 +259,7 @@ RenderWebGL.prototype._isTouchingColor = function(drawableID, color3b, mask3b) {
* @returns {int} The ID of the topmost Drawable under the picking location, or
* Drawable.NONE if there is no Drawable at that location.
*/
RenderWebGL.prototype._pick = function (
RenderWebGL.prototype.pick = function (
centerX, centerY, touchWidth, touchHeight, candidateIDs) {
var gl = this._gl;
@ -349,6 +344,16 @@ RenderWebGL.prototype._pick = function (
return hit | 0;
};
/**
* Update the position, direction, scale, or effect properties of this Drawable.
* @param {int} drawableID The ID of the Drawable to update.
* @param {Object.<string,*>} properties The new property values to set.
*/
RenderWebGL.prototype.updateDrawableProperties = function (
drawableID, properties) {
var drawable = Drawable.getDrawableByID(drawableID);
drawable.updateProperties(properties);
};
/********
* Truly internal functions: these support the functions above.
@ -459,83 +464,3 @@ RenderWebGL.prototype._drawThese = function(
twgl.drawBufferInfo(gl, gl.TRIANGLES, this._bufferInfo);
}
};
/********
* Worker interface
* TODO: Consider moving this to a separate "dispatcher" class or similar.
********/
/**
* Listen for messages from a worker.
* The renderer will post a message to this worker with data='rendererConnected'
* immediately. After that, the renderer will not send messages to the worker
* except in response to messages from that worker.
* @param {Worker} worker Listen to this worker.
*/
RenderWebGL.prototype.connectWorker = function(worker) {
var instance = this;
worker.addEventListener('message', function (event) {
instance._onWorkerMessage(worker, event);
});
worker.postMessage({id: WorkerMessages.FromRenderer.RendererConnected});
};
/**
* Post a ResultValue message to a worker in reply to a particular message.
* The outgoing message's reply token will be copied from the provided message.
* @param {Worker} worker The worker to receive the ResultValue message.
* @param {Object} message The originating message to which this is a reply.
* @param {*} value The value to send as a result.
* @private
*/
RenderWebGL.prototype._postResultValue = function(worker, message, value) {
worker.postMessage({
id: WorkerMessages.FromRenderer.ResultValue,
token: message.data.token,
value: value
});
};
/**
* Handle an event (message) from the specified worker.
* @param {Worker} worker The originating worker for the event.
* @param {MessageEvent} message The event to be handled.
* @private
*/
RenderWebGL.prototype._onWorkerMessage = function(worker, message) {
switch(message.data.id) {
case WorkerMessages.ToRenderer.Ping:
worker.postMessage(WorkerMessages.FromRenderer.Pong);
break;
case WorkerMessages.ToRenderer.CreateDrawable:
this._postResultValue(worker, message, this._createDrawable());
break;
case WorkerMessages.ToRenderer.DestroyDrawable:
this._postResultValue(worker, message,
this._destroyDrawable(message.data.drawableID));
break;
case WorkerMessages.ToRenderer.Draw:
this._draw();
break;
case WorkerMessages.ToRenderer.IsTouchingColor:
this._postResultValue(worker, message,
this._isTouchingColor(
message.data.drawableID,
message.data.color3b,
message.data.mask3b));
break;
case WorkerMessages.ToRenderer.Pick:
this._postResultValue(worker, message,
this._pick(
message.data.centerX,
message.data.centerY,
message.data.touchWidth,
message.data.touchHeight,
message.data.candidateIDs));
break;
case WorkerMessages.ToRenderer.UpdateDrawableProperties:
var drawable = Drawable.getDrawableByID(message.data.drawableID);
drawable.updateProperties(message.data.properties);
break;
}
};

View File

@ -1,81 +0,0 @@
var RenderWebGL = require('./RenderWebGL');
var Drawable = require('./Drawable');
class RenderWebGLLocal extends RenderWebGL {
// inherit constructor
}
module.exports = RenderWebGLLocal;
/**
* Create a new Drawable and add it to the scene.
* @returns {Promise.<int>} The ID of the new Drawable.
*/
RenderWebGLLocal.prototype.createDrawable = function () {
var drawableID = this._createDrawable();
return Promise.resolve(drawableID);
};
/**
* Destroy a Drawable, removing it from the scene.
* @param {int} drawableID The ID of the Drawable to remove.
* @returns {Promise.<Boolean>} True iff the drawable was found and removed.
*/
RenderWebGLLocal.prototype.destroyDrawable = function (drawableID) {
var wasRemoved = this._destroyDrawable(drawableID);
return Promise.resolve(wasRemoved);
};
/**
* Draw all current drawables and present the frame on the canvas.
*/
RenderWebGLLocal.prototype.draw = function () {
this._draw();
};
/**
* Check if a particular Drawable is touching a particular color.
* @param {int} drawableID The ID of the Drawable to check.
* @param {int[]} color3b Test if the Drawable is touching this color.
* @param {int[]} [mask3b] Optionally mask the check to this part of Drawable.
* @returns {Promise.<Boolean>} True iff the Drawable is touching the color.
*/
RenderWebGLLocal.prototype.isTouchingColor = function(
drawableID, color3b, mask3b) {
var isTouching = this._isTouchingColor(drawableID, color3b, mask3b);
return Promise.resolve(isTouching);
};
/**
* Detect which sprite, if any, is at the given location.
* @param {int} centerX The client x coordinate of the picking location.
* @param {int} centerY The client y coordinate of the picking location.
* @param {int} touchWidth The client width of the touch event (optional).
* @param {int} touchHeight The client height of the touch event (optional).
* @param {int[]} candidateIDs The Drawable IDs to pick from, otherwise all.
* @returns {int} The ID of the topmost Drawable under the picking location, or
* Drawable.NONE if there is no Drawable at that location.
*/
RenderWebGLLocal.prototype.pick = function (
centerX, centerY, touchWidth, touchHeight, candidateIDs) {
var drawableID =
this._pick(centerX, centerY, touchWidth, touchHeight, candidateIDs);
return Promise.resolve(drawableID);
};
/**
* Update the position, direction, scale, or effect properties of this Drawable.
* @param {int} drawableID The ID of the Drawable to update.
* @param {Object.<string,*>} properties The new property values to set.
*/
RenderWebGLLocal.prototype.updateDrawableProperties = function (
drawableID, properties) {
var drawable = Drawable.getDrawableByID(drawableID);
drawable.updateProperties(properties);
};

View File

@ -1,172 +0,0 @@
var WorkerMessages = require('./WorkerMessages');
class RenderWebGLWorker {
constructor() {
var instance = this;
/**
* Handle a message from this worker's host. Call this from your
* worker's onmessage function or install it directly.
* @param {MessageEvent} message The message to be handled.
*/
this.onmessage = function (message) {
instance._onmessage(message);
};
/**
* Mapping of message token to Promise resolve function.
* @type {Object.<string, Promise>}
* @private
*/
this._pendingTokens = {};
this._nextToken = 0;
}
}
module.exports = RenderWebGLWorker;
/**
* Create a new Drawable and add it to the scene.
* @returns {Promise.<int>} The ID of the new Drawable.
*/
RenderWebGLWorker.prototype.createDrawable = function() {
return this._postForPromise({
id: WorkerMessages.ToRenderer.CreateDrawable
});
};
/**
* Destroy a Drawable, removing it from the scene.
* @param {int} drawableID The ID of the Drawable to remove.
* @returns {Promise.<Boolean>} True iff the drawable was found and removed.
*/
RenderWebGLWorker.prototype.destroyDrawable = function (drawableID) {
return this._postForPromise({
id: WorkerMessages.ToRenderer.DestroyDrawable,
drawableID: drawableID
});
};
/**
* Draw all current drawables and present the frame on the canvas.
*/
RenderWebGLWorker.prototype.draw = function () {
self.postMessage({
id: WorkerMessages.ToRenderer.Draw
});
};
/**
* Check if a particular Drawable is touching a particular color.
* @param {int} drawableID The ID of the Drawable to check.
* @param {int[]} color3b Test if the Drawable is touching this color.
* @param {int[]} [mask3b] Optionally mask the check to this part of Drawable.
* @returns {Promise.<Boolean>} True iff the Drawable is touching the color.
*/
RenderWebGLWorker.prototype.isTouchingColor = function(
drawableID, color3b, mask3b) {
var messageData = {
id: WorkerMessages.ToRenderer.IsTouchingColor,
drawableID: drawableID,
color3b: color3b
};
if (mask3b != undefined) {
messageData.mask3b = mask3b;
}
return this._postForPromise(messageData);
};
/**
* Detect which sprite, if any, is at the given location.
* @param {int} centerX The client x coordinate of the picking location.
* @param {int} centerY The client y coordinate of the picking location.
* @param {int} touchWidth The client width of the touch event (optional).
* @param {int} touchHeight The client height of the touch event (optional).
* @param {int[]} candidateIDs The Drawable IDs to pick from, otherwise all.
* @returns {int} The ID of the topmost Drawable under the picking location, or
* Drawable.NONE if there is no Drawable at that location.
*/
RenderWebGLWorker.prototype.pick = function (
centerX, centerY, touchWidth, touchHeight, candidateIDs) {
var messageData = {
id: WorkerMessages.ToRenderer.Pick,
centerX: centerX,
centerY: centerY
};
if (touchWidth > 1) {
messageData.touchWidth = touchWidth;
}
if (touchHeight > 1) {
messageData.touchHeight = touchHeight;
}
if (candidateIDs != undefined) {
messageData.candidateIDs = candidateIDs;
}
return this._postForPromise(messageData);
};
/**
* Update the position, direction, scale, or effect properties of this Drawable.
* @param {int} drawableID The ID of the Drawable to update.
* @param {Object.<string,*>} properties The new property values to set.
*/
RenderWebGLWorker.prototype.updateDrawableProperties = function (
drawableID, properties) {
self.postMessage({
id: WorkerMessages.ToRenderer.UpdateDrawableProperties,
drawableID: drawableID,
properties: properties
});
};
/**
* Retrieve a unique token for use in a message which requests a reply.
* @returns {string}
* @private
*/
RenderWebGLWorker.prototype._getToken = function() {
return (this._nextToken++) + '';
};
/**
* Post a message to the renderer and return a Promise awaiting the result.
* WARNING: The messageData object will be modified by this function. The
* `token` property of messageData will be set to the message's reply token.
* @param {Object} messageData The contents of the message.
* @private
*/
RenderWebGLWorker.prototype._postForPromise = function(messageData) {
var instance = this;
return new Promise(function (resolve) {
var token = instance._getToken();
instance._pendingTokens[token] = resolve;
messageData.token = token;
self.postMessage(messageData);
});
};
/**
* Actually handle a message from this worker's host.
* @param {MessageEvent} message The message to be handled.
* @private
*/
RenderWebGLWorker.prototype._onmessage = function(message) {
// It's sometimes valid for a message to have no token
var token = message.data.token;
if (token != undefined) {
var resolve = this._pendingTokens[token];
delete this._pendingTokens[token];
}
switch(message.data.id) {
case WorkerMessages.FromRenderer.ResultValue:
resolve(message.data.value);
break;
}
};

View File

@ -1,65 +0,0 @@
/**
* All messages sent to or from the renderer.
*/
var WorkerMessages = {
/**
* Messages that are sent to the renderer from a worker.
* A message should have this form:
* postMessage({
* id: MessagesToRenderer.ping,
* token: 'uniqueString',
* ...
* });
* If the renderer replies to the message, the 'token' property will be
* copied into the reply message. If a message generates no reply, the
* 'token' property is optional.
* In general these messages correspond to a function on RenderWebGLLocal,
* and in particular each argument in the RenderWebGLLocal method can be
* encoded as a property on the message data object with the same name.
* @enum {string}
*/
ToRenderer: {
Ping: 'Ping',
CreateDrawable: 'CreateDrawable',
DestroyDrawable: 'DestroyDrawable',
Draw: 'Draw',
IsTouchingColor: 'IsTouchingColor',
Pick: 'Pick',
UpdateDrawableProperties: 'UpdateDrawableProperties'
},
/**
* Messages that are sent from the renderer to a worker.
* A message will have this form:
* postMessage({
* id: MessagesFromRenderer.ping,
* token: 'uniqueString',
* ...
* });
* If the message is being sent in reply to another message from the worker,
* the 'token' property will match the originating message. Otherwise the
* 'token' property will be undefined.
* @enum {string}
*/
FromRenderer: {
/**
* The renderer has connected to this worker.
*/
RendererConnected: 'RendererConnected',
/**
* The response to a Ping from a worker.
*/
Pong: 'Pong',
/**
* The message will contain a 'value' field with the result of the
* request with matching token.
*/
ResultValue: 'ResultValue'
}
};
module.exports = WorkerMessages;

View File

@ -1,8 +1,8 @@
require('babel-polyfill');
var RenderWebGLLocal = require('./RenderWebGLLocal');
var RenderWebGL = require('./RenderWebGL');
/**
* Export for use in a web page
*/
window.RenderWebGLLocal = RenderWebGLLocal;
window.RenderWebGL = RenderWebGL;

View File

@ -1,8 +0,0 @@
require('babel-polyfill');
var RenderWebGLWorker = require('./RenderWebGLWorker');
/**
* Export for use in a Web Worker
*/
self.RenderWebGLWorker = RenderWebGLWorker;

View File

@ -1,6 +1,6 @@
var RenderWebGLLocal = require('./RenderWebGLLocal');
var RenderWebGL = require('./RenderWebGL');
/**
* Export for NPM / Node.js
*/
module.exports = RenderWebGLLocal;
module.exports = RenderWebGL;

View File

@ -4,9 +4,7 @@ var webpack = require('webpack');
module.exports = {
entry: {
'render': './src/index-web.js',
'render.min': './src/index-web.js',
'render-worker': './src/index-webworker.js',
'render-worker.min': './src/index-webworker.js'
'render.min': './src/index-web.js'
},
output: {
path: __dirname,