private static void UpdateModelFlags(ChiselModel model)
        {
            if (!IsDefaultModel(model))
            {
                return;
            }

            const HideFlags DefaultGameObjectHideFlags = HideFlags.NotEditable;
            const HideFlags DefaultTransformHideFlags  = HideFlags.NotEditable; // | HideFlags.HideInInspector;

            var gameObject = model.gameObject;
            var transform  = model.transform;

            if (gameObject.hideFlags != DefaultGameObjectHideFlags)
            {
                gameObject.hideFlags = DefaultGameObjectHideFlags;
            }
            if (transform.hideFlags != DefaultTransformHideFlags)
            {
                transform.hideFlags = DefaultTransformHideFlags;
            }

            if (transform.parent != null)
            {
                transform.SetParent(null, false);
                transform.localPosition = Vector3.zero;
                transform.localRotation = Quaternion.identity;
                transform.localScale    = Vector3.one;
            }
        }
        private static void UpdateModelFlags(ChiselModel model)
        {
            if (!IsDefaultModel(model))
            {
                return;
            }

            const HideFlags DefaultGameObjectHideFlags = HideFlags.NotEditable;
            const HideFlags DefaultTransformHideFlags  = HideFlags.NotEditable; // | HideFlags.HideInInspector;

            var gameObject = model.gameObject;
            var transform  = model.transform;

            if (gameObject.hideFlags != DefaultGameObjectHideFlags)
            {
                gameObject.hideFlags = DefaultGameObjectHideFlags;
            }
            if (transform.hideFlags != DefaultTransformHideFlags)
            {
                transform.hideFlags = DefaultTransformHideFlags;
            }

            if (transform.parent != null)
            {
                transform.SetParent(null, false);
                ChiselObjectUtility.ResetTransform(transform);
            }
        }
Beispiel #3
0
        public static void UpdateColliders(ChiselModel model, ChiselColliderObjects[] colliders)
        {
            if (colliders == null)
            {
                return;
            }
            var colliderSettings = model.ColliderSettings;

            for (int i = 0; i < colliders.Length; i++)
            {
                var meshCollider = colliders[i].meshCollider;

                if (meshCollider.cookingOptions != colliderSettings.cookingOptions)
                {
                    meshCollider.cookingOptions = colliderSettings.cookingOptions;
                }
                if (meshCollider.convex != colliderSettings.convex)
                {
                    meshCollider.convex = colliderSettings.convex;
                }
                if (meshCollider.isTrigger != colliderSettings.isTrigger)
                {
                    meshCollider.isTrigger = colliderSettings.isTrigger;
                }
            }
        }
        public static bool NeedUVGeneration(ChiselModel model)
        {
            haveUVsToUpdate = false;

#if UNITY_EDITOR
            if (!model)
            {
                return(false);
            }

            var staticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(model.gameObject);
            if ((staticFlags & UnityEditor.StaticEditorFlags.LightmapStatic) != UnityEditor.StaticEditorFlags.LightmapStatic)
            {
                return(false);
            }

            for (int i = 0; i < model.generatedMeshes.Length; i++)
            {
                var generatedMesh = model.generatedMeshes[i];

                // Avoid light mapping multiple times, when the same mesh is used on multiple MeshRenderers
                if (!ChiselSharedUnityMeshManager.HasLightmapUVs(generatedMesh.sharedMesh))
                {
                    return(true);
                }
            }
#endif
            return(false);
        }
        internal static void UpdateModelMeshDescriptions(ChiselModel model)
        {
            if (!ChiselModelGeneratedObjects.IsValid(model.generated))
            {
                if (model.generated != null)
                {
                    model.generated.Destroy();
                }
                model.generated = ChiselModelGeneratedObjects.Create(model);
            }

            var tree = model.Node;

            if (!tree.Valid)
            {
                return;
            }

            var meshTypes        = ChiselMeshQueryManager.GetMeshQuery(model);
            var meshDescriptions = tree.GetMeshDescriptions(meshTypes, model.VertexChannelMask);

            // Check if the tree creates *any* meshes
            if (meshDescriptions == null || meshDescriptions.Length == 0)
            {
                //componentGenerator.RemoveAllGeneratedComponents(model);
                PostUpdateModel?.Invoke(model);
                return;
            }

            // Sort all meshDescriptions so that meshes that can be merged are next to each other
            Array.Sort(meshDescriptions, kMeshDescriptionSorterDelegate);

            model.generated.Update(model, meshDescriptions);
        }
        public void Unregister(ChiselModel model)
        {
            DestroyAllRegisteredGeneratedComponentsInModel(model);
            RemoveContainerGameObject(model);

            models.Remove(model);
        }
 private void RemoveContainerGameObjectWithUndo(ChiselModel model)
 {
     if (model.generated != null)
     {
         model.generated.DestroyWithUndo();
     }
 }
