コード例 #1
0
        /// <summary>
        /// Reset the polygons to those specified in the brush type. For example if the brush type is a cube, the polygons are reset to a cube.
        /// </summary>
        public void ResetPolygons()
        {
            if (brushType == PrimitiveBrushType.Cube)
            {
                polygons = BrushFactory.GenerateCube();
            }
            else if (brushType == PrimitiveBrushType.Cylinder)
            {
                if (cylinderSideCount < 3)
                {
                    cylinderSideCount = 3;
                }
                polygons = BrushFactory.GenerateCylinder(cylinderSideCount);
            }
            else if (brushType == PrimitiveBrushType.Sphere)
            {
                if (sphereSideCount < 3)
                {
                    sphereSideCount = 3;
                }
                // Lateral only goes halfway around the sphere (180 deg), longitudinal goes all the way (360 deg)
                polygons = BrushFactory.GeneratePolarSphere(sphereSideCount, sphereSideCount * 2);
            }
            else if (brushType == PrimitiveBrushType.IcoSphere)
            {
                if (icoSphereIterationCount < 0)
                {
                    icoSphereIterationCount = 0;
                }
                else if (icoSphereIterationCount > 2)
                {
                    icoSphereIterationCount = 2;
                }

                polygons = BrushFactory.GenerateIcoSphere(icoSphereIterationCount);
            }
            else if (brushType == PrimitiveBrushType.Prism)
            {
                if (prismSideCount < 3)
                {
                    prismSideCount = 3;
                }
                polygons = BrushFactory.GeneratePrism(prismSideCount);
            }
            else if (brushType == Sabresaurus.SabreCSG.PrimitiveBrushType.Custom)
            {
                // Do nothing
                Debug.LogError("PrimitiveBrushType.Custom is not a valid type for new brush creation");
            }
            else
            {
                throw new NotImplementedException();
            }
        }
コード例 #2
0
        /// <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);
            }
        }
コード例 #3
0
        /// <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)
            {
                List <int> polygonIndices;
                BrushFactory.GenerateMeshFromPolygons(polygons, ref renderMesh, out polygonIndices);
            }

            if (mode == CSGMode.Subtract)
            {
                MeshHelper.Invert(ref renderMesh);
            }
            // Displace the triangles for display along the normals very slightly (this is so we can overlay built
            // geometry with semi-transparent geometry and avoid depth fighting)
            MeshHelper.Displace(ref renderMesh, 0.001f);

            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);
        }
