Browse Source

initial functionality for edges - connected is working, others are TODOs

webworkersNetwork^2^2
Eric VanDever 9 years ago
parent
commit
5bfa385924
4 changed files with 79 additions and 34 deletions
  1. +29
    -11
      lib/network/modules/PhysicsEngine.js
  2. +35
    -21
      lib/network/modules/PhysicsWorker.js
  3. +13
    -0
      lib/network/modules/components/Edge.js
  4. +2
    -2
      lib/network/modules/components/Node.js

+ 29
- 11
lib/network/modules/PhysicsEngine.js View File

@ -251,20 +251,34 @@ class PhysicsEngine {
this.physicsUpdateHandler = (properties) => { this.physicsUpdateHandler = (properties) => {
if (properties.options.physics !== undefined) { if (properties.options.physics !== undefined) {
if (properties.options.physics) { if (properties.options.physics) {
let nodes = {};
nodes[properties.id] = this.createPhysicsNode(properties.id);
let data = {
nodes: {},
edges: {}
};
if (properties.type === 'node') {
data.nodes[properties.id] = this.createPhysicsNode(properties.id);
} else if (properties.type === 'edge') {
data.edges[properties.id] = this.createPhysicsEdge(properties.id);
} else {
console.warn('invalid element type');
}
this.physicsWorker.postMessage({ this.physicsWorker.postMessage({
type: 'addElements', type: 'addElements',
data: {
nodes: nodes,
edges: {}
}
data: data
}); });
} else { } else {
this.physicsWorker.postMessage({type: 'removeElements', data: {
nodes: [properties.id.toString()],
edges: []
}});
let data = {
nodeIds: [],
edgeIds: []
};
if (properties.type === 'node') {
data.nodeIds = [properties.id.toString()];
} else if (properties.type === 'edge') {
data.edgeIds = [properties.id.toString()];
} else {
console.warn('invalid element type');
}
this.physicsWorker.postMessage({type: 'removeElements', data: data});
} }
} else { } else {
this.physicsWorker.postMessage({type: 'updateProperties', data: properties}); this.physicsWorker.postMessage({type: 'updateProperties', data: properties});
@ -505,11 +519,14 @@ class PhysicsEngine {
let edge = this.body.edges[edgeId]; let edge = this.body.edges[edgeId];
if (edge && edge.options.physics === true && edge.connected === true) { if (edge && edge.options.physics === true && edge.connected === true) {
let physicsEdge = { let physicsEdge = {
connected: edge.connected,
id: edge.id, id: edge.id,
connected: edge.connected,
edgeType: {}, edgeType: {},
toId: edge.toId, toId: edge.toId,
fromId: edge.fromId, fromId: edge.fromId,
// TODO when will toId not match to.id given that connected is true
// can we rewrite SpringSolver to only use toId and not to.id
// and remove these parameters
to: { to: {
id: edge.to.id id: edge.to.id
}, },
@ -520,6 +537,7 @@ class PhysicsEngine {
length: edge.length length: edge.length
} }
}; };
// TODO test/implment dynamic
if (edge.edgeType.via) { if (edge.edgeType.via) {
physicsEdge.edgeType = { physicsEdge.edgeType = {
via: { via: {

+ 35
- 21
lib/network/modules/PhysicsWorker.js View File

@ -21,8 +21,8 @@ class PhysicsWorker {
this.positions = {}; this.positions = {};
this.timestep = 0.5; this.timestep = 0.5;
this.toRemove = { this.toRemove = {
nodes: [],
edges: []
nodeIds: [],
edgeIds: []
}; };
} }
@ -50,8 +50,8 @@ class PhysicsWorker {
case 'removeElements': case 'removeElements':
// schedule removal of elements on the next physicsTick // schedule removal of elements on the next physicsTick
// avoids having to defensively check every node read in each physics implementation // avoids having to defensively check every node read in each physics implementation
this.toRemove.nodes.push.apply(this.toRemove.nodes, msg.data.nodes);
this.toRemove.edges.push.apply(this.toRemove.edges, msg.data.edges);
this.toRemove.nodeIds.push.apply(this.toRemove.nodeIds, msg.data.nodeIds);
this.toRemove.edgeIds.push.apply(this.toRemove.edgeIds, msg.data.edgeIds);
break; break;
case 'initPhysicsData': case 'initPhysicsData':
this.initPhysicsData(msg.data); this.initPhysicsData(msg.data);
@ -103,8 +103,8 @@ class PhysicsWorker {
this.processRemovals(); this.processRemovals();
this.calculateForces(); this.calculateForces();
this.moveNodes(); this.moveNodes();
for (let i = 0; i < this.toRemove.nodes.length; i++) {
delete this.positions[this.toRemove.nodes[i]];
for (let i = 0; i < this.toRemove.nodeIds.length; i++) {
delete this.positions[this.toRemove.nodeIds[i]];
} }
this.postMessage({ this.postMessage({
type: 'positions', type: 'positions',
@ -116,22 +116,36 @@ class PhysicsWorker {
} }
updateProperties(data) { updateProperties(data) {
let optionsNode = this.body.nodes[data.id];
if (optionsNode) {
let opts = data.options;
if (opts.fixed) {
if (opts.fixed.x !== undefined) {
optionsNode.options.fixed.x = opts.fixed.x;
if (data.type === 'node') {
let optionsNode = this.body.nodes[data.id];
if (optionsNode) {
let opts = data.options;
if (opts.fixed) {
if (opts.fixed.x !== undefined) {
optionsNode.options.fixed.x = opts.fixed.x;
}
if (opts.fixed.y !== undefined) {
optionsNode.options.fixed.y = opts.fixed.y;
}
} }
if (opts.fixed.y !== undefined) {
optionsNode.options.fixed.y = opts.fixed.y;
if (opts.mass !== undefined) {
optionsNode.options.mass = opts.mass;
} }
} else {
console.warn('sending properties to unknown node');
} }
if (opts.mass !== undefined) {
optionsNode.options.mass = opts.mass;
} else if (data.type === 'edge') {
let edge = this.body.edges[data.id];
if (edge) {
let opts = data.options;
if (opts.connected) {
edge.connected = opts.connected;
}
} else {
console.warn('sending properties to unknown edge');
} }
} else { } else {
console.log('sending property to unknown node');
console.warn('sending properties to unknown element');
} }
} }
@ -169,8 +183,8 @@ class PhysicsWorker {
} }
processRemovals() { processRemovals() {
while (this.toRemove.nodes.length > 0) {
let nodeId = this.toRemove.nodes.pop();
while (this.toRemove.nodeIds.length > 0) {
let nodeId = this.toRemove.nodeIds.pop();
let index = this.physicsBody.physicsNodeIndices.indexOf(nodeId); let index = this.physicsBody.physicsNodeIndices.indexOf(nodeId);
if (index > -1) { if (index > -1) {
this.physicsBody.physicsNodeIndices.splice(index,1); this.physicsBody.physicsNodeIndices.splice(index,1);
@ -180,8 +194,8 @@ class PhysicsWorker {
delete this.positions[nodeId]; delete this.positions[nodeId];
delete this.body.nodes[nodeId]; delete this.body.nodes[nodeId];
} }
while (this.toRemove.edges.length > 0) {
let edgeId = this.toRemove.edges.pop();
while (this.toRemove.edgeIds.length > 0) {
let edgeId = this.toRemove.edgeIds.pop();
let index = this.physicsBody.physicsEdgeIndices.indexOf(edgeId); let index = this.physicsBody.physicsEdgeIndices.indexOf(edgeId);
if (index > -1) { if (index > -1) {
this.physicsBody.physicsEdgeIndices.splice(index,1); this.physicsBody.physicsEdgeIndices.splice(index,1);

+ 13
- 0
lib/network/modules/components/Edge.js View File

@ -51,7 +51,10 @@ class Edge {
this.labelModule = new Label(this.body, this.options); this.labelModule = new Label(this.body, this.options);
// prevents sending connected messages on initial creation as it should be handled by added element
this.sendPhysicsUpdates = false;
this.setOptions(options); this.setOptions(options);
this.sendPhysicsUpdates = true;
} }
@ -86,10 +89,14 @@ class Edge {
// A node is connected when it has a from and to node that both exist in the network.body.nodes. // A node is connected when it has a from and to node that both exist in the network.body.nodes.
this.connect(); this.connect();
// TODO make changing physics of 1 edge not trigger a complete rebuild of physics processing.
if (options.hidden !== undefined || options.physics !== undefined) { if (options.hidden !== undefined || options.physics !== undefined) {
dataChanged = true; dataChanged = true;
} }
// TODO if edgeType.via.id, toId, fromId, to.id, or from.id changed
// emit _physicsUpdate
return dataChanged; return dataChanged;
} }
@ -252,6 +259,8 @@ class Edge {
* Connect an edge to its nodes * Connect an edge to its nodes
*/ */
connect() { connect() {
let previousConnected = this.connected;
this.disconnect(); this.disconnect();
this.from = this.body.nodes[this.fromId] || undefined; this.from = this.body.nodes[this.fromId] || undefined;
@ -272,6 +281,10 @@ class Edge {
} }
this.edgeType.connect(); this.edgeType.connect();
if (this.sendPhysicsUpdates && this.connected !== previousConnected) {
this.body.emitter.emit('_physicsUpdate', {type: 'edge', id: this.id, options: {connected: this.connected}});
}
} }

+ 2
- 2
lib/network/modules/components/Node.js View File

@ -106,7 +106,7 @@ class Node {
// TODO split out fixed portion? // TODO split out fixed portion?
let physOpts = Node.parseOptions(this.options, {fixed: newFixed}); let physOpts = Node.parseOptions(this.options, {fixed: newFixed});
if (Object.keys(physOpts).length > 0) { if (Object.keys(physOpts).length > 0) {
this.body.emitter.emit('_physicsUpdate', {id: this.id, options: physOpts});
this.body.emitter.emit('_physicsUpdate', {type: 'node', id: this.id, options: physOpts});
} }
} }
@ -207,7 +207,7 @@ class Node {
} }
if (Object.keys(physOpts).length > 0) { if (Object.keys(physOpts).length > 0) {
this.body.emitter.emit('_physicsUpdate', {id: this.id, options: physOpts});
this.body.emitter.emit('_physicsUpdate', {type: 'node', id: this.id, options: physOpts});
} }
// TODO make embedded physics trigger this or handle _physicsUpdate messages // TODO make embedded physics trigger this or handle _physicsUpdate messages

Loading…
Cancel
Save