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

Feat: Add WebGL & DOM events #275

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
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
36 changes: 32 additions & 4 deletions core/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -641,8 +641,8 @@ Node.prototype.getComponent = function getComponent (index) {
*
* @method removeComponent
*
* @param {Object} component An component that has previously been added
* using {@link Node#addComponent}.
* @param {Object} component A component that has previously been added
* using @{@link addComponent}.
*
* @return {Node} this
*/
Expand All @@ -661,6 +661,33 @@ Node.prototype.removeComponent = function removeComponent (component) {
return component;
};

/**
* Removes a node's subscription to a particular UIEvent. All components
* on the node will have the opportunity to remove all listeners depending
* on this event.
*
* @method
*
* @param {String} eventName the name of the event
*
* @return {Node} this
*/
Node.prototype.removeUIEvent = function removeUIEvent (eventName) {
var UIEvents = this.getUIEvents();
var components = this._components;
var component;

var index = UIEvents.indexOf(eventName);
if (index !== -1) {
UIEvents.splice(index, 1);
for (var i = 0, len = components.length ; i < len ; i++) {
component = components[i];
if (component && component.onRemoveUIEvent) component.onRemoveUIEvent(eventName);
}
}
return this;
};

/**
* Subscribes a node to a UI Event. All components on the node
* will have the opportunity to begin listening to that event
Expand All @@ -670,7 +697,7 @@ Node.prototype.removeComponent = function removeComponent (component) {
*
* @param {String} eventName the name of the event
*
* @return {undefined} undefined
* @return {Node} this
*/
Node.prototype.addUIEvent = function addUIEvent (eventName) {
var UIEvents = this.getUIEvents();
Expand All @@ -685,6 +712,7 @@ Node.prototype.addUIEvent = function addUIEvent (eventName) {
if (component && component.onAddUIEvent) component.onAddUIEvent(eventName);
}
}
return this;
};

/**
Expand Down Expand Up @@ -1105,7 +1133,7 @@ Node.prototype.setOpacity = function setOpacity (val) {
* Sets the size mode being used for determining the node's final width, height
* and depth.
* Size modes are a way to define the way the node's size is being calculated.
* Size modes are enums set on the {@link Size} constructor (and aliased on
* Size modes are enums set on the @{@link Size} constructor (and aliased on
* the Node).
*
* @example
Expand Down
12 changes: 11 additions & 1 deletion renderers/Context.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Context.prototype.getRootSize = function getRootSize() {
Context.prototype.initWebGL = function initWebGL() {
this.canvas = document.createElement('canvas');
this._rootEl.appendChild(this.canvas);
this.WebGLRenderer = new WebGLRenderer(this.canvas, this._compositor);
this.WebGLRenderer = new WebGLRenderer(this.canvas, this._compositor, this._domLayerEl);
this.updateSize();
};

Expand Down Expand Up @@ -261,6 +261,16 @@ Context.prototype.receive = function receive(path, commands, iterator) {
this.DOMRenderer.allowDefault(commands[++localIterator]);
break;

case 'GL_SUBSCRIBE':
if (!this.WebGLRenderer) this.initWebGL();
this.WebGLRenderer.subscribe(path, commands[++localIterator]);
break;

case 'GL_UNSUBSCRIBE':
if (!this.WebGLRenderer) this.initWebGL();
this.WebGLRenderer.unsubscribe(path, commands[++localIterator]);
break;

case 'GL_SET_DRAW_OPTIONS':
if (!this.WebGLRenderer) this.initWebGL();
this.WebGLRenderer.setMeshOptions(path, commands[++localIterator]);
Expand Down
111 changes: 107 additions & 4 deletions webgl-renderables/Mesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

'use strict';
var Geometry = require('../webgl-geometries');
var CallbackStore = require('../utilities/CallbackStore');

/**
* The Mesh class is responsible for providing the API for how
Expand All @@ -42,9 +43,13 @@ var Geometry = require('../webgl-geometries');
function Mesh (node, options) {
this._node = node;
this._changeQueue = [];
this._UIEvents = [];
this._callbacks = new CallbackStore();

this._initialized = false;
this._requestingUpdate = false;
this._inDraw = false;

this.value = {
drawOptions: null,
color: null,
Expand All @@ -57,6 +62,7 @@ function Mesh (node, options) {
};

if (options) this.setDrawOptions(options);

this._id = node.addComponent(this);
}

Expand Down Expand Up @@ -583,16 +589,113 @@ Mesh.prototype.onOpacityChange = function onOpacityChange (opacity) {
};

/**
* Adds functionality for UI events (TODO)
* Method to be invoked by the node as soon as a new UIEvent is being added.
* This results into an `SUBSCRIBE` command being sent.
*
* @param {String} UIEvent UIEvent to be subscribed to (e.g. `click`)
*
* @return {Mesh} this
*/
Mesh.prototype.onAddUIEvent = function onAddUIEvent(UIEvent) {
if (this._UIEvents.indexOf(UIEvent) === -1) {
this._subscribe(UIEvent);
this._UIEvents.push(UIEvent);
}
else if (this._inDraw) {
this._subscribe(UIEvent);
}
return this;
};

/**
* Method to be invoked by the node as soon as a UIEvent is removed from
* the node. This results into an `UNSUBSCRIBE` command being sent.
*
* @param {String} UIEvent UIEvent to be removed (e.g. `click`)
*
* @return {Mesh} this
*/
Mesh.prototype.onRemoveUIEvent = function onRemoveUIEvent(UIEvent) {
var index = this._UIEvents.indexOf(UIEvent);
if (index !== -1) {
this._unsubscribe(UIEvent);
this._UIEvents.splice(index, 1);
}
else if (this._inDraw) {
this._unsubscribe(UIEvent);
}
return this;
};

/**
* Appends an `SUBSCRIBE` command to the command queue.
*
* @method
* @private
*
* @param {String} UIEvent UI Event
* @param {String} UIEvent Event type (e.g. `click`)
*
* @return {undefined} undefined
*/
Mesh.prototype.onAddUIEvent = function onAddUIEvent (UIEvent) {
//TODO
Mesh.prototype._subscribe = function _subscribe(UIEvent) {
if (this._initialized) {
this._changeQueue.push('GL_SUBSCRIBE', UIEvent);
}

if (!this._requestingUpdate) this._requestUpdate();
};

/**
* Appends an `UNSUBSCRIBE` command to the command queue.
*
* @method
* @private
*
* @param {String} UIEvent Event type (e.g. `click`)
*
* @return {undefined} undefined
*/
Mesh.prototype._unsubscribe = function _unsubscribe (UIEvent) {
if (this._initialized) {
this._changeQueue.push('GL_UNSUBSCRIBE', UIEvent);
}

if (!this._requestingUpdate) this._requestUpdate();
};

/**
* Function to be invoked by the Node whenever an event is being received.
* There are two different ways to subscribe for those events:
*
* 1. By overriding the onReceive method (and possibly using `switch` in order
* to differentiate between the different event types).
* 2. By using Mesh and using the built-in CallbackStore.
*
* @method
*
* @param {String} event Event type (e.g. `click`)
* @param {Object} payload Event object.
*
* @return {undefined} undefined
*/
Mesh.prototype.onReceive = function onReceive(event, payload) {
this._callbacks.trigger(event, payload);
};

/**
* Subscribes to a Mesh using
*
* @method on
*
* @param {String} event The event type (e.g. `click`).
* @param {Function} listener Handler function for the specified event type
* in which the payload event object will be
* passed into.
*
* @return {Function} A function to call if you want to remove the callback
*/
Mesh.prototype.on = function on(event, listener) {
return this._callbacks.on(event, listener);
};

/**
Expand Down
4 changes: 3 additions & 1 deletion webgl-renderers/Program.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ var uniforms = keyValueToArrays({
u_lightColor: identityMatrix,
u_ambientLight: [0, 0, 0],
u_flatShading: 0,
u_numLights: 0
u_numLights: 0,
u_pickingMode: 0,
u_meshIdColor: [-1, -1, -1, -1]
});

/**
Expand Down
Loading