From 89aaa6f65795269cf90c26bc4e64cda1282eca9f Mon Sep 17 00:00:00 2001 From: Vaios Kalpias-Ilias Date: Wed, 25 Nov 2015 15:29:08 +0200 Subject: [PATCH 1/2] Load non-preloaded assets only when the components / entities that use them become enabled --- src/audio/audio_channel.js | 3 +- .../animation/animation_component.js | 35 ++++-- .../components/animation/animation_system.js | 2 +- .../audiosource/audiosource_component.js | 17 ++- .../components/model/model_component.js | 111 ++++++++++++++---- .../components/model/model_system.js | 2 +- .../particlesystem_component.js | 92 +++++++++------ .../physics/collision/collision_component.js | 10 ++ .../physics/collision/collision_system.js | 2 +- 9 files changed, 201 insertions(+), 73 deletions(-) diff --git a/src/audio/audio_channel.js b/src/audio/audio_channel.js index 899f8f294f4..e423dca9b19 100644 --- a/src/audio/audio_channel.js +++ b/src/audio/audio_channel.js @@ -92,7 +92,8 @@ pc.extend(pc, function () { */ unpause: function () { if (this.source || !this.paused) { - throw new Error('Call pause() before unpausing.'); + console.warn('Call pause() before unpausing.'); + return; } this._createSource(); diff --git a/src/framework/components/animation/animation_component.js b/src/framework/components/animation/animation_component.js index e94549ab46a..1102e741b72 100644 --- a/src/framework/components/animation/animation_component.js +++ b/src/framework/components/animation/animation_component.js @@ -118,8 +118,14 @@ pc.extend(pc, function () { asset.off('remove', self.onAssetRemoved, self); asset.on('remove', self.onAssetRemoved, self); - asset.ready(onAssetReady); - assets.load(asset); + if (asset.resource) { + onAssetReady(asset); + } else { + asset.once('load', onAssetReady, self); + if (self.enabled && self.entity.enabled) { + assets.load(asset); + } + } }; for(i = 0; i < l; i++) { @@ -174,17 +180,17 @@ pc.extend(pc, function () { var modelComponent = this.entity.model; if (modelComponent) { var m = modelComponent.model; - if (m) { + if (m && m !== data.model) { this.entity.animation.setModel(m); } } - for (var animName in data.animations) { - // Set the first loaded animation as the current - if (data.activate && data.enabled && this.entity.enabled && !this.system._inTools) { + if (! data.currAnim && data.activate && data.enabled && this.entity.enabled && !this.system._inTools) { + for (var animName in data.animations) { + // Set the first loaded animation as the current this.play(animName, 0); + break; } - break; } }, @@ -230,6 +236,21 @@ pc.extend(pc, function () { onEnable: function () { AnimationComponent._super.onEnable.call(this); + + // load assets if they're not loaded + var assets = this.data.assets; + var registry = this.system.app.assets; + if (assets) { + for (var i = 0, len = assets.length; i < len; i++) { + var asset = assets[i]; + if (! (asset instanceof pc.Asset)) + asset = registry.get(asset); + + if (asset && !asset.resource) + registry.load(asset); + } + } + if ( this.data.activate && !this.data.currAnim && !this.system._inTools) { diff --git a/src/framework/components/animation/animation_system.js b/src/framework/components/animation/animation_system.js index 4cbabce637b..ce816d05e7a 100644 --- a/src/framework/components/animation/animation_system.js +++ b/src/framework/components/animation/animation_system.js @@ -42,7 +42,7 @@ pc.extend(pc, function () { pc.extend(AnimationComponentSystem.prototype, { initializeComponentData: function (component, data, properties) { - properties = ['activate', 'loop', 'speed', 'assets', 'enabled']; + properties = ['activate', 'enabled', 'loop', 'speed', 'assets']; AnimationComponentSystem._super.initializeComponentData.call(this, component, data, properties); }, diff --git a/src/framework/components/audiosource/audiosource_component.js b/src/framework/components/audiosource/audiosource_component.js index 273bbd4c0ea..3139d001352 100644 --- a/src/framework/components/audiosource/audiosource_component.js +++ b/src/framework/components/audiosource/audiosource_component.js @@ -230,6 +230,21 @@ pc.extend(pc, function () { onEnable: function () { AudioSourceComponent._super.onEnable.call(this); + + // load assets that haven't been loaded yet + var assets = this.data.assets; + if (assets) { + for (var i = 0, len = assets.length; i < len; i++) { + var asset = assets[i]; + if (! (asset instanceof pc.Asset)) + asset = this.system.app.assets.get(asset); + + if (asset && !asset.resource) { + this.system.app.assets.load(asset); + } + } + } + if (this.system.initialized) { if (this.data.activate && !this.channel) { this.play(this.currentSource); @@ -293,7 +308,7 @@ pc.extend(pc, function () { } }); - if (! asset.resource) + if (! asset.resource && self.enabled && self.entity.enabled) this.system.app.assets.load(asset); } else { // don't wait for assets that aren't in the registry diff --git a/src/framework/components/model/model_component.js b/src/framework/components/model/model_component.js index b1e21b825ef..9b3106deb4a 100644 --- a/src/framework/components/model/model_component.js +++ b/src/framework/components/model/model_component.js @@ -39,8 +39,9 @@ pc.extend(pc, function () { }); this._assetOld = 0; - this._materialEvents = null; + this._dirtyModelAsset = false; + this._dirtyMaterialAsset = false; }; ModelComponent = pc.inherits(ModelComponent, pc.Component); @@ -70,6 +71,8 @@ pc.extend(pc, function () { var assets = this.system.app.assets; var asset = id !== null ? assets.get(id) : null; + this._dirtyModelAsset = true; + this._onModelAsset(asset || null); if (! asset && id !== null) @@ -101,10 +104,14 @@ pc.extend(pc, function () { asset.on('remove', this._onAssetRemove, this); if (asset.resource) { + this._dirtyModelAsset = false; this._onModelLoaded(asset.resource.clone()); - } else { + } else if (this.enabled && this.entity.enabled) { + this._dirtyModelAsset = false; assets.load(asset); } + } else { + this._dirtyModelAsset = false; } }, @@ -269,12 +276,16 @@ pc.extend(pc, function () { if (asset.resource) { this.material = asset.resource; - } else { + this._dirtyMaterialAsset = false; + } else if (this.enabled && this.entity.enabled) { + this._dirtyMaterialAsset = false; assets.load(asset); } }, setMaterialAsset: function (value) { + this._dirtyMaterialAsset = true; + // if the type of the value is not a number assume it is an pc.Asset var id = typeof value === 'number' || !value ? value : value.id; @@ -303,6 +314,7 @@ pc.extend(pc, function () { assets.once('add:' + id, this._onMaterialAsset, this); } else if (id === null) { self.material = pc.ModelHandler.DEFAULT_MATERIAL; + self._dirtyMaterialAsset = false; } var valueOld = this.data.materialAsset; @@ -391,23 +403,42 @@ pc.extend(pc, function () { this._materialEvents = null; }, - _loadAndSetMeshInstanceMaterial: function (idOrPath, meshInstance, index) { - var self = this; - var asset; - var assets = this.system.app.assets; - + _getAssetByIdOrPath: function (idOrPath) { + var asset = null; var isPath = isNaN(parseInt(idOrPath, 10)); // get asset by id or url if (!isPath) { - asset = assets.get(idOrPath); - } else if (self.asset) { - var url = self._getMaterialAssetUrl(idOrPath); - if (!url) return; - - asset = assets.getByUrl(url); + asset = this.system.app.assets.get(idOrPath); + } else if (this.asset) { + var url = this._getMaterialAssetUrl(idOrPath); + if (url) + asset = this.system.app.assets.getByUrl(url); } + return asset; + }, + + _getMaterialAssetUrl: function (path) { + if (!this.asset) return null; + + var modelAsset = this.system.app.assets.get(this.asset); + if (!modelAsset) return null; + + var fileUrl = modelAsset.getFileUrl(); + var dirUrl = pc.path.getDirectory(fileUrl); + return pc.path.join(dirUrl, path); + }, + + _loadAndSetMeshInstanceMaterial: function (idOrPath, meshInstance, index) { + var self = this; + var assets = this.system.app.assets; + + // get asset by id or url + var asset = this._getAssetByIdOrPath(idOrPath); + if (! asset) + return; + var handleMaterial = function (asset) { if (asset.resource) { meshInstance.material = asset.resource; @@ -424,7 +455,8 @@ pc.extend(pc, function () { }); }); - assets.load(asset); + if (self.enabled && self.entity.enabled) + assets.load(asset); } }; @@ -432,21 +464,12 @@ pc.extend(pc, function () { handleMaterial(asset); } else { meshInstance.material = pc.ModelHandler.DEFAULT_MATERIAL; + + var isPath = isNaN(parseInt(idOrPath, 10)); self._setMaterialEvent(index, isPath ? 'add:url' : 'add', idOrPath, handleMaterial); } }, - _getMaterialAssetUrl: function (path) { - if (!this.asset) return null; - - var modelAsset = this.system.app.assets.get(this.asset); - if (!modelAsset) return null; - - var fileUrl = modelAsset.getFileUrl(); - var dirUrl = pc.path.getDirectory(fileUrl); - return pc.path.join(dirUrl, path); - }, - onSetReceiveShadows: function (name, oldValue, newValue) { if (newValue !== undefined) { var componentData = this.data; @@ -463,11 +486,47 @@ pc.extend(pc, function () { ModelComponent._super.onEnable.call(this); var model = this.data.model; + var isAsset = this.data.type === 'asset'; + if (model) { var inScene = this.system.app.scene.containsModel(model); if (!inScene) { this.system.app.scene.addModel(model); } + } else if (isAsset && this._dirtyModelAsset) { + var asset = this.data.asset; + if (! asset) + return; + + asset = this.system.app.assets.get(asset); + if (asset) + this._onModelAsset(asset); + } + + // load materialAsset if necessary + if (this._dirtyMaterialAsset) { + var materialAsset = this.data.materialAsset; + if (materialAsset) { + materialAsset = this.system.app.assets.get(materialAsset); + if (materialAsset && !materialAsset.resource) { + this._onMaterialAsset(materialAsset); + } + } + } + + // load mapping materials if necessary + if (isAsset) { + var mapping = this.data.mapping; + if (mapping) { + for (var index in mapping) { + if (mapping[index]) { + var asset = this._getAssetByIdOrPath(mapping[index]); + if (asset && !asset.resource) { + this.system.app.assets.load(asset); + } + } + } + } } }, diff --git a/src/framework/components/model/model_system.js b/src/framework/components/model/model_system.js index 0f600b332a9..86e7e7dfb20 100644 --- a/src/framework/components/model/model_system.js +++ b/src/framework/components/model/model_system.js @@ -64,7 +64,7 @@ pc.extend(pc, function () { data.material = this.defaultMaterial; // order matters here - properties = ['material', 'materialAsset', 'asset', 'castShadows', 'receiveShadows', 'type', 'enabled', 'mapping']; + properties = ['enabled', 'material', 'materialAsset', 'asset', 'castShadows', 'receiveShadows', 'type', 'mapping']; ModelComponentSystem._super.initializeComponentData.call(this, component, data, properties); }, diff --git a/src/framework/components/particlesystem/particlesystem_component.js b/src/framework/components/particlesystem/particlesystem_component.js index 7985c76f7f7..5e6c599f9e6 100644 --- a/src/framework/components/particlesystem/particlesystem_component.js +++ b/src/framework/components/particlesystem/particlesystem_component.js @@ -4,10 +4,10 @@ pc.extend(pc, function() { var SIMPLE_PROPERTIES = [ 'emitterExtents', 'emitterRadius', - 'normalMap', 'loop', 'initialVelocity', - 'animSpeed' + 'animSpeed', + 'normalMap' ]; // properties that need rebuilding the particle system @@ -56,6 +56,12 @@ pc.extend(pc, function() { 'rotationSpeedGraph2' ]; + var ASSET_PROPERTIES = [ + 'colorMapAsset', + 'normalMapAsset', + 'mesh' + ]; + /** * @component * @name pc.ParticleSystemComponent @@ -172,14 +178,19 @@ pc.extend(pc, function() { asset.ready(function (asset) { self.colorMap = asset.resource; }); - assets.load(asset); + if (self.enabled && self.entity.enabled) { + assets.load(asset); + } } else { assets.once("add:" + newValue, function (asset) { asset.on('remove', this.onColorMapRemoved, this); asset.ready(function (asset) { self.colorMap = asset.resource; }); - assets.load(asset); + + if (self.enabled && self.entity.enabled) { + assets.load(asset); + } }); } } else { @@ -216,14 +227,20 @@ pc.extend(pc, function() { asset.ready(function (asset) { self.normalMap = asset.resource; }); - assets.load(asset); + + if (self.enabled && self.entity.enabled) { + assets.load(asset); + } } else { assets.once("add:" + newValue, function (asset) { asset.on('remove', this.onNormalMapRemoved, this); asset.ready(function (asset) { self.normalMap = asset.resource; }); - assets.load(asset); + + if (self.enabled && self.entity.enabled) { + assets.load(asset); + } }); } } else { @@ -236,32 +253,6 @@ pc.extend(pc, function() { this.normalMapAsset = null; }, - // _loadAsset: function (assetId, callback) { - // var asset = (assetId instanceof pc.Asset ? assetId : this.system.app.assets.get(assetId)); - // if (!asset) { - // logERROR(pc.string.format('Trying to load particle system before asset {0} is loaded.', assetId)); - // return; - // } - - // // try to load the cached asset first - // var resource; - // if (asset.resource) { - // callback(asset.resource); - - // } else { - // // resource is not in cache so load it dynamically - // var options = { - // parent: this.entity.getRequest() - // }; - - // this.system.app.assets.load(asset, [], options).then(function (resources) { - // callback(resources[0]); - // }); - // } - - // return asset; - // }, - onSetMesh: function (name, oldValue, newValue) { var self = this; var asset; @@ -287,14 +278,20 @@ pc.extend(pc, function() { asset.ready(function (asset) { self._onMeshChanged(asset.resource); }); - assets.load(asset); + + if (self.enabled && self.entity.enabled) { + assets.load(asset); + } } else { assets.once('add:' + newValue, function (asset) { asset.on('remove', this.onMeshRemoved, this); asset.ready(function (asset) { self._onMeshChanged(asset.resource); }); - assets.load(asset); + + if (self.enabled && self.entity.enabled) { + assets.load(asset); + } }); } } else { @@ -389,9 +386,34 @@ pc.extend(pc, function() { onEnable: function() { + // load any assets that haven't been loaded yet + for (var i = 0, len = ASSET_PROPERTIES.length; i < len; i++) { + var asset = this.data[ASSET_PROPERTIES[i]]; + if (asset) { + if (! (asset instanceof pc.Asset)) { + var id = parseInt(asset, 10); + if (id >= 0) { + asset = this.system.app.assets.get(asset); + } else { + continue; + } + } + + if (asset && !asset.resource) { + this.system.app.assets.load(asset); + } + } + } + var firstRun = false; if (!this.emitter && !this.system._inTools) { + var mesh = this.data.mesh; + // mesh might be an asset id of an asset + // that hasn't been loaded yet + if (! (mesh instanceof pc.Mesh)) + mesh = null; + firstRun = true; this.emitter = new pc.ParticleEmitter(this.system.app.graphicsDevice, { numParticles: this.data.numParticles, @@ -444,7 +466,7 @@ pc.extend(pc, function() { intensity: this.data.intensity, depthSoftening: this.data.depthSoftening, scene: this.system.app.scene, - mesh: this.data.mesh, + mesh: mesh, depthWrite: this.data.depthWrite, node: this.entity, blendType: this.data.blendType diff --git a/src/framework/components/physics/collision/collision_component.js b/src/framework/components/physics/collision/collision_component.js index fa01b9c3608..c3b11e88f5b 100644 --- a/src/framework/components/physics/collision/collision_component.js +++ b/src/framework/components/physics/collision/collision_component.js @@ -186,6 +186,16 @@ pc.extend(pc, function () { onEnable: function () { CollisionComponent._super.onEnable.call(this); + if (this.data.type === 'mesh' && this.data.asset && this.data.initialized) { + var asset = this.system.app.assets.get(this.data.asset); + // recreate the collision shape if the model asset is not loaded + // or the shape does not exist + if (asset && (!asset.resource || !this.data.shape)) { + this.system.recreatePhysicalShapes(this); + return; + } + } + if (this.entity.trigger) { this.entity.trigger.enable(); } else if (this.entity.rigidbody) { diff --git a/src/framework/components/physics/collision/collision_system.js b/src/framework/components/physics/collision/collision_system.js index 7a92b03a6ac..a9969d1c3c9 100644 --- a/src/framework/components/physics/collision/collision_system.js +++ b/src/framework/components/physics/collision/collision_system.js @@ -476,7 +476,7 @@ pc.extend(pc, function () { recreatePhysicalShapes: function (component) { var data = component.data; - if (data.asset !== null) { + if (data.asset !== null && component.enabled && component.entity.enabled) { this.loadModelAsset(component); } else { data.model = null; From 5346d1a9cbd3306657923dc84c1eb14198eb8b68 Mon Sep 17 00:00:00 2001 From: Vaios Kalpias-Ilias Date: Wed, 25 Nov 2015 16:34:55 +0200 Subject: [PATCH 2/2] Cleanup --- .../components/audiosource/audiosource_component.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/framework/components/audiosource/audiosource_component.js b/src/framework/components/audiosource/audiosource_component.js index 3139d001352..037c133bb4a 100644 --- a/src/framework/components/audiosource/audiosource_component.js +++ b/src/framework/components/audiosource/audiosource_component.js @@ -234,13 +234,15 @@ pc.extend(pc, function () { // load assets that haven't been loaded yet var assets = this.data.assets; if (assets) { + var registry = this.system.app.assets; + for (var i = 0, len = assets.length; i < len; i++) { var asset = assets[i]; if (! (asset instanceof pc.Asset)) - asset = this.system.app.assets.get(asset); + asset = registry.get(asset); if (asset && !asset.resource) { - this.system.app.assets.load(asset); + registry.load(asset); } } }