< Summary

Class:DCL.Components.ParametrizedShape[T]
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/ParametrizedShapes/ParametrizedShape.cs
Covered lines:96
Uncovered lines:7
Coverable lines:103
Total lines:229
Line coverage:93.2% (96 of 103)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ParametrizedShape()0%110100%
GenerateGeometry()0%2100%
DestroyGeometry()0%2.032080%
UpdateFromModel(...)0%110100%
UpdateRenderer(...)0%660100%
OnShapeAttached(...)0%44096%
OnShapeFinishedLoading(...)0%220100%
OnShapeDetached(...)0%4.024090%
ApplyChanges(...)0%770100%
AttachTo(...)0%2.062075%
IsVisible()0%110100%
HasCollisions()0%110100%
ShouldGenerateNewMesh(...)0%2100%
RemoveRendereableFromDataStore(...)0%220100%
AddRendereableToDataStore(...)0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/ParametrizedShapes/ParametrizedShape.cs

#LineLine coverage
 1using DCL.Controllers;
 2using DCL.Helpers;
 3using DCL.Models;
 4using System.Collections;
 5using System.Collections.Generic;
 6using System.Linq;
 7using UnityEditor;
 8using UnityEngine;
 9
 10namespace DCL.Components
 11{
 12    public abstract class ParametrizedShape<T> : BaseShape
 13        where T : BaseShape.Model, new()
 14    {
 14315        public Dictionary<IDCLEntity, Rendereable> attachedRendereables = new Dictionary<IDCLEntity, Rendereable>();
 16        bool visibilityDirty = false;
 17        bool collisionsDirty = false;
 18
 19        public virtual Mesh GenerateGeometry()
 20        {
 021            return null;
 22        }
 23
 24        protected virtual void DestroyGeometry()
 25        {
 2926            if (currentMesh == null)
 027                return;
 28
 2929            Object.Destroy(currentMesh);
 2930            currentMesh = null;
 2931        }
 32
 033        public Mesh currentMesh { get; protected set; }
 34        private Model previousModel;
 35        private Model cachedModel;
 36
 14337        public ParametrizedShape()
 38        {
 14339            OnAttach += OnShapeAttached;
 14340            OnDetach += OnShapeDetached;
 14341        }
 42
 43        public override void UpdateFromModel(BaseModel newModel)
 44        {
 19545            cachedModel = (Model) newModel;
 19546            base.UpdateFromModel(newModel);
 19547        }
 48
 49        void UpdateRenderer(IDCLEntity entity, Model model = null)
 50        {
 20651            if (model == null)
 14952                model = (T) this.model;
 53
 20654            if (visibilityDirty)
 55            {
 17356                ConfigureVisibility(entity.meshRootGameObject, model.visible, entity.meshesInfo.renderers);
 17357                visibilityDirty = false;
 58            }
 59
 20660            if (collisionsDirty)
 61            {
 17162                CollidersManager.i.ConfigureColliders(entity.meshRootGameObject, model.withCollisions, false, entity, Ca
 17163                collisionsDirty = false;
 64            }
 65
 20666            if (entity.meshesInfo.meshFilters.Length > 0 && entity.meshesInfo.meshFilters[0].sharedMesh != currentMesh)
 67            {
 268                entity.meshesInfo.UpdateExistingMeshAtIndex(currentMesh, 0);
 69            }
 70
 71            // First we remove the old rendereable, then we compute and add the new one.
 20672            RemoveRendereableFromDataStore(entity);
 20673            AddRendereableToDataStore(entity);
 20674        }
 75
 76        void OnShapeAttached(IDCLEntity entity)
 77        {
 14978            if (entity == null)
 079                return;
 80
 14981            entity.EnsureMeshGameObject(componentName + " mesh");
 82
 14983            if (currentMesh == null)
 84            {
 13385                currentMesh = GenerateGeometry();
 86            }
 87
 14988            MeshFilter meshFilter = entity.meshRootGameObject.AddComponent<MeshFilter>();
 14989            MeshRenderer meshRenderer = entity.meshRootGameObject.AddComponent<MeshRenderer>();
 90
 14991            entity.meshesInfo.renderers = new Renderer[] { meshRenderer };
 14992            entity.meshesInfo.currentShape = this;
 93
 14994            meshFilter.sharedMesh = currentMesh;
 95
 14996            if (Configuration.ParcelSettings.VISUAL_LOADING_ENABLED)
 97            {
 198                MaterialTransitionController transition = entity.meshRootGameObject.AddComponent<MaterialTransitionContr
 199                Material finalMaterial = Utils.EnsureResourcesMaterial("Materials/Default");
 1100                transition.delay = 0;
 1101                transition.useHologram = false;
 1102                transition.fadeThickness = 20;
 1103                transition.OnDidFinishLoading(finalMaterial);
 104
 3105                transition.onFinishedLoading += () => { OnShapeFinishedLoading(entity); };
 1106            }
 107            else
 108            {
 148109                meshRenderer.sharedMaterial = Utils.EnsureResourcesMaterial("Materials/Default");
 110            }
 111
 149112            visibilityDirty = true;
 149113            collisionsDirty = true;
 149114            UpdateRenderer(entity);
 149115            OnShapeFinishedLoading(entity);
 149116        }
 117
 118        void OnShapeFinishedLoading(IDCLEntity entity)
 119        {
 150120            entity.OnShapeUpdated?.Invoke(entity);
 150121        }
 122
 123        void OnShapeDetached(IDCLEntity entity)
 124        {
 146125            if (entity == null || entity.meshRootGameObject == null)
 0126                return;
 127
 146128            if (attachedEntities.Count == 0)
 129            {
 130130                DestroyGeometry();
 130131                Utils.CleanMaterials(entity.meshRootGameObject.GetComponent<Renderer>());
 130132                currentMesh = null;
 133            }
 134
 146135            Utils.SafeDestroy(entity.meshRootGameObject);
 146136            entity.meshesInfo.CleanReferences();
 137
 146138            RemoveRendereableFromDataStore(entity);
 146139        }
 140
 141        public override IEnumerator ApplyChanges(BaseModel newModelRaw)
 142        {
 195143            var newModel = (T) newModelRaw;
 144
 195145            if (previousModel != null)
 146            {
 52147                visibilityDirty = newModel.visible != previousModel.visible;
 52148                collisionsDirty = newModel.withCollisions != previousModel.withCollisions || newModel.isPointerBlocker !
 149            }
 150
 195151            bool shouldGenerateMesh = ShouldGenerateNewMesh(previousModel);
 152
 153            //NOTE(Brian): Only generate meshes here if they already are attached to something.
 154            //             Otherwise, the mesh will be created on the OnShapeAttached.
 195155            if (attachedEntities.Count > 0)
 156            {
 41157                if (shouldGenerateMesh)
 158                {
 3159                    DestroyGeometry();
 3160                    currentMesh = GenerateGeometry();
 161                }
 162
 41163                using (var iterator = attachedEntities.GetEnumerator())
 164                {
 41165                    bool cachedVisibilityDirty = visibilityDirty;
 41166                    bool cachedCollisionDirty = collisionsDirty;
 98167                    while (iterator.MoveNext())
 168                    {
 169                        //NOTE(Alex): Since UpdateRenderer updates the dirty flags as well we have to make sure every en
 170                        //            gets updated accordingly to the original flags.
 57171                        visibilityDirty = cachedVisibilityDirty;
 57172                        collisionsDirty = cachedCollisionDirty;
 173
 57174                        var entity = iterator.Current;
 57175                        UpdateRenderer(entity, newModel);
 176
 57177                        entity.OnShapeUpdated?.Invoke(entity);
 178                    }
 41179                }
 180            }
 181
 195182            previousModel = newModel;
 195183            return null;
 184        }
 185
 186        public override void AttachTo(IDCLEntity entity, System.Type overridenAttachedType = null)
 187        {
 149188            if (attachedEntities.Contains(entity))
 0189                return;
 190
 149191            base.AttachTo(entity);
 149192        }
 193
 67194        public override bool IsVisible() { return cachedModel.visible; }
 195
 31196        public override bool HasCollisions() { return cachedModel.withCollisions; }
 197
 0198        protected virtual bool ShouldGenerateNewMesh(BaseShape.Model newModel) { return true; }
 199
 200        private void RemoveRendereableFromDataStore(IDCLEntity entity)
 201        {
 352202            if ( attachedRendereables.ContainsKey(entity) )
 203            {
 203204                DataStore.i.sceneWorldObjects.RemoveRendereable(entity, attachedRendereables[entity]);
 203205                attachedRendereables.Remove(entity);
 206            }
 352207        }
 208
 209        private void AddRendereableToDataStore(IDCLEntity entity)
 210        {
 206211            int triangleCount = currentMesh.triangles.Length;
 212
 206213            var newRendereable = new Rendereable()
 214            {
 215                renderers = new List<Renderer>(entity.meshesInfo.renderers),
 216                container = entity.meshRootGameObject,
 217                totalTriangleCount = triangleCount,
 218                meshes = new List<Mesh>() { currentMesh },
 219                meshToTriangleCount = new Dictionary<Mesh, int>() { { currentMesh, triangleCount } }
 220            };
 221
 206222            if ( !attachedRendereables.ContainsKey(entity) )
 223            {
 206224                attachedRendereables.Add(entity, newRendereable);
 206225                DataStore.i.sceneWorldObjects.AddRendereable(entity, newRendereable);
 226            }
 206227        }
 228    }
 229}