Skip to content

Commit 679a5d9

Browse files
ngokevindmarcos
authored andcommitted
wait for scene load before default camera check (fixes #1723) (#1724)
1 parent 778d41e commit 679a5d9

File tree

4 files changed

+69
-32
lines changed

4 files changed

+69
-32
lines changed

‎src/core/a-entity.js‎

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
/* global HTMLElement */
22
var ANode = require('./a-node');
33
var components = require('./component').components;
4-
var re = require('./a-register-element');
4+
var registerElement = require('./a-register-element').registerElement;
55
var THREE = require('../lib/three');
66
var utils = require('../utils/');
77

88
var AEntity;
9-
var isNode = re.isNode;
109
var debug = utils.debug('core:a-entity:debug');
11-
var registerElement = re.registerElement;
1210

1311
var MULTIPLE_COMPONENT_DELIMITER = '__';
1412

@@ -41,6 +39,7 @@ var proto = Object.create(ANode.prototype, {
4139
this.object3D = new THREE.Group();
4240
this.object3D.el = this;
4341
this.object3DMap = {};
42+
this.parentEl = null;
4443
this.states = [];
4544
}
4645
},
@@ -206,7 +205,11 @@ var proto = Object.create(ANode.prototype, {
206205
return object3D;
207206
}
208207
},
209-
208+
/**
209+
* Add child entity.
210+
*
211+
* @param {Element} el - Child entity.
212+
*/
210213
add: {
211214
value: function (el) {
212215
if (!el.object3D) {
@@ -217,24 +220,18 @@ var proto = Object.create(ANode.prototype, {
217220
}
218221
},
219222

223+
/**
224+
* Tell parentNode to add this entity to itself.
225+
*/
220226
addToParent: {
221227
value: function () {
222-
var self = this;
223-
var parent = this.parentEl = this.parentNode;
224-
var attachedToParent = this.attachedToParent;
225-
if (!parent || attachedToParent) { return; }
226-
if (isNode(parent)) {
227-
attach();
228-
return;
229-
}
230-
parent.addEventListener('nodeready', attach);
231-
function attach () {
232-
// To prevent an object to attach itself multiple times to the parent.
233-
self.attachedToParent = true;
234-
if (parent.add) {
235-
parent.add(self);
236-
}
237-
}
228+
var parentNode = this.parentEl = this.parentNode;
229+
230+
// `!parentNode` check primarily for unit tests.
231+
if (!parentNode || !parentNode.add || this.attachedToParent) { return; }
232+
233+
parentNode.add(this);
234+
this.attachedToParent = true; // To prevent multiple attachments to same parent.
238235
}
239236
},
240237

@@ -265,6 +262,11 @@ var proto = Object.create(ANode.prototype, {
265262
writable: window.debug
266263
},
267264

265+
/**
266+
* Remove child entity.
267+
*
268+
* @param {Element} el - Child entity.
269+
*/
268270
remove: {
269271
value: function (el) {
270272
this.object3D.remove(el.object3D);

‎src/systems/camera.js‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,35 @@ module.exports.System = registerSystem('camera', {
1515
},
1616

1717
/**
18-
* Creates a default camera if user has not added one during the initial scene traversal.
18+
* Create a default camera if user has not added one during the initial scene traversal.
1919
*
20-
* Default camera height is at human level (~1.8m) and back such that
21-
* entities at the origin (0, 0, 0) are well-centered.
20+
* Default camera offset height is at average eye level (~1.6m).
2221
*/
2322
setupDefaultCamera: function () {
2423
var self = this;
2524
var sceneEl = this.sceneEl;
2625
var defaultCameraEl;
27-
// setTimeout in case the camera is being set dynamically with a setAttribute.
28-
setTimeout(checkForCamera);
29-
function checkForCamera () {
26+
27+
// Wait for all entities to fully load before checking for existence of camera.
28+
// Since entities wait for <a-assets> to load, any cameras attaching to the scene
29+
// will do so asynchronously.
30+
sceneEl.addEventListener('loaded', function checkForCamera () {
3031
var currentCamera = sceneEl.camera;
3132
if (currentCamera) {
32-
sceneEl.emit('camera-ready', { cameraEl: currentCamera.el });
33+
sceneEl.emit('camera-ready', {cameraEl: currentCamera.el});
3334
return;
3435
}
3536
defaultCameraEl = document.createElement('a-entity');
3637
defaultCameraEl.setAttribute('position', '0 0 0');
3738
defaultCameraEl.setAttribute(DEFAULT_CAMERA_ATTR, '');
38-
defaultCameraEl.setAttribute('camera',
39-
{active: true, userHeight: DEFAULT_USER_HEIGHT});
39+
defaultCameraEl.setAttribute('camera', {active: true, userHeight: DEFAULT_USER_HEIGHT});
4040
defaultCameraEl.setAttribute('wasd-controls', '');
4141
defaultCameraEl.setAttribute('look-controls', '');
4242
sceneEl.appendChild(defaultCameraEl);
4343
sceneEl.addEventListener('enter-vr', self.removeDefaultOffset);
4444
sceneEl.addEventListener('exit-vr', self.addDefaultOffset);
4545
sceneEl.emit('camera-ready', {cameraEl: defaultCameraEl});
46-
}
46+
});
4747
},
4848

4949
/**

‎tests/core/a-entity.test.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,15 @@ suite('a-entity', function () {
357357
var parentEl = entityFactory();
358358
var el = document.createElement('a-entity');
359359

360-
parentEl.appendChild(el);
361-
362360
el.addEventListener('loaded', function () {
363361
parentEl.removeChild(el);
364362
process.nextTick(function () {
365363
assert.equal(parentEl.object3D.children.length, 0);
366364
done();
367365
});
368366
});
367+
368+
parentEl.appendChild(el);
369369
});
370370

371371
test('removes itself from scene parent', function (done) {

‎tests/systems/camera.test.js‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,41 @@ suite('camera system', function () {
1010
});
1111
});
1212

13+
suite('setupDefaultCamera', function () {
14+
test('uses defined camera if defined', function (done) {
15+
var assetsEl;
16+
var imgEl; // Image that will never load.
17+
var cameraEl;
18+
var sceneEl;
19+
20+
// Create assets.
21+
assetsEl = document.createElement('a-assets');
22+
imgEl = document.createElement('img');
23+
imgEl.setAttribute('src', 'neverloadlalala5.gif');
24+
assetsEl.appendChild(imgEl);
25+
26+
// Create scene.
27+
sceneEl = document.createElement('a-scene');
28+
sceneEl.appendChild(assetsEl);
29+
30+
// Create camera.
31+
cameraEl = document.createElement('a-entity');
32+
cameraEl.setAttribute('camera', '');
33+
sceneEl.appendChild(cameraEl);
34+
35+
sceneEl.addEventListener('loaded', function () {
36+
assert.equal(sceneEl.camera.el, cameraEl);
37+
done();
38+
});
39+
40+
document.body.appendChild(sceneEl);
41+
42+
// Trigger scene load through assets. Camera will be waiting for assets.
43+
// Add `setTimeout` to mimic asynchrony of asset loading.
44+
setTimeout(function () { assetsEl.load(); });
45+
});
46+
});
47+
1348
suite('setActiveCamera', function () {
1449
test('sets new active camera on scene', function () {
1550
var el = this.el;

0 commit comments

Comments
 (0)