| | 1 | | using System; |
| | 2 | | using DCL.Components; |
| | 3 | | using DCL.Configuration; |
| | 4 | | using DCL.Controllers; |
| | 5 | | using DCL.ECSRuntime; |
| | 6 | | using DCL.Models; |
| | 7 | | using DCL.ECSComponents; |
| | 8 | | using UnityEngine; |
| | 9 | |
|
| | 10 | | namespace DCL.ECSComponents |
| | 11 | | { |
| | 12 | | public class GLTFShapeComponentHandler : IECSComponentHandler<PBGLTFShape> |
| | 13 | | { |
| | 14 | | internal MeshesInfo meshesInfo; |
| | 15 | | internal Rendereable rendereable; |
| | 16 | | internal PBGLTFShape model; |
| | 17 | | internal readonly LoadWrapper_GLTF loadWrapper; |
| | 18 | | internal IDCLEntity entity; |
| | 19 | |
|
| | 20 | | private readonly ShapeRepresentation shapeRepresentation; |
| | 21 | | private readonly DataStore_ECS7 dataStore; |
| | 22 | |
|
| 9 | 23 | | public GLTFShapeComponentHandler(DataStore_ECS7 dataStoreEcs7) |
| | 24 | | { |
| 9 | 25 | | shapeRepresentation = new ShapeRepresentation(); |
| 9 | 26 | | dataStore = dataStoreEcs7; |
| 9 | 27 | | loadWrapper = new LoadWrapper_GLTF(); |
| 9 | 28 | | } |
| | 29 | |
|
| 0 | 30 | | public void OnComponentCreated(IParcelScene scene, IDCLEntity entity) { } |
| | 31 | |
|
| | 32 | | public void OnComponentRemoved(IParcelScene scene, IDCLEntity entity) |
| | 33 | | { |
| 12 | 34 | | loadWrapper?.Unload(); |
| 12 | 35 | | DisposeMesh(scene); |
| 12 | 36 | | } |
| | 37 | |
|
| | 38 | | public void OnComponentModelUpdated(IParcelScene scene, IDCLEntity entity, PBGLTFShape model) |
| | 39 | | { |
| 5 | 40 | | this.entity = entity; |
| | 41 | |
|
| | 42 | | // If we didn't create the shape, or if the shape is different from the last time, we load the shape, if not |
| 5 | 43 | | if(ShouldLoadShape(model)) |
| 4 | 44 | | LoadShape(scene,entity,model); |
| | 45 | | else |
| 1 | 46 | | ApplyModel(model); |
| | 47 | |
|
| 5 | 48 | | this.model = model; |
| 5 | 49 | | } |
| | 50 | |
|
| 0 | 51 | | public bool IsVisible() { return model.GetVisible(); } |
| | 52 | |
|
| 0 | 53 | | public bool HasCollisions() { return model.GetWithCollisions(); } |
| | 54 | |
|
| | 55 | | private bool ShouldLoadShape(PBGLTFShape model) |
| | 56 | | { |
| | 57 | | // If we didn't create the shape, or if the shape is different from the last time, we load the shape, if not |
| 5 | 58 | | return meshesInfo == null || (this.model != null && this.model.Src != model.Src); |
| | 59 | | } |
| | 60 | |
|
| | 61 | | private void LoadShape(IParcelScene scene, IDCLEntity entity, PBGLTFShape model) |
| | 62 | | { |
| 4 | 63 | | ContentProvider provider = scene.contentProvider; |
| 4 | 64 | | if (provider.HasContentsUrl(model.Src)) |
| | 65 | | { |
| 0 | 66 | | entity.EnsureMeshGameObject("GLTF mesh"); |
| | 67 | |
|
| 0 | 68 | | if (loadWrapper != null) |
| | 69 | | { |
| 0 | 70 | | loadWrapper.Unload(); |
| 0 | 71 | | DisposeMesh(scene); |
| | 72 | | } |
| | 73 | |
|
| | 74 | | // We prepare the load wrapper to load the GLTF |
| 0 | 75 | | loadWrapper.customContentProvider = provider; |
| | 76 | |
|
| 0 | 77 | | entity.meshesInfo.currentShape = shapeRepresentation; |
| | 78 | |
|
| 0 | 79 | | loadWrapper.entity = entity; |
| 0 | 80 | | loadWrapper.useVisualFeedback = Configuration.ParcelSettings.VISUAL_LOADING_ENABLED; |
| 0 | 81 | | loadWrapper.initialVisibility = model.GetVisible(); // TODO: check if entity is inside scene's boundarie |
| 0 | 82 | | loadWrapper.Load(model.Src, (wrapper) => |
| | 83 | | { |
| | 84 | | // We remove the transition from the GLTF |
| 0 | 85 | | if (!model.GetVisible()) |
| | 86 | | { |
| 0 | 87 | | MaterialTransitionController[] materialTransitionControllers = entity.meshRootGameObject.GetComp |
| | 88 | |
|
| 0 | 89 | | for (var i = 0; i < materialTransitionControllers.Length; i++) |
| 0 | 90 | | GameObject.Destroy(materialTransitionControllers[i]); |
| | 91 | | } |
| 0 | 92 | | entity.meshesInfo.meshRootGameObject = entity.meshRootGameObject; |
| 0 | 93 | | meshesInfo = entity.meshesInfo; |
| | 94 | |
|
| | 95 | | // Apply the model for visibility, collision and event pointer |
| 0 | 96 | | ApplyModel(model); |
| 0 | 97 | | dataStore.RemovePendingResource(scene.sceneData.id, model); |
| 0 | 98 | | dataStore.AddShapeReady(entity.entityId,meshesInfo.meshRootGameObject); |
| | 99 | |
|
| 0 | 100 | | }, (wrapper, exception) => |
| | 101 | | { |
| 0 | 102 | | dataStore.RemovePendingResource(scene.sceneData.id, model); |
| 0 | 103 | | }); |
| 0 | 104 | | } |
| | 105 | | else |
| | 106 | | { |
| | 107 | | #if UNITY_EDITOR |
| 4 | 108 | | Debug.LogWarning($"LoadableShape '{model.Src}' not found in scene '{scene.sceneData.id}' mappings"); |
| | 109 | | #endif |
| | 110 | | } |
| 4 | 111 | | dataStore.AddPendingResource(scene.sceneData.id, model); |
| 4 | 112 | | } |
| | 113 | |
|
| | 114 | | internal void ApplyModel(PBGLTFShape model) |
| | 115 | | { |
| 1 | 116 | | shapeRepresentation.UpdateModel(model.GetVisible(), model.GetWithCollisions()); |
| | 117 | |
|
| | 118 | | // Set visibility |
| 1 | 119 | | meshesInfo.meshRootGameObject.SetActive(model.GetVisible()); |
| | 120 | |
|
| | 121 | | // Set collisions and pointer blocker |
| 1 | 122 | | ECSComponentsUtils.UpdateMeshInfoColliders(model.GetWithCollisions(), model.GetIsPointerBlocker(), meshesInf |
| 1 | 123 | | } |
| | 124 | |
|
| | 125 | | internal void DisposeMesh(IParcelScene scene) |
| | 126 | | { |
| 13 | 127 | | if (entity != null) |
| 9 | 128 | | dataStore.RemoveShapeReady(entity.entityId); |
| 13 | 129 | | if (rendereable != null) |
| 0 | 130 | | ECSComponentsUtils.RemoveRendereableFromDataStore( scene.sceneData.id, rendereable); |
| 13 | 131 | | if (model != null) |
| 5 | 132 | | dataStore.RemovePendingResource(scene.sceneData.id, model); |
| | 133 | |
|
| 13 | 134 | | meshesInfo = null; |
| 13 | 135 | | rendereable = null; |
| 13 | 136 | | model = null; |
| 13 | 137 | | } |
| | 138 | | } |
| | 139 | | } |