< Summary

Class:DCL.Controllers.ParcelScene
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/ParcelScene.cs
Covered lines:295
Uncovered lines:83
Coverable lines:378
Total lines:873
Line coverage:78% (295 of 378)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ParcelScene()0%110100%
Awake()0%110100%
OnDestroy()0%220100%
OnDisable()0%220100%
Update()0%330100%
SetData(...)0%440100%
OnWorldReposition(...)0%110100%
SetUpdateData(...)0%110100%
InitializeDebugPlane()0%440100%
RemoveDebugPlane()0%6200%
Cleanup(...)0%55095%
ToString()0%12300%
GetSceneName()0%6200%
IsInsideSceneBoundaries(...)0%330100%
IsInsideSceneBoundaries(...)0%3.333066.67%
IsInsideSceneBoundaries(...)0%8.338082.76%
GetSceneTransform()0%110100%
CreateEntity(...)0%440100%
RemoveEntity(...)0%4.14081.82%
CleanUpEntityRecursively(...)0%550100%
RemoveAllEntities(...)0%660100%
RemoveAllEntitiesImmediate()0%110100%
SetEntityParent(...)0%12.0712092.31%
SharedComponentAttach(...)0%330100%
EntityComponentCreateOrUpdateWithModel(...)0%13.3613087.1%
EntityComponentCreateOrUpdate(...)0%110100%
EntityComponentUpdate(...)0%3.793055.56%
SharedComponentCreate(...)0%7.187084.62%
SharedComponentDispose(...)0%4.134080%
EntityComponentRemove(...)0%2.032080%
GetSharedComponent[T]()0%220100%
RemoveComponentType[T](...)0%12300%
RemoveEntityComponent(...)0%39.5825071.43%
SharedComponentUpdate(...)0%5.23037.5%
SharedComponentUpdate(...)0%5.23037.5%
SendMetricsEvent()0%220100%
GetSharedComponent(...)0%220100%
GetEntityForUpdate(...)0%7.195055.56%
DisposeAllSceneComponents()0%330100%
GetStateString()0%27.1510044.44%
RefreshLoadingState()0%2.032080%
GetWaitingComponentsDebugInfo()0%42600%
CalculateSceneLoadingState()0%7.397080%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/ParcelScene.cs

