-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathindex.js
165 lines (145 loc) · 4.35 KB
/
index.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
var debug = AFRAME.utils.debug;
var coordinates = AFRAME.utils.coordinates;
var warn = debug('components:look-at:warn');
var isCoordinate = coordinates.isCoordinate;
delete AFRAME.components['look-at'];
/**
* Look-at component.
*
* Modifies rotation to either track another entity OR do a one-time turn towards a position
* vector.
*
* If tracking an object via setting the component value via a selector, look-at will register
* a behavior to the scene to update rotation on every tick.
*/
AFRAME.registerComponent('look-at', {
schema: {
src: {
default: '',
parse: function (value) {
// A static position to look at.
if (isCoordinate(value) || typeof value === 'object') {
return coordinates.parse(value);
}
// A selector to a target entity.
return value;
},
stringify: function (data) {
if (typeof data === 'object') {
return coordinates.stringify(data);
}
return data;
},
},
checkSrcEveryFrame: {
default: false,
},
updateWorldTransform: {
default: false,
}
},
init: function () {
this.target3D = null;
this.vector = new THREE.Vector3();
},
/**
* If tracking an object, this will be called on every tick.
* If looking at a position vector, this will only be called once (until further updates).
*/
update: function () {
var self = this;
var target = self.data.src;
var object3D = self.el.object3D;
var targetEl;
// No longer looking at anything (i.e., look-at="").
if (!target || (typeof target === 'object' && !Object.keys(target).length)) {
return self.remove();
}
// Look at a position.
if (typeof target === 'object') {
return object3D.lookAt(new THREE.Vector3(target.x, target.y, target.z));
}
return this.updateTarget(target);
},
updateTarget: function (target) {
var self = this;
// Assume target is a string.
// Query for the element, grab its object3D, then register a behavior on the scene to
// track the target on every tick.
targetEl = this.el.sceneEl.querySelector(target);
if (!targetEl) {
warn('"' + target + '" does not point to a valid entity to look-at');
return;
}
if (!targetEl.hasLoaded) {
return targetEl.addEventListener('loaded', function () {
self.beginTracking(targetEl);
});
}
return self.beginTracking(targetEl);
},
tick: function (t) {
var self = this;
var target = self.data.target;
var object3D = self.el.object3D;
var targetEl;
// Track target object position. Depends on parent object keeping
// global transforms up to state with updateMatrixWorld().
// In practice, this is handled by the renderer, but will result in
//
if (typeof self.data.target === 'string' && self.data.checkSrcEveryFrame) {
targetEl = self.el.sceneEl.querySelector(target);
if (!targetEl) {
warn('"' + target + '" does not point to a valid entity to look-at');
this.target3D = null;
return;
}
if (!targetEl.hasLoaded) {
return targetEl.addEventListener('loaded', function () {
self.beginTracking(targetEl);
});
} else {
self.beginTracking(targetEl);
}
}
if (this.target3D) {
this.vector.setFromMatrixPosition(this.target3D.matrixWorld);
if (object3D.parent) {
if (this.data.updateWorldTransform) {
object3D.parent.updateMatrixWorld();
}
object3D.parent.worldToLocal(this.vector);
}
return object3D.lookAt(this.vector);
}
},
beginTracking: function (targetEl) {
this.target3D = targetEl.object3D;
}
});
/**
* Billboard component.
*
* Modifies rotation to track the current camera, keeping the entity facing it
*
*/
AFRAME.registerComponent('billboard', {
init: function () {
this.vector = new THREE.Vector3();
},
tick: function (t) {
var self = this;
var target = self.el.sceneEl.camera;
var object3D = self.el.object3D;
// make sure camera is set
if (target) {
target.updateMatrixWorld();
this.vector.setFromMatrixPosition(target.matrixWorld);
if (object3D.parent) {
object3D.parent.updateMatrixWorld();
object3D.parent.worldToLocal(this.vector);
}
return object3D.lookAt(this.vector);
}
}
});