diff --git a/src/framework/components/render/component.js b/src/framework/components/render/component.js index d0b47aca093..aa45faf44ee 100644 --- a/src/framework/components/render/component.js +++ b/src/framework/components/render/component.js @@ -12,8 +12,6 @@ import { AssetReference } from '../../asset/asset-reference.js'; import { Component } from '../component.js'; -import { EntityReference } from '../../utils/entity-reference.js'; - /** * The RenderComponent enables an {@link Entity} to render 3D meshes. The {@link RenderComponent#type} * property can be set to one of several predefined shape types (such as `box`, `sphere`, `cone` @@ -54,9 +52,6 @@ import { EntityReference } from '../../utils/entity-reference.js'; * - [Primitive Shapes](https://playcanvas.github.io/#/graphics/shapes) * - [Loading Render Assets](https://playcanvas.github.io/#/graphics/render-asset) * - * @property {import('../../entity.js').Entity} rootBone A reference to the entity to be used as - * the root bone for any skinned meshes that are rendered by this component. - * * @category Graphics */ class RenderComponent extends Component { @@ -136,10 +131,12 @@ class RenderComponent extends Component { _material; /** - * @type {EntityReference} - * @private + * A reference to the entity to be used as the root bone for any skinned meshes that + * are rendered by this component. + * + * @type {import('../../entity.js').Entity|null} */ - _rootBone; + _rootBone = null; /** * @type {import('../../../core/event-handle.js').EventHandle|null} @@ -177,8 +174,6 @@ class RenderComponent extends Component { super(system, entity); // the entity that represents the root bone if this render component has skinned meshes - this._rootBone = new EntityReference(this, 'rootBone'); - this._rootBone.on('set:entity', this._onSetRootBone, this); // render asset reference this._assetReference = new AssetReference( @@ -275,7 +270,6 @@ class RenderComponent extends Component { * @type {string} */ set type(value) { - if (this._type !== value) { this._area = null; this._type = value; @@ -312,7 +306,6 @@ class RenderComponent extends Component { * @type {MeshInstance[]} */ set meshInstances(value) { - Debug.assert(Array.isArray(value), 'MeshInstances set to a Render component must be an array.'); this.destroyMeshInstances(); @@ -702,28 +695,37 @@ class RenderComponent extends Component { this._assetReference.id = id; } - /** - * @param {import('../../entity.js').Entity} entity - The entity set as the root bone. - * @private - */ - _onSetRootBone(entity) { - if (entity) { - this._onRootBoneChanged(); + set rootBone(value) { + if (this._rootBone !== value) { + const isString = typeof (value) === 'string'; + if (this._rootBone && isString && this._rootBone.getGuid() === value) { + return; + } + + if (this._rootBone) { + this._clearSkinInstances(); + } + + if (value instanceof GraphNode) { + this._rootBone = value; + } else if (isString) { + this._rootBone = this.system.app.getEntityFromIndex(value) || null; + } else { + this._rootBone = null; + } + + if (this._rootBone) { + this._cloneSkinInstances(); + } } } - /** @private */ - _onRootBoneChanged() { - // remove existing skin instances and create new ones, connected to new root bone - this._clearSkinInstances(); - if (this.enabled && this.entity.enabled) { - this._cloneSkinInstances(); - } + get rootBone() { + return this._rootBone; } /** @private */ destroyMeshInstances() { - const meshInstances = this._meshInstances; if (meshInstances) { this.removeFromLayers(); @@ -814,9 +816,9 @@ class RenderComponent extends Component { const scene = app.scene; const layers = scene.layers; - this._rootBone.onParentComponentEnable(); - - this._cloneSkinInstances(); + if (this._rootBone) { + this._cloneSkinInstances(); + } this._evtLayersChanged = scene.on('set:layers', this.onLayersChanged, this); @@ -852,6 +854,10 @@ class RenderComponent extends Component { this._evtLayersChanged?.off(); this._evtLayersChanged = null; + if (this._rootBone) { + this._clearSkinInstances(); + } + if (layers) { this._evtLayerAdded?.off(); this._evtLayerAdded = null; @@ -904,7 +910,6 @@ class RenderComponent extends Component { } _onRenderAssetLoad() { - // remove existing instances this.destroyMeshInstances(); @@ -923,7 +928,6 @@ class RenderComponent extends Component { } _clearSkinInstances() { - for (let i = 0; i < this._meshInstances.length; i++) { const meshInstance = this._meshInstances[i]; @@ -934,23 +938,20 @@ class RenderComponent extends Component { } _cloneSkinInstances() { - - if (this._meshInstances.length && this._rootBone.entity instanceof GraphNode) { - + if (this._meshInstances.length && this._rootBone instanceof GraphNode) { for (let i = 0; i < this._meshInstances.length; i++) { const meshInstance = this._meshInstances[i]; const mesh = meshInstance.mesh; // if skinned but does not have instance created yet if (mesh.skin && !meshInstance.skinInstance) { - meshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(mesh.skin, this._rootBone.entity, this.entity); + meshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(mesh.skin, this._rootBone, this.entity); } } } } _cloneMeshes(meshes) { - if (meshes && meshes.length) { // cloned mesh instances @@ -1031,10 +1032,9 @@ class RenderComponent extends Component { } resolveDuplicatedEntityReferenceProperties(oldRender, duplicatedIdsMap) { - if (oldRender.rootBone && duplicatedIdsMap[oldRender.rootBone]) { - this.rootBone = duplicatedIdsMap[oldRender.rootBone]; + if (oldRender.rootBone) { + this.rootBone = duplicatedIdsMap[oldRender.rootBone.getGuid()]; } - this._clearSkinInstances(); } } diff --git a/src/framework/components/render/data.js b/src/framework/components/render/data.js index 5ff36ded89e..53ac9f97c13 100644 --- a/src/framework/components/render/data.js +++ b/src/framework/components/render/data.js @@ -1,7 +1,6 @@ class RenderComponentData { constructor() { this.enabled = true; - this.rootBone = null; } } diff --git a/src/framework/components/render/system.js b/src/framework/components/render/system.js index 12688a94cb1..df3d4484cc6 100644 --- a/src/framework/components/render/system.js +++ b/src/framework/components/render/system.js @@ -11,7 +11,6 @@ import { RenderComponent } from './component.js'; import { RenderComponentData } from './data.js'; const _schema = [ - { name: 'rootBone', type: 'entity' }, 'enabled' ]; @@ -30,7 +29,8 @@ const _properties = [ 'type', 'layers', 'isStatic', - 'batchGroupId' + 'batchGroupId', + 'rootBone' ]; /**