| | 1 | | using System; |
| | 2 | | using System.Collections.Generic; |
| | 3 | | using DCL.Components; |
| | 4 | | using DCL.Configuration; |
| | 5 | | using DCL.Controllers; |
| | 6 | | using DCL.ECS7.InternalComponents; |
| | 7 | | using DCL.ECSRuntime; |
| | 8 | | using DCL.Helpers; |
| | 9 | | using DCL.Models; |
| | 10 | | using UnityEngine; |
| | 11 | | using Object = UnityEngine.Object; |
| | 12 | |
|
| | 13 | | namespace DCL.ECSComponents |
| | 14 | | { |
| | 15 | | public class GltfContainerHandler : IECSComponentHandler<PBGltfContainer> |
| | 16 | | { |
| | 17 | | private const string POINTER_COLLIDER_NAME = "OnPointerEventCollider"; |
| | 18 | | private const string FEATURE_GLTFAST = "gltfast"; |
| | 19 | | private const StringComparison IGNORE_CASE = StringComparison.CurrentCultureIgnoreCase; |
| | 20 | |
|
| | 21 | | internal RendereableAssetLoadHelper gltfLoader; |
| | 22 | | internal GameObject gameObject; |
| | 23 | | private IList<Collider> physicColliders; |
| | 24 | | private IList<Collider> pointerColliders; |
| | 25 | | private IList<Renderer> renderers; |
| | 26 | | private string prevLoadedGltf = null; |
| | 27 | |
|
| | 28 | | private readonly IInternalECSComponent<InternalColliders> pointerColliderComponent; |
| | 29 | | private readonly IInternalECSComponent<InternalColliders> physicColliderComponent; |
| | 30 | | private readonly IInternalECSComponent<InternalRenderers> renderersComponent; |
| | 31 | | private readonly DataStore_ECS7 dataStoreEcs7; |
| | 32 | | private DataStore_FeatureFlag featureFlags; |
| | 33 | |
|
| 6 | 34 | | public GltfContainerHandler(IInternalECSComponent<InternalColliders> pointerColliderComponent, |
| | 35 | | IInternalECSComponent<InternalColliders> physicColliderComponent, |
| | 36 | | IInternalECSComponent<InternalRenderers> renderersComponent, |
| | 37 | | DataStore_ECS7 dataStoreEcs7, DataStore_FeatureFlag featureFlags) |
| | 38 | | { |
| 6 | 39 | | this.featureFlags = featureFlags; |
| 6 | 40 | | this.pointerColliderComponent = pointerColliderComponent; |
| 6 | 41 | | this.physicColliderComponent = physicColliderComponent; |
| 6 | 42 | | this.renderersComponent = renderersComponent; |
| 6 | 43 | | this.dataStoreEcs7 = dataStoreEcs7; |
| 6 | 44 | | } |
| | 45 | |
|
| | 46 | | public void OnComponentCreated(IParcelScene scene, IDCLEntity entity) |
| | 47 | | { |
| 6 | 48 | | gameObject = new GameObject("GLTF mesh"); |
| | 49 | |
|
| 6 | 50 | | Transform transform = gameObject.transform; |
| 6 | 51 | | transform.SetParent(entity.gameObject.transform); |
| 6 | 52 | | transform.ResetLocalTRS(); |
| | 53 | |
|
| 18 | 54 | | gltfLoader = new RendereableAssetLoadHelper(scene.contentProvider, scene.sceneData.baseUrlBundles, () => fea |
| 6 | 55 | | gltfLoader.settings.forceGPUOnlyMesh = true; |
| 6 | 56 | | gltfLoader.settings.parent = transform; |
| 6 | 57 | | gltfLoader.settings.visibleFlags = AssetPromiseSettings_Rendering.VisibleFlags.VISIBLE_WITH_TRANSITION; |
| 6 | 58 | | } |
| | 59 | |
|
| | 60 | | public void OnComponentRemoved(IParcelScene scene, IDCLEntity entity) |
| | 61 | | { |
| 8 | 62 | | CleanUp(scene, entity); |
| 8 | 63 | | Object.Destroy(gameObject); |
| 8 | 64 | | } |
| | 65 | |
|
| | 66 | | public void OnComponentModelUpdated(IParcelScene scene, IDCLEntity entity, PBGltfContainer model) |
| | 67 | | { |
| 12 | 68 | | if (string.IsNullOrEmpty(model.Src) || prevLoadedGltf == model.Src) |
| 0 | 69 | | return; |
| | 70 | |
|
| 12 | 71 | | prevLoadedGltf = model.Src; |
| | 72 | |
|
| 12 | 73 | | CleanUp(scene, entity); |
| | 74 | |
|
| 23 | 75 | | gltfLoader.OnSuccessEvent += rendereable => OnLoadSuccess(scene, entity, rendereable); |
| 12 | 76 | | gltfLoader.OnFailEvent += exception => OnLoadFail(scene, exception); |
| | 77 | |
|
| 12 | 78 | | dataStoreEcs7.AddPendingResource(scene.sceneData.sceneNumber, prevLoadedGltf); |
| 12 | 79 | | gltfLoader.Load(model.Src); |
| 12 | 80 | | } |
| | 81 | |
|
| | 82 | | private void OnLoadSuccess(IParcelScene scene, IDCLEntity entity, Rendereable rendereable) |
| | 83 | | { |
| | 84 | | // create physic colliders |
| 11 | 85 | | MeshFilter[] meshFilters = gameObject.GetComponentsInChildren<MeshFilter>(); |
| 11 | 86 | | physicColliders = SetUpPhysicColliders(meshFilters); |
| | 87 | |
|
| | 88 | | // create pointer colliders and renderers |
| 11 | 89 | | (pointerColliders, renderers) = SetUpPointerCollidersAndRenderers(rendereable.renderers); |
| | 90 | |
|
| | 91 | | // set colliders and renderers |
| 100 | 92 | | for (int i = 0; i < pointerColliders.Count; i++) { pointerColliderComponent.AddCollider(scene, entity, point |
| | 93 | |
|
| 40 | 94 | | for (int i = 0; i < physicColliders.Count; i++) { physicColliderComponent.AddCollider(scene, entity, physicC |
| | 95 | |
|
| 100 | 96 | | for (int i = 0; i < renderers.Count; i++) { renderersComponent.AddRenderer(scene, entity, renderers[i]); } |
| | 97 | |
|
| | 98 | | // TODO: modify Animator component to remove `AddShapeReady` usage |
| 11 | 99 | | dataStoreEcs7.AddShapeReady(entity.entityId, gameObject); |
| 11 | 100 | | dataStoreEcs7.RemovePendingResource(scene.sceneData.sceneNumber, prevLoadedGltf); |
| 11 | 101 | | } |
| | 102 | |
|
| | 103 | | private void OnLoadFail(IParcelScene scene, Exception exception) |
| | 104 | | { |
| 0 | 105 | | MaterialTransitionController[] transitionController = |
| | 106 | | gameObject.GetComponentsInChildren<MaterialTransitionController>(true); |
| | 107 | |
|
| 0 | 108 | | for (int i = 0; i < transitionController.Length; i++) |
| | 109 | | { |
| 0 | 110 | | MaterialTransitionController material = transitionController[i]; |
| 0 | 111 | | Object.Destroy(material); |
| | 112 | | } |
| | 113 | |
|
| 0 | 114 | | dataStoreEcs7.RemovePendingResource(scene.sceneData.sceneNumber, prevLoadedGltf); |
| 0 | 115 | | } |
| | 116 | |
|
| | 117 | | private void CleanUp(IParcelScene scene, IDCLEntity entity) |
| | 118 | | { |
| 20 | 119 | | int count = pointerColliders?.Count ?? 0; |
| | 120 | |
|
| 118 | 121 | | for (int i = 0; i < count; i++) { pointerColliderComponent.RemoveCollider(scene, entity, pointerColliders[i] |
| | 122 | |
|
| 20 | 123 | | count = physicColliders?.Count ?? 0; |
| | 124 | |
|
| 58 | 125 | | for (int i = 0; i < count; i++) { physicColliderComponent.RemoveCollider(scene, entity, physicColliders[i]); |
| | 126 | |
|
| 20 | 127 | | count = renderers?.Count ?? 0; |
| | 128 | |
|
| 118 | 129 | | for (int i = 0; i < count; i++) { renderersComponent.RemoveRenderer(scene, entity, renderers[i]); } |
| | 130 | |
|
| 20 | 131 | | physicColliders = null; |
| 20 | 132 | | pointerColliders = null; |
| 20 | 133 | | renderers = null; |
| | 134 | |
|
| 40 | 135 | | if (!string.IsNullOrEmpty(prevLoadedGltf)) { dataStoreEcs7.RemovePendingResource(scene.sceneData.sceneNumber |
| | 136 | |
|
| | 137 | | // TODO: modify Animator component to remove `RemoveShapeReady` usage |
| 20 | 138 | | dataStoreEcs7.RemoveShapeReady(entity.entityId); |
| | 139 | |
|
| 20 | 140 | | gltfLoader.ClearEvents(); |
| 20 | 141 | | gltfLoader.Unload(); |
| 20 | 142 | | } |
| | 143 | |
|
| | 144 | | private static List<Collider> SetUpPhysicColliders(MeshFilter[] meshFilters) |
| | 145 | | { |
| 11 | 146 | | List<Collider> physicColliders = new List<Collider>(meshFilters.Length); |
| | 147 | |
|
| 86 | 148 | | for (int i = 0; i < meshFilters.Length; i++) |
| | 149 | | { |
| 32 | 150 | | if (meshFilters[i].gameObject.layer == PhysicsLayers.characterOnlyLayer) |
| | 151 | | { |
| 1 | 152 | | physicColliders.Add(meshFilters[i].gameObject.GetComponent<Collider>()); |
| 1 | 153 | | continue; |
| | 154 | | } |
| | 155 | |
|
| 31 | 156 | | if (!IsCollider(meshFilters[i])) |
| | 157 | | continue; |
| | 158 | |
|
| 5 | 159 | | MeshCollider collider = meshFilters[i].gameObject.AddComponent<MeshCollider>(); |
| 5 | 160 | | collider.sharedMesh = meshFilters[i].sharedMesh; |
| 5 | 161 | | meshFilters[i].gameObject.layer = PhysicsLayers.characterOnlyLayer; |
| 5 | 162 | | physicColliders.Add(collider); |
| | 163 | |
|
| 5 | 164 | | Object.Destroy(meshFilters[i].GetComponent<Renderer>()); |
| | 165 | | } |
| | 166 | |
|
| 11 | 167 | | return physicColliders; |
| | 168 | | } |
| | 169 | |
|
| | 170 | | // Compatibility layer for old GLTF importer and GLTFast |
| | 171 | | private static bool IsCollider(MeshFilter meshFilter) => |
| 31 | 172 | | meshFilter.name.Contains("_collider", IGNORE_CASE) |
| | 173 | | || meshFilter.transform.parent.name.Contains("_collider", IGNORE_CASE); |
| | 174 | |
|
| | 175 | | private static (List<Collider>, List<Renderer>) SetUpPointerCollidersAndRenderers(HashSet<Renderer> renderers) |
| | 176 | | { |
| 11 | 177 | | List<Collider> pointerColliders = new List<Collider>(renderers.Count); |
| 11 | 178 | | List<Renderer> rendererList = new List<Renderer>(renderers.Count); |
| | 179 | |
|
| | 180 | | // (sadly we are stuck with a hashset here) |
| 74 | 181 | | foreach (var renderer in renderers) |
| | 182 | | { |
| 26 | 183 | | rendererList.Add(renderer); |
| 26 | 184 | | Transform rendererT = renderer.transform; |
| 26 | 185 | | bool alreadyHasCollider = false; |
| | 186 | |
|
| 52 | 187 | | for (int i = 0; i < rendererT.childCount; i++) |
| | 188 | | { |
| 5 | 189 | | Transform child = rendererT.GetChild(i); |
| | 190 | |
|
| 5 | 191 | | if (child.gameObject.layer != PhysicsLayers.onPointerEventLayer) |
| | 192 | | continue; |
| | 193 | |
|
| 5 | 194 | | alreadyHasCollider = true; |
| 5 | 195 | | pointerColliders.Add(child.GetComponent<Collider>()); |
| 5 | 196 | | break; |
| | 197 | | } |
| | 198 | |
|
| 26 | 199 | | if (alreadyHasCollider) |
| | 200 | | continue; |
| | 201 | |
|
| 21 | 202 | | GameObject colliderGo = new GameObject(POINTER_COLLIDER_NAME); |
| 21 | 203 | | colliderGo.layer = PhysicsLayers.onPointerEventLayer; |
| 21 | 204 | | MeshCollider collider = colliderGo.AddComponent<MeshCollider>(); |
| 21 | 205 | | MeshFilter meshFilter = renderer.GetComponent<MeshFilter>(); |
| 21 | 206 | | if (meshFilter == null) continue; |
| | 207 | |
|
| 21 | 208 | | collider.sharedMesh = meshFilter.sharedMesh; |
| 21 | 209 | | colliderGo.transform.SetParent(renderer.transform); |
| 21 | 210 | | colliderGo.transform.ResetLocalTRS(); |
| 21 | 211 | | pointerColliders.Add(collider); |
| | 212 | | } |
| | 213 | |
|
| 11 | 214 | | return (pointerColliders, rendererList); |
| | 215 | | } |
| | 216 | | } |
| | 217 | | } |