Skip to content

Commit

Permalink
Merge pull request #17 from linev/eve7_scene
Browse files Browse the repository at this point in the history
eve7: add EveScene.js which is responsible for all scene operations
  • Loading branch information
linev authored Jan 16, 2019
2 parents 1824447 + e5efa69 commit 72d6bf7
Show file tree
Hide file tree
Showing 4 changed files with 384 additions and 351 deletions.
71 changes: 30 additions & 41 deletions etc/eve7/EveManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,31 @@
this.handle.Send(JSON.stringify(obj));
}

/** Configure dependency for given element id - invoke function when element changed */
EveManager.prototype.Register = function(id, receiver, func_name) {
/** Configure receiver for scene-respective events. Following event used:
* onSceneChanged */
EveManager.prototype.RegisterSceneReceiver = function(id, receiver, func_name) {

var elem = this.GetElement(id);

if (!elem) return;

if (!elem.$receivers) elem.$receivers = [];

elem.$receivers.push({ obj: receiver, func: func_name });
if (elem.$receivers.indexOf(receiver)<0)
elem.$receivers.push(receiver);
}

/** Invoke function on all receiver of scene events - when such function exists */
EveManager.prototype.callSceneReceivers = function (scene, fname, arg) {
if (scene.$receivers) {
for (var i=0; i < scene.$receivers.length; i++) {
var receiver = scene.$receivers[i];
if (typeof receiver[fname] == "function")
receiver[fname](arg);
}
}
}

/** returns master id for given element id
* master id used for highlighting element in all dependent views */
EveManager.prototype.GetMasterId = function(elemid) {
Expand Down Expand Up @@ -185,13 +198,10 @@
}

EveManager.prototype.ProcessModified = function(sceneid) {
var elem = this.map[sceneid];
if (!elem || !elem.$modified || !elem.$receivers) return;

for (var k=0;k<elem.$receivers.length;++k) {
var f = elem.$receivers[k];
f.obj[f.func](sceneid, elem);
}
var elem = this.GetElement(sceneid);
if (!elem || !elem.$modified) return;

this.callSceneReceivers(elem, "onSceneChanged", sceneid);

delete elem.$modified;
}
Expand Down Expand Up @@ -262,24 +272,18 @@
this.last_json = null;
this.scene_changes = msg;

var scene = this.map[msg.header.fSceneId];
var scene = this.GetElement(msg.header.fSceneId);

// notify scenes for beginning of changes and
// notify for element removal
var removedIds = msg.header["removedElements"];

if (scene.$receivers)
{
for (var i = 0; i < scene.$receivers.length; i++)
{
var controller = scene.$receivers[i].obj;
controller.beginChanges();
for (var r = 0; r != removedIds.length; ++r)
{
controller.elementRemoved(removedIds[r]);
}
}
}
// do we need this?
this.callSceneReceivers(scene, "beginChanges");

for (var r = 0; r < removedIds.length; ++r)
this.callSceneReceivers(scene, "elementRemoved", removedIds[r]);

// wait for binary if needed
if (msg.header.fTotalBinarySize)
{
Expand All @@ -295,16 +299,6 @@
//______________________________________________________________________________


EveManager.prototype.callSceneReceivers = function (scene, fname, el) {
if (scene.$receivers) {
for (var i=0; i != scene.$receivers.length; i++) {
var receiver = scene.$receivers[i].obj;
receiver[fname](el);
}
}
}


EveManager.prototype.PostProcessSceneChanges = function()
{
if (!this.scene_changes) return;
Expand Down Expand Up @@ -365,12 +359,7 @@
}
}

if (scene.$receivers) {
for (var i=0; i != scene.$receivers.length; i++) {
var ctrl = scene.$receivers[i].obj;
if (ctrl) ctrl.endChanges();
}
}
this.callSceneReceivers(scene, "endChanges");

var treeRebuild = header.removedElements.length || (arr.length != nModified );

Expand All @@ -394,7 +383,7 @@
if (!ids) return;

for (var n=0;n<ids.length;++n) {
var element = this.map[ids[n]];
var element = this.GetElement(ids[n]);
if (!element) {
console.log("try to delete non-existing element with id", ids[n]);
continue;
Expand Down
253 changes: 253 additions & 0 deletions etc/eve7/EveScene.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
/// @file EveScene.js

(function( factory ) {
if ( typeof define === "function" && define.amd ) {
define( ['JSRootCore'], factory );
} else if (typeof exports === 'object' && typeof module !== 'undefined') {
factory(require("./JSRootCore.js"));
} else {
if (typeof JSROOT == 'undefined')
throw new Error('JSROOT is not defined', 'EveScene.js');

factory(JSROOT);
}
} (function(JSROOT) {

"use strict";

console.log("loading EveScene.js");

/// constructor, handle for REveScene class

function EveScene(mgr,scene,viewer)
{
this.mgr = mgr;
this.scene = scene;
this.id = scene.fSceneId;
this.viewer = viewer;
this.creator = new JSROOT.EVE.EveElements();
this.creator.useIndexAsIs = (JSROOT.GetUrlOption('useindx') !== null);
this.id2obj_map = {};

// register ourself for scene events
this.mgr.RegisterSceneReceiver(scene.fSceneId, this);
}

EveScene.prototype.hasRenderData = function(elem)
{
if (elem===undefined)
elem = this.mgr.GetElement(this.id);

if (!elem) return false;
if (elem.render_data) return true;
if (elem.childs)
for (var k = 0; k < elem.childs.length; ++k)
if (this.hasRenderData(elem.childs[k])) return true;
return false;
}

EveScene.prototype.makeGLRepresentation = function(elem)
{
if (!elem.render_data) return null;
var fname = elem.render_data.rnr_func;
var obj3d = this.creator[fname](elem, elem.render_data);
if (obj3d)
{
obj3d._typename = "THREE.Mesh";

// SL: this is just identifier for highlight, required to show items on other places, set in creator
obj3d.geo_object = elem.fMasterId || elem.fElementId;
obj3d.geo_name = elem.fName; // used for highlight

//AMT: reference needed in MIR callback
obj3d.eveId = elem.fElementId;

if (elem.render_data.matrix)
{
obj3d.matrixAutoUpdate = false;
obj3d.matrix.fromArray( elem.render_data.matrix );
obj3d.updateMatrixWorld(true);
}
return obj3d;
}
}

EveScene.prototype.create3DObjects = function(res3d, all_ancestor_children_visible, elem0)
{
if (elem0 === undefined)
elem0 = this.mgr.GetElement(this.id);

if (!elem0 || !elem0.childs) return;

for (var k = 0; k < elem0.childs.length; ++k)
{
var elem = elem0.childs[k];
if (elem.render_data)
{
var fname = elem.render_data.rnr_func, obj3d = null;
if (!this.creator[fname])
{
console.error("Function " + fname + " missing in creator");
}
else
{
var obj3d = this.makeGLRepresentation(elem);
if (obj3d)
{
// MT - should maintain hierarchy ????
// Easier to remove ... but might need sub-class of
// Object3D to separate "graphical" children and structural children.

res3d.push(obj3d);

this.id2obj_map[elem.fElementId] = obj3d;

obj3d.visible = elem.fRnrSelf && all_ancestor_children_visible;
obj3d.all_ancestor_children_visible = all_ancestor_children_visible;
}
}
}

this.create3DObjects(res3d, elem.fRnrChildren && all_ancestor_children_visible, elem);
}
}

/** method insert all objects into three.js container */
EveScene.prototype.redrawScene = function()
{
if (!this.viewer) return;

var res3d = [];
this.create3DObjects(res3d, true);

var cont = this.viewer.getThreejsContainer("scene" + this.id);
while (cont.children.length > 0)
cont.remove(cont.children[0]);

for (var k = 0; k < res3d.length; ++k)
cont.add(res3d[k]);

this.viewer.render();
}

EveScene.prototype.getObj3D = function(elementId)
{
return this.id2obj_map[elementId];
}

EveScene.prototype.update3DObjectsVisibility = function(arr, all_ancestor_children_visible)
{
if (!arr) return;

for (var k = 0; k < arr.length; ++k)
{
var elem = arr[k];
if (elem.render_data)
{
var obj3d = this.getObj3D(elem.fElementId);
if (obj3d)
{
obj3d.visible = elem.fRnrSelf && all_ancestor_children_visible;
obj3d.all_ancestor_children_visible = all_ancestor_children_visible;
}
}

this.update3DObjectsVisibility(elem.childs, elem.fRnrChildren && all_ancestor_children_visible);
}
}

EveScene.prototype.visibilityChildrenChanged = function(el)
{
console.log("visibility children changed ", this.mgr, el);

if (el.childs)
{
// XXXX Overkill, but I don't have obj3d for all elements.
// Also, can do this traversal once for the whole update package,
// needs to be managed from EveManager.js.
// Or marked here and then recomputed before rendering (probably better).

var scene = this.mgr.GetElement(el.fSceneId);

this.update3DObjectsVisibility(scene.childs, true);

if (this.viewer)
this.viewer.render();
}
}

EveScene.prototype.colorChanged = function(el)
{
console.log("color change ", el.fElementId, el.fMainColor);

this.replaceElement(el);
}

EveScene.prototype.replaceElement = function(el)
{
if (!this.viewer) return;

var obj3d = this.getObj3D(el.fElementId);

var container = this.viewer.getThreejsContainer("scene" + this.id);

container.remove(obj3d);

obj3d = this.makeGLRepresentation(el);

container.add(obj3d);

this.id2obj_map[el.fElementId] = obj3d;

this.viewer.render();
}

EveScene.prototype.elementAdded = function(el) {
if (!this.viewer) return;

var obj3d = this.makeGLRepresentation(el);
if (!obj3d) return;

var container = this.viewer.getThreejsContainer("scene" + this.id);

container.add(obj3d);
console.log("element added ", el);

this.viewer.render();
}

EveScene.prototype.visibilityChanged = function(el)
{
var obj3d = this.getObj3D( el.fElementId );

if (obj3d)
{
obj3d.visible = obj3d.all_ancestor_children_visible && el.fRnrSelf;
}

if (this.viewer)
this.viewer.render();
}


EveScene.prototype.elementRemoved = function() {
}

EveScene.prototype.beginChanges = function() {
}

EveScene.prototype.endChanges = function() {
}

EveScene.prototype.onSceneChanged = function(id)
{
console.log("scene changed", id);

this.redrawScene();
}

JSROOT.EVE.EveScene = EveScene;

return JSROOT;

}));
Loading

0 comments on commit 72d6bf7

Please sign in to comment.