At the moment a looping scene graph render goes at full-tilt,
using a lot of CPU, even when not much is happening, ie. no
animations.
With the render loop encapsulation introduced in V0.7.7 (start
and stop methods on SceneJS.Scene), a solution is to have a global
flag that is set when scene state changes occur that would warrant
another frame being rendered. Each node setter method could set the
flag, which is check after each idle period, like this:
SceneJS.Scene.prototype.start = function(cfg) {
if (!this._running) {
this._running = true;
var self = this;
var fnName = "__scenejs_renderScene" + this._sceneId;
window[fnName] = function() {
if (cfg.idleFunc) {
/* Global flag will be set if any state changes occur on the
* scene graph within either the idleFunc or the traversal,
* indicating that at least another traversal is then required
* in order to show the new state updates.
*/
SceneJS._mods = false;
cfg.idleFunc(self);
self._needRender = self._needRender || SceneJS._mods;
SceneJS._mods = false;
}
if (self._needRender) {
self._render(); // Render can set SceneJS._mods true again
}
};
self._needRender = true; // render at least one frame
this._pInterval = setInterval("window['" + fnName + "']()", 1000.0 / (cfg.fps || 10));
}
};
Another solution for non-deterministic scene state
Problem is how to detect the state changes in dynamic,
nondeterministic scenes (ie. in which nodes are configured with
callback functions that can change their nodes' states, eg.
triggered by the functions' own private state changes). Another
approach would be to have the FPS variable, with a low "idling" FPS
in which the scene is traversed without rendering, just to pump the
callbacks and then have the nodes flag the state change when they
receive new data from the callbacks. Then the FPS could ramp up for
as long as the flag remains set.