#LineLine coverage
 1using DCL.Components;
 2using DCL.Configuration;
 3using DCL.Helpers;
 4using DCL.Models;
 5using DCL.Controllers.ParcelSceneDebug;
 6using System.Collections.Generic;
 7using System.Linq;
 8using MainScripts.DCL.WorldRuntime;
 9using UnityEngine;
 10using UnityEngine.Assertions;
 11
 12namespace DCL.Controllers
 13{
 14    public class ParcelScene : MonoBehaviour, IParcelScene, ISceneMessageProcessor
 15    {
 50816        public Dictionary<string, IDCLEntity> entities { get; private set; } = new Dictionary<string, IDCLEntity>();
 85017        public Dictionary<string, ISharedComponent> disposableComponents { get; private set; } = new Dictionary<string, 
 240118        public LoadParcelScenesMessage.UnityParcelScene sceneData { get; protected set; }
 19
 50320        public HashSet<Vector2Int> parcels = new HashSet<Vector2Int>();
 1421        public ISceneMetricsCounter metricsCounter { get; set; }
 22        public event System.Action<IDCLEntity> OnEntityAdded;
 23        public event System.Action<IDCLEntity> OnEntityRemoved;
 24        public event System.Action<IComponent> OnComponentAdded;
 25        public event System.Action<IComponent> OnComponentRemoved;
 26        public event System.Action OnChanged;
 27        public event System.Action<LoadParcelScenesMessage.UnityParcelScene> OnSetData;
 28        public event System.Action<string, ISharedComponent> OnAddSharedComponent;
 29        public event System.Action<float> OnLoadingStateUpdated;
 30
 14431        public ContentProvider contentProvider { get; set; }
 32
 033        public bool isTestScene { get; set; } = false;
 97134        public bool isPersistent { get; set; } = false;
 035        public float loadingProgress { get; private set; }
 36
 37        [System.NonSerialized]
 38        public string sceneName;
 39
 40        [System.NonSerialized]
 50341        public bool unloadWithDistance = true;
 42
 43        SceneDebugPlane sceneDebugPlane = null;
 44
 45        public SceneLifecycleHandler sceneLifecycleHandler;
 46
 047        public bool isReleased { get; private set; }
 48
 49        public void Awake()
 50        {
 50351            CommonScriptableObjects.worldOffset.OnChange += OnWorldReposition;
 50352            sceneLifecycleHandler = new SceneLifecycleHandler(this);
 50353            metricsCounter = new SceneMetricsCounter(DataStore.i.sceneWorldObjects);
 50354        }
 55
 56        private void OnDestroy()
 57        {
 50358            CommonScriptableObjects.worldOffset.OnChange -= OnWorldReposition;
 50359            metricsCounter?.Dispose();
 50360        }
 61
 100662        void OnDisable() { metricsCounter?.Disable(); }
 63
 64        private void Update()
 65        {
 673366            if (sceneLifecycleHandler.state == SceneLifecycleHandler.State.READY
 67                && CommonScriptableObjects.rendererState.Get())
 669368                SendMetricsEvent();
 673369        }
 70
 96871        protected virtual string prettyName => sceneData.basePosition.ToString();
 72
 73        public virtual void SetData(LoadParcelScenesMessage.UnityParcelScene data)
 74        {
 50075            Assert.IsTrue( !string.IsNullOrEmpty(data.id), "Scene must have an ID!" );
 76
 50077            this.sceneData = data;
 78
 50079            contentProvider = new ContentProvider();
 50080            contentProvider.baseUrl = data.baseUrl;
 50081            contentProvider.contents = data.contents;
 50082            contentProvider.BakeHashes();
 83
 50084            parcels.Clear();
 85
 203286            for (int i = 0; i < sceneData.parcels.Length; i++)
 87            {
 51688                parcels.Add(sceneData.parcels[i]);
 89            }
 90
 50091            if (DCLCharacterController.i != null)
 92            {
 39293                gameObject.transform.position = PositionUtils.WorldToUnityPosition(Utils.GridToWorldPosition(data.basePo
 94            }
 95
 50096            DataStore.i.sceneWorldObjects.AddScene(sceneData.id);
 97
 50098            metricsCounter.Configure(sceneData.id, sceneData.basePosition, sceneData.parcels.Length);
 50099            metricsCounter.Enable();
 100
 500101            OnSetData?.Invoke(data);
 500102        }
 103
 104        void OnWorldReposition(Vector3 current, Vector3 previous)
 105        {
 2106            Vector3 sceneWorldPos = Utils.GridToWorldPosition(sceneData.basePosition.x, sceneData.basePosition.y);
 2107            gameObject.transform.position = PositionUtils.WorldToUnityPosition(sceneWorldPos);
 2108        }
 109
 110        public virtual void SetUpdateData(LoadParcelScenesMessage.UnityParcelScene data)
 111        {
 15112            contentProvider = new ContentProvider();
 15113            contentProvider.baseUrl = data.baseUrl;
 15114            contentProvider.contents = data.contents;
 15115            contentProvider.BakeHashes();
 15116        }
 117
 118        public void InitializeDebugPlane()
 119        {
 388120            if (EnvironmentSettings.DEBUG && sceneData.parcels != null && sceneDebugPlane == null)
 121            {
 386122                sceneDebugPlane = new SceneDebugPlane(sceneData, gameObject.transform);
 123            }
 388124        }
 125
 126        public void RemoveDebugPlane()
 127        {
 0128            if (sceneDebugPlane != null)
 129            {
 0130                sceneDebugPlane.Dispose();
 0131                sceneDebugPlane = null;
 132            }
 0133        }
 134
 135        public void Cleanup(bool immediate)
 136        {
 428137            if (isReleased)
 0138                return;
 139
 428140            if (sceneDebugPlane != null)
 141            {
 377142                sceneDebugPlane.Dispose();
 377143                sceneDebugPlane = null;
 144            }
 145
 428146            DisposeAllSceneComponents();
 147
 428148            if (immediate) //!CommonScriptableObjects.rendererState.Get())
 149            {
 24150                RemoveAllEntitiesImmediate();
 24151                PoolManager.i.Cleanup(true, true);
 24152                DataStore.i.sceneWorldObjects.RemoveScene(sceneData.id);
 24153            }
 154            else
 155            {
 404156                if (entities.Count > 0)
 157                {
 208158                    this.gameObject.transform.position = EnvironmentSettings.MORDOR;
 208159                    this.gameObject.SetActive(false);
 160
 208161                    RemoveAllEntities();
 208162                }
 163                else
 164                {
 196165                    Destroy(this.gameObject);
 196166                    DataStore.i.sceneWorldObjects.RemoveScene(sceneData.id);
 167                }
 168            }
 169
 428170            isReleased = true;
 428171        }
 172
 0173        public override string ToString() { return "Parcel Scene: " + base.ToString() + "\n" + sceneData; }
 174
 175        public string GetSceneName()
 176        {
 0177            return string.IsNullOrEmpty(sceneName) ? "Unnamed" : sceneName;
 178        }
 179
 180        public bool IsInsideSceneBoundaries(Bounds objectBounds)
 181        {
 157182            if (!IsInsideSceneBoundaries(objectBounds.min + CommonScriptableObjects.worldOffset, objectBounds.max.y))
 116183                return false;
 41184            if (!IsInsideSceneBoundaries(objectBounds.max + CommonScriptableObjects.worldOffset, objectBounds.max.y))
 14185                return false;
 186
 27187            return true;
 188        }
 189
 190        public virtual bool IsInsideSceneBoundaries(Vector2Int gridPosition, float height = 0f)
 191        {
 84192            if (parcels.Count == 0)
 0193                return false;
 194
 84195            float heightLimit = metricsCounter.maxCount.sceneHeight;
 196
 84197            if (height > heightLimit)
 0198                return false;
 199
 84200            return parcels.Contains(gridPosition);
 201        }
 202
 203        public virtual bool IsInsideSceneBoundaries(Vector3 worldPosition, float height = 0f)
 204        {
 237205            if (parcels.Count == 0)
 0206                return false;
 207
 237208            float heightLimit = metricsCounter.maxCount.sceneHeight;
 237209            if (height > heightLimit)
 24210                return false;
 211
 213212            int noThresholdZCoordinate = Mathf.FloorToInt(worldPosition.z / ParcelSettings.PARCEL_SIZE);
 213213            int noThresholdXCoordinate = Mathf.FloorToInt(worldPosition.x / ParcelSettings.PARCEL_SIZE);
 214
 215            // We check the target world position
 213216            Vector2Int targetCoordinate = new Vector2Int(noThresholdXCoordinate, noThresholdZCoordinate);
 213217            if (parcels.Contains(targetCoordinate))
 97218                return true;
 219
 220            // We need to check using a threshold from the target point, in order to cover correctly the parcel "border/
 116221            Vector2Int coordinateMin = new Vector2Int();
 116222            coordinateMin.x = Mathf.FloorToInt((worldPosition.x - ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 116223            coordinateMin.y = Mathf.FloorToInt((worldPosition.z - ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 224
 116225            Vector2Int coordinateMax = new Vector2Int();
 116226            coordinateMax.x = Mathf.FloorToInt((worldPosition.x + ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 116227            coordinateMax.y = Mathf.FloorToInt((worldPosition.z + ParcelSettings.PARCEL_BOUNDARIES_THRESHOLD) / ParcelSe
 228
 229            // We check the east/north-threshold position
 116230            targetCoordinate.Set(coordinateMax.x, coordinateMax.y);
 116231            if (parcels.Contains(targetCoordinate))
 0232                return true;
 233
 234            // We check the east/south-threshold position
 116235            targetCoordinate.Set(coordinateMax.x, coordinateMin.y);
 116236            if (parcels.Contains(targetCoordinate))
 0237                return true;
 238
 239            // We check the west/north-threshold position
 116240            targetCoordinate.Set(coordinateMin.x, coordinateMax.y);
 116241            if (parcels.Contains(targetCoordinate))
 0242                return true;
 243
 244            // We check the west/south-threshold position
 116245            targetCoordinate.Set(coordinateMin.x, coordinateMin.y);
 116246            if (parcels.Contains(targetCoordinate))
 0247                return true;
 248
 116249            return false;
 250        }
 251
 53252        public Transform GetSceneTransform() { return transform; }
 253
 254        public IDCLEntity CreateEntity(string id)
 255        {
 584256            if (entities.ContainsKey(id))
 257            {
 1258                return entities[id];
 259            }
 260
 583261            var newEntity = new DecentralandEntity();
 583262            newEntity.entityId = id;
 263
 583264            PoolManagerFactory.EnsureEntityPool(false);
 265
 266            // As we know that the pool already exists, we just get one gameobject from it
 583267            PoolableObject po = PoolManager.i.Get(PoolManagerFactory.EMPTY_GO_POOL_NAME);
 268
 583269            newEntity.meshesInfo.innerGameObject = po.gameObject;
 583270            newEntity.gameObject = po.gameObject;
 271
 272#if UNITY_EDITOR
 583273            newEntity.gameObject.name = "ENTITY_" + id;
 274#endif
 583275            newEntity.gameObject.transform.SetParent(gameObject.transform, false);
 583276            newEntity.gameObject.SetActive(true);
 583277            newEntity.scene = this;
 278
 583279            newEntity.OnCleanupEvent += po.OnCleanup;
 280
 583281            if (Environment.i.world.sceneBoundsChecker.enabled)
 432282                newEntity.OnShapeUpdated += Environment.i.world.sceneBoundsChecker.AddEntityToBeChecked;
 283
 583284            entities.Add(id, newEntity);
 285
 583286            DataStore.i.sceneWorldObjects.sceneData[sceneData.id].owners.Add(id);
 287
 583288            OnEntityAdded?.Invoke(newEntity);
 289
 583290            return newEntity;
 291        }
 292
 293        public void RemoveEntity(string id, bool removeImmediatelyFromEntitiesList = true)
 294        {
 69295            if (entities.ContainsKey(id))
 296            {
 69297                IDCLEntity entity = entities[id];
 298
 69299                if (!entity.markedForCleanup)
 300                {
 301                    // This will also cleanup its children
 69302                    CleanUpEntityRecursively(entity, removeImmediatelyFromEntitiesList);
 303                }
 304
 69305                entities.Remove(id);
 306
 69307                var data = DataStore.i.sceneWorldObjects.sceneData;
 308
 69309                if (data.ContainsKey(sceneData.id))
 310                {
 69311                    data[sceneData.id].owners.Remove(id);
 312                }
 69313            }
 314#if UNITY_EDITOR || DEVELOPMENT_BUILD
 315            else
 316            {
 0317                Debug.LogWarning($"Couldn't remove entity with ID: {id} as it doesn't exist.");
 318            }
 319#endif
 0320        }
 321
 322        void CleanUpEntityRecursively(IDCLEntity entity, bool removeImmediatelyFromEntitiesList)
 323        {
 324            // Iterate through all entity children
 70325            using (var iterator = entity.children.GetEnumerator())
 326            {
 71327                while (iterator.MoveNext())
 328                {
 1329                    CleanUpEntityRecursively(iterator.Current.Value, removeImmediatelyFromEntitiesList);
 330                }
 70331            }
 332
 70333            OnEntityRemoved?.Invoke(entity);
 334
 70335            if (Environment.i.world.sceneBoundsChecker.enabled)
 336            {
 29337                entity.OnShapeUpdated -= Environment.i.world.sceneBoundsChecker.AddEntityToBeChecked;
 29338                Environment.i.world.sceneBoundsChecker.RemoveEntityToBeChecked(entity);
 339            }
 340
 70341            if (removeImmediatelyFromEntitiesList)
 342            {
 343                // Every entity ends up being removed through here
 69344                entity.Cleanup();
 69345                entities.Remove(entity.entityId);
 69346            }
 347            else
 348            {
 1349                Environment.i.platform.parcelScenesCleaner.MarkForCleanup(entity);
 350            }
 1351        }
 352
 353        void RemoveAllEntities(bool instant = false)
 354        {
 355            //NOTE(Brian): We need to remove only the rootEntities.
 356            //             If we don't, duplicated entities will get removed when destroying
 357            //             recursively, making this more complicated than it should.
 232358            List<IDCLEntity> rootEntities = new List<IDCLEntity>();
 359
 232360            using (var iterator = entities.GetEnumerator())
 361            {
 718362                while (iterator.MoveNext())
 363                {
 486364                    if (iterator.Current.Value.parent == null)
 365                    {
 479366                        if (instant)
 34367                            rootEntities.Add(iterator.Current.Value);
 368                        else
 445369                            Environment.i.platform.parcelScenesCleaner.MarkRootEntityForCleanup(this, iterator.Current.V
 370                    }
 371                }
 232372            }
 373
 232374            if (instant)
 375            {
 24376                int rootEntitiesCount = rootEntities.Count;
 116377                for (int i = 0; i < rootEntitiesCount; i++)
 378                {
 34379                    IDCLEntity entity = rootEntities[i];
 34380                    RemoveEntity(entity.entityId, instant);
 381                }
 382
 24383                entities.Clear();
 384
 24385                Destroy(this.gameObject);
 386            }
 232387        }
 388
 48389        private void RemoveAllEntitiesImmediate() { RemoveAllEntities(instant: true); }
 390
 391        public void SetEntityParent(string entityId, string parentId)
 392        {
 15393            if (entityId == parentId)
 394            {
 0395                return;
 396            }
 397
 15398            IDCLEntity me = GetEntityForUpdate(entityId);
 399
 15400            if (me == null)
 0401                return;
 402
 15403            Environment.i.platform.cullingController.MarkDirty();
 15404            Environment.i.platform.physicsSyncController.MarkDirty();
 405
 15406            if ( DCLCharacterController.i != null )
 407            {
 13408                if (parentId == "FirstPersonCameraEntityReference" || parentId == "PlayerEntityReference") // PlayerEnti
 409                {
 410                    // In this case, the entity will attached to the first person camera
 411                    // On first person mode, the entity will rotate with the camera. On third person mode, the entity wi
 1412                    me.SetParent(DCLCharacterController.i.firstPersonCameraReference);
 1413                    Environment.i.world.sceneBoundsChecker.AddPersistent(me);
 1414                    return;
 415                }
 416
 12417                if (parentId == "AvatarEntityReference" || parentId == "AvatarPositionEntityReference") // AvatarPositio
 418                {
 419                    // In this case, the entity will be attached to the avatar
 420                    // It will simply rotate with the avatar, regardless of where the camera is pointing
 1421                    me.SetParent(DCLCharacterController.i.avatarReference);
 1422                    Environment.i.world.sceneBoundsChecker.AddPersistent(me);
 1423                    return;
 424                }
 425
 11426                if (me.parent == DCLCharacterController.i.firstPersonCameraReference || me.parent == DCLCharacterControl
 427                {
 1428                    Environment.i.world.sceneBoundsChecker.RemoveEntityToBeChecked(me);
 429                }
 430            }
 431
 13432            if (parentId == "0")
 433            {
 434                // The entity will be child of the scene directly
 2435                me.SetParent(null);
 2436                me.gameObject.transform.SetParent(gameObject.transform, false);
 2437            }
 438            else
 439            {
 11440                IDCLEntity myParent = GetEntityForUpdate(parentId);
 441
 11442                if (myParent != null)
 443                {
 11444                    me.SetParent(myParent);
 445                }
 446            }
 11447        }
 448
 449        /**
 450          * This method is called when we need to attach a disposable component to the entity
 451          */
 452        public void SharedComponentAttach(string entityId, string componentId)
 453        {
 454454            IDCLEntity entity = GetEntityForUpdate(entityId);
 455
 454456            if (entity == null)
 2457                return;
 458
 452459            if (disposableComponents.TryGetValue(componentId, out ISharedComponent sharedComponent))
 460            {
 450461                sharedComponent.AttachTo(entity);
 462            }
 452463        }
 464
 465        public IEntityComponent EntityComponentCreateOrUpdateWithModel(string entityId, CLASS_ID_COMPONENT classId, obje
 466        {
 381467            IDCLEntity entity = GetEntityForUpdate(entityId);
 468
 381469            if (entity == null)
 470            {
 0471                Debug.LogError($"scene '{sceneData.id}': Can't create entity component if the entity {entityId} doesn't 
 0472                return null;
 473            }
 474
 381475            IEntityComponent newComponent = null;
 476
 381477            if (classId == CLASS_ID_COMPONENT.UUID_CALLBACK)
 478            {
 69479                OnPointerEvent.Model model = JsonUtility.FromJson<OnPointerEvent.Model>(data as string);
 69480                classId = model.GetClassIdFromType();
 69481            }
 482            // NOTE: TRANSFORM and AVATAR_ATTACH can't be used in the same Entity at the same time.
 483            // so we remove AVATAR_ATTACH (if exists) when a TRANSFORM is created.
 312484            else if (classId == CLASS_ID_COMPONENT.TRANSFORM
 485                     && entity.TryGetBaseComponent(CLASS_ID_COMPONENT.AVATAR_ATTACH, out IEntityComponent component))
 486            {
 0487                component.Cleanup();
 0488                entity.components.Remove( CLASS_ID_COMPONENT.AVATAR_ATTACH );
 489            }
 490
 381491            if (!entity.components.ContainsKey(classId))
 492            {
 304493                var factory = Environment.i.world.componentFactory;
 304494                newComponent = factory.CreateComponent((int) classId) as IEntityComponent;
 495
 304496                if (newComponent != null)
 497                {
 304498                    entity.components.Add(classId, newComponent);
 304499                    OnComponentAdded?.Invoke(newComponent);
 500
 304501                    newComponent.Initialize(this, entity);
 502
 304503                    if (data is string json)
 504                    {
 269505                        newComponent.UpdateFromJSON(json);
 269506                    }
 507                    else
 508                    {
 35509                        newComponent.UpdateFromModel(data as BaseModel);
 510                    }
 511                }
 35512            }
 513            else
 514            {
 77515                newComponent = EntityComponentUpdate(entity, classId, data as string);
 516            }
 517
 381518            if (newComponent != null && newComponent is IOutOfSceneBoundariesHandler)
 15519                Environment.i.world.sceneBoundsChecker?.AddEntityToBeChecked(entity);
 520
 381521            OnChanged?.Invoke();
 381522            Environment.i.platform.physicsSyncController.MarkDirty();
 381523            Environment.i.platform.cullingController.MarkDirty();
 381524            return newComponent;
 525        }
 526
 346527        public IEntityComponent EntityComponentCreateOrUpdate(string entityId, CLASS_ID_COMPONENT classId, string data) 
 528
 529        // The EntityComponentUpdate() parameters differ from other similar methods because there is no EntityComponentU
 530        public IEntityComponent EntityComponentUpdate(IDCLEntity entity, CLASS_ID_COMPONENT classId,
 531            string componentJson)
 532        {
 99533            if (entity == null)
 534            {
 0535                Debug.LogError($"Can't update the {classId} component of a nonexistent entity!", this);
 0536                return null;
 537            }
 538
 99539            if (!entity.components.ContainsKey(classId))
 540            {
 0541                Debug.LogError($"Entity {entity.entityId} doesn't have a {classId} component to update!", this);
 0542                return null;
 543            }
 544
 99545            IComponent targetComponent = entity.components[classId];
 99546            targetComponent.UpdateFromJSON(componentJson);
 547
 99548            return targetComponent as IEntityComponent;
 549        }
 550
 551        public ISharedComponent SharedComponentCreate(string id, int classId)
 552        {
 634553            if (disposableComponents.TryGetValue(id, out ISharedComponent component))
 4554                return component;
 555
 630556            if (classId == (int) CLASS_ID.UI_SCREEN_SPACE_SHAPE || classId == (int) CLASS_ID.UI_FULLSCREEN_SHAPE)
 557            {
 44558                if (GetSharedComponent<UIScreenSpace>() != null)
 0559                    return null;
 560            }
 561
 630562            var factory = Environment.i.world.componentFactory;
 630563            ISharedComponent newComponent = factory.CreateComponent(classId) as ISharedComponent;
 564
 630565            if (newComponent == null)
 0566                return null;
 567
 630568            disposableComponents.Add(id, newComponent);
 630569            OnAddSharedComponent?.Invoke(id, newComponent);
 570
 630571            newComponent.Initialize(this, id);
 572
 630573            return newComponent;
 574        }
 575
 576        public void SharedComponentDispose(string id)
 577        {
 88578            if (disposableComponents.TryGetValue(id, out ISharedComponent sharedComponent))
 579            {
 88580                sharedComponent?.Dispose();
 88581                disposableComponents.Remove(id);
 88582                OnComponentRemoved?.Invoke(sharedComponent);
 583            }
 0584        }
 585
 586        public void EntityComponentRemove(string entityId, string name)
 587        {
 20588            IDCLEntity decentralandEntity = GetEntityForUpdate(entityId);
 589
 20590            if (decentralandEntity == null)
 591            {
 0592                return;
 593            }
 594
 20595            RemoveEntityComponent(decentralandEntity, name);
 20596        }
 597
 598        public T GetSharedComponent<T>()
 599            where T : class
 600        {
 433601            return disposableComponents.Values.FirstOrDefault(x => x is T) as T;
 602        }
 603
 604        private void RemoveComponentType<T>(IDCLEntity entity, CLASS_ID_COMPONENT classId)
 605            where T : MonoBehaviour
 606        {
 0607            var component = entity.components[classId] as IEntityComponent;
 608
 0609            if (component == null)
 0610                return;
 611
 0612            var monoBehaviour = component.GetTransform().GetComponent<T>();
 613
 0614            if (monoBehaviour != null)
 615            {
 0616                Utils.SafeDestroy(monoBehaviour);
 617            }
 0618        }
 619
 620        private void RemoveEntityComponent(IDCLEntity entity, string componentName)
 621        {
 622            switch (componentName)
 623            {
 624                case "shape":
 0625                    if (entity.meshesInfo.currentShape is BaseShape baseShape)
 626                    {
 0627                        baseShape.DetachFrom(entity);
 628                    }
 629
 0630                    return;
 631
 632                case OnClick.NAME:
 633                    {
 1634                        if ( entity.TryGetBaseComponent(CLASS_ID_COMPONENT.UUID_ON_CLICK, out IEntityComponent component
 635                        {
 1636                            Utils.SafeDestroy(component.GetTransform().gameObject);
 1637                            entity.components.Remove( CLASS_ID_COMPONENT.UUID_ON_CLICK );
 638                        }
 639
 1640                        return;
 641                    }
 642                case OnPointerDown.NAME:
 643                    {
 1644                        if ( entity.TryGetBaseComponent(CLASS_ID_COMPONENT.UUID_ON_DOWN, out IEntityComponent component 
 645                        {
 1646                            Utils.SafeDestroy(component.GetTransform().gameObject);
 1647                            entity.components.Remove( CLASS_ID_COMPONENT.UUID_ON_DOWN );
 648                        }
 649                    }
 1650                    return;
 651                case OnPointerUp.NAME:
 652                    {
 1653                        if ( entity.TryGetBaseComponent(CLASS_ID_COMPONENT.UUID_ON_UP, out IEntityComponent component ))
 654                        {
 1655                            Utils.SafeDestroy(component.GetTransform().gameObject);
 1656                            entity.components.Remove( CLASS_ID_COMPONENT.UUID_ON_UP );
 657                        }
 658                    }
 1659                    return;
 660                case OnPointerHoverEnter.NAME:
 661                    {
 1662                        if ( entity.TryGetBaseComponent(CLASS_ID_COMPONENT.UUID_ON_HOVER_ENTER, out IEntityComponent com
 663                        {
 1664                            Utils.SafeDestroy(component.GetTransform().gameObject);
 1665                            entity.components.Remove( CLASS_ID_COMPONENT.UUID_ON_HOVER_ENTER );
 666                        }
 667                    }
 1668                    return;
 669                case OnPointerHoverExit.NAME:
 670                    {
 1671                        if ( entity.TryGetBaseComponent(CLASS_ID_COMPONENT.UUID_ON_HOVER_EXIT, out IEntityComponent comp
 672                        {
 1673                            Utils.SafeDestroy(component.GetTransform().gameObject);
 1674                            entity.components.Remove( CLASS_ID_COMPONENT.UUID_ON_HOVER_EXIT );
 675                        }
 676                    }
 1677                    return;
 678                case "transform":
 679                    {
 0680                        if ( entity.TryGetBaseComponent(CLASS_ID_COMPONENT.AVATAR_ATTACH, out IEntityComponent component
 681                        {
 0682                            component.Cleanup();
 0683                            entity.components.Remove( CLASS_ID_COMPONENT.AVATAR_ATTACH );
 684                        }
 685                    }
 0686                    return;
 687            }
 0688        }
 689
 690        public ISharedComponent SharedComponentUpdate(string id, BaseModel model)
 691        {
 27692            if (disposableComponents.TryGetValue(id, out ISharedComponent sharedComponent))
 693            {
 27694                sharedComponent.UpdateFromModel(model);
 27695                return sharedComponent;
 696            }
 697
 0698            if (gameObject == null)
 699            {
 0700                Debug.LogError($"Unknown disposableComponent {id} -- scene has been destroyed?");
 0701            }
 702            else
 703            {
 0704                Debug.LogError($"Unknown disposableComponent {id}", gameObject);
 705            }
 706
 0707            return null;
 708        }
 709
 710        public ISharedComponent SharedComponentUpdate(string id, string json)
 711        {
 673712            if (disposableComponents.TryGetValue(id, out ISharedComponent disposableComponent))
 713            {
 673714                disposableComponent.UpdateFromJSON(json);
 673715                return disposableComponent;
 716            }
 717
 0718            if (gameObject == null)
 719            {
 0720                Debug.LogError($"Unknown disposableComponent {id} -- scene has been destroyed?");
 0721            }
 722            else
 723            {
 0724                Debug.LogError($"Unknown disposableComponent {id}", gameObject);
 725            }
 726
 0727            return null;
 728        }
 729
 730        protected virtual void SendMetricsEvent()
 731        {
 6693732            if (Time.frameCount % 10 == 0)
 669733                metricsCounter.SendEvent();
 6693734        }
 735
 736        public ISharedComponent GetSharedComponent(string componentId)
 737        {
 571738            if (!disposableComponents.TryGetValue(componentId, out ISharedComponent result))
 739            {
 526740                return null;
 741            }
 742
 45743            return result;
 744        }
 745
 746        private IDCLEntity GetEntityForUpdate(string entityId)
 747        {
 881748            if (string.IsNullOrEmpty(entityId))
 749            {
 0750                Debug.LogError("Null or empty entityId");
 0751                return null;
 752            }
 753
 881754            if (!entities.TryGetValue(entityId, out IDCLEntity entity))
 755            {
 2756                return null;
 757            }
 758
 759            //NOTE(Brian): This is for removing stray null references? This should never happen.
 760            //             Maybe move to a different 'clean-up' method to make this method have a single responsibility?
 879761            if (entity == null || entity.gameObject == null)
 762            {
 0763                entities.Remove(entityId);
 0764                return null;
 765            }
 766
 879767            return entity;
 768        }
 769
 770        private void DisposeAllSceneComponents()
 771        {
 923772            List<string> allDisposableComponents = disposableComponents.Select(x => x.Key).ToList();
 1846773            foreach (string id in allDisposableComponents)
 774            {
 495775                Environment.i.platform.parcelScenesCleaner.MarkDisposableComponentForCleanup(this, id);
 776            }
 428777        }
 778
 779        public string GetStateString()
 780        {
 968781            string baseState = isPersistent ? "global-scene" : "scene";
 968782            switch (sceneLifecycleHandler.state)
 783            {
 784                case SceneLifecycleHandler.State.NOT_READY:
 0785                    return $"{baseState}:{prettyName} - not ready...";
 786                case SceneLifecycleHandler.State.WAITING_FOR_INIT_MESSAGES:
 500787                    return $"{baseState}:{prettyName} - waiting for init messages...";
 788                case SceneLifecycleHandler.State.WAITING_FOR_COMPONENTS:
 0789                    if (disposableComponents != null && disposableComponents.Count > 0)
 0790                        return $"{baseState}:{prettyName} - left to ready:{disposableComponents.Count - sceneLifecycleHa
 791                    else
 0792                        return $"{baseState}:{prettyName} - no components. waiting...";
 793                case SceneLifecycleHandler.State.READY:
 468794                    return $"{baseState}:{prettyName} - ready!";
 795            }
 796
 0797            return $"scene:{prettyName} - no state?";
 798        }
 799
 800        public void RefreshLoadingState()
 801        {
 802#if UNITY_STANDALONE || UNITY_EDITOR
 968803            if (DataStore.i.common.isApplicationQuitting.Get())
 0804                return;
 805#endif
 806
 968807            CalculateSceneLoadingState();
 808
 809#if UNITY_EDITOR
 968810            gameObject.name = GetStateString();
 811#endif
 968812        }
 813
 814        [ContextMenu("Get Waiting Components Debug Info")]
 815        public void GetWaitingComponentsDebugInfo()
 816        {
 0817            switch (sceneLifecycleHandler.state)
 818            {
 819                case SceneLifecycleHandler.State.WAITING_FOR_COMPONENTS:
 820
 0821                    foreach (string componentId in sceneLifecycleHandler.disposableNotReady)
 822                    {
 0823                        if (disposableComponents.ContainsKey(componentId))
 824                        {
 0825                            var component = disposableComponents[componentId];
 826
 0827                            Debug.Log($"Waiting for: {component.ToString()}");
 828
 0829                            foreach (var entity in component.GetAttachedEntities())
 830                            {
 0831                                var loader = LoadableShape.GetLoaderForEntity(entity);
 832
 0833                                string loadInfo = "No loader";
 834
 0835                                if (loader != null)
 836                                {
 0837                                    loadInfo = loader.ToString();
 838                                }
 839
 0840                                Debug.Log($"This shape is attached to {entity.entityId} entity. Click here for highlight
 841                            }
 842                        }
 843                        else
 844                        {
 0845                            Debug.Log($"Waiting for missing component? id: {componentId}");
 846                        }
 847                    }
 848
 849                    break;
 850
 851                default:
 0852                    Debug.Log("This scene is not waiting for any components. Its current state is " + sceneLifecycleHand
 853                    break;
 854            }
 0855        }
 856
 857        /// <summary>
 858        /// Calculates the current loading progress of the scene and raise the event OnLoadingStateUpdated with the perc
 859        /// </summary>
 860        public void CalculateSceneLoadingState()
 861        {
 968862            loadingProgress = 0f;
 863
 968864            if (sceneLifecycleHandler.state == SceneLifecycleHandler.State.WAITING_FOR_COMPONENTS ||
 865                sceneLifecycleHandler.state == SceneLifecycleHandler.State.READY)
 866            {
 468867                loadingProgress = disposableComponents != null && disposableComponents.Count > 0 ? (disposableComponents
 868            }
 869
 968870            OnLoadingStateUpdated?.Invoke(loadingProgress);
 0871        }
 872    }
 873}

Methods/Properties

entities()
entities(System.Collections.Generic.Dictionary[String,IDCLEntity])
ParcelScene()
disposableComponents()
disposableComponents(System.Collections.Generic.Dictionary[String,ISharedComponent])
sceneData()
sceneData(DCL.Models.LoadParcelScenesMessage/UnityParcelScene)
metricsCounter()
metricsCounter(DCL.ISceneMetricsCounter)
contentProvider()
contentProvider(DCL.ContentProvider)
isTestScene()
isTestScene(System.Boolean)
isPersistent()
isPersistent(System.Boolean)
loadingProgress()
loadingProgress(System.Single)
isReleased()
isReleased(System.Boolean)
Awake()
OnDestroy()
OnDisable()
Update()
prettyName()
SetData(DCL.Models.LoadParcelScenesMessage/UnityParcelScene)
OnWorldReposition(UnityEngine.Vector3, UnityEngine.Vector3)
SetUpdateData(DCL.Models.LoadParcelScenesMessage/UnityParcelScene)
InitializeDebugPlane()
RemoveDebugPlane()
Cleanup(System.Boolean)
ToString()
GetSceneName()
IsInsideSceneBoundaries(UnityEngine.Bounds)
IsInsideSceneBoundaries(UnityEngine.Vector2Int, System.Single)
IsInsideSceneBoundaries(UnityEngine.Vector3, System.Single)
GetSceneTransform()
CreateEntity(System.String)
RemoveEntity(System.String, System.Boolean)
CleanUpEntityRecursively(DCL.Models.IDCLEntity, System.Boolean)
RemoveAllEntities(System.Boolean)
RemoveAllEntitiesImmediate()
SetEntityParent(System.String, System.String)
SharedComponentAttach(System.String, System.String)
EntityComponentCreateOrUpdateWithModel(System.String, DCL.Models.CLASS_ID_COMPONENT, System.Object)
EntityComponentCreateOrUpdate(System.String, DCL.Models.CLASS_ID_COMPONENT, System.String)
EntityComponentUpdate(DCL.Models.IDCLEntity, DCL.Models.CLASS_ID_COMPONENT, System.String)
SharedComponentCreate(System.String, System.Int32)
SharedComponentDispose(System.String)
EntityComponentRemove(System.String, System.String)
GetSharedComponent[T]()
RemoveComponentType[T](DCL.Models.IDCLEntity, DCL.Models.CLASS_ID_COMPONENT)
RemoveEntityComponent(DCL.Models.IDCLEntity, System.String)
SharedComponentUpdate(System.String, BaseModel)
SharedComponentUpdate(System.String, System.String)
SendMetricsEvent()
GetSharedComponent(System.String)
GetEntityForUpdate(System.String)
DisposeAllSceneComponents()
GetStateString()
RefreshLoadingState()
GetWaitingComponentsDebugInfo()
CalculateSceneLoadingState()