Beispiel #8
0
        public static void UpdateModel(ChiselModel model)
        {
            if (PreUpdateModel != null)
            {
                PreUpdateModel(model);
            }

            UpdateModelMeshDescriptions(model);

            // Re-use existing UnityEngine.Mesh if they exist
            sharedUnityMeshes.ReuseExistingMeshes(model);

            // Find all meshes whose refCounts are 0
            sharedUnityMeshes.FindAllUnusedUnityMeshes();

            // Generate new UnityEngine.Mesh instances and fill them with data from the CSG algorithm (if necessary)
            //	note: reuses garbage collected meshes when possible
            sharedUnityMeshes.CreateNewMeshes(model);

            // Generate (or re-use) components and set them up properly
            componentGenerator.Rebuild(model);

            if (PostUpdateModel != null)
            {
                PostUpdateModel(model);
            }

            // Destroy all meshes whose refCounts are 0
            sharedUnityMeshes.DestroyNonRecycledUnusedUnityMeshes();
        }
Beispiel #9
0
        //*/
        public static void UpdateProperties(ChiselModel model, ChiselColliderObjects[] colliders)
        {
            var colliderSettings = model.ColliderSettings;

            for (int i = 0; i < colliders.Length; i++)
            {
                var meshCollider = colliders[i].meshCollider;
                if (!meshCollider)
                {
                    continue;
                }

                // If the cookingOptions are not the default values it would force a full slow rebake later,
                // even if we already did a Bake in a job
                //if (meshCollider.cookingOptions != colliderSettings.cookingOptions)
                //    meshCollider.cookingOptions = colliderSettings.cookingOptions;

                if (meshCollider.convex != colliderSettings.convex)
                {
                    meshCollider.convex = colliderSettings.convex;
                }
                if (meshCollider.isTrigger != colliderSettings.isTrigger)
                {
                    meshCollider.isTrigger = colliderSettings.isTrigger;
                }

                var sharedMesh      = colliders[i].sharedMesh;
                var expectedEnabled = sharedMesh.vertexCount > 0;
                if (meshCollider.enabled != expectedEnabled)
                {
                    meshCollider.enabled = expectedEnabled;
                }
            }
        }
        private GameObject CreateComponentGameObject(ChiselModel model, string name, params Type[] components)
        {
            var modelScene     = model.gameObject.scene;
            var oldActiveScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();

            if (modelScene != oldActiveScene)
            {
                UnityEngine.SceneManagement.SceneManager.SetActiveScene(modelScene);
            }
            try
            {
                var container  = model.GeneratedDataContainer;
                var gameObject = new GameObject(name, components);
                var transform  = gameObject.GetComponent <Transform>();
                transform.SetParent(container.transform, false);
                transform.localPosition = Vector3.zero;
                transform.localRotation = Quaternion.identity;
                transform.localScale    = Vector3.one;
                return(gameObject);
            }
            finally
            {
                if (modelScene != oldActiveScene)
                {
                    UnityEngine.SceneManagement.SceneManager.SetActiveScene(oldActiveScene);
                }
            }
        }