コード例 #4
0
        public override void OnInspectorGUI()
        {
            float drawableWidth = EditorGUIUtility.currentViewWidth;

            drawableWidth -= 42;             // Take some off for scroll bars and padding

            PrimitiveBrushType[] selectedTypes = BrushTargets.Select(item => ((PrimitiveBrush)item).BrushType).ToArray();

            PrimitiveBrushType?activeType = (selectedTypes.Length == 1) ? (PrimitiveBrushType?)selectedTypes[0] : null;

            using (new NamedVerticalScope("Type"))
            {
                GUILayout.BeginHorizontal();

                float areaWidth          = drawableWidth - 18;
                int   buttonWidth        = Mathf.RoundToInt(areaWidth / 5f);
                int   stretchButtonWidth = Mathf.RoundToInt(areaWidth - buttonWidth * 4); // To ensure a justified alignment one button must be stretched slightly
                int   buttonHeight       = 50;

                GUIStyle brushButtonStyle = new GUIStyle(GUI.skin.button);
                brushButtonStyle.imagePosition = ImagePosition.ImageAbove;
                brushButtonStyle.fontSize      = 10;

                GUIStyle labelStyle = new GUIStyle(GUI.skin.label);
                labelStyle.alignment = TextAnchor.LowerCenter;
                labelStyle.fontSize  = brushButtonStyle.fontSize;

                bool shortMode = (areaWidth < 260); // Whether certain words need to be abbreviated to fit in the box

                DrawBrushButton(PrimitiveBrushType.Cube, activeType, brushButtonStyle, labelStyle, buttonWidth, buttonHeight, shortMode);
                DrawBrushButton(PrimitiveBrushType.Prism, activeType, brushButtonStyle, labelStyle, buttonWidth, buttonHeight, shortMode);
                DrawBrushButton(PrimitiveBrushType.Cylinder, activeType, brushButtonStyle, labelStyle, stretchButtonWidth, buttonHeight, shortMode);
                DrawBrushButton(PrimitiveBrushType.Sphere, activeType, brushButtonStyle, labelStyle, buttonWidth, buttonHeight, shortMode);
                DrawBrushButton(PrimitiveBrushType.IcoSphere, activeType, brushButtonStyle, labelStyle, buttonWidth, buttonHeight, shortMode);

                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal();

                DrawBrushButton(PrimitiveBrushType.Cone, activeType, brushButtonStyle, labelStyle, buttonWidth, buttonHeight, shortMode);

                GUI.enabled = true; // Reset GUI enabled so that the next items aren't disabled
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();

                if (activeType.HasValue)
                {
                    GUILayout.Label("Active: " + selectedTypes[0]);
                }
                else
                {
                    GUILayout.Label("Active: Mixed");
                }

                if (activeType.HasValue)
                {
                    EditorGUIUtility.labelWidth = 60;
                    EditorGUIUtility.fieldWidth = 50;
                    EditorGUI.BeginChangeCheck();
                    if (activeType.Value == PrimitiveBrushType.Prism)
                    {
                        EditorGUILayout.PropertyField(prismSideCountProp, new GUIContent("Sides"));
                    }
                    else if (activeType.Value == PrimitiveBrushType.Cylinder)
                    {
                        EditorGUILayout.PropertyField(cylinderSideCountProp, new GUIContent("Sides"));
                    }
                    else if (activeType.Value == PrimitiveBrushType.Sphere)
                    {
                        EditorGUILayout.PropertyField(sphereSideCountProp, new GUIContent("Sides"));
                    }
                    else if (activeType.Value == PrimitiveBrushType.IcoSphere)
                    {
                        EditorGUILayout.PropertyField(icoSphereIterationCountProp, new GUIContent("Iterations"));
                    }
                    else if (activeType.Value == PrimitiveBrushType.Cone)
                    {
                        EditorGUILayout.PropertyField(coneSideCountProp, new GUIContent("Sides"));
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        // One of the properties has changed
                        serializedObject.ApplyModifiedProperties();
                        ResetPolygonsKeepScale();
                    }
                }

                GUILayout.EndHorizontal();
            }

            using (new NamedVerticalScope("Size"))
            {
                if (GUILayout.Button(new GUIContent("Reset Bounds", "Resets the bounds of the brush to [2,2,2]")))
                {
                    ResetBounds();
                }

                GUILayout.BeginHorizontal();

                GUI.SetNextControlName("rescaleTextbox");

                scaleString = EditorGUILayout.TextField(scaleString);

                bool keyboardEnter = Event.current.isKey &&
                                     Event.current.keyCode == KeyCode.Return &&
                                     Event.current.type == EventType.KeyUp &&
                                     GUI.GetNameOfFocusedControl() == "rescaleTextbox";

                if (GUILayout.Button("Scale", GUILayout.MaxWidth(drawableWidth / 3f)) || keyboardEnter)
                {
                    // Try to parse a Vector3 scale from the input string
                    Vector3 scaleVector3;
                    if (StringHelper.TryParseScale(scaleString, out scaleVector3))
                    {
                        // None of the scale components can be zero
                        if (scaleVector3.x != 0 && scaleVector3.y != 0 && scaleVector3.z != 0)
                        {
                            // Rescale all the brushes
                            Undo.RecordObjects(targets, "Scale Polygons");
                            foreach (var thisBrush in targets)
                            {
                                BrushUtility.Scale((PrimitiveBrush)thisBrush, scaleVector3);
                            }
                        }
                    }
                }

                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();

                GUI.SetNextControlName("resizeTextbox");

                resizeString = EditorGUILayout.TextField(resizeString);

                keyboardEnter = Event.current.isKey &&
                                Event.current.keyCode == KeyCode.Return &&
                                Event.current.type == EventType.KeyUp &&
                                GUI.GetNameOfFocusedControl() == "resizeTextbox";

                if (GUILayout.Button("Resize", GUILayout.MaxWidth(drawableWidth / 3f)) || keyboardEnter)
                {
                    // Try to parse a Vector3 scale from the input string
                    Vector3 resizeVector3;
                    if (StringHelper.TryParseScale(resizeString, out resizeVector3))
                    {
                        // None of the size components can be zero
                        if (resizeVector3.x != 0 && resizeVector3.y != 0 && resizeVector3.z != 0)
                        {
                            // Rescale all the brushes so that the local bounds is the same size as the resize vector
                            Undo.RecordObjects(targets, "Resize Polygons");
                            PrimitiveBrush[] brushes = BrushTargets.Cast <PrimitiveBrush>().ToArray();
                            foreach (PrimitiveBrush brush in brushes)
                            {
                                BrushUtility.Resize(brush, resizeVector3);
                            }
                        }
                    }
                }

                GUILayout.EndHorizontal();
            }

            using (new NamedVerticalScope("Rotation"))
            {
                GUILayout.Label("Align up direction", EditorStyles.boldLabel);
                GUILayout.BeginHorizontal();
                if (GUILayout.Button("X"))
                {
                    AlignUpToAxis(new Vector3(1, 0, 0), false);
                }
                if (GUILayout.Button("Y"))
                {
                    AlignUpToAxis(new Vector3(0, 1, 0), false);
                }
                if (GUILayout.Button("Z"))
                {
                    AlignUpToAxis(new Vector3(0, 0, 1), false);
                }
                GUILayout.EndHorizontal();

                GUILayout.Label("Align up direction (keep positions)", EditorStyles.boldLabel);

                GUILayout.BeginHorizontal();
                if (GUILayout.Button("X"))
                {
                    AlignUpToAxis(new Vector3(1, 0, 0), true);
                }
                if (GUILayout.Button("Y"))
                {
                    AlignUpToAxis(new Vector3(0, 1, 0), true);
                }
                if (GUILayout.Button("Z"))
                {
                    AlignUpToAxis(new Vector3(0, 0, 1), true);
                }
                GUILayout.EndHorizontal();
            }

            using (new NamedVerticalScope("Misc"))
            {
                // Import Row
                GUILayout.BeginHorizontal();
                sourceMesh = EditorGUILayout.ObjectField(sourceMesh, typeof(Mesh), false) as Mesh;

                if (GUILayout.Button("Import", GUILayout.MaxWidth(drawableWidth / 3f)))
                {
                    if (sourceMesh != null)
                    {
                        Undo.RecordObjects(targets, "Import Polygons From Mesh");

                        Polygon[] polygons = BrushFactory.GeneratePolygonsFromMesh(sourceMesh).ToArray();
                        bool      convex   = GeometryHelper.IsBrushConvex(polygons);
                        if (!convex)
                        {
                            Debug.LogError("Concavities detected in imported mesh. This may result in issues during CSG, please change the source geometry so that it is convex");
                        }
                        foreach (var thisBrush in targets)
                        {
                            ((PrimitiveBrush)thisBrush).SetPolygons(polygons, true);
                        }
                    }
                }

                GUILayout.EndHorizontal();

                // Shell Row
                GUILayout.BeginHorizontal();

                if (shellDistance == 0)
                {
                    shellDistance = CurrentSettings.PositionSnapDistance;
                }

                shellDistance = EditorGUILayout.FloatField("Distance", shellDistance);

                if (GUILayout.Button("Shell", GUILayout.MaxWidth(drawableWidth / 3f)))
                {
                    List <GameObject> newSelection = new List <GameObject>();
                    foreach (var thisBrush in targets)
                    {
                        GameObject newObject = ((PrimitiveBrush)thisBrush).Duplicate();
                        Polygon[]  polygons  = newObject.GetComponent <PrimitiveBrush>().GetPolygons();
                        VertexUtility.DisplacePolygons(polygons, -shellDistance);
                        Bounds newBounds = newObject.GetComponent <PrimitiveBrush>().GetBounds();
                        // Verify the new geometry
                        if (GeometryHelper.IsBrushConvex(polygons) &&
                            newBounds.GetSmallestExtent() > 0)
                        {
                            Undo.RegisterCreatedObjectUndo(newObject, "Shell");
                            newSelection.Add(newObject);
                        }
                        else
                        {
                            // Produced a concave brush, delete it and pretend nothing happened
                            GameObject.DestroyImmediate(newObject);
                            Debug.LogWarning("Could not shell " + thisBrush.name + " as shelled geometry would not be valid. Try lowering the shell distance and attempt Shell again.");
                        }
                    }

                    if (newSelection.Count > 0)
                    {
                        Selection.objects = newSelection.ToArray();
                    }
                }

                GUILayout.EndHorizontal();

                // Split Intersecting Row
                if (GUILayout.Button("Split Intersecting Brushes"))
                {
                    // Chop up the intersecting brushes by the brush planes, ideally into as few new brushes as possible

                    PrimitiveBrush[] brushes = BrushTargets.Cast <PrimitiveBrush>().ToArray();

                    BrushUtility.SplitIntersecting(brushes);
                }


                //			BrushOrder brushOrder = BrushTarget.GetBrushOrder();
                //			string positionString = string.Join(",", brushOrder.Position.Select(item => item.ToString()).ToArray());
                //            GUILayout.Label(positionString, EditorStyles.boldLabel);

                //List<BrushCache> intersections = ((PrimitiveBrush)BrushTarget).BrushCache.IntersectingVisualBrushCaches;
                //GUILayout.Label("Intersecting brushes " + intersections.Count, EditorStyles.boldLabel);

                //for (int i = 0; i < intersections.Count; i++)
                //{
                //    GUILayout.Label(intersections[i].Mode.ToString(), EditorStyles.boldLabel);
                //}
            }

            base.OnInspectorGUI();
        }
