public override void Invalidate(bool polygonsChanged) { base.Invalidate(polygonsChanged); for (int i = 0; i < BrushCount; i++) { generatedBrushes[i].Mode = this.Mode; generatedBrushes[i].IsNoCSG = this.IsNoCSG; generatedBrushes[i].IsVisible = this.IsVisible; generatedBrushes[i].HasCollision = this.HasCollision; } if (IsBrushXYZTooSmall) { generatedBrushes[0].Mode = CSGMode.Add; BrushUtility.Resize(generatedBrushes[0], localBounds.size); generatedBrushes[1].Mode = CSGMode.Subtract; BrushUtility.Resize(generatedBrushes[1], localBounds.size - new Vector3(wallThickness * 2, wallThickness * 2, wallThickness * 2)); for (int i = 0; i < BrushCount; i++) { generatedBrushes[i].SetPolygons(GeneratePolys(i)); generatedBrushes[i].Invalidate(true); } } else { BrushUtility.Resize(generatedBrushes[0], localBounds.size); } }
private void ResetBounds() { // Reset the bounds to a 2,2,2 cube Undo.RecordObjects(targets, "Reset Bounds"); PrimitiveBrush[] brushes = BrushTargets.Cast <PrimitiveBrush>().ToArray(); foreach (PrimitiveBrush brush in brushes) { BrushUtility.Resize(brush, new Vector3(2, 2, 2)); } }
public override void Invalidate(bool polygonsChanged) { base.Invalidate(polygonsChanged); for (int i = 0; i < BrushCount; i++) { generatedBrushes[i].Mode = this.Mode; generatedBrushes[i].IsNoCSG = this.IsNoCSG; generatedBrushes[i].IsVisible = this.IsVisible; generatedBrushes[i].HasCollision = this.HasCollision; } Vector3 baseSize; if (localBounds.size.x > trimSize * 2.0f && localBounds.size.z > trimSize * 2.0f) { float sizeX = localBounds.size.x - trimSize * 2.0f; float sizeZ = localBounds.size.z - trimSize * 2.0f; baseSize = new Vector3(sizeX, localBounds.size.y, sizeZ); // Build the trims here for (int i = 1; i < BrushCount; i++) { // Vector3 brushPos = localBounds.center; // brushPos.x += Mathf.Sin(i * Mathf.PI * 0.5f) * ((localBounds.size.x - trimSize) * 0.5f); // brushPos.z += Mathf.Cos(i * Mathf.PI * 0.5f) * ((localBounds.size.z - trimSize) * 0.5f); // generatedBrushes[i].transform.localPosition = brushPos; Vector3 brushSize = new Vector3(); if (i % 2 == 0) { brushSize.x = sizeX; brushSize.z = trimSize; } else { brushSize.x = trimSize; brushSize.z = sizeZ; } brushSize.y = localBounds.size.y; BrushUtility.Resize(generatedBrushes[i], brushSize); generatedBrushes[i].SetPolygons(GeneratePolys(i)); generatedBrushes[i].Invalidate(true); } } else { baseSize = localBounds.size; } generatedBrushes[0].transform.localPosition = localBounds.center; BrushUtility.Resize(generatedBrushes[0], baseSize); }
public override void Invalidate(bool polygonsChanged) { base.Invalidate(polygonsChanged); int brushCount = BrushCount; float activeHeight = stepHeight; float activeDepth = stepDepth; if (autoHeight) { activeHeight = localBounds.size.y / brushCount; } if (autoDepth) { activeDepth = localBounds.size.z / brushCount; } Vector3 stepSize = new Vector3(localBounds.size.x, activeHeight, activeDepth); Vector3 startPosition = localBounds.center; if (leadFromTop) { startPosition.y += stepSize.y / 2f + localBounds.size.y / 2f - stepSize.y * brushCount; startPosition.z += stepSize.z / 2f + localBounds.size.z / 2f - stepSize.z * brushCount; } else { startPosition.y += stepSize.y / 2f - localBounds.size.y / 2f; startPosition.z += stepSize.z / 2f - localBounds.size.z / 2f; } for (int i = 0; i < brushCount; i++) { Vector3 localPosition = startPosition + Vector3.forward * i * (activeDepth + stepDepthSpacing) + Vector3.up * i * (activeHeight + stepHeightSpacing) * (fillToBottom ? 0.5f : 1f); generatedBrushes[i].transform.localPosition = localPosition; generatedBrushes[i].Mode = this.Mode; generatedBrushes[i].IsNoCSG = this.IsNoCSG; generatedBrushes[i].IsVisible = this.IsVisible; generatedBrushes[i].HasCollision = this.HasCollision; BrushUtility.Resize(generatedBrushes[i], stepSize); if (fillToBottom) { stepSize.y += (activeHeight) + stepHeightSpacing; } } }
private void ResetPolygonsKeepScale() { PrimitiveBrush[] brushes = BrushTargets.Cast <PrimitiveBrush>().ToArray(); foreach (PrimitiveBrush brush in brushes) { Bounds localBounds = brush.GetBounds(); brush.ResetPolygons(); if (localBounds.size != new Vector3(2, 2, 2)) { BrushUtility.Resize(brush, localBounds.size); } else { brush.Invalidate(true); } } }
/// <summary> /// Creates a brush under the CSG Model with the specified attributes. /// </summary> /// <returns>The created game object.</returns> /// <param name="brushType">Brush type.</param> /// <param name="localPosition">Local position of the brush's transform</param> /// <param name="localSize">Local bounds size of the brush (Optional, defaults to 2,2,2).</param> /// <param name="localRotation">Local rotation of the brush (Optional, defaults to identity quaternion).</param> /// <param name="material">Material to apply to all faces, (Optional, defaults to null for default material).</param> /// <param name="csgMode">Whether the brush is additive or subtractive (Optional, defaults to additive).</param> /// <param name="brushName">Name for the game object (Optional, defaults to "AppliedBrush").</param> public GameObject CreateBrush(PrimitiveBrushType brushType, Vector3 localPosition, Vector3 localSize = default(Vector3), Quaternion localRotation = default(Quaternion), Material material = null, CSGMode csgMode = CSGMode.Add, string brushName = null) { GameObject brushObject; if (!string.IsNullOrEmpty(brushName)) { brushObject = new GameObject(brushName); } else { brushObject = new GameObject(""); } brushObject.transform.localScale = this.transform.lossyScale; brushObject.transform.parent = this.transform; brushObject.transform.localPosition = localPosition; if (localRotation != default(Quaternion)) { brushObject.transform.localRotation = localRotation; } PrimitiveBrush primitiveBrush = brushObject.AddComponent <PrimitiveBrush>(); primitiveBrush.BrushType = brushType; primitiveBrush.Mode = csgMode; primitiveBrush.ResetPolygons(); if (localSize != default(Vector3) && localSize != new Vector3(2, 2, 2)) { BrushUtility.Resize(primitiveBrush, localSize); } else { // Resize automatically invalidates a brush with changed polygons set, if no resize took place we still need to make sure it happens primitiveBrush.Invalidate(true); } if (material != null) { SurfaceUtility.SetAllPolygonsMaterials(primitiveBrush, material); } return(brushObject); }
private void ChangeBrushesToType(PrimitiveBrushType newType) { Undo.RecordObjects(targets, "Change Brush Type"); PrimitiveBrush[] brushes = BrushTargets.Cast <PrimitiveBrush>().ToArray(); foreach (PrimitiveBrush brush in brushes) { Bounds localBounds = brush.GetBounds(); brush.BrushType = newType; brush.ResetPolygons(); if (localBounds.size != new Vector3(2, 2, 2)) { BrushUtility.Resize(brush, localBounds.size); } else { brush.Invalidate(true); } } }
/// <summary> /// Creates a brush under the CSG Model with the specified attributes. /// </summary> /// <returns>The created game object.</returns> /// <param name="brushType">Brush type.</param> /// <param name="localPosition">Local position of the brush's transform</param> /// <param name="localSize">Local bounds size of the brush (Optional, defaults to 2,2,2).</param> /// <param name="localRotation">Local rotation of the brush (Optional, defaults to identity quaternion).</param> /// <param name="material">Material to apply to all faces, (Optional, defaults to null for default material).</param> /// <param name="csgMode">Whether the brush is additive or subtractive (Optional, defaults to additive).</param> /// <param name="brushName">Name for the game object (Optional, defaults to "AppliedBrush").</param> public GameObject CreateBrush(PrimitiveBrushType brushType, Vector3 localPosition, Vector3 localSize = default(Vector3), Quaternion localRotation = default(Quaternion), Material material = null, CSGMode csgMode = CSGMode.Add, string brushName = null) { GameObject brushObject; if (!string.IsNullOrEmpty(brushName)) { brushObject = new GameObject(brushName); } else { brushObject = new GameObject("AppliedBrush"); } brushObject.transform.parent = this.transform; brushObject.transform.localPosition = localPosition; if (localRotation != default(Quaternion)) { brushObject.transform.localRotation = localRotation; } PrimitiveBrush primitiveBrush = brushObject.AddComponent <PrimitiveBrush>(); primitiveBrush.BrushType = brushType; primitiveBrush.Mode = csgMode; primitiveBrush.ResetPolygons(); if (localSize != default(Vector3) && localSize != new Vector3(2, 2, 2)) { BrushUtility.Resize(primitiveBrush, localSize); // primitiveBrush.Invalidate(true); } if (material != null) { SurfaceUtility.SetAllPolygonsMaterials(primitiveBrush, material); } return(brushObject); }
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(); }
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; }