| | 1 | | using System; |
| | 2 | | using DCL.ECSRuntime; |
| | 3 | | using DCL.Models; |
| | 4 | | using DCL.WorldRuntime; |
| | 5 | | using UnityEngine; |
| | 6 | |
|
| | 7 | | namespace DCL.Controllers |
| | 8 | | { |
| | 9 | | /// <summary> |
| | 10 | | /// This handler is in charge of handling the scene lifecycle events |
| | 11 | | /// and upkeep the scene lifecycle state. |
| | 12 | | /// </summary> |
| | 13 | | public class SceneLifecycleHandler |
| | 14 | | { |
| | 15 | | public static bool VERBOSE = false; |
| | 16 | |
|
| | 17 | | public enum State |
| | 18 | | { |
| | 19 | | NOT_READY, |
| | 20 | | WAITING_FOR_INIT_MESSAGES, |
| | 21 | | WAITING_FOR_COMPONENTS, |
| | 22 | | READY, |
| | 23 | | } |
| | 24 | |
|
| 2 | 25 | | public int pendingResourcesCount => sceneResourcesLoadTracker.pendingResourcesCount; |
| 497 | 26 | | public float loadingProgress => sceneResourcesLoadTracker.loadingProgress; |
| 0 | 27 | | public bool isReady => state == State.READY; |
| | 28 | |
|
| | 29 | | State stateValue = State.NOT_READY; |
| | 30 | |
|
| | 31 | | public State state |
| | 32 | | { |
| 0 | 33 | | get { return stateValue; } |
| | 34 | | set |
| | 35 | | { |
| 1563 | 36 | | stateValue = value; |
| 1563 | 37 | | OnStateRefreshed?.Invoke(owner); |
| 0 | 38 | | } |
| | 39 | | } |
| | 40 | |
|
| 1074 | 41 | | public SceneResourcesLoadTracker sceneResourcesLoadTracker { get; } |
| | 42 | |
|
| | 43 | | public event Action<ParcelScene> OnSceneReady; |
| | 44 | | public event Action<ParcelScene> OnStateRefreshed; |
| | 45 | |
|
| | 46 | | private ParcelScene owner; |
| | 47 | |
|
| 537 | 48 | | public SceneLifecycleHandler(ParcelScene ownerScene) |
| | 49 | | { |
| 537 | 50 | | state = State.NOT_READY; |
| 537 | 51 | | this.owner = ownerScene; |
| 537 | 52 | | owner.OnSetData += OnSceneSetData; |
| | 53 | |
|
| 537 | 54 | | sceneResourcesLoadTracker = new SceneResourcesLoadTracker(); |
| 537 | 55 | | sceneResourcesLoadTracker.Track(owner.componentsManagerLegacy, Environment.i.world.state); |
| 537 | 56 | | sceneResourcesLoadTracker.OnResourcesStatusUpdate += OnResourcesStatusUpdated; |
| | 57 | |
|
| | 58 | | // This is done while the two ECS are living together, if we detect that a component from the new ECS has in |
| | 59 | | // resource for the scene, we changed the track since that means that this scene is from the new ECS. |
| | 60 | | // This should disappear when the old ecs is removed from the project. This should be the default track |
| 537 | 61 | | DataStore.i.ecs7.scenes.OnAdded += ChangeTrackingSystem; |
| 537 | 62 | | } |
| | 63 | |
|
| | 64 | | private void ChangeTrackingSystem(IParcelScene scene) |
| | 65 | | { |
| 2 | 66 | | if (scene.sceneData.id != owner.sceneData.id) |
| 0 | 67 | | return; |
| | 68 | |
|
| 2 | 69 | | DataStore.i.ecs7.scenes.OnAdded -= ChangeTrackingSystem; |
| | 70 | |
|
| 2 | 71 | | sceneResourcesLoadTracker.Dispose(); |
| 2 | 72 | | sceneResourcesLoadTracker.Track(scene.sceneData.id); |
| 2 | 73 | | } |
| | 74 | |
|
| | 75 | | private void OnSceneSetData(LoadParcelScenesMessage.UnityParcelScene data) |
| | 76 | | { |
| 529 | 77 | | state = State.WAITING_FOR_INIT_MESSAGES; |
| 529 | 78 | | owner.RefreshLoadingState(); |
| | 79 | |
|
| | 80 | | #if UNITY_EDITOR |
| 529 | 81 | | DebugConfig debugConfig = DataStore.i.debugConfig; |
| | 82 | | //NOTE(Brian): Don't generate parcel blockers if debugScenes is active and is not the desired scene. |
| 529 | 83 | | if (debugConfig.soloScene && debugConfig.soloSceneCoords != data.basePosition) |
| | 84 | | { |
| 0 | 85 | | SetSceneReady(); |
| 0 | 86 | | return; |
| | 87 | | } |
| | 88 | | #endif |
| | 89 | |
|
| 529 | 90 | | if (owner.isTestScene) |
| 497 | 91 | | SetSceneReady(); |
| 529 | 92 | | } |
| | 93 | |
|
| | 94 | | private void OnResourcesStatusUpdated() |
| | 95 | | { |
| 0 | 96 | | if (owner.isReleased) |
| 0 | 97 | | return; |
| | 98 | |
|
| 0 | 99 | | if (VERBOSE) |
| | 100 | | { |
| 0 | 101 | | Debug.Log($"{owner.sceneData.basePosition} Disposable objects left... {sceneResourcesLoadTracker.pending |
| | 102 | | } |
| | 103 | |
|
| 0 | 104 | | OnStateRefreshed?.Invoke(owner); |
| 0 | 105 | | owner.RefreshLoadingState(); |
| 0 | 106 | | } |
| | 107 | |
|
| | 108 | | public void SetInitMessagesDone() |
| | 109 | | { |
| 1 | 110 | | if (owner.isReleased) |
| 0 | 111 | | return; |
| | 112 | |
|
| 1 | 113 | | if (state == State.READY) |
| | 114 | | { |
| 1 | 115 | | Debug.LogWarning($"Init messages done after ready?! {owner.sceneData.basePosition}", owner.gameObject); |
| 1 | 116 | | return; |
| | 117 | | } |
| | 118 | |
|
| 0 | 119 | | state = State.WAITING_FOR_COMPONENTS; |
| 0 | 120 | | owner.RefreshLoadingState(); |
| | 121 | |
|
| 0 | 122 | | if (sceneResourcesLoadTracker.ShouldWaitForPendingResources()) |
| | 123 | | { |
| 0 | 124 | | sceneResourcesLoadTracker.OnResourcesLoaded -= SetSceneReady; |
| 0 | 125 | | sceneResourcesLoadTracker.OnResourcesLoaded += SetSceneReady; |
| 0 | 126 | | } |
| | 127 | | else |
| | 128 | | { |
| 0 | 129 | | SetSceneReady(); |
| | 130 | | } |
| 0 | 131 | | } |
| | 132 | |
|
| | 133 | | private void SetSceneReady() |
| | 134 | | { |
| | 135 | | #if UNITY_STANDALONE || UNITY_EDITOR |
| 497 | 136 | | if (DataStore.i.common.isApplicationQuitting.Get()) |
| 0 | 137 | | return; |
| | 138 | | #endif |
| | 139 | |
|
| 497 | 140 | | if (state == State.READY) |
| 0 | 141 | | return; |
| | 142 | |
|
| 497 | 143 | | if (VERBOSE) |
| 0 | 144 | | Debug.Log($"{owner.sceneData.basePosition} Scene Ready!"); |
| | 145 | |
|
| 497 | 146 | | state = State.READY; |
| | 147 | |
|
| 497 | 148 | | Environment.i.world.sceneController.SendSceneReady(owner.sceneData.id); |
| 497 | 149 | | owner.RefreshLoadingState(); |
| | 150 | |
|
| 497 | 151 | | sceneResourcesLoadTracker.OnResourcesLoaded -= SetSceneReady; |
| 497 | 152 | | sceneResourcesLoadTracker.OnResourcesStatusUpdate -= OnResourcesStatusUpdated; |
| 497 | 153 | | sceneResourcesLoadTracker.Dispose(); |
| | 154 | |
|
| 497 | 155 | | OnSceneReady?.Invoke(owner); |
| 0 | 156 | | } |
| | 157 | | } |
| | 158 | | } |