/// <summary> /// Rebuilds the volume, creating or deleting the volume component and applying new settings. /// </summary> internal void RebuildVolume() { // volumes can only be primitive brushes at the moment. if (GetType() != typeof(PrimitiveBrush)) { return; } PrimitiveBrush self = (PrimitiveBrush)this; // remove volumes from brushes that are no longer volumes: if (Mode != CSGMode.Volume && Volume != null) { // set volume handle to null. Volume = null; // delete any built volume. Transform volume1 = transform.Find(Constants.GameObjectVolumeComponentIdentifier); if (volume1 != null) { GameObject.DestroyImmediate(volume1.gameObject); } } // generate all of the volume brushes: if (Mode == CSGMode.Volume && Volume != null) { // remove any existing built volume: Transform volume2 = transform.Find(Constants.GameObjectVolumeComponentIdentifier); if (volume2 != null) { GameObject.DestroyImmediate(volume2.gameObject); } // create the game object with convex mesh collider: Mesh mesh = new Mesh(); BrushFactory.GenerateMeshFromPolygonsFast(self.GetPolygons(), ref mesh, 0.0f); GameObject gameObject = CreateVolumeMeshCollider(mesh); gameObject.transform.position = transform.position; gameObject.transform.rotation = transform.rotation; // execute custom volume generation code: Volume.OnCreateVolume(gameObject); } }
/// <summary> /// Tells the brush it has changed /// </summary> /// <param name="polygonsChanged">If set to <c>true</c> polygons will be recached.</param> public override void Invalidate(bool polygonsChanged) { base.Invalidate(polygonsChanged); if (!gameObject.activeInHierarchy) { return; } // previous versions of sabrecsg used to use mesh colliders for ray collision, but that's no longer the case so we clean them up. MeshCollider[] meshColliders = GetComponents <MeshCollider>(); if (meshColliders.Length > 0) { for (int i = 0; i < meshColliders.Length; i++) { DestroyImmediate(meshColliders[i]); } } // Make sure there is a mesh filter on this object MeshFilter meshFilter = gameObject.AddOrGetComponent <MeshFilter>(); MeshRenderer meshRenderer = gameObject.AddOrGetComponent <MeshRenderer>(); bool requireRegen = false; // If the cached ID hasn't been set or we mismatch if (cachedInstanceID == 0 || gameObject.GetInstanceID() != cachedInstanceID) { requireRegen = true; cachedInstanceID = gameObject.GetInstanceID(); } Mesh renderMesh = meshFilter.sharedMesh; if (requireRegen) { renderMesh = new Mesh(); } if (polygons != null) { // generate a mesh preview for the transparent brushes. // we also displace the triangles along the normals slightly so we can overlay built geometry // with semi-transparent geometry and avoid depth fighting. BrushFactory.GenerateMeshFromPolygonsFast(polygons, ref renderMesh, mode == CSGMode.Add ? 0.001f : -0.001f); } if (mode == CSGMode.Subtract) { MeshHelper.Invert(ref renderMesh); } meshFilter.sharedMesh = renderMesh; meshRenderer.receiveShadows = false; meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; meshFilter.hideFlags = HideFlags.NotEditable; // | HideFlags.HideInInspector; meshRenderer.hideFlags = HideFlags.NotEditable; // | HideFlags.HideInInspector; #if UNITY_EDITOR Material material; if (IsNoCSG) { material = SabreCSGResources.GetNoCSGMaterial(); } else { if (this.mode == CSGMode.Add) { material = SabreCSGResources.GetAddMaterial(); } else { material = SabreCSGResources.GetSubtractMaterial(); } } if (meshRenderer.sharedMaterial != material) { meshRenderer.sharedMaterial = material; } #endif // isBrushConvex = GeometryHelper.IsBrushConvex(polygons); if (polygonsChanged) { RecalculateBrushCache(); } UpdateVisibility(); objectVersionSerialized++; objectVersionUnserialized = objectVersionSerialized; if (cachedWorldTransform == null) { cachedWorldTransform = new WorldTransformData(transform); } cachedWorldTransform.SetFromTransform(transform); }