コード例 #5
0
        public override void OnInspectorGUI()
        {
//            DrawDefaultInspector();

            DrawBrushTypeField();

//			BrushOrder brushOrder = BrushTarget.GetBrushOrder();
//			string positionString = string.Join(",", brushOrder.Position.Select(item => item.ToString()).ToArray());
//            GUILayout.Label(positionString, EditorStyles.boldLabel);

//			List<BrushCache> intersections = BrushTarget.BrushCache.IntersectingVisualBrushCaches;
//
//			for (int i = 0; i < intersections.Count; i++)
//			{
//				GUILayout.Label(intersections[i].Mode.ToString(), EditorStyles.boldLabel);
//			}

            GUILayout.BeginHorizontal();

            GUI.SetNextControlName("rescaleTextbox");

            rescaleString = EditorGUILayout.TextField(rescaleString);

            bool keyboardEnter = Event.current.isKey &&
                                 Event.current.keyCode == KeyCode.Return &&
                                 Event.current.type == EventType.KeyUp &&
                                 GUI.GetNameOfFocusedControl() == "rescaleTextbox";

            if (GUILayout.Button("Rescale") || keyboardEnter)
            {
                // Try to parse a Vector3 scale from the input string
                Vector3 rescaleVector3;
                if (StringHelper.TryParseScale(rescaleString, out rescaleVector3))
                {
                    // None of the scale components can be zero
                    if (rescaleVector3.x != 0 && rescaleVector3.y != 0 && rescaleVector3.z != 0)
                    {
                        // Rescale all the brushes
                        Undo.RecordObjects(targets, "Rescale Polygons");
                        foreach (var thisBrush in targets)
                        {
                            BrushUtility.Rescale((PrimitiveBrush)thisBrush, rescaleVector3);
                        }
                    }
                }
            }

            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();

            GUI.SetNextControlName("resizeTextbox");

            resizeString = EditorGUILayout.TextField(resizeString);

            keyboardEnter = Event.current.isKey &&
                            Event.current.keyCode == KeyCode.Return &&
                            Event.current.type == EventType.KeyUp &&
                            GUI.GetNameOfFocusedControl() == "resizeTextbox";

            if (GUILayout.Button("Resize") || keyboardEnter)
            {
                // Try to parse a Vector3 scale from the input string
                Vector3 resizeVector3;
                if (StringHelper.TryParseScale(resizeString, out resizeVector3))
                {
                    // None of the size components can be zero
                    if (resizeVector3.x != 0 && resizeVector3.y != 0 && resizeVector3.z != 0)
                    {
                        // Rescale all the brushes so that the local bounds is the same size as the resize vector
                        Undo.RecordObjects(targets, "Resize Polygons");
                        PrimitiveBrush[] brushes = BrushTargets;
                        foreach (PrimitiveBrush brush in brushes)
                        {
                            BrushUtility.Resize(brush, resizeVector3);
                        }
                    }
                }
            }

            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            sourceMesh = EditorGUILayout.ObjectField(sourceMesh, typeof(Mesh), false) as Mesh;

            if (GUILayout.Button("Import"))
            {
                if (sourceMesh != null)
                {
                    Undo.RecordObjects(targets, "Import Polygons From Mesh");

                    Polygon[] polygons = BrushFactory.GeneratePolygonsFromMesh(sourceMesh).ToArray();
                    bool      convex   = GeometryHelper.IsBrushConvex(polygons);
                    if (!convex)
                    {
                        Debug.LogError("Concavities detected in imported mesh. This may result in issues during CSG, please change the source geometry so that it is convex");
                    }
                    foreach (var thisBrush in targets)
                    {
                        ((PrimitiveBrush)thisBrush).SetPolygons(polygons, true);
                    }
                }
            }

            GUILayout.EndHorizontal();

            List <PrimitiveBrush> orderedTargets = BrushTargets.ToList();

            orderedTargets.Sort((x, y) => x.transform.GetSiblingIndex().CompareTo(y.transform.GetSiblingIndex()));

            if (GUILayout.Button("Set As First"))
            {
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    // REVERSED
                    PrimitiveBrush thisBrush = orderedTargets[orderedTargets.Count - 1 - i];

                    Undo.SetTransformParent(thisBrush.transform, thisBrush.transform.parent, "Change Order");
                    thisBrush.transform.SetAsFirstSibling();
                }

                // Force all the brushes to recalculate their intersections and get ready for rebuilding
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    orderedTargets[i].RecalculateIntersections();
                    orderedTargets[i].BrushCache.SetUnbuilt();
                }
            }

            if (GUILayout.Button("Send Earlier"))
            {
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    PrimitiveBrush thisBrush = orderedTargets[i];

                    int siblingIndex = thisBrush.transform.GetSiblingIndex();
                    if (siblingIndex > 0)
                    {
                        Undo.SetTransformParent(thisBrush.transform, thisBrush.transform.parent, "Change Order");
                        siblingIndex--;
                        thisBrush.transform.SetSiblingIndex(siblingIndex);
                    }
                }

                // Force all the brushes to recalculate their intersections and get ready for rebuilding
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    orderedTargets[i].RecalculateIntersections();
                    orderedTargets[i].BrushCache.SetUnbuilt();
                }
            }

            if (GUILayout.Button("Send Later"))
            {
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    // REVERSED
                    PrimitiveBrush thisBrush = orderedTargets[orderedTargets.Count - 1 - i];

                    int siblingIndex = thisBrush.transform.GetSiblingIndex();
                    Undo.SetTransformParent(thisBrush.transform, thisBrush.transform.parent, "Change Order");
                    siblingIndex++;
                    thisBrush.transform.SetSiblingIndex(siblingIndex);
                }

                // Force all the brushes to recalculate their intersections and get ready for rebuilding
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    orderedTargets[i].RecalculateIntersections();
                    orderedTargets[i].BrushCache.SetUnbuilt();
                }
            }

            if (GUILayout.Button("Set As Last"))
            {
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    PrimitiveBrush thisBrush = orderedTargets[i];

                    Undo.SetTransformParent(thisBrush.transform, thisBrush.transform.parent, "Change Order");
                    thisBrush.transform.SetAsLastSibling();
                }

                // Force all the brushes to recalculate their intersections and get ready for rebuilding
                for (int i = 0; i < orderedTargets.Count; i++)
                {
                    orderedTargets[i].RecalculateIntersections();
                    orderedTargets[i].BrushCache.SetUnbuilt();
                }
            }

            serializedObject.ApplyModifiedProperties();



//            GUILayout.Label("UVs", EditorStyles.boldLabel);
//
//            if (GUILayout.Button("Flip XY"))
//            {
//                UVUtility.FlipUVsXY(thisBrush.Polygons);
//            }
//
//            GUILayout.BeginHorizontal();
//            if (GUILayout.Button("Flip X"))
//            {
//                UVUtility.FlipUVsX(thisBrush.Polygons);
//            }
//            if (GUILayout.Button("Flip Y"))
//            {
//                UVUtility.FlipUVsY(thisBrush.Polygons);
//            }
//            GUILayout.EndHorizontal();
//
//            GUILayout.BeginHorizontal();
//            if (GUILayout.Button("UVs x 2"))
//            {
//                UVUtility.ScaleUVs(thisBrush.Polygons, 2f);
//            }
//            if (GUILayout.Button("UVs / 2"))
//            {
//                UVUtility.ScaleUVs(thisBrush.Polygons, .5f);
//            }
//            GUILayout.EndHorizontal();
            // Ensure Edit Mode is on
//            csgModel.EditMode = true;
        }