Beispiel #11
0
        void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified)
        {
#if UNITY_EDITOR
            Profiler.BeginSample("CheckIfFullMeshNeedsToBeHidden");
            // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh
            ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this);
            Profiler.EndSample();
            if (meshIsModified)
            {
                // Setting the sharedMesh to ensure the meshFilter knows it needs to be updated
                Profiler.BeginSample("OverrideMesh");
                meshFilter.sharedMesh = meshFilter.sharedMesh;
                Profiler.EndSample();
                Profiler.BeginSample("SetDirty");
                UnityEditor.EditorUtility.SetDirty(meshFilter);
                UnityEditor.EditorUtility.SetDirty(model);
                Profiler.EndSample();
                Profiler.BeginSample("SetHasLightmapUVs");
                ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false);
                Profiler.EndSample();
                Profiler.BeginSample("ClearLightmapData");
                ChiselGeneratedComponentManager.ClearLightmapData(state, this);
                Profiler.EndSample();
            }
#endif
        }
 private void RemoveContainerGameObject(ChiselModel model)
 {
     if (model.generated != null)
     {
         model.generated.Destroy();
         model.generated = null;
     }
 }
 internal static bool IsDefaultModel(ChiselModel model)
 {
     if (!model)
     {
         return(false);
     }
     return(model.IsDefaultModel);
 }
Beispiel #14
0
 public void AddUnityMeshes(ChiselModel model)
 {
     for (int i = 0; i < model.generatedMeshes.Length; i++)
     {
         var generatedMesh = model.generatedMeshes[i];
         generatedMesh.sharedMesh = ReturnOrRegisterUnityMeshAndIncreaseRefCount(generatedMesh.meshKey, generatedMesh.sharedMesh);
     }
 }
        internal void DestroyAllRegisteredGeneratedComponentsInModel(ChiselModel model)
        {
            GameObject modelGameObject = null;

            if (model)
            {
                modelGameObject = model.gameObject;
            }

            __uniqueGameObjects.Clear();
            foreach (var components in model.generatedRenderComponents.Values)
            {
                foreach (var component in components)
                {
                    if (component == null)
                    {
                        continue;
                    }

                    if (component.gameObject)
                    {
                        var gameObject = component.gameObject;
                        if (gameObject != modelGameObject)
                        {
                            __uniqueGameObjects.Add(gameObject);
                        }
                    }
                }
            }
            foreach (var components in model.generatedMeshColliders.Values)
            {
                foreach (var component in components)
                {
                    if (component == null)
                    {
                        continue;
                    }

                    if (component.gameObject)
                    {
                        var gameObject = component.gameObject;
                        if (gameObject != modelGameObject)
                        {
                            __uniqueGameObjects.Add(gameObject);
                        }
                    }
                }
            }
            foreach (var gameObject in __uniqueGameObjects)
            {
                ChiselObjectUtility.SafeDestroy(gameObject);
            }

            __uniqueGameObjects.Clear();
            model.generatedRenderComponents.Clear();
            model.generatedMeshColliders.Clear();
            model.generatedComponents.Clear();
        }
Beispiel #16
0
 public void RemoveUnityMeshes(ChiselModel model)
 {
     for (int i = 0; i < model.generatedMeshes.Length; i++)
     {
         var generatedMesh = model.generatedMeshes[i];
         DecreaseRefCount(generatedMesh.meshKey);
         generatedMesh.sharedMesh = null;
     }
 }
        public static void CheckIfFullMeshNeedsToBeHidden(ChiselModel model, ChiselRenderObjects renderable)
        {
            var shouldHideMesh = (model.generated.visibilityState != VisibilityState.AllVisible && model.generated.visibilityState != VisibilityState.Unknown);

            if (renderable.meshRenderer.forceRenderingOff != shouldHideMesh)
            {
                renderable.meshRenderer.forceRenderingOff = shouldHideMesh;
            }
        }
