Skip to content

Commit d35e56e

Browse files
committed
Merge pull request #769 from ngokevin/flat5
schema property types, single-property schemas (fixes #740)
2 parents 551ab7d + 9216648 commit d35e56e

26 files changed

+778
-337
lines changed

src/components/geometry.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var utils = require('../utils');
55

66
var DEFAULT_RADIUS = 1;
77
var helperMatrix = new THREE.Matrix4();
8-
var rad = THREE.Math.degToRad;
8+
var degToRad = THREE.Math.degToRad;
99
var warn = debug('components:geometry:warn');
1010

1111
/**
@@ -50,7 +50,6 @@ module.exports.Component = registerComponent('geometry', {
5050
height: { default: 2, min: 0, if: { primitive: ['box', 'plane'] } },
5151
openEnded: { default: false, if: { primitive: ['cylinder'] } },
5252
p: { default: 2, if: { primitive: ['torusKnot'] }, type: 'int' },
53-
translate: { default: { x: 0, y: 0, z: 0 } },
5453
primitive: {
5554
default: '',
5655
oneOf: ['', 'box', 'circle', 'cylinder', 'plane',
@@ -75,6 +74,7 @@ module.exports.Component = registerComponent('geometry', {
7574
thetaLength: { default: 360, min: 0, if: { primitive: ['circle', 'cylinder', 'ring',
7675
'sphere'] } },
7776
thetaStart: { default: 0, if: { primitive: ['circle', 'cylinder', 'ring', 'sphere'] } },
77+
translate: { type: 'vec3' },
7878
width: { default: 2, min: 0, if: { primitive: ['box', 'plane'] } }
7979
},
8080

@@ -125,40 +125,40 @@ function getGeometry (data, schema) {
125125
}
126126
case 'circle': {
127127
return new THREE.CircleGeometry(
128-
data.radius, data.segments, rad(data.thetaStart), rad(data.thetaLength));
128+
data.radius, data.segments, degToRad(data.thetaStart), degToRad(data.thetaLength));
129129
}
130130
case 'cone': {
131131
return new THREE.CylinderGeometry(
132132
data.radiusTop, data.radiusBottom, data.height,
133133
data.segmentsRadial, data.segmentsHeight,
134-
data.openEnded, rad(data.thetaStart), rad(data.thetaLength));
134+
data.openEnded, degToRad(data.thetaStart), degToRad(data.thetaLength));
135135
}
136136
case 'cylinder': {
137137
return new THREE.CylinderGeometry(
138138
data.radius, data.radius, data.height,
139139
data.segmentsRadial, data.segmentsHeight,
140-
data.openEnded, rad(data.thetaStart), rad(data.thetaLength));
140+
data.openEnded, degToRad(data.thetaStart), degToRad(data.thetaLength));
141141
}
142142
case 'plane': {
143143
return new THREE.PlaneBufferGeometry(data.width, data.height);
144144
}
145145
case 'ring': {
146146
return new THREE.RingGeometry(
147147
data.radiusInner, data.radiusOuter, data.segmentsTheta, data.segmentsPhi,
148-
rad(data.thetaStart), rad(data.thetaLength));
148+
degToRad(data.thetaStart), degToRad(data.thetaLength));
149149
}
150150
case 'sphere': {
151151
// thetaLength's default for spheres is different from those of the other geometries.
152152
// For now, we detect if thetaLength is exactly 360 to switch to a different default.
153153
if (data.thetaLength === 360) { data.thetaLength = 180; }
154154
return new THREE.SphereBufferGeometry(
155-
data.radius, data.segmentsWidth, data.segmentsHeight, rad(data.phiStart),
156-
rad(data.phiLength), rad(data.thetaStart), rad(data.thetaLength));
155+
data.radius, data.segmentsWidth, data.segmentsHeight, degToRad(data.phiStart),
156+
degToRad(data.phiLength), degToRad(data.thetaStart), degToRad(data.thetaLength));
157157
}
158158
case 'torus': {
159159
return new THREE.TorusGeometry(
160160
data.radius, data.radiusTubular * 2, data.segmentsRadial, data.segmentsTubular,
161-
rad(data.arc));
161+
degToRad(data.arc));
162162
}
163163
case 'torusKnot': {
164164
return new THREE.TorusKnotGeometry(

src/components/light.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ var debug = require('../utils/debug');
33
var registerComponent = require('../core/component').registerComponent;
44
var THREE = require('../../lib/three');
55

6-
var rad = THREE.Math.degToRad;
6+
var degToRad = THREE.Math.degToRad;
77
var warn = debug('components:light:warn');
88

99
/**
@@ -123,7 +123,7 @@ function getLight (data) {
123123
return new THREE.PointLight(color, intensity, distance, decay);
124124
}
125125
case 'spot': {
126-
return new THREE.SpotLight(color, intensity, distance, rad(angle), data.exponent,
126+
return new THREE.SpotLight(color, intensity, distance, degToRad(angle), data.exponent,
127127
decay);
128128
}
129129
default: {

src/components/look-at.js

Lines changed: 38 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ var isCoordinate = coordinates.isCoordinate;
2626
* @member {object} vector - Helper vector to do matrix transformations.
2727
*/
2828
module.exports.Component = registerComponent('look-at', {
29+
schema: { default: '' },
30+
2931
init: function () {
3032
this.target3D = null;
3133
this.vector = new THREE.Vector3();
@@ -37,84 +39,67 @@ module.exports.Component = registerComponent('look-at', {
3739
*/
3840
update: function () {
3941
var self = this;
40-
var data = self.data;
41-
var position = data.position;
42+
var target = self.data;
4243
var object3D = self.el.object3D;
4344
var target3D = self.target3D;
4445
var targetEl;
45-
var targetSelector = data.targetSelector;
4646

4747
// Track target object position. Depends on parent object keeping global transforms up
4848
// to state with updateMatrixWorld(). In practice, this is handled by the renderer.
4949
if (target3D) {
5050
return object3D.lookAt(self.vector.setFromMatrixPosition(target3D.matrixWorld));
5151
}
5252

53-
// Query for the element, grab its object3D, then register a behavior on the scene to
54-
// track the target on every tick.
55-
if (targetSelector) {
56-
targetEl = document.querySelector(targetSelector);
57-
if (!targetEl) {
58-
warn('"' + targetSelector + '" does not point to a valid entity to look-at');
59-
return;
60-
}
61-
if (!targetEl.hasLoaded) {
62-
return targetEl.addEventListener('loaded', function () {
63-
self.beginTracking(targetEl);
64-
});
65-
}
66-
return self.beginTracking(targetEl);
53+
// No longer looking at anything (i.e., look-at="").
54+
if (!target ||
55+
(typeof target === 'object' && !Object.keys(target).length)) {
56+
return self.remove();
6757
}
6858

6959
// Look at a position.
70-
if (position) {
71-
object3D.lookAt(new THREE.Vector3(position.x, position.y, position.z));
72-
return;
60+
if (typeof target === 'object') {
61+
return object3D.lookAt(new THREE.Vector3(target.x, target.y, target.z));
7362
}
7463

75-
// No longer looking at anything (i.e., look-at="").
76-
if (!position && !targetSelector) { return self.remove(); }
64+
// Assume target is a string.
65+
// Query for the element, grab its object3D, then register a behavior on the scene to
66+
// track the target on every tick.
67+
targetEl = self.el.sceneEl.querySelector(target);
68+
if (!targetEl) {
69+
warn('"' + target + '" does not point to a valid entity to look-at');
70+
return;
71+
}
72+
if (!targetEl.hasLoaded) {
73+
return targetEl.addEventListener('loaded', function () {
74+
self.beginTracking(targetEl);
75+
});
76+
}
77+
return self.beginTracking(targetEl);
7778
},
7879

7980
/**
8081
* Remove follow behavior on remove (callback).
8182
*/
8283
remove: function () {
83-
this.el.sceneEl.removeBehavior(this);
84-
},
85-
86-
beginTracking: function (targetEl) {
87-
this.target3D = targetEl.object3D;
88-
this.el.sceneEl.addBehavior(this);
84+
if (this.target3D) {
85+
this.el.sceneEl.removeBehavior(this);
86+
this.target3D = null;
87+
}
8988
},
9089

91-
/**
92-
* Determine whether attribute value is a target selector or a position.
93-
* Parse the attribute value if it is a position.
94-
*
95-
* @param {string} value - HTML attribute of component.
96-
* @returns {object}
97-
*/
9890
parse: function (value) {
99-
if (!value) {
100-
return {
101-
position: null,
102-
targetSelector: null
103-
};
91+
if (isCoordinate(value) || typeof value === 'object') {
92+
return coordinates.parse(value);
10493
}
105-
// Check if value is a position. Need to match digits since a target selector could have
106-
// three values as well (e.g., look-at="#el .el .box").
107-
if (isCoordinate(value)) {
108-
return {
109-
position: coordinates.parse(value),
110-
targetSelector: null
111-
};
112-
}
113-
return {
114-
position: null,
115-
targetSelector: value
116-
};
94+
return value;
95+
},
96+
97+
stringify: function (data) {
98+
return coordinates.stringify(data);
11799
},
118100

119-
stringify: coordinates.componentMixin.stringify
101+
beginTracking: function (targetEl) {
102+
this.target3D = targetEl.object3D;
103+
this.el.sceneEl.addBehavior(this);
104+
}
120105
});

src/components/position.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
var coordinatesMixin = require('../utils/coordinates').componentMixin;
21
var registerComponent = require('../core/component').registerComponent;
3-
var utils = require('../utils/');
42

5-
module.exports.Component = registerComponent('position', utils.extend({
6-
schema: {
7-
x: { default: 0 },
8-
y: { default: 0 },
9-
z: { default: 0 }
10-
},
3+
module.exports.Component = registerComponent('position', {
4+
schema: { type: 'vec3' },
115

126
update: function () {
137
var object3D = this.el.object3D;
148
var data = this.data;
159
object3D.position.set(data.x, data.y, data.z);
1610
}
17-
}, coordinatesMixin));
11+
});

src/components/rotation.js

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,16 @@
1-
var coordinatesMixin = require('../utils/coordinates').componentMixin;
1+
var degToRad = require('../../lib/three').Math.degToRad;
22
var registerComponent = require('../core/component').registerComponent;
3-
var THREE = require('../../lib/three');
4-
var utils = require('../utils/');
53

6-
module.exports.Component = registerComponent('rotation', utils.extend({
7-
schema: {
8-
x: { default: 0 },
9-
y: { default: 0 },
10-
z: { default: 0 }
11-
},
4+
module.exports.Component = registerComponent('rotation', {
5+
schema: { type: 'vec3' },
126

137
/**
148
* Updates object3D rotation.
159
*/
1610
update: function () {
1711
var data = this.data;
1812
var object3D = this.el.object3D;
19-
object3D.rotation.set(THREE.Math.degToRad(data.x),
20-
THREE.Math.degToRad(data.y),
21-
THREE.Math.degToRad(data.z));
13+
object3D.rotation.set(degToRad(data.x), degToRad(data.y), degToRad(data.z));
2214
object3D.rotation.order = 'YXZ';
2315
}
24-
}, coordinatesMixin));
16+
});

src/components/scale.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
var coordinatesMixin = require('../utils/coordinates').componentMixin;
21
var registerComponent = require('../core/component').registerComponent;
3-
var utils = require('../utils/');
42

53
// Avoids triggering a zero-determinant which makes object3D matrix non-invertible.
64
var zeroScale = 0.00001;
75

8-
module.exports.Component = registerComponent('scale', utils.extend({
6+
module.exports.Component = registerComponent('scale', {
97
schema: {
10-
x: { default: 1 },
11-
y: { default: 1 },
12-
z: { default: 1 }
8+
type: 'vec3',
9+
default: { x: 1, y: 1, z: 1 }
1310
},
1411

1512
update: function () {
@@ -20,4 +17,4 @@ module.exports.Component = registerComponent('scale', utils.extend({
2017
var z = data.z === 0 ? zeroScale : data.z;
2118
object3D.scale.set(x, y, z);
2219
}
23-
}, coordinatesMixin));
20+
});

src/components/visible.js

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,14 @@ var registerComponent = require('../core/component').registerComponent;
22

33
/**
44
* Visibility component.
5-
*
6-
* @param {bool}
75
*/
86
module.exports.Component = registerComponent('visible', {
9-
schema: { default: true },
7+
schema: {
8+
type: 'boolean',
9+
default: true
10+
},
1011

1112
update: function () {
1213
this.el.object3D.visible = this.data;
13-
},
14-
15-
parse: function (value) {
16-
return value !== 'false';
17-
},
18-
19-
stringify: function (value) {
20-
return value.toString();
2114
}
2215
});

src/core/a-animation.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
var ANode = require('./a-node');
2-
var coerce = require('../utils/').coerce;
32
var constants = require('../constants/animation');
43
var coordinates = require('../utils/').coordinates;
4+
var parseProperty = require('./schema').parseProperty;
55
var registerElement = require('./a-register-element').registerElement;
66
var TWEEN = require('tween.js');
77
var utils = require('../utils/');
@@ -367,7 +367,7 @@ function cloneValue (val) {
367367
*/
368368
function getAnimationValues (el, attribute, dataFrom, dataTo, currentValue) {
369369
var attributeSplit = attribute.split('.');
370-
var coerceSchema;
370+
var schema;
371371
var component;
372372
var componentPropName;
373373
var componentName;
@@ -401,14 +401,14 @@ function getAnimationValues (el, attribute, dataFrom, dataTo, currentValue) {
401401
el.setAttribute(componentName, '');
402402
component = el.components[componentName];
403403
}
404-
coerceSchema = component.schema;
404+
schema = component.schema;
405405
if (dataFrom === undefined) { // dataFrom can be 0.
406406
from[attribute] = el.getComputedAttribute(componentName)[componentPropName];
407407
} else {
408408
from[attribute] = dataFrom;
409409
}
410-
from[attribute] = coerce(from[attribute], coerceSchema, componentPropName);
411-
to[attribute] = coerce(dataTo, coerceSchema, componentPropName);
410+
from[attribute] = parseProperty(from[attribute], schema[componentPropName]);
411+
to[attribute] = parseProperty(dataTo, schema[componentPropName]);
412412
partialSetAttribute = function (value) {
413413
el.setAttribute(componentName, componentPropName, value[attribute]);
414414
};

src/core/a-entity.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,6 @@ var proto = Object.create(ANode.prototype, {
322322
delete this.components[name];
323323
return;
324324
}
325-
if (typeof newData === 'string') {
326-
newData = component.parse(newData);
327-
}
328325
// Component already initialized. Update component.
329326
component.updateProperties(newData);
330327
return;
@@ -447,6 +444,7 @@ var proto = Object.create(ANode.prototype, {
447444
value = value === undefined ? '' : value;
448445
var valueStr = value;
449446
var oldValue;
447+
450448
if (component) {
451449
if (typeof value === 'string' && componentPropValue !== undefined) {
452450
// Update currently-defined component data with the new property value.

0 commit comments

Comments
 (0)