| | 1 | | using DCL.Helpers; |
| | 2 | | using System.Collections.Generic; |
| | 3 | | using UnityEngine; |
| | 4 | |
|
| | 5 | | public class MaterialTransitionController : MonoBehaviour |
| | 6 | | { |
| | 7 | | enum State |
| | 8 | | { |
| | 9 | | NOT_LOADED, |
| | 10 | | SHOWING_LOADED, |
| | 11 | | FINISHED, |
| | 12 | | INVALID, |
| | 13 | | } |
| | 14 | |
|
| | 15 | | State state = State.NOT_LOADED; |
| | 16 | |
|
| 1 | 17 | | private static int ShaderId_CullYPlane = Shader.PropertyToID("_CullYPlane"); |
| 1 | 18 | | private static int ShaderId_FadeThickness = Shader.PropertyToID("_FadeThickness"); |
| 1 | 19 | | private static int ShaderId_FadeDirection = Shader.PropertyToID("_FadeDirection"); |
| 1 | 20 | | private static int ShaderId_LoadingColor = Shader.PropertyToID("_LoadingColor"); |
| | 21 | |
|
| | 22 | | Material loadingMaterial; |
| | 23 | |
|
| 86 | 24 | | [System.NonSerialized] public float delay = 0.5f; |
| 86 | 25 | | [System.NonSerialized] public bool useHologram = true; |
| 86 | 26 | | [System.NonSerialized] public float fadeThickness = 10; |
| | 27 | | [System.NonSerialized] public System.Action onFinishedLoading; |
| | 28 | |
|
| | 29 | | static Material hologramMaterial; |
| | 30 | |
|
| | 31 | | List<Material> loadingMaterialCopies; |
| | 32 | | Material hologramMaterialCopy; |
| | 33 | |
|
| | 34 | | public Material[] finalMaterials; |
| | 35 | | Material[] cullingFXMaterials; |
| | 36 | |
|
| | 37 | | Renderer targetRendererValue; |
| | 38 | |
|
| | 39 | | Renderer targetRenderer |
| | 40 | | { |
| | 41 | | get |
| | 42 | | { |
| 258 | 43 | | if (targetRendererValue == null) |
| | 44 | | { |
| 86 | 45 | | targetRendererValue = GetComponent<Renderer>(); |
| | 46 | | } |
| | 47 | |
|
| 258 | 48 | | return targetRendererValue; |
| | 49 | | } |
| | 50 | | } |
| | 51 | |
|
| 0 | 52 | | public GameObject placeholder { get; private set; } |
| 0 | 53 | | public Renderer placeholderRenderer { get; private set; } |
| | 54 | |
|
| | 55 | | float lowerYRendererBounds; |
| | 56 | | float topYRendererBounds; |
| | 57 | | float currentCullYPlane; |
| | 58 | | float time; |
| | 59 | |
|
| 0 | 60 | | public bool materialReady { get; private set; } |
| 0 | 61 | | public bool canSwitchMaterial { get { return materialReady && state != State.FINISHED; } } |
| | 62 | |
|
| | 63 | | public void PopulateTargetRendererWithMaterial(Material[] newMaterials, bool updateCulling = false) |
| | 64 | | { |
| 172 | 65 | | if (newMaterials == null) |
| 0 | 66 | | return; |
| | 67 | |
|
| | 68 | | Material material; |
| 688 | 69 | | for (int i = 0; i < newMaterials.Length; i++) |
| | 70 | | { |
| 172 | 71 | | material = newMaterials[i]; |
| | 72 | |
|
| 172 | 73 | | material.SetColor(ShaderId_LoadingColor, Color.clear); |
| 172 | 74 | | material.SetFloat(ShaderId_FadeDirection, 0); |
| 172 | 75 | | material.SetFloat(ShaderId_FadeThickness, fadeThickness); |
| | 76 | |
|
| 172 | 77 | | if (updateCulling) |
| 86 | 78 | | material.SetFloat(ShaderId_CullYPlane, currentCullYPlane); |
| | 79 | | } |
| | 80 | |
|
| 172 | 81 | | targetRenderer.sharedMaterials = newMaterials; |
| 172 | 82 | | } |
| | 83 | |
|
| | 84 | | void UpdateCullYValueFXMaterial() |
| | 85 | | { |
| 4471 | 86 | | if (cullingFXMaterials != null) |
| | 87 | | { |
| 17884 | 88 | | for (int i = 0; i < cullingFXMaterials.Length; i++) |
| | 89 | | { |
| 4471 | 90 | | Material material = cullingFXMaterials[i]; |
| 4471 | 91 | | material.SetFloat(ShaderId_CullYPlane, currentCullYPlane); |
| | 92 | | } |
| | 93 | | } |
| 4471 | 94 | | } |
| | 95 | |
|
| | 96 | | void UpdateCullYValueHologram() |
| | 97 | | { |
| 13563 | 98 | | if (hologramMaterialCopy != null) |
| 13504 | 99 | | hologramMaterialCopy.SetFloat(ShaderId_CullYPlane, currentCullYPlane); |
| 13563 | 100 | | } |
| | 101 | |
|
| | 102 | | void PrepareCullingFXMaterials() |
| | 103 | | { |
| 86 | 104 | | cullingFXMaterials = new Material[finalMaterials.Length]; |
| 344 | 105 | | for (int i = 0; i < finalMaterials.Length; i++) |
| | 106 | | { |
| 86 | 107 | | cullingFXMaterials[i] = new Material(finalMaterials[i]); |
| | 108 | | } |
| 86 | 109 | | } |
| | 110 | |
|
| | 111 | | private void Awake() |
| | 112 | | { |
| 86 | 113 | | state = State.NOT_LOADED; |
| 86 | 114 | | time = 0; |
| 86 | 115 | | materialReady = false; |
| 86 | 116 | | } |
| | 117 | |
|
| | 118 | | private void Start() |
| | 119 | | { |
| 86 | 120 | | Renderer tr = targetRenderer; |
| | 121 | |
|
| 86 | 122 | | if (float.IsInfinity(tr.bounds.min.y) || float.IsNaN(tr.bounds.min.y)) |
| | 123 | | { |
| 0 | 124 | | Destroy(this); |
| 0 | 125 | | return; |
| | 126 | | } |
| | 127 | |
|
| 86 | 128 | | if (float.IsInfinity(tr.bounds.max.y) || float.IsNaN(tr.bounds.max.y)) |
| | 129 | | { |
| 0 | 130 | | Destroy(this); |
| 0 | 131 | | return; |
| | 132 | | } |
| | 133 | |
|
| 86 | 134 | | tr.enabled = false; |
| | 135 | |
|
| 86 | 136 | | if (useHologram) |
| | 137 | | { |
| 85 | 138 | | InitHologram(); |
| | 139 | | } |
| | 140 | |
|
| 86 | 141 | | lowerYRendererBounds = GetLowerBoundsY(tr); |
| 86 | 142 | | topYRendererBounds = GetTopBoundsY(tr); |
| 86 | 143 | | currentCullYPlane = lowerYRendererBounds; |
| 86 | 144 | | } |
| | 145 | |
|
| | 146 | | void InitHologram() |
| | 147 | | { |
| 85 | 148 | | placeholder = new GameObject("Load Placeholder"); |
| | 149 | |
|
| 85 | 150 | | placeholder.transform.SetParent(transform, false); |
| 85 | 151 | | placeholder.transform.ResetLocalTRS(); |
| | 152 | |
|
| 85 | 153 | | placeholderRenderer = placeholder.AddComponent<MeshRenderer>(); |
| 85 | 154 | | MeshFilter newMeshFilter = placeholder.AddComponent<MeshFilter>(); |
| 85 | 155 | | newMeshFilter.sharedMesh = GetComponent<MeshFilter>().sharedMesh; |
| | 156 | |
|
| 85 | 157 | | if (hologramMaterial == null) |
| 1 | 158 | | hologramMaterial = Resources.Load("Materials/HologramMaterial") as Material; |
| | 159 | |
|
| 85 | 160 | | hologramMaterialCopy = new Material(hologramMaterial); |
| 85 | 161 | | placeholderRenderer.sharedMaterials = new Material[] { hologramMaterialCopy }; |
| 85 | 162 | | } |
| | 163 | |
|
| | 164 | | private void Update() |
| | 165 | | { |
| 13649 | 166 | | if (targetRendererValue == null) |
| | 167 | | { |
| 0 | 168 | | DestroyPlaceholder(); |
| 0 | 169 | | state = State.INVALID; |
| 0 | 170 | | return; |
| | 171 | | } |
| | 172 | |
|
| 13649 | 173 | | switch (state) |
| | 174 | | { |
| | 175 | | case State.NOT_LOADED: |
| | 176 | | { |
| 9092 | 177 | | currentCullYPlane += (topYRendererBounds - currentCullYPlane) * 0.1f; |
| 9092 | 178 | | currentCullYPlane = Mathf.Clamp(currentCullYPlane, lowerYRendererBounds, topYRendererBounds); |
| 9092 | 179 | | time += Time.deltaTime; |
| | 180 | |
|
| 9092 | 181 | | UpdateCullYValueHologram(); |
| | 182 | |
|
| 9092 | 183 | | if (materialReady && time > delay) |
| | 184 | | { |
| 86 | 185 | | currentCullYPlane = topYRendererBounds; |
| 86 | 186 | | targetRendererValue.enabled = true; |
| | 187 | |
|
| 86 | 188 | | PrepareCullingFXMaterials(); |
| 86 | 189 | | PopulateTargetRendererWithMaterial(cullingFXMaterials, true); |
| | 190 | |
|
| 86 | 191 | | state = State.SHOWING_LOADED; |
| | 192 | | } |
| | 193 | |
|
| 86 | 194 | | break; |
| | 195 | | } |
| | 196 | |
|
| | 197 | | case State.SHOWING_LOADED: |
| | 198 | | { |
| 4471 | 199 | | currentCullYPlane += (lowerYRendererBounds - currentCullYPlane) * 0.1f; |
| 4471 | 200 | | currentCullYPlane = Mathf.Clamp(currentCullYPlane, lowerYRendererBounds, topYRendererBounds); |
| | 201 | |
|
| 4471 | 202 | | UpdateCullYValueHologram(); |
| 4471 | 203 | | UpdateCullYValueFXMaterial(); |
| | 204 | |
|
| 4471 | 205 | | if (currentCullYPlane <= lowerYRendererBounds + 0.1f) |
| | 206 | | { |
| | 207 | | // We don't update the culling value in the final material to avoid affecting the already-loaded |
| 86 | 208 | | PopulateTargetRendererWithMaterial(finalMaterials); |
| | 209 | |
|
| 86 | 210 | | DestroyPlaceholder(); |
| 86 | 211 | | state = State.FINISHED; |
| | 212 | | } |
| | 213 | |
|
| 86 | 214 | | break; |
| | 215 | | } |
| | 216 | |
|
| | 217 | | case State.FINISHED: |
| | 218 | | { |
| 86 | 219 | | onFinishedLoading?.Invoke(); |
| 86 | 220 | | Destroy(this); |
| | 221 | | break; |
| | 222 | | } |
| | 223 | | } |
| 13477 | 224 | | } |
| | 225 | |
|
| | 226 | | private void OnDestroy() |
| | 227 | | { |
| 86 | 228 | | DestroyPlaceholder(); |
| | 229 | |
|
| 86 | 230 | | if (loadingMaterialCopies != null) |
| | 231 | | { |
| 0 | 232 | | for (int i = 0; i < loadingMaterialCopies.Count; i++) |
| | 233 | | { |
| 0 | 234 | | Material m = loadingMaterialCopies[i]; |
| 0 | 235 | | if (m != null) |
| | 236 | | { |
| 0 | 237 | | Destroy(m); |
| | 238 | | } |
| | 239 | | } |
| | 240 | | } |
| 86 | 241 | | } |
| | 242 | |
|
| | 243 | | void DestroyPlaceholder() |
| | 244 | | { |
| 172 | 245 | | Destroy(hologramMaterialCopy); |
| 172 | 246 | | hologramMaterialCopy = null; |
| | 247 | |
|
| 172 | 248 | | if (placeholder != null) |
| | 249 | | { |
| 85 | 250 | | Destroy(placeholder); |
| | 251 | | } |
| | 252 | |
|
| 172 | 253 | | if (cullingFXMaterials != null) |
| | 254 | | { |
| 688 | 255 | | for (int i = 0; i < cullingFXMaterials.Length; i++) |
| | 256 | | { |
| 172 | 257 | | Destroy(cullingFXMaterials[i]); |
| | 258 | | } |
| | 259 | | } |
| 172 | 260 | | } |
| | 261 | |
|
| | 262 | | public void OnDidFinishLoading(Material finishMaterial) |
| | 263 | | { |
| 86 | 264 | | finalMaterials = new Material[] { finishMaterial }; |
| 86 | 265 | | materialReady = true; |
| 86 | 266 | | } |
| | 267 | |
|
| 86 | 268 | | public float GetLowerBoundsY(Renderer targetRenderer) { return targetRenderer.bounds.min.y - fadeThickness; } |
| | 269 | |
|
| 86 | 270 | | public float GetTopBoundsY(Renderer targetRenderer) { return targetRenderer.bounds.max.y + fadeThickness; } |
| | 271 | |
|
| | 272 | | public static void ApplyToLoadedObject(GameObject meshContainer, bool useHologram = true, float fadeThickness = 20, |
| | 273 | | { |
| 0 | 274 | | Renderer[] renderers = meshContainer.GetComponentsInChildren<Renderer>(); |
| | 275 | |
|
| 0 | 276 | | for (int i = 0; i < renderers.Length; i++) |
| | 277 | | { |
| 0 | 278 | | Renderer r = renderers[i]; |
| | 279 | |
|
| 0 | 280 | | if (r.gameObject.GetComponent<MaterialTransitionController>() != null) |
| | 281 | | continue; |
| | 282 | |
|
| 0 | 283 | | MaterialTransitionController transition = r.gameObject.AddComponent<MaterialTransitionController>(); |
| 0 | 284 | | Material finalMaterial = r.sharedMaterial; |
| 0 | 285 | | transition.delay = delay; |
| 0 | 286 | | transition.useHologram = useHologram; |
| 0 | 287 | | transition.fadeThickness = fadeThickness; |
| 0 | 288 | | transition.OnDidFinishLoading(finalMaterial); |
| | 289 | | } |
| 0 | 290 | | } |
| | 291 | | } |