| | 1 | | using DCL.Controllers; |
| | 2 | | using DCL.Helpers; |
| | 3 | | using DCL.Models; |
| | 4 | | using System.Collections; |
| | 5 | | using UnityEngine; |
| | 6 | |
|
| | 7 | | namespace DCL.Components |
| | 8 | | { |
| | 9 | | public abstract class ParametrizedShape<T> : BaseShape where T : BaseShape.Model, new() |
| | 10 | | { |
| | 11 | | bool visibilityDirty = false; |
| | 12 | | bool collisionsDirty = false; |
| | 13 | |
|
| | 14 | | public abstract Mesh GenerateGeometry(); |
| | 15 | |
|
| | 16 | | protected virtual void DestroyGeometry() |
| | 17 | | { |
| 27 | 18 | | if (currentMesh != null) |
| | 19 | | { |
| 27 | 20 | | GameObject.Destroy(currentMesh); |
| 27 | 21 | | currentMesh = null; |
| | 22 | | } |
| 27 | 23 | | } |
| | 24 | |
|
| 0 | 25 | | public Mesh currentMesh { get; protected set; } |
| | 26 | | private Model previousModel; |
| | 27 | | private Model cachedModel; |
| | 28 | |
|
| 139 | 29 | | public ParametrizedShape() |
| | 30 | | { |
| 139 | 31 | | OnAttach += OnShapeAttached; |
| 139 | 32 | | OnDetach += OnShapeDetached; |
| 139 | 33 | | } |
| | 34 | |
|
| | 35 | | public override void UpdateFromModel(BaseModel newModel) |
| | 36 | | { |
| 190 | 37 | | cachedModel = (Model) newModel; |
| 190 | 38 | | base.UpdateFromModel(newModel); |
| 190 | 39 | | } |
| | 40 | |
|
| | 41 | | void UpdateRenderer(IDCLEntity entity, Model model = null) |
| | 42 | | { |
| 201 | 43 | | if (model == null) |
| 145 | 44 | | model = (T) this.model; |
| | 45 | |
|
| 201 | 46 | | if (visibilityDirty) |
| | 47 | | { |
| 169 | 48 | | ConfigureVisibility(entity.meshRootGameObject, model.visible, entity.meshesInfo.renderers); |
| 169 | 49 | | visibilityDirty = false; |
| | 50 | | } |
| | 51 | |
|
| 201 | 52 | | if (collisionsDirty) |
| | 53 | | { |
| 167 | 54 | | CollidersManager.i.ConfigureColliders(entity.meshRootGameObject, model.withCollisions, false, entity, Ca |
| 167 | 55 | | collisionsDirty = false; |
| | 56 | | } |
| | 57 | |
|
| 201 | 58 | | if (entity.meshesInfo.meshFilters.Length > 0 && entity.meshesInfo.meshFilters[0].sharedMesh != currentMesh) |
| | 59 | | { |
| 0 | 60 | | entity.meshesInfo.UpdateExistingMeshAtIndex(currentMesh, 0); |
| | 61 | | } |
| 201 | 62 | | } |
| | 63 | |
|
| | 64 | | void OnShapeAttached(IDCLEntity entity) |
| | 65 | | { |
| 145 | 66 | | if (entity == null) |
| 0 | 67 | | return; |
| | 68 | |
|
| 145 | 69 | | entity.EnsureMeshGameObject(componentName + " mesh"); |
| | 70 | |
|
| 145 | 71 | | if (currentMesh == null) |
| 129 | 72 | | currentMesh = GenerateGeometry(); |
| | 73 | |
|
| 145 | 74 | | MeshFilter meshFilter = entity.meshRootGameObject.AddComponent<MeshFilter>(); |
| 145 | 75 | | MeshRenderer meshRenderer = entity.meshRootGameObject.AddComponent<MeshRenderer>(); |
| 145 | 76 | | entity.meshesInfo.renderers = new Renderer[] { meshRenderer }; |
| 145 | 77 | | entity.meshesInfo.currentShape = this; |
| | 78 | |
|
| 145 | 79 | | meshFilter.sharedMesh = currentMesh; |
| | 80 | |
|
| 145 | 81 | | if (Configuration.ParcelSettings.VISUAL_LOADING_ENABLED) |
| | 82 | | { |
| 1 | 83 | | MaterialTransitionController transition = entity.meshRootGameObject.AddComponent<MaterialTransitionContr |
| 1 | 84 | | Material finalMaterial = Utils.EnsureResourcesMaterial("Materials/Default"); |
| 1 | 85 | | transition.delay = 0; |
| 1 | 86 | | transition.useHologram = false; |
| 1 | 87 | | transition.fadeThickness = 20; |
| 1 | 88 | | transition.OnDidFinishLoading(finalMaterial); |
| | 89 | |
|
| 3 | 90 | | transition.onFinishedLoading += () => { entity.OnShapeUpdated?.Invoke(entity); }; |
| 1 | 91 | | } |
| | 92 | | else |
| | 93 | | { |
| 144 | 94 | | meshRenderer.sharedMaterial = Utils.EnsureResourcesMaterial("Materials/Default"); |
| | 95 | | } |
| | 96 | |
|
| 145 | 97 | | visibilityDirty = true; |
| 145 | 98 | | collisionsDirty = true; |
| 145 | 99 | | UpdateRenderer(entity); |
| | 100 | |
|
| 145 | 101 | | entity.OnShapeUpdated?.Invoke(entity); |
| 145 | 102 | | } |
| | 103 | |
|
| | 104 | | void OnShapeDetached(IDCLEntity entity) |
| | 105 | | { |
| 144 | 106 | | if (entity == null || entity.meshRootGameObject == null) |
| 0 | 107 | | return; |
| | 108 | |
|
| 144 | 109 | | if (attachedEntities.Count == 0) |
| | 110 | | { |
| 128 | 111 | | DestroyGeometry(); |
| 128 | 112 | | Utils.CleanMaterials(entity.meshRootGameObject.GetComponent<Renderer>()); |
| 128 | 113 | | currentMesh = null; |
| | 114 | | } |
| | 115 | |
|
| 144 | 116 | | Utils.SafeDestroy(entity.meshRootGameObject); |
| 144 | 117 | | entity.meshesInfo.CleanReferences(); |
| 144 | 118 | | } |
| | 119 | |
|
| | 120 | | public override IEnumerator ApplyChanges(BaseModel newModelRaw) |
| | 121 | | { |
| 190 | 122 | | var newModel = (T) newModelRaw; |
| | 123 | |
|
| 190 | 124 | | if (previousModel != null) |
| | 125 | | { |
| 51 | 126 | | visibilityDirty = newModel.visible != previousModel.visible; |
| 51 | 127 | | collisionsDirty = newModel.withCollisions != previousModel.withCollisions || newModel.isPointerBlocker ! |
| | 128 | | } |
| | 129 | |
|
| 190 | 130 | | bool shouldGenerateMesh = ShouldGenerateNewMesh(previousModel); |
| | 131 | |
|
| | 132 | | //NOTE(Brian): Only generate meshes here if they already are attached to something. |
| | 133 | | // Otherwise, the mesh will be created on the OnShapeAttached. |
| 190 | 134 | | if (attachedEntities.Count > 0) |
| | 135 | | { |
| 40 | 136 | | if (shouldGenerateMesh) |
| 2 | 137 | | currentMesh = GenerateGeometry(); |
| | 138 | |
|
| 40 | 139 | | using (var iterator = attachedEntities.GetEnumerator()) |
| | 140 | | { |
| 40 | 141 | | bool cachedVisibilityDirty = visibilityDirty; |
| 40 | 142 | | bool cachedCollisionDirty = collisionsDirty; |
| 96 | 143 | | while (iterator.MoveNext()) |
| | 144 | | { |
| | 145 | | //NOTE(Alex): Since UpdateRenderer updates the dirty flags as well we have to make sure every en |
| | 146 | | // gets updated accordingly to the original flags. |
| 56 | 147 | | visibilityDirty = cachedVisibilityDirty; |
| 56 | 148 | | collisionsDirty = cachedCollisionDirty; |
| | 149 | |
|
| 56 | 150 | | var entity = iterator.Current; |
| 56 | 151 | | UpdateRenderer(entity, newModel); |
| | 152 | |
|
| 56 | 153 | | entity.OnShapeUpdated?.Invoke(entity); |
| | 154 | | } |
| 40 | 155 | | } |
| | 156 | | } |
| | 157 | |
|
| 190 | 158 | | previousModel = newModel; |
| 190 | 159 | | return null; |
| | 160 | | } |
| | 161 | |
|
| | 162 | | public override void AttachTo(IDCLEntity entity, System.Type overridenAttachedType = null) |
| | 163 | | { |
| 145 | 164 | | if (attachedEntities.Contains(entity)) |
| 0 | 165 | | return; |
| | 166 | |
|
| 145 | 167 | | base.AttachTo(entity); |
| 145 | 168 | | } |
| | 169 | |
|
| 65 | 170 | | public override bool IsVisible() { return cachedModel.visible; } |
| | 171 | |
|
| 30 | 172 | | public override bool HasCollisions() { return cachedModel.withCollisions; } |
| | 173 | |
|
| 0 | 174 | | protected virtual bool ShouldGenerateNewMesh(BaseShape.Model newModel) { return true; } |
| | 175 | | } |
| | 176 | | } |