Beispiel #18
0
        static List <ChiselGeneratedModelMesh> __allocateGeneratedMeshesTable = new List <ChiselGeneratedModelMesh>();  // static to avoid allocations
        internal static void UpdateModelMeshDescriptions(ChiselModel model)
        {
            var tree = model.Node;

            if (!tree.Valid)
            {
                return;
            }

            var meshTypes        = ChiselMeshQueryManager.GetMeshQuery(model);
            var meshDescriptions = tree.GetMeshDescriptions(meshTypes, model.VertexChannelMask);

            // Make sure we remove all old generated meshes
            sharedUnityMeshes.DecreaseMeshRefCount(model);

            // Check if the tree creates *any* meshes
            if (meshDescriptions == null)
            {
                model.generatedMeshes = __emptyGeneratedMeshesTable;
                componentGenerator.RemoveAllGeneratedComponents(model);
                if (PostUpdateModel != null)
                {
                    PostUpdateModel(model);
                }
                return;
            }

            __allocateGeneratedMeshesTable.Clear();
            for (int d = 0; d < meshDescriptions.Length; d++)
            {
                var meshDescription = meshDescriptions[d];

                // Make sure the meshDescription actually holds a mesh
                if (meshDescription.vertexCount == 0 ||
                    meshDescription.indexCount == 0)
                {
                    continue;
                }

                // Make sure the mesh is valid
                if (meshDescription.vertexCount >= MaxVertexCount)
                {
                    Debug.LogError("Mesh has too many vertices (" + meshDescription.vertexCount + " > " + MaxVertexCount + ")");
                    continue;
                }

                // Add the generated mesh to the list
                __allocateGeneratedMeshesTable.Add(new ChiselGeneratedModelMesh {
                    meshDescription = meshDescription, meshKey = new GeneratedMeshKey(meshDescription)
                });
            }

            // TODO: compare with existing generated meshes, only rebuild stuff for things that have actually changed

            model.generatedMeshes = __allocateGeneratedMeshesTable.ToArray();
        }
        static readonly List <GeneratedMeshContents> __foundContents = new List <GeneratedMeshContents>(); // static to avoid allocations
        public void Update(ChiselModel model, GameObjectState state, GeneratedMeshDescription[] meshDescriptions, int startIndex, int endIndex)
        {
            bool meshIsModified = false;

            // Retrieve the generatedMeshes and its materials, combine them into a single Unity Mesh/Material array
            try
            {
                for (int i = startIndex; i < endIndex; i++)
                {
                    ref var meshDescription       = ref meshDescriptions[i];
                    var     generatedMeshContents = model.Node.GetGeneratedMesh(meshDescription);
                    if (generatedMeshContents == null)
                    {
                        continue;
                    }
                    if (generatedMeshContents.indices.Length == 0)
                    {
                        generatedMeshContents.Dispose();
                        continue;
                    }
                    var renderMaterial = ChiselBrushMaterialManager.GetRenderMaterialByInstanceID(meshDescription.surfaceParameter);
                    __foundContents.Add(generatedMeshContents);
                    __foundMaterials.Add(renderMaterial);
                }
                triangleBrushes.Clear();
                if (__foundContents.Count == 0)
                {
                    if (sharedMesh.vertexCount > 0)
                    {
                        sharedMesh.Clear(keepVertexLayout: true);
                    }
                }
                else
                {
                    sharedMesh.CopyFrom(__foundContents, triangleBrushes);
#if UNITY_EDITOR
                    ChiselGeneratedComponentManager.SetHasLightmapUVs(sharedMesh, false);
#endif
                }
                if (renderMaterials != null &&
                    renderMaterials.Length == __foundMaterials.Count)
                {
                    __foundMaterials.CopyTo(renderMaterials);
                }
                else
                {
                    renderMaterials = __foundMaterials.ToArray();
                }
                if (meshFilter.sharedMesh != sharedMesh)
                {
                    meshFilter.sharedMesh = sharedMesh;
                    meshIsModified        = true;
                }
                meshRenderer.sharedMaterials = renderMaterials;
                meshRenderer.enabled         = sharedMesh.vertexCount > 0;
            }
        internal static void SetActiveModel()
        {
            var model = GetSelectedModel();

            if (!model)
            {
                return;
            }
            ChiselModelManager.ActiveModel = model;
        }
        public void Register(ChiselModel model)
        {
            // Destroy leftover components in model lookups
            DestroyAllRegisteredGeneratedComponentsInModel(model);

            // Rebuild component lookup tables used by generatedMeshes
            BuildGeneratedComponentLookupTables(model);

            models.Add(model);
        }
        public void Unregister(ChiselModel model)
        {
            // If we removed our model component, we should remove the containers
            if (!model && model.hierarchyItem.GameObject)
            {
                RemoveContainerGameObjectWithUndo(model);
            }

            models.Remove(model);
        }
Beispiel #23
0
 public void ReuseExistingMeshes(ChiselModel model)
 {
     for (int i = 0; i < model.generatedMeshes.Length; i++)
     {
         var generatedMesh = model.generatedMeshes[i];
         // See if we already know a mesh that has the same description
         generatedMesh.sharedMesh  = ReturnUnityMeshAndIncreaseRefCountIfExists(generatedMesh.meshKey);
         generatedMesh.needsUpdate = !generatedMesh.sharedMesh;
     }
 }
        void UpdateSettings(ChiselModel model, GameObjectState state, bool meshIsModified)
        {
#if UNITY_EDITOR
            // If we need to render partial meshes (where some brushes are hidden) then we should show the full mesh
            ChiselGeneratedComponentManager.CheckIfFullMeshNeedsToBeHidden(model, this);
            if (meshIsModified)
            {
                ChiselGeneratedComponentManager.ClearLightmapData(state, this);
            }
#endif
        }
Beispiel #25
0
        public static GameObjectState Create(ChiselModel model)
        {
            var modelGameObject = model.gameObject;

            return(new GameObjectState
            {
                layer = modelGameObject.layer,
#if UNITY_EDITOR
                staticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(modelGameObject)
#endif
            });
        }
        void UpdateComponentFlags(ChiselModel model, ModelState modelState, Component component, GameObject componentGameObject, Transform componentTransform, string componentName, bool notEditable)
        {
            const HideFlags GameObjectHideFlags = HideFlags.NotEditable;
            const HideFlags TransformHideFlags  = HideFlags.NotEditable;// | HideFlags.HideInInspector;

            if (componentGameObject.name != componentName)
            {
                componentGameObject.name = componentName;
            }

            // TODO: make components turn off this flag when its gameObject is directly selected?
            HideFlags ComponentHideFlags = HideFlags.HideInHierarchy | (notEditable ? HideFlags.NotEditable : HideFlags.None); // Avoids MeshCollider showing wireframe

            // Some components could theoretically just be put on the model itself, so we don't modify any flags then
            if (componentGameObject == modelState.modelGameObject)
            {
                return;
            }

            // Make sure we're always a child of the current data container
            if (componentTransform.parent != modelState.containerTransform)
            {
                componentTransform.SetParent(modelState.containerTransform, false);
                componentTransform.localPosition = Vector3.zero;
                componentTransform.localRotation = Quaternion.identity;
                componentTransform.localScale    = Vector3.one;
            }

            if (componentGameObject.layer != modelState.layer)
            {
                componentGameObject.layer = modelState.layer;
            }
            if (componentGameObject.hideFlags != GameObjectHideFlags)
            {
                componentGameObject.hideFlags = GameObjectHideFlags;
            }
            if (componentTransform.hideFlags != TransformHideFlags)
            {
                componentTransform.hideFlags = TransformHideFlags;
            }
            if (component.hideFlags != ComponentHideFlags)
            {
                component.hideFlags = ComponentHideFlags;
            }

#if UNITY_EDITOR
            var prevStaticFlags = UnityEditor.GameObjectUtility.GetStaticEditorFlags(componentGameObject);
            if (prevStaticFlags != modelState.staticFlags)
            {
                UnityEditor.GameObjectUtility.SetStaticEditorFlags(componentGameObject, modelState.staticFlags);
            }
#endif
        }
        private ChiselColliderComponents CreateColliderComponents(ChiselModel model, GeneratedMeshDescription meshDescription)
        {
            var gameObject         = CreateComponentGameObject(model, GeneratedMeshColliderName, typeof(MeshCollider));
            var colliderComponents = new ChiselColliderComponents
            {
                meshCollider = gameObject.GetComponent <MeshCollider>(),
                gameObject   = gameObject,
                transform    = gameObject.transform
            };

            return(colliderComponents);
        }
Beispiel #28
0
        public static void UpdateProperties(ChiselModel model, MeshRenderer[] meshRenderers)
        {
            if (meshRenderers == null || meshRenderers.Length == 0)
            {
                return;
            }

            var renderSettings = model.RenderSettings;

            Profiler.BeginSample("serializedObject");
#if UNITY_EDITOR
            if (renderSettings.serializedObjectFieldsDirty)
            {
                renderSettings.serializedObjectFieldsDirty = false;
                // These SerializedObject settings can *only* be modified in the inspector,
                //      so we should only be calling this on creation /
                //      when something in inspector changed.

                // Warning: calling new UnityEditor.SerializedObject with an empty array crashes Unity
                using (var serializedObject = new UnityEditor.SerializedObject(meshRenderers))
                {
                    serializedObject.SetPropertyValue("m_ImportantGI", renderSettings.ImportantGI);
                    serializedObject.SetPropertyValue("m_PreserveUVs", renderSettings.OptimizeUVs);
                    serializedObject.SetPropertyValue("m_IgnoreNormalsForChartDetection", renderSettings.IgnoreNormalsForChartDetection);
                    serializedObject.SetPropertyValue("m_AutoUVMaxDistance", renderSettings.AutoUVMaxDistance);
                    serializedObject.SetPropertyValue("m_AutoUVMaxAngle", renderSettings.AutoUVMaxAngle);
                    serializedObject.SetPropertyValue("m_MinimumChartSize", renderSettings.MinimumChartSize);
                }
            }
            Profiler.EndSample();
#endif

            Profiler.BeginSample("meshRenderers");
            for (int i = 0; i < meshRenderers.Length; i++)
            {
                var meshRenderer = meshRenderers[i];
                var isRenderable = meshRenderer.shadowCastingMode != ShadowCastingMode.ShadowsOnly;
                meshRenderer.lightProbeProxyVolumeOverride = !isRenderable ? null : renderSettings.lightProbeProxyVolumeOverride;
                meshRenderer.probeAnchor = !isRenderable ? null : renderSettings.probeAnchor;
                meshRenderer.motionVectorGenerationMode = !isRenderable ? MotionVectorGenerationMode.ForceNoMotion : renderSettings.motionVectorGenerationMode;
                meshRenderer.reflectionProbeUsage       = !isRenderable ? ReflectionProbeUsage.Off : renderSettings.reflectionProbeUsage;
                meshRenderer.lightProbeUsage            = !isRenderable ? LightProbeUsage.Off : renderSettings.lightProbeUsage;
                meshRenderer.allowOcclusionWhenDynamic  = renderSettings.allowOcclusionWhenDynamic;
                meshRenderer.renderingLayerMask         = renderSettings.renderingLayerMask;
#if UNITY_EDITOR
                meshRenderer.stitchLightmapSeams = isRenderable && renderSettings.stitchLightmapSeams;
                meshRenderer.scaleInLightmap     = !isRenderable ? 0.0f : renderSettings.scaleInLightmap;
                meshRenderer.receiveGI           = renderSettings.receiveGI;
#endif
            }
            Profiler.EndSample();
        }
Beispiel #29
0
 public ChiselModel GetOrCreateDefaultModel()
 {
     if (!DefaultModel)
     {
         DefaultModel = null;
         if (Scene.IsValid() &&
             Scene.isLoaded)
         {
             DefaultModel = ChiselGeneratedComponentManager.CreateDefaultModel(this);
         }
     }
     return(DefaultModel);
 }
 private void RemoveContainerGameObject(ChiselModel model)
 {
     if (model.GeneratedDataTransform)
     {
         model.GeneratedDataContainer.hideFlags            = HideFlags.None;
         model.GeneratedDataTransform.hideFlags            = HideFlags.None;
         CSGNodeHierarchyManager.ignoreNextChildrenChanged = true;
         ChiselObjectUtility.SafeDestroy(model.GeneratedDataContainer);
         CSGNodeHierarchyManager.ignoreNextChildrenChanged = false;
         model.GeneratedDataContainer = null;
         model.GeneratedDataTransform = null;
     }
 }