-
Notifications
You must be signed in to change notification settings - Fork 2
/
part_mediator.js
110 lines (96 loc) · 3.98 KB
/
part_mediator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/* global THREE, convertStringToVec3, convertStringToQuaternion */
'use strict';
class PartMediator { // eslint-disable-line no-unused-vars
constructor(part) {
this.model = part;
// Create the root container.
this.rootObject = new THREE.Object3D(); // The THREEjs container (contains the slots container and the part representation.)
this.rootObject.matrixAutoUpdate = false;
this.rootObject.mediator = this;
this.rootObject.userData.isPartContainer = true;
// Create the representation (async load).
var model = '/robot-designer/assets/models/' + this.model.name + '/model.x3d';
var loader = new THREE.X3DLoader();
loader.load(model, (object3dList) => {
if (!Array.isArray(object3dList) || object3dList.length === 0)
return;
this.representation = object3dList[0]; // The THREEjs representation of the part.
this.representation.userData.isRepresentation = true;
this.rootObject.add(this.representation);
});
// Create the slot containers.
this.childrenSlots = {};
Object.keys(this.model.asset.slots).forEach((slotName) => {
var slot = this.model.asset.slots[slotName];
var object = new THREE.Object3D();
object.userData.isSlotContainer = true;
object.userData.slotType = slot.type;
object.userData.slotName = slotName;
var position = convertStringToVec3(slot.translation ? slot.translation : '0 0 0');
object.position.copy(position);
var quaternion = convertStringToQuaternion(slot.rotation ? slot.rotation : '0 1 0 0');
object.quaternion.copy(quaternion);
this.rootObject.add(object);
this.childrenSlots[slotName] = object;
});
// Link signals
this.model.addObserver('PartAdded', (d) => this.onPartAdded(d));
this.model.addObserver('PartRemoved', (d) => this.onPartRemoved(d));
this.model.addObserver('Translated', (d) => this.onTranslated(d));
this.model.addObserver('Rotated', (d) => this.onRotated(d));
this.model.addObserver('ColorChanged', (d) => this.onColorChanged(d));
// Apply initial parameters.
this.onTranslated({'translation': this.model.translation});
this.onRotated({'quaternion': this.model.quaternion});
if (typeof this.model.color !== 'undefined')
this.onColorChanged({'color': this.model.color});
}
onPartAdded(data) {
// Create the new part mediator, attach its root parts to this slot.
var mediator = new PartMediator(data.part);
this.childrenSlots[data.slotName].add(mediator.rootObject);
}
onPartRemoved(data) {
// Remove the child part containers.
// The slot container should contain only one part container and eventually the handle target.
for (let c = this.childrenSlots[data.slotName].children.length - 1; c >= 0; c--) { // technique to loop through array while removing array items.
var child = this.childrenSlots[data.slotName].children[c];
if (child.userData.isPartContainer)
child.parent.remove(child);
else
console.assert(child.userData.isHandleTarget);
}
}
onTranslated(data) {
var translation = new THREE.Vector3(
data.translation[0],
data.translation[1],
data.translation[2]
);
this.rootObject.position.copy(translation);
this.rootObject.updateMatrix();
}
onRotated(data) {
var quaternion = new THREE.Quaternion(
data.quaternion[0],
data.quaternion[1],
data.quaternion[2],
data.quaternion[3]
);
this.rootObject.quaternion.copy(quaternion);
this.rootObject.updateMatrix();
}
onColorChanged(data) {
// TODO: color should not be hardcoded here.
if (!this.representation)
return; // TODO: this.representation may not exists a this point :-(
this.representation.traverse((child) => {
if (child.isMesh) {
if (data.color === 'yellow')
child.material.color = new THREE.Color('rgb(100%, 60%, 0%)');
else if (data.color === 'blue')
child.material.color = new THREE.Color('rgb(0%, 45%, 100%)');
}
});
}
}