Esempio n. 1
0
        public void EndCommit()
        {
            if (generatedBrushes == null)
            {
                return;
            }
            var bounds = BoundsUtilities.GetBounds(generatedBrushes);

            if (!bounds.IsEmpty())
            {
                var center = bounds.Center - operationGameObject.transform.position;
                GeometryUtility.MoveControlMeshVertices(generatedBrushes, -center);
                SurfaceUtility.TranslateSurfacesInWorldSpace(generatedBrushes, -center);
                ControlMeshUtility.RebuildShapes(generatedBrushes);
                InternalCSGModelManager.Refresh(forceHierarchyUpdate: true);

                operationGameObject.transform.position += center;

                Undo.CollapseUndoOperations(undoGroupIndex);
                Cleanup();

                if (generatedGameObjects != null &&
                    generatedGameObjects.Length > 0)
                {
                    Selection.objects = generatedGameObjects;
                }

                Reset();
            }

            if (shapeCommitted != null)
            {
                shapeCommitted();
            }
        }
Esempio n. 2
0
        public void UpdateSmoothingGroups(HashSet <uint> usedSmoothingGroupIndices)
        {
            for (int i = 0; i < curveEdgeHandles.Length; i++)
            {
                curveEdgeHandles[i].Texgen.SmoothingGroup = 0;
            }

            for (int i = 0; i < curveEdgeHandles.Length; i++)
            {
                if (curveEdgeHandles[i].Texgen.SmoothingGroup != 0)
                {
                    continue;
                }

                var smoothingGroup = SurfaceUtility.FindUnusedSmoothingGroupIndex(usedSmoothingGroupIndices);
                usedSmoothingGroupIndices.Add(smoothingGroup);
                curveEdgeHandles[i].Texgen.SmoothingGroup = smoothingGroup;

                if (i == 0 &&
                    curveTangentHandles[(i * 2) + 0].Constraint == HandleConstraints.Mirrored ||
                    curveTangentHandles[(i * 2) + 1].Constraint == HandleConstraints.Mirrored)
                {
                    var last = curveEdgeHandles.Length - 1;
                    curveEdgeHandles[last].Texgen.SmoothingGroup = smoothingGroup;
                }
                if (i < (curveEdgeHandles.Length - 1) &&
                    i < (curve.Points.Length - 1) &&
                    (curveTangentHandles[((i + 1) * 2) + 0].Constraint == HandleConstraints.Mirrored ||
                     curveTangentHandles[((i + 1) * 2) + 1].Constraint == HandleConstraints.Mirrored))
                {
                    curveEdgeHandles[i + 1].Texgen.SmoothingGroup = smoothingGroup;
                }
            }
        }
Esempio n. 3
0
        /*
         * public static bool ContinueTexGenFromSurfaceToSurface(CSGBrush srcBrush, int srcSurfaceIndex, CSGBrush dstBrush, int dstSurfaceIndex)
         * {
         *      if (srcSurfaceIndex < 0 || srcSurfaceIndex >= srcBrush.Shape.Materials.Length ||
         *              srcBrush == null)
         *              return false;
         *
         *      var src_brush_cache = CSGModelManager.GetBrushCache(srcBrush);
         *      if (src_brush_cache == null ||
         *              src_brush_cache.childData == null ||
         *              src_brush_cache.childData.modelTransform == null)
         *              return false;
         *
         *      var dst_brush_cache = CSGModelManager.GetBrushCache(dstBrush);
         *      if (dst_brush_cache == null ||
         *              dst_brush_cache.childData == null ||
         *              dst_brush_cache.childData.modelTransform == null)
         *              return false;
         *
         *      var dstPlane	= dstBrush.Shape.Surfaces[dstSurfaceIndex].Plane;
         *      var srcPlane	= srcBrush.Shape.Surfaces[srcSurfaceIndex].Plane;
         *
         *      // convert planes into worldspace
         *      dstPlane = GeometryUtility.InverseTransformPlane(dstBrush.transform.worldToLocalMatrix, dstPlane);
         *      srcPlane = GeometryUtility.InverseTransformPlane(srcBrush.transform.worldToLocalMatrix, srcPlane);
         *
         *      var dstNormal	= dstPlane.normal;
         *      var srcNormal	= srcPlane.normal;
         *
         *      var srcTexGenIndex = srcBrush.Shape.Surfaces[srcSurfaceIndex].TexGenIndex;
         *      var dstTexGenIndex = dstBrush.Shape.Surfaces[dstSurfaceIndex].TexGenIndex;
         *
         *      var scrShape = srcBrush.Shape;
         *
         *      dstBrush.Shape.Materials[dstSurfaceIndex] = scrShape.Materials[srcSurfaceIndex];
         *      Vector3 srcPoint1, srcPoint2;
         *      Vector3 dstPoint1, dstPoint2;
         *      var edgeDirection = Vector3.Cross(dstNormal, srcNormal);
         *      var det = edgeDirection.sqrMagnitude;
         *      if (det < Constants.AlignmentTestEpsilon)
         *      {
         *              // Find 2 points on intersection of 2 planes
         *              srcPoint1 = srcPlane.pointOnPlane;
         *              srcPoint2 = GeometryUtility.ProjectPointOnPlane(srcPlane, srcPoint1 + MathConstants.oneVector3);
         *
         *              dstPoint1 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint1);
         *              dstPoint2 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint2);
         *      } else
         *      {
         *              // Find 2 points on intersection of 2 planes
         *              srcPoint1 = ((Vector3.Cross(edgeDirection, srcNormal) * -dstPlane.d) +
         *                                              (Vector3.Cross(dstNormal, edgeDirection) * -srcPlane.d)) / det;
         *              srcPoint2 = srcPoint1 + edgeDirection;
         *              dstPoint1 = srcPoint1;
         *              dstPoint2 = srcPoint2;
         *      }
         *
         *      Vector3 srcLocalPoint1 = srcBrush.transform.InverseTransformPoint(srcPoint1);
         *      Vector3 srcLocalPoint2 = srcBrush.transform.InverseTransformPoint(srcPoint2);
         *
         *      Vector3 dstLocalPoint1 = dstBrush.transform.InverseTransformPoint(dstPoint1);
         *      Vector3 dstLocalPoint2 = dstBrush.transform.InverseTransformPoint(dstPoint2);
         *
         *      var srcShape	= srcBrush.Shape;
         *      var srcTexGens	= srcShape.TexGens;
         *      var srcSurfaces	= srcShape.Surfaces;
         *      var dstShape	= dstBrush.Shape;
         *      var dstTexGens	= dstShape.TexGens;
         *      var dstSurfaces	= dstShape.Surfaces;
         *
         *
         *      // Reset destination shape to simplify calculations
         *      dstTexGens[dstTexGenIndex].Scale			= scrShape.TexGens[srcTexGenIndex].Scale;
         *      dstTexGens[dstTexGenIndex].Translation		= MathConstants.zeroVector2;
         *      dstTexGens[dstTexGenIndex].RotationAngle	= 0;
         *
         *      if (!CSGModelManager.AlignTextureSpacesInLocalSpace(ref srcTexGens[srcTexGenIndex], ref srcSurfaces[srcSurfaceIndex],
         *                                                                                                              srcLocalPoint1, srcLocalPoint2,
         *                                                                                                              ref dstTexGens[dstTexGenIndex], ref dstSurfaces[dstSurfaceIndex],
         *                                                                                                              dstLocalPoint1, dstLocalPoint2))
         *              return false;
         *      return true;
         * }
         */

        public static bool ContinueTexGenFromSurfaceToSurface(CSGBrush brush, int srcSurfaceIndex, int dstSurfaceIndex)
        {
            if (srcSurfaceIndex < 0 || srcSurfaceIndex >= brush.Shape.Materials.Length ||
                !brush)
            {
                return(false);
            }

            var shape       = brush.Shape;
            var texGens     = shape.TexGens;
            var texGenFlags = shape.TexGenFlags;
            var surfaces    = shape.Surfaces;

            var dstPlane = surfaces[dstSurfaceIndex].Plane;
            var srcPlane = surfaces[srcSurfaceIndex].Plane;

            // convert planes into worldspace
            dstPlane = InverseTransformPlane(brush.transform.worldToLocalMatrix, dstPlane);
            srcPlane = InverseTransformPlane(brush.transform.worldToLocalMatrix, srcPlane);

            var dstNormal = dstPlane.normal;
            var srcNormal = srcPlane.normal;

            var srcTexGenIndex = surfaces[srcSurfaceIndex].TexGenIndex;
            var dstTexGenIndex = surfaces[dstSurfaceIndex].TexGenIndex;

            shape.Materials[dstSurfaceIndex] = shape.Materials[srcSurfaceIndex];
            Vector3 srcPoint1, srcPoint2;
            Vector3 dstPoint1, dstPoint2;
            var     edgeDirection = Vector3.Cross(dstNormal, srcNormal);
            var     det           = edgeDirection.sqrMagnitude;

            if (det < MathConstants.AlignmentTestEpsilon)
            {
                // Find 2 points on intersection of 2 planes
                srcPoint1 = srcPlane.pointOnPlane;
                srcPoint2 = GeometryUtility.ProjectPointOnPlane(srcPlane, srcPoint1 + MathConstants.oneVector3);

                dstPoint1 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint1);
                dstPoint2 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint2);
            }
            else
            {
                // Find 2 points on intersection of 2 planes
                srcPoint1 = ((Vector3.Cross(edgeDirection, srcNormal) * -dstPlane.d) +
                             (Vector3.Cross(dstNormal, edgeDirection) * -srcPlane.d)) / det;
                srcPoint2 = srcPoint1 + edgeDirection;
                dstPoint1 = srcPoint1;
                dstPoint2 = srcPoint2;
            }

            // Reset destination shape to simplify calculations
            texGens[dstTexGenIndex].Scale         = shape.TexGens[srcTexGenIndex].Scale;
            texGens[dstTexGenIndex].Translation   = MathConstants.zeroVector2;
            texGens[dstTexGenIndex].RotationAngle = 0;

            return(SurfaceUtility.AlignTextureSpaces(brush.transform, ref texGens[srcTexGenIndex], texGenFlags[srcTexGenIndex], ref surfaces[srcSurfaceIndex], srcPoint1, srcPoint2, false,
                                                     brush.transform, ref texGens[dstTexGenIndex], texGenFlags[dstTexGenIndex], ref surfaces[dstSurfaceIndex], dstPoint1, dstPoint2, false));
        }
        private static void ApplyMaterial(Material material)
        {
            var activetool = EditModeManager.ActiveTool as EditModeSurface;

            if (activetool != null)
            {
                var selectedBrushSurfaces = activetool.GetSelectedSurfaces();
                SurfaceUtility.SetMaterials(selectedBrushSurfaces, material);
            }
        }
Esempio n. 5
0
        static void OnGUIContentsMaterialImage(bool isSceneGUI, Material material, bool mixedValues, SelectedBrushSurface[] selectedBrushSurfaces)
        {
            GUILayout.BeginHorizontal(materialWidth, materialHeight);
            {
                //if (materialEditor == null || prevMaterial != material)
                {
                    var editor = materialEditor as Editor;
                    Editor.CreateCachedEditor(material, typeof(MaterialEditor), ref editor);
                    materialEditor = editor as MaterialEditor;
                    //prevMaterial = material;
                }

                if (materialEditor != null)
                {
                    var rect = GUILayoutUtility.GetRect(materialSize, materialSize);
                    EditorGUI.showMixedValue = mixedValues;
                    materialEditor.OnPreviewGUI(rect, GUIStyle.none);
                    EditorGUI.showMixedValue = false;
                }
                else
                {
                    GUILayout.Box(new GUIContent(), CSG_GUIStyleUtility.emptyMaterialStyle, materialWidth, materialHeight);
                }
            }
            GUILayout.EndHorizontal();
            var currentArea  = GUILayoutUtility.GetLastRect();
            var currentPoint = Event.current.mousePosition;

            if (currentArea.Contains(currentPoint))
            {
                if (Event.current.type == EventType.DragUpdated &&
                    GetDragMaterial())
                {
                    DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
                    Event.current.Use();
                }
                if (Event.current.type == EventType.DragPerform)
                {
                    var new_material = GetDragMaterial();
                    if (new_material)
                    {
                        SurfaceUtility.SetMaterials(selectedBrushSurfaces, new_material);
                        CSGSettings.DefaultMaterial = new_material;
                        CSGSettings.Save();
                        GUI.changed = true;
                        Event.current.Use();
                    }
                }
            }
        }
Esempio n. 6
0
        /// <summary>Converts a <see cref="RealtimeCSG.Legacy.Surface"/>/<see cref="RealtimeCSG.Legacy.TexGen"/>/<see cref="RealtimeCSG.Legacy.TexGenFlags"/> combination into a <see cref="RealtimeCSG.Foundation.SurfaceDescription"/>.</summary>
        /// <param name="surface">A legacy <see cref="RealtimeCSG.Legacy.Surface"/> that describes how the texture space is orientated relative to the brush.</param>
        /// <param name="texGen">A legacy <see cref="RealtimeCSG.Legacy.TexGen"/> that describes how the texture coordinates are calculated in the <see cref="RealtimeCSG.Foundation.SurfaceDescription"/>.</param>
        /// <param name="texGenFlags">A legacy <see cref="RealtimeCSG.Legacy.TexGenFlags"/> enum that describes if the <see cref="RealtimeCSG.Foundation.SurfaceDescription"/> texture generation will be in world-space or brush-space.</param>
        /// <returns>A new <see cref="RealtimeCSG.Foundation.SurfaceDescription"/></returns>
        public static SurfaceDescription CreateSurfaceDescription(Surface surface, TexGen texGen, TexGenFlags texGenFlags)
        {
            var localToTextureSpace = SurfaceUtility.GetLocalToTextureSpaceMatrix(texGen, surface);

            SurfaceDescription description;

            description.smoothingGroup = texGen.SmoothingGroup;
            description.surfaceFlags   = ((texGenFlags & TexGenFlags.WorldSpaceTexture) == 0) ? SurfaceFlags.None : SurfaceFlags.TextureIsInWorldSpace;

            description.UV0.U = localToTextureSpace.GetRow(0);
            description.UV0.V = localToTextureSpace.GetRow(1);

            return(description);
        }
Esempio n. 7
0
        private bool GenerateStairs(CSGBrush[] stepBrushes, int totalSteps, float stepLength, float stepHeight, float stairsDepth, float stairsWidth, float stairsHeight, float extraDepth, float extraHeight)
        {
            bool success = true;

            for (int stepIndex = 0; stepIndex < totalSteps; stepIndex++)
            {
                var brush = stepBrushes[stepIndex];
                if (!brush)
                {
                    continue;
                }

                var curStepHeight = Mathf.Min(stairsHeight, (stepIndex == 0) ? (extraHeight + stepHeight) : stepHeight);
                var curStepY      = (stepIndex == 0) ? (stepHeight * stepIndex) : (extraHeight + (stepHeight * stepIndex));

                var extraLength = lengthDirection * (stepLength * stepIndex);
                var heightPos   = heightDirection * curStepY;

                var widthSize  = (widthDirection * stairsWidth);
                var lengthSize = (lengthDirection * stairsDepth) - extraLength;
                var heightSize = (heightDirection * curStepHeight);

                var size     = widthSize + heightSize + lengthSize;
                var position = (totalSteps == 1) ? (heightPos + brushPosition) : heightPos;

                ControlMesh newControlMesh;
                Shape       newShape;
                if (!BrushFactory.CreateCubeControlMesh(out newControlMesh, out newShape, Vector3.zero, size))
                {
                    success = false;
                    if (brush.gameObject.activeSelf)
                    {
                        brush.gameObject.SetActive(false);
                    }
                    continue;
                }

                if (!brush.gameObject.activeSelf)
                {
                    brush.gameObject.SetActive(true);
                }

                brush.Shape                   = newShape;
                brush.ControlMesh             = newControlMesh;
                brush.transform.localPosition = position;
                SurfaceUtility.TranslateSurfacesInWorldSpace(brush, -position);
            }
            return(success);
        }
Esempio n. 8
0
        public static void TranslatePivot(CSGBrush[] brushes, Vector3 offset)
        {
            if (brushes == null ||
                brushes.Length == 0 ||
                offset.sqrMagnitude < MathConstants.ConsideredZero)
            {
                return;
            }

            for (int i = 0; i < brushes.Length; i++)
            {
                brushes[i].transform.position += offset;
            }

            GeometryUtility.MoveControlMeshVertices(brushes, -offset);
            SurfaceUtility.TranslateSurfacesInWorldSpace(brushes, -offset);
            ControlMeshUtility.RebuildShapes(brushes);
        }
Esempio n. 9
0
        public static void SetPivot(CSGBrush brush, Vector3 newCenter)
        {
            if (!brush)
            {
                return;
            }

            var transform  = brush.transform;
            var realCenter = transform.position;
            var difference = newCenter - realCenter;

            if (difference.sqrMagnitude < MathConstants.ConsideredZero)
            {
                return;
            }

            transform.position += difference;

            GeometryUtility.MoveControlMeshVertices(brush, -difference);
            SurfaceUtility.TranslateSurfacesInWorldSpace(brush, -difference);
            ControlMeshUtility.RebuildShape(brush);
        }
        public static void OnSurfaceFlagButtons(SurfaceFlagState state, SelectedBrushSurface[] selectedBrushSurfaces, bool isSceneGUI = false)
        {
            var leftStyle = isSceneGUI ? EditorStyles.miniButtonLeft  : GUI.skin.button;
            //var middleStyle	= isSceneGUI ? EditorStyles.miniButtonMid   : GUI.skin.button;
            var rightStyle = isSceneGUI ? EditorStyles.miniButtonRight : GUI.skin.button;

            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
            {
                if (!isSceneGUI)
                {
                    GUILayout.Label(ContentShadows, EditModeSurfaceGUI.largeLabelWidth);
                }
                else
                {
                    GUILayout.Label(ContentShadows, EditorStyles.miniLabel, EditModeSurfaceGUI.smallLabelWidth);
                }

                EditorGUI.BeginChangeCheck();
                {
                    // TODO: implement support
                    EditorGUI.showMixedValue = !state.noReceiveShadows.HasValue;
                    state.noReceiveShadows   = !GUILayout.Toggle(!(state.noReceiveShadows ?? (state.noRender ?? true)), ContentReceiveShadowsSurfaces, leftStyle);
                    TooltipUtility.SetToolTip(ToolTipReceiveShadowsSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoReceiveShadows, state.noReceiveShadows.Value);
                }
                EditorGUI.BeginChangeCheck();
                {
                    // TODO: implement support
                    EditorGUI.showMixedValue = !state.noCastShadows.HasValue;
                    state.noCastShadows      = !GUILayout.Toggle(!(state.noCastShadows ?? true), ContentCastShadowsSurfaces, rightStyle);
                    TooltipUtility.SetToolTip(ToolTipCastShadowsSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoCastShadows, state.noCastShadows.Value);
                }
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
            {
                EditorGUI.BeginChangeCheck();
                {
                    EditorGUI.showMixedValue = !state.noRender.HasValue;
                    state.noRender           = !GUILayout.Toggle(!(state.noRender ?? true), ContentVisibleSurfaces, leftStyle);
                    TooltipUtility.SetToolTip(ToolTipVisibleSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoRender, state.noRender.Value);
                }
                EditorGUI.BeginChangeCheck();
                {
                    EditorGUI.showMixedValue = !state.noCollision.HasValue;
                    state.noCollision        = !GUILayout.Toggle(!(state.noCollision ?? true), ContentCollisionSurfaces, rightStyle);
                    TooltipUtility.SetToolTip(ToolTipCollisionSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoCollision, state.noCollision.Value);
                }
            }
            GUILayout.EndHorizontal();
            EditorGUI.showMixedValue = false;
        }
        public static void OnSurfaceFlagButtons(Rect rect, SurfaceFlagState state, SelectedBrushSurface[] selectedBrushSurfaces)
        {
            var leftStyle  = EditorStyles.miniButtonLeft;
            var rightStyle = EditorStyles.miniButtonRight;

            var tempRect = rect;

            {
                tempRect.Set(rect.x + 4, rect.y + 1, 45, 16);
                GUI.Label(tempRect, ContentShadows, EditorStyles.miniLabel);

                EditorGUI.BeginChangeCheck();
                {
                    var mixed   = !state.noReceiveShadows.HasValue;
                    var enabled = !(state.noReceiveShadows ?? (state.noRender ?? true));
                    EditorGUI.showMixedValue = mixed;
                    tempRect.Set(rect.x + 53, rect.y + 1, 90 - 4, 15);
                    state.noReceiveShadows = !GUI.Toggle(tempRect, enabled, ContentReceiveShadowsSurfaces, leftStyle);
                    TooltipUtility.SetToolTip(ToolTipReceiveShadowsSurfaces, tempRect);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoReceiveShadows, state.noReceiveShadows.Value);
                }
                EditorGUI.BeginChangeCheck();
                {
                    var mixed   = !state.noCastShadows.HasValue;
                    var enabled = !(state.noCastShadows ?? true);
                    EditorGUI.showMixedValue = mixed;
                    tempRect.Set(rect.x + 143 - 4, rect.y + 1, 74 - 4, 15);
                    state.noCastShadows = !GUI.Toggle(tempRect, enabled, ContentCastShadowsSurfaces, rightStyle);
                    TooltipUtility.SetToolTip(ToolTipCastShadowsSurfaces, tempRect);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoCastShadows, state.noCastShadows.Value);
                }
            }
            {
                EditorGUI.BeginChangeCheck();
                {
                    var mixed   = !state.noRender.HasValue;
                    var enabled = !(state.noRender ?? true);
                    EditorGUI.showMixedValue = mixed;
                    tempRect.Set(rect.x + 4, rect.y + 18, 94, 15);
                    state.noRender = !GUI.Toggle(tempRect, enabled, ContentVisibleSurfaces, leftStyle);
                    TooltipUtility.SetToolTip(ToolTipVisibleSurfaces, tempRect);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoRender, state.noRender.Value);
                }
                EditorGUI.BeginChangeCheck();
                {
                    var mixed   = !state.noCollision.HasValue;
                    var enabled = !(state.noCollision ?? true);
                    EditorGUI.showMixedValue = mixed;
                    tempRect.Set(rect.x + 98, rect.y + 18, 112, 15);
                    state.noCollision = !GUI.Toggle(tempRect, enabled, ContentCollisionSurfaces, rightStyle);
                    TooltipUtility.SetToolTip(ToolTipCollisionSurfaces, tempRect);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoCollision, state.noCollision.Value);
                }
            }
            EditorGUI.showMixedValue = false;
        }
        public static Transform[] CloneTargets(SetTransformation setTransform = null)
        {
            if (instance.filteredSelection.NodeTargets.Length == 0)
            {
                return(new Transform[0]);
            }

            var groupId = Undo.GetCurrentGroup();
            //Undo.IncrementCurrentGroup();

            var newTargets    = new GameObject[instance.filteredSelection.NodeTargets.Length];
            var newTransforms = new Transform[instance.filteredSelection.NodeTargets.Length];

            for (int i = 0; i < instance.filteredSelection.NodeTargets.Length; i++)
            {
                var originalGameObject = instance.filteredSelection.NodeTargets[i].gameObject;
                var originalTransform  = originalGameObject.GetComponent <Transform>();

                newTargets[i] = CSGPrefabUtility.Instantiate(originalGameObject);
                var newTransform = newTargets[i].GetComponent <Transform>();
                if (originalTransform.parent != null)
                {
                    newTransform.SetParent(originalTransform.parent, false);
                    newTransform.SetSiblingIndex(originalTransform.GetSiblingIndex() + 1);
                    newTransform.name = GameObjectUtility.GetUniqueNameForSibling(originalTransform.parent, originalTransform.name);
                }
                if (setTransform == null)
                {
                    newTransform.localScale    = originalTransform.localScale;
                    newTransform.localPosition = originalTransform.localPosition;
                    newTransform.localRotation = originalTransform.localRotation;
                }
                else
                {
                    setTransform(newTransform, originalTransform);
                }

                var childBrushes = newTargets[i].GetComponentsInChildren <CSGBrush>();

                Dictionary <uint, uint> uniqueSmoothingGroups = new Dictionary <uint, uint>();
                foreach (var childBrush in childBrushes)
                {
                    for (int g = 0; g < childBrush.Shape.TexGens.Length; g++)
                    {
                        var smoothingGroup = childBrush.Shape.TexGens[g].SmoothingGroup;
                        if (smoothingGroup == 0)
                        {
                            continue;
                        }

                        uint newSmoothingGroup;
                        if (!uniqueSmoothingGroups.TryGetValue(smoothingGroup, out newSmoothingGroup))
                        {
                            newSmoothingGroup = SurfaceUtility.FindUnusedSmoothingGroupIndex();
                            uniqueSmoothingGroups[smoothingGroup] = newSmoothingGroup;
                        }

                        childBrush.Shape.TexGens[g].SmoothingGroup = newSmoothingGroup;
                    }
                }

                newTransforms[i] = newTransform;
                Undo.RegisterCreatedObjectUndo(newTargets[i], "Created clone of " + originalGameObject.name);
            }

            Selection.objects = newTargets;
            Undo.CollapseUndoOperations(groupId);

            return(newTransforms);
        }
        protected bool UpdateExtrudedShape(bool registerUndo = true)
        {
            if (polygons == null || polygons.Length == 0)
            {
                return(false);
            }

            bool failures          = false;
            bool modifiedHierarchy = false;

            if (HaveExtrusion)
            {
                UpdateBrushOperation();

                if (generatedGameObjects != null && generatedGameObjects.Length > 0)
                {
                    for (int i = generatedGameObjects.Length - 1; i >= 0; i--)
                    {
                        if (generatedGameObjects[i])
                        {
                            continue;
                        }
                        ArrayUtility.RemoveAt(ref generatedGameObjects, i);
                    }
                }
                if (generatedGameObjects == null || generatedGameObjects.Length == 0)
                {
                    Cancel();
                    return(false);
                }

                if (generatedGameObjects != null && generatedGameObjects.Length > 0)
                {
                    if (registerUndo)
                    {
                        Undo.RecordObjects(generatedGameObjects, "Extruded shape");
                    }

                    int brushIndex = 0;
                    for (int slice = 0; slice < extrusionPoints.Length - 1; slice++)
                    {
                        for (int p = 0; p < polygons.Length; p++)
                        {
                            var brush = generatedBrushes[brushIndex]; brushIndex++;

                            if (!brush || !brush.gameObject)
                            {
                                continue;
                            }

                            var direction = haveForcedDirection ? forcedDirection : buildPlane.normal;
                            var distance  = new CSGPlane(direction, extrusionPoints[slice].Position).Distance(extrusionPoints[slice + 1].Position);
                            if (float.IsInfinity(distance) || float.IsNaN(distance))
                            {
                                distance = 1.0f;
                            }

                            var poly2dToWorldMatrix = brush.transform.worldToLocalMatrix *
                                                      Matrix4x4.TRS(extrusionPoints[slice].Position, Quaternion.FromToRotation(MathConstants.upVector3, buildPlane.normal),
                                                                    Vector3.one);                                                                             // * parentModel.transform.localToWorldMatrix;


                            ControlMesh newControlMesh;
                            Shape       newShape;
                            if (!CreateControlMeshForBrushIndex(parentModel, brush, polygons[p], poly2dToWorldMatrix, distance, out newControlMesh, out newShape))
                            {
                                failures = true;
                                if (brush.gameObject.activeSelf)
                                {
                                    modifiedHierarchy = true;
                                    brush.gameObject.SetActive(false);
                                }
                                continue;
                            }

                            if (!brush.gameObject.activeSelf)
                            {
                                modifiedHierarchy = true;
                                brush.gameObject.SetActive(true);
                            }

                            brush.ControlMesh.SetDirty();
                            if (registerUndo)
                            {
                                EditorUtility.SetDirty(brush);
                            }
                        }
                    }
                }
            }
            else
            {
                if (generatedGameObjects != null)
                {
                    if (registerUndo)
                    {
                        Undo.RecordObjects(generatedGameObjects, "Extruded brush");
                    }
                    InternalCSGModelManager.skipCheckForChanges = false;
                    int brushIndex = 0;
                    for (int slice = 0; slice < extrusionPoints.Length - 1; slice++)
                    {
                        for (int p = 0; p < polygons.Length; p++)
                        {
                            if (p >= generatedBrushes.Length)
                            {
                                continue;
                            }
                            var brush = generatedBrushes[brushIndex];
                            brushIndex++;
                            brush.ControlMesh.SetDirty();
                            if (registerUndo)
                            {
                                EditorUtility.SetDirty(brush);
                            }
                        }
                    }
                    HideGenerateBrushes();
                }
            }

            try
            {
                InternalCSGModelManager.skipCheckForChanges = true;
                if (registerUndo)
                {
                    EditorUtility.SetDirty(this);
                }
                //CSGModelManager.External.SetDirty(parentModel.modelNodeID);
                InternalCSGModelManager.CheckForChanges(forceHierarchyUpdate: modifiedHierarchy);
            }
            finally
            {
                InternalCSGModelManager.skipCheckForChanges = false;
            }

            if (shapeEdges != null && smearTextures)
            {
                CSGBrush lastBrush        = null;
                int      lastSurfaceIndex = -1;
                for (int slice = 0; slice < extrusionPoints.Length - 1; slice++)
                {
                    for (int se = 0; se < shapeEdges.Length; se++)
                    {
                        var brushIndex   = shapeEdges[se].PolygonIndex + (slice * shapeEdges.Length);
                        var surfaceIndex = shapeEdges[se].EdgeIndex;

                        if (brushIndex < 0 ||
                            brushIndex >= generatedBrushes.Length ||
                            surfaceIndex == -1)
                        {
                            continue;
                        }

                        var brush = generatedBrushes[brushIndex];
                        if (brush && brush.brushNodeID != CSGNode.InvalidNodeID)
                        {
                            if (lastBrush && lastBrush.brushNodeID != CSGNode.InvalidNodeID)
                            {
                                SurfaceUtility.CopyLastMaterial(brush, surfaceIndex, false,
                                                                lastBrush, lastSurfaceIndex, false,
                                                                registerUndo = false);
                            }
                            else
                            {
                                brush.Shape.TexGens[surfaceIndex].Translation   = Vector3.zero;
                                brush.Shape.TexGens[surfaceIndex].Scale         = Vector2.one;
                                brush.Shape.TexGens[surfaceIndex].RotationAngle = 0;
                            }
                            lastBrush        = brush;
                            lastSurfaceIndex = surfaceIndex;
                        }
                    }
                }
            }
            InternalCSGModelManager.RefreshMeshes();

            return(!failures);
        }
Esempio n. 14
0
        public static void OnSurfaceFlagButtons(SelectedBrushSurface[] selectedBrushSurfaces, bool isSceneGUI = false)
        {
            var leftStyle = isSceneGUI ? EditorStyles.miniButtonLeft  : GUI.skin.button;
            //var middleStyle	= isSceneGUI ? EditorStyles.miniButtonMid   : GUI.skin.button;
            var rightStyle = isSceneGUI ? EditorStyles.miniButtonRight : GUI.skin.button;

            bool?noRender         = false;
            bool?noCollision      = false;
            bool?noCastShadows    = false;
            bool?noReceiveShadows = false;

            if (selectedBrushSurfaces.Length > 0)
            {
                for (var i = 0; i < selectedBrushSurfaces.Length; i++)
                {
                    var brush        = selectedBrushSurfaces[i].brush;
                    var surfaceIndex = selectedBrushSurfaces[i].surfaceIndex;
                    if (surfaceIndex >= brush.Shape.Surfaces.Length)
                    {
                        Debug.LogWarning("surface_index >= brush.Shape.Surfaces.Length");
                        continue;
                    }
                    var texGenIndex = brush.Shape.Surfaces[surfaceIndex].TexGenIndex;
                    if (texGenIndex >= brush.Shape.TexGens.Length)
                    {
                        Debug.LogWarning("texGen_index >= brush.Shape.TexGens.Length");
                        continue;
                    }

                    var texGenFlags             = brush.Shape.TexGenFlags[texGenIndex];
                    var surfaceNoRender         = ((texGenFlags & TexGenFlags.NoRender) == TexGenFlags.NoRender);
                    var surfaceNoCollision      = ((texGenFlags & TexGenFlags.NoCollision) == TexGenFlags.NoCollision);
                    var surfaceNoCastShadows    = ((texGenFlags & TexGenFlags.NoCastShadows) == TexGenFlags.NoCastShadows);
                    var surfaceNoReceiveShadows = ((texGenFlags & TexGenFlags.NoReceiveShadows) == TexGenFlags.NoReceiveShadows);

                    if (i == 0)
                    {
                        noRender         = surfaceNoRender;
                        noCollision      = surfaceNoCollision;
                        noCastShadows    = surfaceNoCastShadows;
                        noReceiveShadows = surfaceNoReceiveShadows;
                    }
                    else
                    {
                        if (noRender.HasValue && noRender.Value != surfaceNoRender)
                        {
                            noRender = surfaceNoRender;
                        }
                        if (noCollision.HasValue && noCollision.Value != surfaceNoCollision)
                        {
                            noCollision = surfaceNoCollision;
                        }
                        if (noCastShadows.HasValue && noCastShadows.Value != surfaceNoCastShadows)
                        {
                            noCastShadows = surfaceNoCastShadows;
                        }
                        if (noReceiveShadows.HasValue && noReceiveShadows.Value != surfaceNoReceiveShadows)
                        {
                            noReceiveShadows = surfaceNoReceiveShadows;
                        }
                    }
                }
            }

            GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty);
            {
                if (!isSceneGUI)
                {
                    GUILayout.Label(ContentShadows, SurfaceToolGUI.largeLabelWidth);
                }
                else
                {
                    GUILayout.Label(ContentShadows, EditorStyles.miniLabel, SurfaceToolGUI.smallLabelWidth);
                }

                EditorGUI.BeginChangeCheck();
                {
                    // TODO: implement support
                    EditorGUI.showMixedValue = !noReceiveShadows.HasValue;
                    noReceiveShadows         = !GUILayout.Toggle(!(noReceiveShadows ?? (noRender ?? true)), ContentReceiveShadowsSurfaces, leftStyle);
                    TooltipUtility.SetToolTip(ToolTipReceiveShadowsSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoReceiveShadows, noReceiveShadows.Value);
                }
                EditorGUI.EndDisabledGroup();
                EditorGUI.BeginChangeCheck();
                {
                    // TODO: implement support
                    EditorGUI.showMixedValue = !noCastShadows.HasValue;
                    noCastShadows            = !GUILayout.Toggle(!(noCastShadows ?? true), ContentCastShadowsSurfaces, rightStyle);
                    TooltipUtility.SetToolTip(ToolTipCastShadowsSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoCastShadows, noCastShadows.Value);
                }
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty);
            {
                EditorGUI.BeginChangeCheck();
                {
                    EditorGUI.showMixedValue = !noRender.HasValue;
                    noRender = !GUILayout.Toggle(!(noRender ?? true), ContentVisibleSurfaces, leftStyle);
                    TooltipUtility.SetToolTip(ToolTipVisibleSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoRender, noRender.Value);
                }
                EditorGUI.BeginChangeCheck();
                {
                    EditorGUI.showMixedValue = !noCollision.HasValue;
                    noCollision = !GUILayout.Toggle(!(noCollision ?? true), ContentCollisionSurfaces, rightStyle);
                    TooltipUtility.SetToolTip(ToolTipCollisionSurfaces);
                }
                if (EditorGUI.EndChangeCheck())
                {
                    SurfaceUtility.SetSurfaceTexGenFlags(selectedBrushSurfaces, TexGenFlags.NoCollision, noCollision.Value);
                }
            }
            GUILayout.EndHorizontal();
            EditorGUI.showMixedValue = false;
        }
Esempio n. 15
0
        /*
         * static void OnGUIContentsMaterialInspector(Material material, bool mixedValues)
         * {
         *      //if (materialEditor == null || prevMaterial != material)
         *      {
         *              var editor = materialEditor as Editor;
         *              Editor.CreateCachedEditor(material, typeof(MaterialEditor), ref editor);
         *              materialEditor = editor as MaterialEditor;
         *      }
         *
         *      if (materialEditor != null)
         *      {
         *              EditorGUI.showMixedValue = mixedValues;
         *              try
         *              {
         *                      materialEditor.DrawHeader();
         *                      if (materialEditor.PropertiesGUI())
         *                      {
         *                              materialEditor.PropertiesChanged();
         *                      }
         *              }
         *              catch
         *              {}
         *              EditorGUI.showMixedValue = false;
         *      }
         * }
         */

        private static void OnGUIContents(bool isSceneGUI, EditModeSurface tool)
        {
            EditModeCommonGUI.StartToolGUI();

            var selectedBrushSurfaces = (tool == null) ? new SelectedBrushSurface[0] : tool.GetSelectedSurfaces();
            var enabled = selectedBrushSurfaces.Length > 0;

            EditorGUI.BeginDisabledGroup(!enabled);
            {
                Material material      = null;
                var      currentTexGen = new TexGen();

                var  haveTexgen            = false;
                var  multipleColors        = !enabled;
                var  multipleTranslationX  = !enabled;
                var  multipleTranslationY  = !enabled;
                var  multipleScaleX        = !enabled;
                var  multipleScaleY        = !enabled;
                var  multipleRotationAngle = !enabled;
                var  multipleMaterials     = !enabled;
                bool?textureLocked         = null;

                bool foundHelperMaterial = false;
                RenderSurfaceType?firstRenderSurfaceType = null;
                Material          firstMaterial          = null;
                if (selectedBrushSurfaces.Length > 0)
                {
                    for (var i = 0; i < selectedBrushSurfaces.Length; i++)
                    {
                        var brush = selectedBrushSurfaces[i].brush;
                        if (!brush)
                        {
                            continue;
                        }
                        var surfaceIndex = selectedBrushSurfaces[i].surfaceIndex;
                        if (surfaceIndex >= brush.Shape.Surfaces.Length)
                        {
                            Debug.LogWarning("surface_index >= brush.Shape.Surfaces.Length");
                            continue;
                        }
                        var texGenIndex = brush.Shape.Surfaces[surfaceIndex].TexGenIndex;
                        if (texGenIndex >= brush.Shape.TexGens.Length)
                        {
                            Debug.LogWarning("texGen_index >= brush.Shape.TexGens.Length");
                            continue;
                        }
                        var      brushCache = InternalCSGModelManager.GetBrushCache(brush);
                        var      model      = (brushCache != null) ? brushCache.childData.Model : null;
                        Material foundMaterial;
                        var      texGenFlags = brush.Shape.TexGenFlags[texGenIndex];
                        if (model && (!model.IsRenderable || model.ShadowsOnly))
                        {
                            foundHelperMaterial = true;
                            if (!firstRenderSurfaceType.HasValue)
                            {
                                firstRenderSurfaceType = ModelTraits.GetModelSurfaceType(model);
                            }
                            foundMaterial = null;
                        }
                        else
                        if ((texGenFlags & TexGenFlags.NoRender) == TexGenFlags.NoRender)
                        {
                            foundHelperMaterial = true;
                            if (!firstRenderSurfaceType.HasValue)
                            {
                                if ((texGenFlags & TexGenFlags.NoCastShadows) != TexGenFlags.NoCastShadows)
                                {
                                    firstRenderSurfaceType = RenderSurfaceType.ShadowOnly;
                                }
                                else
                                if ((texGenFlags & TexGenFlags.NoCollision) != TexGenFlags.NoCollision)
                                {
                                    firstRenderSurfaceType = RenderSurfaceType.Collider;
                                }
                                else
                                {
                                    firstRenderSurfaceType = RenderSurfaceType.Hidden;
                                }
                            }
                            foundMaterial = null;
                        }
                        else
                        {
                            var surfaceMaterial = brush.Shape.TexGens[texGenIndex].RenderMaterial;
                            if (!foundHelperMaterial)
                            {
                                var surfaceType = MaterialUtility.GetMaterialSurfaceType(surfaceMaterial);
                                if (!firstRenderSurfaceType.HasValue)
                                {
                                    firstRenderSurfaceType = surfaceType;
                                }
                                foundHelperMaterial = surfaceType != RenderSurfaceType.Normal;
                            }
                            foundMaterial = surfaceMaterial;
                        }
                        if ((texGenFlags & TexGenFlags.WorldSpaceTexture) == TexGenFlags.WorldSpaceTexture)
                        {
                            if (i == 0)
                            {
                                textureLocked = false;
                            }
                            else if (textureLocked.HasValue && textureLocked.Value)
                            {
                                textureLocked = null;
                            }
                        }
                        else
                        {
                            if (i == 0)
                            {
                                textureLocked = true;
                            }
                            else if (textureLocked.HasValue && !textureLocked.Value)
                            {
                                textureLocked = null;
                            }
                        }
                        if (foundMaterial != material)
                        {
                            if (!material)
                            {
                                firstMaterial = foundMaterial;
                                material      = foundMaterial;
                            }
                            else
                            {
                                multipleMaterials = true;
                            }
                        }
                        if (!haveTexgen)
                        {
                            currentTexGen = brush.Shape.TexGens[texGenIndex];
                            haveTexgen    = true;
                        }
                        else
                        {
                            if (!multipleColors)
                            {
                                var color = brush.Shape.TexGens[texGenIndex].Color;
                                multipleColors = currentTexGen.Color.a != color.a ||
                                                 currentTexGen.Color.b != color.b ||
                                                 currentTexGen.Color.g != color.g ||
                                                 currentTexGen.Color.r != color.r;
                            }
                            if (!multipleScaleX || !multipleScaleY)
                            {
                                var scale = brush.Shape.TexGens[texGenIndex].Scale;
                                multipleScaleX = multipleScaleX || currentTexGen.Scale.x != scale.x;
                                multipleScaleY = multipleScaleY || currentTexGen.Scale.y != scale.y;
                            }

                            if (!multipleTranslationX || !multipleTranslationY)
                            {
                                var translation = brush.Shape.TexGens[texGenIndex].Translation;
                                multipleTranslationX = multipleTranslationX || currentTexGen.Translation.x != translation.x;
                                multipleTranslationY = multipleTranslationY || currentTexGen.Translation.y != translation.y;
                            }

                            if (!multipleRotationAngle)
                            {
                                var rotationAngle = brush.Shape.TexGens[texGenIndex].RotationAngle;
                                multipleRotationAngle = currentTexGen.RotationAngle != rotationAngle;
                            }
                        }
                    }
                    if (foundHelperMaterial && !firstMaterial)
                    {
                        if (firstRenderSurfaceType.HasValue)
                        {
                            firstMaterial = MaterialUtility.GetSurfaceMaterial(firstRenderSurfaceType.Value);
                        }
                        else
                        {
                            firstMaterial = MaterialUtility.HiddenMaterial;
                        }
                    }
                }

                GUILayout.BeginVertical(isSceneGUI ? materialDoubleWidth : CSG_GUIStyleUtility.ContentEmpty);
                {
                    GUILayout.BeginVertical(isSceneGUI ? GUI.skin.box : GUIStyle.none);
                    {
                        /*
                         * Color new_color;
                         * EditorGUI.BeginChangeCheck();
                         * {
                         *      EditorGUI.showMixedValue = multipleColors;
                         *      // why doesn't the colorfield return a modified color?
                         *      try
                         *      {
                         *              new_color = EditorGUILayout.ColorField(GUIContent.none, currentTexGen.Color);
                         *      }
                         *      catch
                         *      {
                         *              new_color = currentTexGen.Color;
                         *      }
                         * }
                         * if (EditorGUI.EndChangeCheck() || currentTexGen.Color != new_color)
                         * {
                         *      SurfaceUtility.SetColors(selectedBrushSurfaces, new_color);
                         * }
                         */
                        if (isSceneGUI)
                        {
                            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                EditorGUI.BeginDisabledGroup(material == null);
                                {
                                    GUILayout.BeginVertical(CSG_GUIStyleUtility.ContentEmpty);
                                    {
                                        GUILayout.Space(1);

                                        /*
                                         * Color new_color;
                                         * EditorGUI.BeginChangeCheck();
                                         * {
                                         *      EditorGUI.showMixedValue = multipleColors;
                                         *      // why doesn't the colorfield return a modified color?
                                         *      try
                                         *      {
                                         *              new_color = EditorGUILayout.ColorField(GUIContent.none, currentTexGen.Color);
                                         *      }
                                         *      catch
                                         *      {
                                         *              new_color = currentTexGen.Color;
                                         *      }
                                         * }
                                         * if (EditorGUI.EndChangeCheck() || currentTexGen.Color != new_color)
                                         * {
                                         *      SurfaceUtility.SetColors(selectedBrushSurfaces, new_color);
                                         * }
                                         *
                                         * GUILayout.Space(1);
                                         */
                                        Material newMaterial;
                                        EditorGUI.BeginChangeCheck();
                                        {
                                            EditorGUI.showMixedValue = multipleMaterials;
                                            newMaterial = EditorGUILayout.ObjectField(material, typeof(Material), true) as Material;
                                            EditorGUI.showMixedValue = false;
                                        }
                                        if (EditorGUI.EndChangeCheck())
                                        {
                                            if (newMaterial)
                                            {
                                                SurfaceUtility.SetMaterials(selectedBrushSurfaces, newMaterial);
                                                CSGSettings.DefaultMaterial = newMaterial;
                                                CSGSettings.Save();
                                            }
                                        }
                                    }
                                    GUILayout.EndVertical();
                                    GUILayout.Space(1);
                                }
                                EditorGUI.EndDisabledGroup();
                            }
                            GUILayout.EndHorizontal();
                            GUILayout.Space(4);
                            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                GUILayout.Space(2);
                                OnGUIContentsMaterialImage(isSceneGUI, firstMaterial, multipleMaterials, selectedBrushSurfaces);
                                GUILayout.BeginHorizontal(materialWidth);
                                {
                                    GUILayout.FlexibleSpace();
                                    GUILayout.BeginVertical(materialHeight);
                                    {
                                        OnGUIContentsJustify(isSceneGUI, selectedBrushSurfaces);
                                        GUILayout.FlexibleSpace();
                                    }
                                    GUILayout.EndVertical();
                                }
                                GUILayout.EndHorizontal();
                                GUILayout.FlexibleSpace();
                            }
                            GUILayout.EndHorizontal();
                        }
                    }
                    GUILayout.EndVertical();

                    if (!isSceneGUI)
                    {
                        EditorGUILayout.Space();
                    }

                    if (currentTexGen.Scale.x == 0.0f)
                    {
                        currentTexGen.Scale.x = 1.0f;
                    }
                    if (currentTexGen.Scale.y == 0.0f)
                    {
                        currentTexGen.Scale.y = 1.0f;
                    }

                    const float scale_round = 10000.0f;
                    currentTexGen.Scale.x       = Mathf.RoundToInt(currentTexGen.Scale.x * scale_round) / scale_round;
                    currentTexGen.Scale.y       = Mathf.RoundToInt(currentTexGen.Scale.y * scale_round) / scale_round;
                    currentTexGen.Translation.x = Mathf.RoundToInt(currentTexGen.Translation.x * scale_round) / scale_round;
                    currentTexGen.Translation.y = Mathf.RoundToInt(currentTexGen.Translation.y * scale_round) / scale_round;
                    currentTexGen.RotationAngle = Mathf.RoundToInt(currentTexGen.RotationAngle * scale_round) / scale_round;

                    var leftStyle   = isSceneGUI ? EditorStyles.miniButtonLeft  : GUI.skin.button;
                    var middleStyle = isSceneGUI ? EditorStyles.miniButtonMid   : GUI.skin.button;
                    var rightStyle  = isSceneGUI ? EditorStyles.miniButtonRight : GUI.skin.button;

                    GUILayout.BeginVertical(isSceneGUI ? GUI.skin.box : GUIStyle.none);
                    {
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = !textureLocked.HasValue;
                            textureLocked            = EditorGUILayout.ToggleLeft(ContentLockTexture, textureLocked.HasValue ? textureLocked.Value : false);
                            TooltipUtility.SetToolTip(ToolTipLockTexture);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            SurfaceUtility.SetTextureLock(selectedBrushSurfaces, textureLocked.Value);
                        }
                    }
                    GUILayout.EndVertical();

                    GUILayout.BeginVertical(isSceneGUI ? GUI.skin.box : GUIStyle.none);
                    {
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            if (isSceneGUI)
                            {
                                EditorGUILayout.LabelField(ContentUVScale, EditorStyles.miniLabel, labelWidth);
                            }
                            else
                            {
                                EditorGUILayout.LabelField(ContentUVScale, largeLabelWidth);
                            }
                            TooltipUtility.SetToolTip(ToolTipScaleUV);

                            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                if (!isSceneGUI)
                                {
                                    EditorGUILayout.LabelField(ContentUSymbol, unitWidth);
                                }
                                EditorGUI.BeginChangeCheck();
                                {
                                    EditorGUI.showMixedValue = multipleScaleX;
                                    currentTexGen.Scale.x    = EditorGUILayout.FloatField(currentTexGen.Scale.x, minFloatFieldWidth);
                                }
                                if (EditorGUI.EndChangeCheck())
                                {
                                    SurfaceUtility.SetScaleX(selectedBrushSurfaces, currentTexGen.Scale.x);
                                }
                                if (!isSceneGUI)
                                {
                                    EditorGUILayout.LabelField(ContentVSymbol, unitWidth);
                                }
                                EditorGUI.BeginChangeCheck();
                                {
                                    EditorGUI.showMixedValue = multipleScaleY;
                                    currentTexGen.Scale.y    = EditorGUILayout.FloatField(currentTexGen.Scale.y, minFloatFieldWidth);
                                }
                                if (EditorGUI.EndChangeCheck())
                                {
                                    SurfaceUtility.SetScaleY(selectedBrushSurfaces, currentTexGen.Scale.y);
                                }
                            }
                            GUILayout.EndHorizontal();
                        }
                        GUILayout.EndHorizontal();
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            if (isSceneGUI)
                            {
                                EditorGUILayout.LabelField(ContentOffset, EditorStyles.miniLabel, labelWidth);
                            }
                            else
                            {
                                EditorGUILayout.LabelField(ContentOffset, largeLabelWidth);
                            }
                            TooltipUtility.SetToolTip(ToolTipOffsetUV);

                            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                if (!isSceneGUI)
                                {
                                    EditorGUILayout.LabelField(ContentUSymbol, unitWidth);
                                }
                                EditorGUI.BeginChangeCheck();
                                {
                                    EditorGUI.showMixedValue    = multipleTranslationX;
                                    currentTexGen.Translation.x = EditorGUILayout.FloatField(currentTexGen.Translation.x, minFloatFieldWidth);
                                }
                                if (EditorGUI.EndChangeCheck())
                                {
                                    SurfaceUtility.SetTranslationX(selectedBrushSurfaces, currentTexGen.Translation.x);
                                }

                                if (!isSceneGUI)
                                {
                                    EditorGUILayout.LabelField(ContentVSymbol, unitWidth);
                                }
                                EditorGUI.BeginChangeCheck();
                                {
                                    EditorGUI.showMixedValue    = multipleTranslationY;
                                    currentTexGen.Translation.y = EditorGUILayout.FloatField(currentTexGen.Translation.y, minFloatFieldWidth);
                                }
                                if (EditorGUI.EndChangeCheck())
                                {
                                    SurfaceUtility.SetTranslationY(selectedBrushSurfaces, currentTexGen.Translation.y);
                                }
                            }
                            GUILayout.EndHorizontal();
                        }
                        GUILayout.EndHorizontal();
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            if (isSceneGUI)
                            {
                                EditorGUILayout.LabelField(ContentRotate, EditorStyles.miniLabel, labelWidth);
                            }
                            else
                            {
                                EditorGUILayout.LabelField(ContentRotate, largeLabelWidth);
                            }
                            TooltipUtility.SetToolTip(ToolTipRotation);

                            if (!isSceneGUI)
                            {
                                GUILayout.BeginVertical(CSG_GUIStyleUtility.ContentEmpty);
                            }

                            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                EditorGUI.BeginChangeCheck();
                                {
                                    EditorGUI.showMixedValue    = multipleRotationAngle;
                                    currentTexGen.RotationAngle = EditorGUILayout.FloatField(currentTexGen.RotationAngle, minFloatFieldWidth);
                                    if (!isSceneGUI)
                                    {
                                        EditorGUILayout.LabelField(ContentAngleSymbol, unitWidth);
                                    }
                                }
                                if (EditorGUI.EndChangeCheck())
                                {
                                    SurfaceUtility.SetRotationAngle(selectedBrushSurfaces, currentTexGen.RotationAngle);
                                }
                            }
                            GUILayout.EndHorizontal();

                            var buttonWidth = isSceneGUI ? new GUILayoutOption[] { angleButtonWidth } : new GUILayoutOption[0];
                            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                if (GUILayout.Button(ContentRotate90Negative, leftStyle, buttonWidth))
                                {
                                    SurfaceUtility.AddRotationAngle(selectedBrushSurfaces, -90.0f);
                                }
                                TooltipUtility.SetToolTip(ToolTipRotate90Negative);
                                if (GUILayout.Button(ContentRotate90Positive, rightStyle, buttonWidth))
                                {
                                    SurfaceUtility.AddRotationAngle(selectedBrushSurfaces, +90.0f);
                                }
                                TooltipUtility.SetToolTip(ToolTipRotate90Positive);
                            }
                            GUILayout.EndHorizontal();
                            if (!isSceneGUI)
                            {
                                GUILayout.EndVertical();
                            }
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndVertical();

                    if (!isSceneGUI)
                    {
                        EditorGUILayout.Space();
                    }

                    GUILayout.BeginVertical(isSceneGUI ? GUI.skin.box : GUIStyle.none);
                    {
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            if (!isSceneGUI)
                            {
                                GUILayout.Label(ContentFit, largeLabelWidth);
                            }
                            else
                            {
                                GUILayout.Label(ContentFit, EditorStyles.miniLabel, smallLabelWidth);
                            }
                            if (GUILayout.Button(ContentFitX, leftStyle))
                            {
                                SurfaceUtility.FitSurfaceX(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipFitX);
                            if (GUILayout.Button(ContentFitXY, middleStyle))
                            {
                                SurfaceUtility.FitSurface(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipFitXY);
                            if (GUILayout.Button(ContentFitY, rightStyle))
                            {
                                SurfaceUtility.FitSurfaceY(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipFitY);
                        }
                        GUILayout.EndHorizontal();
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            if (!isSceneGUI)
                            {
                                GUILayout.Label(ContentReset, largeLabelWidth);
                            }
                            else
                            {
                                GUILayout.Label(ContentReset, EditorStyles.miniLabel, smallLabelWidth);
                            }
                            if (GUILayout.Button(ContentResetX, leftStyle))
                            {
                                SurfaceUtility.ResetSurfaceX(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipResetX);
                            if (GUILayout.Button(ContentResetXY, middleStyle))
                            {
                                SurfaceUtility.ResetSurface(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipResetXY);
                            if (GUILayout.Button(ContentResetY, rightStyle))
                            {
                                SurfaceUtility.ResetSurfaceY(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipResetY);
                        }
                        GUILayout.EndHorizontal();
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            if (!isSceneGUI)
                            {
                                GUILayout.Label(ContentFlip, largeLabelWidth);
                            }
                            else
                            {
                                GUILayout.Label(ContentFlip, EditorStyles.miniLabel, smallLabelWidth);
                            }
                            if (GUILayout.Button(ContentFlipX, leftStyle))
                            {
                                SurfaceUtility.FlipX(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipFlipX);
                            if (GUILayout.Button(ContentFlipXY, middleStyle))
                            {
                                SurfaceUtility.FlipXY(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipFlipXY);
                            if (GUILayout.Button(ContentFlipY, rightStyle))
                            {
                                SurfaceUtility.FlipY(selectedBrushSurfaces);
                            }
                            TooltipUtility.SetToolTip(ToolTipFlipY);
                        }
                        GUILayout.EndHorizontal();
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            if (!isSceneGUI)
                            {
                                GUILayout.Label(ContentScale, largeLabelWidth);
                            }
                            else
                            {
                                GUILayout.Label(ContentScale, EditorStyles.miniLabel, smallLabelWidth);
                            }
                            if (GUILayout.Button(ContentDoubleScale, leftStyle))
                            {
                                SurfaceUtility.MultiplyScale(selectedBrushSurfaces, 2.0f);
                            }
                            TooltipUtility.SetToolTip(ToolTipDoubleScale);
                            if (GUILayout.Button(ContentHalfScale, rightStyle))
                            {
                                SurfaceUtility.MultiplyScale(selectedBrushSurfaces, 0.5f);
                            }
                            TooltipUtility.SetToolTip(ToolTipHalfScale);
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndVertical();

                    if (!isSceneGUI)
                    {
                        EditorGUILayout.Space();
                    }

                    if (!isSceneGUI)
                    {
                        OnGUIContentsJustify(isSceneGUI, selectedBrushSurfaces);
                    }

                    if (!isSceneGUI)
                    {
                        EditorGUILayout.Space();
                    }

                    GUILayout.BeginVertical(isSceneGUI ? GUI.skin.box : GUIStyle.none);
                    {
                        EditModeCommonGUI.OnSurfaceFlagButtons(selectedBrushSurfaces, isSceneGUI);
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            EditorGUI.BeginDisabledGroup(!SurfaceUtility.CanSmooth(selectedBrushSurfaces));
                            {
                                if (GUILayout.Button(ContentSmoothSurfaces, leftStyle))
                                {
                                    SurfaceUtility.Smooth(selectedBrushSurfaces);
                                }
                                TooltipUtility.SetToolTip(ToolTipSmoothSurfaces);
                            }
                            EditorGUI.EndDisabledGroup();
                            EditorGUI.BeginDisabledGroup(!SurfaceUtility.CanUnSmooth(selectedBrushSurfaces));
                            {
                                if (GUILayout.Button(ContentUnSmoothSurfaces, rightStyle))
                                {
                                    SurfaceUtility.UnSmooth(selectedBrushSurfaces);
                                }
                                TooltipUtility.SetToolTip(ToolTipUnSmoothSurfaces);
                            }
                            EditorGUI.EndDisabledGroup();
                        }
                        GUILayout.EndHorizontal();
                    }
                    GUILayout.EndVertical();

                    if (!isSceneGUI)
                    {
                        EditorGUILayout.Space();
                        Material new_material;
                        GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                        {
                            EditorGUILayout.LabelField(ContentMaterial, largeLabelWidth);
                            GUILayout.BeginVertical(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                EditorGUI.BeginChangeCheck();
                                {
                                    EditorGUI.showMixedValue = multipleMaterials;
                                    new_material             = EditorGUILayout.ObjectField(material, typeof(Material), true) as Material;
                                    EditorGUI.showMixedValue = false;
                                }
                                if (EditorGUI.EndChangeCheck())
                                {
                                    if (!new_material)
                                    {
                                        new_material = MaterialUtility.MissingMaterial;
                                    }
                                    SurfaceUtility.SetMaterials(selectedBrushSurfaces, new_material);
                                }
                            }
                            GUILayout.Space(2);
                            GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                            {
                                GUILayout.Space(5);
                                OnGUIContentsMaterialImage(isSceneGUI, firstMaterial, multipleMaterials, selectedBrushSurfaces);
                            }
                            GUILayout.EndHorizontal();
                            GUILayout.EndVertical();
                        }
                        GUILayout.EndHorizontal();
                        // Unity won't let us do this
                        //GUILayout.BeginVertical(GUIStyleUtility.ContentEmpty);
                        //OnGUIContentsMaterialInspector(first_material, multiple_materials);
                        //GUILayout.EndVertical();
                    }
                }
                GUILayout.EndVertical();
            }
            EditorGUI.EndDisabledGroup();
            EditorGUI.showMixedValue = false;
        }
        /// <summary>Generate a <see cref="RealtimeCSG.Legacy.ControlMesh"/>/<see cref="RealtimeCSG.Legacy.Shape"/> pair from the given planes (and optional other values)</summary>
        /// <remarks><note>Keep in mind that the planes encapsulate the geometry we're generating, so it can only be <i>convex</i>.</note></remarks>
        /// <param name="controlMesh">The generated <see cref="RealtimeCSG.Legacy.ControlMesh"/></param>
        /// <param name="shape">The generated <see cref="RealtimeCSG.Legacy.Shape"/></param>
        /// <param name="planes">The geometric planes of all the surfaces that define this convex shape</param>
        /// <param name="tangents">The tangents for each plane (optional)</param>
        /// <param name="binormals">The binormals for each plane (optional)</param>
        /// <param name="materials">The materials for each plane (optional)</param>
        /// <param name="textureMatrices">The texture matrices for each plane (optional)</param>
        /// <param name="textureMatrixSpace">The texture matrix space for each plane (optional)</param>
        /// <param name="smoothingGroups">The smoothing groups for each plane (optional)</param>
        /// <param name="texGenFlags">The <see cref="RealtimeCSG.Legacy.TexGenFlags"/> for each plane (optional)</param>
        /// <returns>*true* on success, *false* on failure</returns>
        public static bool CreateControlMeshFromPlanes(out ControlMesh controlMesh,
                                                       out Shape shape,
                                                       UnityEngine.Plane[]              planes,
                                                       UnityEngine.Vector3[]    tangents        = null,
                                                       UnityEngine.Vector3[]    binormals       = null,
                                                       UnityEngine.Material[]   materials       = null,
                                                       UnityEngine.Matrix4x4[]  textureMatrices = null,
                                                       TextureMatrixSpace textureMatrixSpace    = TextureMatrixSpace.WorldSpace,
                                                       uint[]                                   smoothingGroups = null,
                                                       TexGenFlags[]                    texGenFlags             = null)
        {
            controlMesh = null;
            shape       = null;
            if (planes == null)
            {
                Debug.LogError("The planes array is not allowed to be null");
                return(false);
            }
            if (planes.Length < 4)
            {
                Debug.LogError("The planes array must have at least 4 planes");
                return(false);
            }
            if (materials == null)
            {
                materials = new Material[planes.Length];
                for (int i = 0; i < materials.Length; i++)
                {
                    materials[i] = CSGSettings.DefaultMaterial;
                }
            }
            if (planes.Length != materials.Length ||
                (textureMatrices != null && planes.Length != textureMatrices.Length) ||
                (tangents != null && tangents.Length != textureMatrices.Length) ||
                (binormals != null && binormals.Length != textureMatrices.Length) ||
                (smoothingGroups != null && smoothingGroups.Length != materials.Length))
            {
                Debug.LogError("All non null arrays need to be of equal length");
                return(false);
            }

            shape             = new Shape();
            shape.TexGenFlags = new TexGenFlags[planes.Length];
            shape.Surfaces    = new Surface[planes.Length];
            shape.TexGens     = new TexGen[planes.Length];
            for (int i = 0; i < planes.Length; i++)
            {
                shape.Surfaces[i].Plane = new CSGPlane(planes[i].normal, -planes[i].distance);

                Vector3 tangent, binormal;
                if (tangents != null && binormals != null)
                {
                    tangent  = tangents[i];
                    binormal = binormals[i];
                }
                else
                {
                    GeometryUtility.CalculateTangents(planes[i].normal, out tangent, out binormal);
                }

                shape.Surfaces[i].Tangent     = -tangent;
                shape.Surfaces[i].BiNormal    = -binormal;
                shape.Surfaces[i].TexGenIndex = i;
                shape.TexGens[i] = new TexGen(materials[i]);
                if (smoothingGroups != null)
                {
                    shape.TexGens[i].SmoothingGroup = smoothingGroups[i];
                }
                if (texGenFlags != null)
                {
                    shape.TexGenFlags[i] = texGenFlags[i];
                }
                else
                {
                    shape.TexGenFlags[i] = RealtimeCSG.CSGSettings.DefaultTexGenFlags;
                }
            }

            controlMesh = ControlMeshUtility.CreateFromShape(shape, MathConstants.DistanceEpsilon);
            if (controlMesh == null)
            {
                return(false);
            }

            if (!ControlMeshUtility.Validate(controlMesh, shape))
            {
                //Debug.LogError("Generated mesh is not valid");
                return(false);
            }

            if (textureMatrices != null)
            {
                int n = 0;
                for (var i = 0; i < planes.Length; i++)
                {
                    if (shape.Surfaces[n].TexGenIndex != i)
                    {
                        continue;
                    }
                    shape.Surfaces[n].TexGenIndex = n;
                    SurfaceUtility.AlignTextureSpaces(textureMatrices[i], textureMatrixSpace == TextureMatrixSpace.PlaneSpace, ref shape.TexGens[n], ref shape.TexGenFlags[n], ref shape.Surfaces[n]);
                    n++;
                }
            }
            return(true);
        }
Esempio n. 17
0
        private bool GenerateStairs(CSGBrush[] stepBrushes, int totalSteps, float stepLength, float stepHeight, float stepDepth, float stairsDepth, float stairsWidth, float stairsHeight, float extraDepth, float extraHeight, StairsBottom stairsBottom)
        {
            //var currentModel = parentModel ? parentModel : SelectionUtility.LastUsedModel;
            //var modelRotation = Quaternion.Inverse(currentModel.transform.rotation);

            stairsDepth = Math.Max(0, stairsDepth);

            bool success = true;

            for (int stepIndex = 0; stepIndex < totalSteps; stepIndex++)
            {
                var brush = stepBrushes[stepIndex];
                if (!brush)
                {
                    continue;
                }

                float   curStepDepth;
                float   curStepHeight;
                float   curStepY;
                Vector3 extraLength;
                Vector3 lengthPos;

                switch (stairsBottom)
                {
                default:
                case StairsBottom.Filled:
                {
                    curStepHeight = Mathf.Min(stairsHeight, (stepIndex == 0) ? (extraHeight + stepHeight) : stepHeight);
                    curStepY      = (stepIndex == 0) ? (stepHeight * stepIndex) : (extraHeight + (stepHeight * stepIndex));
                    extraLength   = lengthDirection * (stepLength * stepIndex);
                    curStepDepth  = stairsDepth;
                    lengthPos     = Vector3.zero;
                    break;
                }

                case StairsBottom.Steps:
                {
                    curStepHeight = stepHeight;
                    curStepY      = extraHeight + (stepHeight * stepIndex);
                    extraLength   = Vector3.zero;
                    curStepDepth  = (stepIndex == totalSteps - 1) ? (stepDepth + extraDepth) : stepDepth;
                    lengthPos     = (stepIndex == totalSteps - 1) ? Vector3.zero : (lengthDirection * Mathf.Max(0, ((totalSteps - (stepIndex + 1)) * stepDepth) + extraDepth));
                    break;
                }
                }

                var heightPos = heightDirection * curStepY;

                var widthSize  = (widthDirection * stairsWidth);
                var lengthSize = (lengthDirection * curStepDepth) - extraLength;
                var heightSize = (heightDirection * curStepHeight);

                var size     = widthSize + heightSize + lengthSize;
                var position = (totalSteps == 1) ? (heightPos + lengthPos + brushPosition) : (heightPos + lengthPos);

                ControlMesh newControlMesh;
                Shape       newShape;
                if (!BrushFactory.CreateCubeControlMesh(out newControlMesh, out newShape, Vector3.zero, size))
                {
                    success = false;
                    if (brush.gameObject.activeSelf)
                    {
                        brush.gameObject.SetActive(false);
                    }
                    continue;
                }

                if (!brush.gameObject.activeSelf)
                {
                    brush.gameObject.SetActive(true);
                }

                brush.Shape       = newShape;
                brush.ControlMesh = newControlMesh;
                if (totalSteps != 1)
                {
                    brush.transform.localPosition = position;
                }
                //brush.transform.localRotation = Quaternion.identity;
                SurfaceUtility.TranslateSurfacesInWorldSpace(brush, -position);
            }
            return(success);
        }
Esempio n. 18
0
        public static void OnSurfaceFlagButtons(SelectedBrushSurface[] selectedBrushSurfaces, bool isSceneGUI = false)
        {
            var leftStyle   = isSceneGUI ? EditorStyles.miniButtonLeft  : GUI.skin.button;
            var middleStyle = isSceneGUI ? EditorStyles.miniButtonMid   : GUI.skin.button;
            var rightStyle  = isSceneGUI ? EditorStyles.miniButtonRight : GUI.skin.button;

            var canDiscard        = false;
            var canMakeShadowOnly = false;
            var canMakeVisible    = false;

            if (selectedBrushSurfaces.Length > 0)
            {
                for (var i = 0; i < selectedBrushSurfaces.Length; i++)
                {
                    var brush        = selectedBrushSurfaces[i].brush;
                    var surfaceIndex = selectedBrushSurfaces[i].surfaceIndex;
                    if (surfaceIndex >= brush.Shape.Surfaces.Length)
                    {
                        Debug.Log("surface_index >= brush.Shape.Surfaces.Length");
                        continue;
                    }
                    var texGenIndex = brush.Shape.Surfaces[surfaceIndex].TexGenIndex;
                    if (texGenIndex >= brush.Shape.TexGens.Length)
                    {
                        Debug.Log("texGen_index >= brush.Shape.TexGens.Length");
                        continue;
                    }

                    var texGenFlags = brush.Shape.TexGenFlags[texGenIndex];
                    if ((texGenFlags & TexGenFlags.Discarded) == TexGenFlags.Discarded)
                    {
                        canMakeVisible    = true;
                        canMakeShadowOnly = true;
                    }
                    else
                    if ((texGenFlags & TexGenFlags.ShadowOnly) == TexGenFlags.ShadowOnly)
                    {
                        canDiscard     = true;
                        canMakeVisible = true;
                    }
                    else
                    {
                        canDiscard        = true;
                        canMakeShadowOnly = true;
                    }
                }
            }


            GUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty);
            {
                EditorGUI.BeginDisabledGroup(!canDiscard);
                {
                    if (GUILayout.Button(ContentDiscardSurfaces, leftStyle))
                    {
                        SurfaceUtility.DiscardSurfaces(selectedBrushSurfaces);
                    }
                    TooltipUtility.SetToolTip(ToolTipDiscardSurfaces);
                }
                EditorGUI.EndDisabledGroup();
                EditorGUI.BeginDisabledGroup(!canMakeShadowOnly);
                {
                    if (GUILayout.Button(ContentShadowOnlySurfaces, middleStyle))
                    {
                        SurfaceUtility.MakeSurfacesShadowOnly(selectedBrushSurfaces);
                    }
                    TooltipUtility.SetToolTip(ToolTipShadowOnlySurfaces);
                }
                EditorGUI.EndDisabledGroup();
                EditorGUI.BeginDisabledGroup(!canMakeVisible);
                {
                    if (GUILayout.Button(ContentVisibleSurfaces, rightStyle))
                    {
                        SurfaceUtility.MakeSurfacesVisible(selectedBrushSurfaces);
                    }
                    TooltipUtility.SetToolTip(ToolTipVisibleSurfaces);
                }
                EditorGUI.EndDisabledGroup();
            }
            GUILayout.EndHorizontal();
        }
Esempio n. 19
0
        /*
         * public static bool ContinueTexGenFromSurfaceToSurface(CSGBrush srcBrush, int srcSurfaceIndex, CSGBrush dstBrush, int dstSurfaceIndex)
         * {
         *  if (srcSurfaceIndex < 0 || srcSurfaceIndex >= srcBrush.Shape.Materials.Length ||
         *      srcBrush == null)
         *      return false;
         *
         *  var src_brush_cache = CSGModelManager.GetBrushCache(srcBrush);
         *  if (src_brush_cache == null ||
         *      src_brush_cache.childData == null ||
         *      src_brush_cache.childData.modelTransform == null)
         *      return false;
         *
         *  var dst_brush_cache = CSGModelManager.GetBrushCache(dstBrush);
         *  if (dst_brush_cache == null ||
         *      dst_brush_cache.childData == null ||
         *      dst_brush_cache.childData.modelTransform == null)
         *      return false;
         *
         *  var dstPlane	= dstBrush.Shape.Surfaces[dstSurfaceIndex].Plane;
         *  var srcPlane	= srcBrush.Shape.Surfaces[srcSurfaceIndex].Plane;
         *
         *  // convert planes into worldspace
         *  dstPlane = GeometryUtility.InverseTransformPlane(dstBrush.transform.worldToLocalMatrix, dstPlane);
         *  srcPlane = GeometryUtility.InverseTransformPlane(srcBrush.transform.worldToLocalMatrix, srcPlane);
         *
         *  var dstNormal	= dstPlane.normal;
         *  var srcNormal	= srcPlane.normal;
         *
         *  var srcTexGenIndex = srcBrush.Shape.Surfaces[srcSurfaceIndex].TexGenIndex;
         *  var dstTexGenIndex = dstBrush.Shape.Surfaces[dstSurfaceIndex].TexGenIndex;
         *
         *  var scrShape = srcBrush.Shape;
         *
         *  dstBrush.Shape.Materials[dstSurfaceIndex] = scrShape.Materials[srcSurfaceIndex];
         *  Vector3 srcPoint1, srcPoint2;
         *  Vector3 dstPoint1, dstPoint2;
         *  var edgeDirection = Vector3.Cross(dstNormal, srcNormal);
         *  var det = edgeDirection.sqrMagnitude;
         *  if (det < Constants.AlignmentTestEpsilon)
         *  {
         *      // Find 2 points on intersection of 2 planes
         *      srcPoint1 = srcPlane.pointOnPlane;
         *      srcPoint2 = GeometryUtility.ProjectPointOnPlane(srcPlane, srcPoint1 + MathConstants.oneVector3);
         *
         *      dstPoint1 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint1);
         *      dstPoint2 = GeometryUtility.ProjectPointOnPlane(dstPlane, srcPoint2);
         *  } else
         *  {
         *      // Find 2 points on intersection of 2 planes
         *      srcPoint1 = ((Vector3.Cross(edgeDirection, srcNormal) * -dstPlane.d) +
         *                      (Vector3.Cross(dstNormal, edgeDirection) * -srcPlane.d)) / det;
         *      srcPoint2 = srcPoint1 + edgeDirection;
         *      dstPoint1 = srcPoint1;
         *      dstPoint2 = srcPoint2;
         *  }
         *
         *  Vector3 srcLocalPoint1 = srcBrush.transform.InverseTransformPoint(srcPoint1);
         *  Vector3 srcLocalPoint2 = srcBrush.transform.InverseTransformPoint(srcPoint2);
         *
         *  Vector3 dstLocalPoint1 = dstBrush.transform.InverseTransformPoint(dstPoint1);
         *  Vector3 dstLocalPoint2 = dstBrush.transform.InverseTransformPoint(dstPoint2);
         *
         *  var srcShape	= srcBrush.Shape;
         *  var srcTexGens	= srcShape.TexGens;
         *  var srcSurfaces	= srcShape.Surfaces;
         *  var dstShape	= dstBrush.Shape;
         *  var dstTexGens	= dstShape.TexGens;
         *  var dstSurfaces	= dstShape.Surfaces;
         *
         *
         *  // Reset destination shape to simplify calculations
         *  dstTexGens[dstTexGenIndex].Scale			= scrShape.TexGens[srcTexGenIndex].Scale;
         *  dstTexGens[dstTexGenIndex].Translation		= MathConstants.zeroVector2;
         *  dstTexGens[dstTexGenIndex].RotationAngle	= 0;
         *
         *  if (!CSGModelManager.AlignTextureSpacesInLocalSpace(ref srcTexGens[srcTexGenIndex], ref srcSurfaces[srcSurfaceIndex],
         *                                                      srcLocalPoint1, srcLocalPoint2,
         *                                                      ref dstTexGens[dstTexGenIndex], ref dstSurfaces[dstSurfaceIndex],
         *                                                      dstLocalPoint1, dstLocalPoint2))
         *      return false;
         *  return true;
         * }
         */

        public static bool ContinueTexGenFromSurfaceToSurface(CSGBrush brush, int srcSurfaceIndex, int dstSurfaceIndex)
        {
            if (srcSurfaceIndex < 0 || srcSurfaceIndex >= brush.Shape.TexGens.Length ||
                !brush)
            {
                return(false);
            }

            var shape       = brush.Shape;
            var texGens     = shape.TexGens;
            var texGenFlags = shape.TexGenFlags;
            var surfaces    = shape.Surfaces;

            var srcTexGenIndex = surfaces[srcSurfaceIndex].TexGenIndex;
            var dstTexGenIndex = surfaces[dstSurfaceIndex].TexGenIndex;

//          var src_is_world_space = (texGenFlags[srcTexGenIndex] & TexGenFlags.WorldSpaceTexture) != TexGenFlags.None;
//          var dst_is_world_space = (texGenFlags[dstTexGenIndex] & TexGenFlags.WorldSpaceTexture) != TexGenFlags.None;

//          if (src_is_world_space) SurfaceUtility.SetTextureLock(brush, srcSurfaceIndex, true);
//          if (dst_is_world_space) SurfaceUtility.SetTextureLock(brush, dstSurfaceIndex, true);

            var dstLocalPlane = surfaces[dstSurfaceIndex].Plane;
            var srcLocalPlane = surfaces[srcSurfaceIndex].Plane;

            CSGModel     parentModel;
            CSGOperation parentOp;

            InternalCSGModelManager.FindParentOperationAndModel(brush.transform, out parentOp, out parentModel);

            var localFromWorld = brush.transform.worldToLocalMatrix;
            var worldFromModel = parentModel.transform.localToWorldMatrix;
            var modelFromWorld = parentModel.transform.worldToLocalMatrix;
            var localFromModel = localFromWorld * worldFromModel;
            //var localToWorldMatrix = brush.transform.localToWorldMatrix;

            // convert planes into worldspace
            var dstWorldPlane = InverseTransformPlane(localFromWorld, dstLocalPlane);
            var srcWorldPlane = InverseTransformPlane(localFromWorld, srcLocalPlane);

            var dstWorldNormal = dstWorldPlane.normal;
            var srcWorldNormal = srcWorldPlane.normal;


            shape.TexGens[dstSurfaceIndex].RenderMaterial = shape.TexGens[srcSurfaceIndex].RenderMaterial;
            Vector3 srcWorldPoint1, srcWorldPoint2;
            Vector3 dstWorldPoint1, dstWorldPoint2;
            var     edgeDirection = Vector3.Cross(dstWorldNormal, srcWorldNormal);
            var     det           = edgeDirection.sqrMagnitude;

            if (det < MathConstants.AlignmentTestEpsilon)
            {
                // Find 2 points on intersection of 2 planes
                srcWorldPoint1 = srcWorldPlane.pointOnPlane;
                srcWorldPoint2 = GeometryUtility.ProjectPointOnPlane(srcWorldPlane, srcWorldPoint1 + MathConstants.oneVector3);

                dstWorldPoint1 = GeometryUtility.ProjectPointOnPlane(dstWorldPlane, srcWorldPoint1);
                dstWorldPoint2 = GeometryUtility.ProjectPointOnPlane(dstWorldPlane, srcWorldPoint2);
            }
            else
            {
                // Find 2 points on intersection of 2 planes
                srcWorldPoint1 = ((Vector3.Cross(edgeDirection, srcWorldNormal) * -dstWorldPlane.d) +
                                  (Vector3.Cross(dstWorldNormal, edgeDirection) * -srcWorldPlane.d)) / det;
                srcWorldPoint2 = srcWorldPoint1 + edgeDirection;
                dstWorldPoint1 = srcWorldPoint1;
                dstWorldPoint2 = srcWorldPoint2;
            }

            var srcModelPoint1 = modelFromWorld.MultiplyPoint(srcWorldPoint1);
            var srcModelPoint2 = modelFromWorld.MultiplyPoint(srcWorldPoint2);

            var dstModelPoint1 = modelFromWorld.MultiplyPoint(dstWorldPoint1);
            var dstModelPoint2 = modelFromWorld.MultiplyPoint(dstWorldPoint2);

            var result = SurfaceUtility.AlignTextureSpaces(localFromModel, texGens[srcTexGenIndex], texGenFlags[srcTexGenIndex], ref surfaces[srcSurfaceIndex], srcModelPoint1, srcModelPoint2,
                                                           localFromModel, ref texGens[dstTexGenIndex], texGenFlags[dstTexGenIndex], ref surfaces[dstSurfaceIndex], dstModelPoint1, dstModelPoint2, false, Vector3.one);

//          if (src_is_world_space) SurfaceUtility.SetTextureLock(brush, srcSurfaceIndex, false);
//          if (dst_is_world_space) SurfaceUtility.SetTextureLock(brush, dstSurfaceIndex, false);
            return(result);
        }
Esempio n. 20
0
		private bool GenerateSphere(float radius, int splits, CSGModel parentModel, CSGBrush brush, out ControlMesh controlMesh, out Shape shape)
        {
			if (prevSplits != splits || prevIsHemisphere != IsHemiSphere || splitControlMesh == null || splitShape == null)
			{
				splitControlMesh = null;
				splitShape = null;
				BrushFactory.CreateCubeControlMesh(out splitControlMesh, out splitShape, Vector3.one);

				var axi = new Vector3[] { MathConstants.upVector3, MathConstants.leftVector3, MathConstants.forwardVector3 };
				List<int> intersectedEdges = new List<int>();
				float step = 1.0f / (float)(splits + 1);
				float offset;
				for (int i = 0; i < axi.Length; i++)
				{
					var normal = axi[i];
					offset = 0.5f - step;
					while (offset > 0.0f)
					{
						ControlMeshUtility.CutMesh(splitControlMesh, splitShape, new CSGPlane(-normal, -offset), ref intersectedEdges);
						if (i != 0 || !IsHemiSphere)
						{
							ControlMeshUtility.CutMesh(splitControlMesh, splitShape, new CSGPlane(normal, -offset), ref intersectedEdges);
						}
						offset -= step;
					}
					if (i != 0 || !IsHemiSphere)
					{
						if ((splits & 1) == 1)
							ControlMeshUtility.CutMesh(splitControlMesh, splitShape, new CSGPlane(normal, 0), ref intersectedEdges);
					}
				}

				if (IsHemiSphere)
				{
					var cuttingPlane = new CSGPlane(MathConstants.upVector3, 0);
					intersectedEdges.Clear();
					if (ControlMeshUtility.CutMesh(splitControlMesh, splitShape, cuttingPlane, ref intersectedEdges))
					{
						var edge_loop = ControlMeshUtility.FindEdgeLoop(splitControlMesh, ref intersectedEdges);
						if (edge_loop != null)
						{
							if (ControlMeshUtility.SplitEdgeLoop(splitControlMesh, splitShape, edge_loop))
							{
								Shape foundShape;
								ControlMesh foundControlMesh;
								ControlMeshUtility.FindAndDetachSeparatePiece(splitControlMesh, splitShape, cuttingPlane, out foundControlMesh, out foundShape);
							}
						}
					}
				}


				// Spherize the cube
				for (int i = 0; i < splitControlMesh.Vertices.Length; i++)
				{
					Vector3 v = splitControlMesh.Vertices[i] * 2.0f;
					float x2 = v.x * v.x;
					float y2 = v.y * v.y;
					float z2 = v.z * v.z;
					Vector3 s;
					s.x = v.x * Mathf.Sqrt(1f - (y2 * 0.5f) - (z2 * 0.5f) + ((y2 * z2) / 3.0f));
					s.y = v.y * Mathf.Sqrt(1f - (z2 * 0.5f) - (x2 * 0.5f) + ((z2 * x2) / 3.0f));
					s.z = v.z * Mathf.Sqrt(1f - (x2 * 0.5f) - (y2 * 0.5f) + ((x2 * y2) / 3.0f));
					splitControlMesh.Vertices[i] = s;//(splitControlMesh.Vertices[i] * 0.75f) + (splitControlMesh.Vertices[i].normalized * 0.25f);
				}


				if (!ControlMeshUtility.Triangulate(null, splitControlMesh, splitShape))
				{
					Debug.LogWarning("!ControlMeshUtility.IsConvex");
					controlMesh = null;
					shape = null;
					return false;
				}
				ControlMeshUtility.FixTexGens(splitControlMesh, splitShape);

				if (!ControlMeshUtility.IsConvex(splitControlMesh, splitShape))
				{
					Debug.LogWarning("!ControlMeshUtility.IsConvex");
					controlMesh = null;
					shape = null;
					return false;
				}
				ControlMeshUtility.UpdateTangents(splitControlMesh, splitShape);

				prevSplits = splits;
				prevIsHemisphere = IsHemiSphere;
			}

			if (splitControlMesh == null || splitShape == null || !splitControlMesh.Valid)
			{
				Debug.LogWarning("splitControlMesh == null || splitShape == null || !splitControlMesh.IsValid");
				controlMesh = null;
				shape = null;
				return false;
			}

			controlMesh = splitControlMesh.Clone();
			shape = splitShape.Clone();

			/*
			float angle_offset = GeometryUtility.SignedAngle(gridTangent, delta / sphereRadius, buildPlane.normal);
			angle_offset -= 90;

			angle_offset += sphereOffset;
			angle_offset *= Mathf.Deg2Rad;

			Vector3 p1 = MathConstants.zeroVector3;
			for (int i = 0; i < realSplits; i++)
			{
				var angle = ((i * Mathf.PI * 2.0f) / (float)realSplits) + angle_offset;

				p1.x = (Mathf.Sin(angle) * sphereRadius);
				p1.z = (Mathf.Cos(angle) * sphereRadius);
			}
			*/

			for (int i = 0; i < controlMesh.Vertices.Length; i++)
			{
				var vertex = controlMesh.Vertices[i];
				vertex *= radius;
				controlMesh.Vertices[i] = vertex;
			}

			for (int i = 0; i < shape.Surfaces.Length; i++)
			{
				var plane = shape.Surfaces[i].Plane;
				plane.d *= radius;
				shape.Surfaces[i].Plane = plane;
			}

			bool smoothShading = SphereSmoothShading;
			if (!sphereSmoothingGroup.HasValue && smoothShading)
			{
				sphereSmoothingGroup = SurfaceUtility.FindUnusedSmoothingGroupIndex();
			}

			for (int i = 0; i < shape.TexGenFlags.Length; i++)
			{
				shape.TexGens[i].SmoothingGroup = smoothShading ? sphereSmoothingGroup.Value : 0;
			}

			var defaultTexGen = new TexGen();
			defaultTexGen.Scale = MathConstants.oneVector3;
			//defaultTexGen.Color = Color.white;
			
			var fakeSurface = new Surface();
			fakeSurface.TexGenIndex = 0;
			
			var defaultMaterial = CSGSettings.DefaultMaterial;
			for (var s = 0; s < shape.Surfaces.Length; s++)
			{
				var texGenIndex = shape.Surfaces[s].TexGenIndex;

				var axis		= GeometryUtility.SnapToClosestAxis(shape.Surfaces[s].Plane.normal);
				var rotation	= Quaternion.FromToRotation(axis, MathConstants.backVector3);
				var matrix		= Matrix4x4.TRS(MathConstants.zeroVector3, rotation, MathConstants.oneVector3);

				SurfaceUtility.AlignTextureSpaces(matrix, false, ref shape.TexGens[texGenIndex], ref shape.TexGenFlags[texGenIndex], ref shape.Surfaces[s]);
				shape.TexGens[texGenIndex].RenderMaterial = defaultMaterial;
			}

			return true;
        }
Esempio n. 21
0
        public static bool GenerateControlMeshFromVertices(ShapePolygon shape2DPolygon,
                                                           Matrix4x4 localToWorld,
                                                           Vector3 direction,
                                                           float height,
                                                           Material capMaterial,
                                                           TexGen capTexgen,
                                                           bool?smooth,
                                                           bool singleSurfaceEnds,                                                                                 //Plane buildPlane,
                                                           out ControlMesh controlMesh,
                                                           out Shape shape)
        {
            if (shape2DPolygon == null)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }

            var vertices = shape2DPolygon.Vertices;

            if (vertices.Length < 3)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }
            if (height == 0.0f)
            {
                controlMesh = null;
                shape       = null;
                return(false);
            }

            Vector3 from;
            Vector3 to;

            if (height > 0)
            {
                @from = direction * height;                // buildPlane.normal * height;
                to    = MathConstants.zeroVector3;
            }
            else
            {
                @from = MathConstants.zeroVector3;
                to    = direction * height;               //buildPlane.normal * height;
            }

            var count           = vertices.Length;
            var doubleCount     = (count * 2);
            var extraPoints     = 0;
            var extraEdges      = 0;
            var endsPolygons    = 2;
            var startEdgeOffset = doubleCount;

            if (!singleSurfaceEnds)
            {
                extraPoints      = 2;
                extraEdges       = (4 * count);
                endsPolygons     = doubleCount;
                startEdgeOffset += extraEdges;
            }


            var dstPoints   = new Vector3 [doubleCount + extraPoints];
            var dstEdges    = new HalfEdge[(count * 6) + extraEdges];
            var dstPolygons = new Polygon [count + endsPolygons];

            var center1 = MathConstants.zeroVector3;
            var center2 = MathConstants.zeroVector3;


            for (int i = 0; i < count; i++)
            {
                var point1 = vertices[i];
                var point2 = vertices[(count + i - 1) % count];

                point1 += @from;
                point2 += to;

                // swap y/z to solve texgen issues
                dstPoints[i].x = point1.x;
                dstPoints[i].y = point1.y;
                dstPoints[i].z = point1.z;

                center1 += dstPoints[i];

                dstEdges [i].VertexIndex = (short)i;
                dstEdges [i].HardEdge    = true;

                // swap y/z to solve texgen issues
                dstPoints[i + count].x = point2.x;
                dstPoints[i + count].y = point2.y;
                dstPoints[i + count].z = point2.z;
                center2 += dstPoints[i + count];

                dstEdges [i + count].VertexIndex = (short)(i + count);
                dstEdges [i + count].HardEdge    = true;
            }

            if (!singleSurfaceEnds)
            {
                dstPoints[doubleCount]     = center1 / count;
                dstPoints[doubleCount + 1] = center2 / count;

                int   edge_offset   = doubleCount;
                short polygon_index = (short)count;

                // 'top'
                for (int i = 0, j = count - 1; i < count; j = i, i++)
                {
                    var jm = (j) % count;
                    var im = (i) % count;

                    var edgeOut0 = edge_offset + (jm * 2) + 1;
                    var edgeIn0  = edge_offset + (im * 2) + 0;
                    var edgeOut1 = edge_offset + (im * 2) + 1;

                    dstEdges[edgeIn0].VertexIndex = (short)(doubleCount);
                    dstEdges[edgeIn0].HardEdge    = true;
                    dstEdges[edgeIn0].TwinIndex   = edgeOut1;

                    dstEdges[edgeOut1].VertexIndex = (short)im;
                    dstEdges[edgeOut1].HardEdge    = true;
                    dstEdges[edgeOut1].TwinIndex   = edgeIn0;

                    dstEdges[im].PolygonIndex       = polygon_index;
                    dstEdges[edgeIn0].PolygonIndex  = polygon_index;
                    dstEdges[edgeOut0].PolygonIndex = polygon_index;

                    dstPolygons[polygon_index] = new Polygon(new int[] { im, edgeIn0, edgeOut0 }, polygon_index);
                    polygon_index++;
                }

                edge_offset = doubleCount * 2;
                // 'bottom'
                for (int i = 0, j = count - 1; j >= 0; i = j, j--)
                {
                    var jm = (count + count - j) % count;
                    var im = (count + count - i) % count;

                    var edgeOut0 = edge_offset + (jm * 2) + 1;
                    var edgeIn0  = edge_offset + (im * 2) + 0;
                    var edgeOut1 = edge_offset + (im * 2) + 1;

                    dstEdges[edgeIn0].VertexIndex = (short)(doubleCount + 1);
                    dstEdges[edgeIn0].HardEdge    = true;
                    dstEdges[edgeIn0].TwinIndex   = edgeOut1;

                    dstEdges[edgeOut1].VertexIndex = (short)(im + count);
                    dstEdges[edgeOut1].HardEdge    = true;
                    dstEdges[edgeOut1].TwinIndex   = edgeIn0;

                    dstEdges[im + count].PolygonIndex = polygon_index;
                    dstEdges[edgeIn0].PolygonIndex    = polygon_index;
                    dstEdges[edgeOut0].PolygonIndex   = polygon_index;

                    dstPolygons[polygon_index] = new Polygon(new int[] { im + count, edgeIn0, edgeOut0 }, polygon_index);
                    polygon_index++;
                }
            }
            else
            {
                var polygon0Edges = new int[count];
                var polygon1Edges = new int[count];
                for (var i = 0; i < count; i++)
                {
                    dstEdges [i].PolygonIndex         = (short)(count + 0);
                    dstEdges [i + count].PolygonIndex = (short)(count + 1);
                    polygon0Edges[i] = i;
                    polygon1Edges[count - (i + 1)] = i + count;
                }
                dstPolygons[count + 0] = new Polygon(polygon0Edges, count + 0);
                dstPolygons[count + 1] = new Polygon(polygon1Edges, count + 1);
            }


            for (int v0 = count - 1, v1 = 0; v1 < count; v0 = v1, v1++)
            {
                var polygonIndex = (short)(v1);

                var nextOffset = startEdgeOffset + (((v1 + 1) % count) * 4);
                var currOffset = startEdgeOffset + (((v1)) * 4);
                var prevOffset = startEdgeOffset + (((v1 + count - 1) % count) * 4);

                var nextTwin = nextOffset + 1;
                var prevTwin = prevOffset + 3;

                dstEdges[v1].TwinIndex         = currOffset + 0;
                dstEdges[v1 + count].TwinIndex = currOffset + 2;

                dstEdges[currOffset + 0].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 1].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 2].PolygonIndex = polygonIndex;
                dstEdges[currOffset + 3].PolygonIndex = polygonIndex;

                dstEdges[currOffset + 0].TwinIndex = (v1);
                dstEdges[currOffset + 1].TwinIndex = prevTwin;
                dstEdges[currOffset + 2].TwinIndex = (v1 + count);
                dstEdges[currOffset + 3].TwinIndex = nextTwin;

                dstEdges[currOffset + 0].VertexIndex = (short)(v0);
                dstEdges[currOffset + 1].VertexIndex = (short)(v1 + count);
                dstEdges[currOffset + 2].VertexIndex = (short)(((v1 + 1) % count) + count);
                dstEdges[currOffset + 3].VertexIndex = (short)(v1);

                dstEdges[currOffset + 0].HardEdge = true;
                dstEdges[currOffset + 1].HardEdge = true;
                dstEdges[currOffset + 2].HardEdge = true;
                dstEdges[currOffset + 3].HardEdge = true;

                dstPolygons[polygonIndex] = new Polygon(new [] { currOffset + 0,
                                                                 currOffset + 1,
                                                                 currOffset + 2,
                                                                 currOffset + 3 }, polygonIndex);
            }

            for (int i = 0; i < dstPoints.Length; i++)
            {
                dstPoints[i] = localToWorld.MultiplyPoint(dstPoints[i]);
            }

            controlMesh = new ControlMesh
            {
                Vertices = dstPoints,
                Edges    = dstEdges,
                Polygons = dstPolygons
            };
            controlMesh.SetDirty();

            shape = new Shape
            {
                Materials   = new Material[dstPolygons.Length],
                Surfaces    = new Surface[dstPolygons.Length],
                TexGenFlags = new TexGenFlags[dstPolygons.Length],
                TexGens     = new TexGen[dstPolygons.Length]
            };


            var smoothinggroup = (smooth.HasValue && smooth.Value) ? SurfaceUtility.FindUnusedSmoothingGroupIndex() : 0;


            var containedMaterialCount = 0;

            if (shape2DPolygon.EdgeMaterials != null &&
                shape2DPolygon.EdgeTexgens != null /* &&
                                                    * shape2DPolygon.edgeTexgenFlags != null*/)
            {
                containedMaterialCount = Mathf.Min(shape2DPolygon.EdgeMaterials.Length,
                                                   shape2DPolygon.EdgeTexgens.Length /*,
                                                                                      *                        shape2DPolygon.edgeTexgenFlags.Length*/);
            }

            if (!capMaterial)
            {
                capMaterial = CSGSettings.DefaultMaterial;
                capTexgen   = new TexGen(-1);
            }

            for (var i = 0; i < dstPolygons.Length; i++)
            {
                if (i < containedMaterialCount)
                {
                    //shape.TexGenFlags[i] = shape2DPolygon.edgeTexgenFlags[i];
                    shape.Materials  [i]             = shape2DPolygon.EdgeMaterials[i];
                    shape.TexGens    [i]             = shape2DPolygon.EdgeTexgens[i];
                    shape.Surfaces   [i].TexGenIndex = i;
                    shape.TexGens[i].MaterialIndex   = -1;
                }
                else
                {
                    shape.Materials[i] = capMaterial;
                    shape.TexGens[i]   = capTexgen;
                    //shape.TexGenFlags[i]			= TexGenFlags.None;
                    shape.Surfaces[i].TexGenIndex  = i;
                    shape.TexGens[i].MaterialIndex = -1;
                }
                if (smooth.HasValue)
                {
                    if (i < count)
                    {
                        shape.TexGens[i].SmoothingGroup = smoothinggroup;
                    }
                    else
                    {
                        shape.TexGens[i].SmoothingGroup = 0;
                    }
                }
            }

            for (var s = 0; s < dstPolygons.Length; s++)
            {
                var normal = shape.Surfaces[s].Plane.normal;
                shape.Surfaces[s].Plane = GeometryUtility.CalcPolygonPlane(controlMesh, (short)s);
                Vector3 tangent, binormal;
                GeometryUtility.CalculateTangents(normal, out tangent, out binormal);
                //var tangent		= Vector3.Cross(GeometryUtility.CalculateTangent(normal), normal).normalized;
                //var binormal	= Vector3.Cross(normal, tangent);
                shape.Surfaces[s].Tangent     = tangent;
                shape.Surfaces[s].BiNormal    = binormal;
                shape.Surfaces[s].TexGenIndex = s;
            }

            controlMesh.IsValid = ControlMeshUtility.Validate(controlMesh, shape);
            if (controlMesh.IsValid)
            {
                return(true);
            }

            controlMesh = null;
            shape       = null;
            return(false);
        }
Esempio n. 22
0
        static void OnGUIContentsJustify(bool isSceneGUI, SelectedBrushSurface[] selectedBrushSurfaces)
        {
            GUILayout.BeginVertical(CSG_GUIStyleUtility.ContentEmpty);
            {
                if (!isSceneGUI)
                {
                    GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                    EditorGUILayout.LabelField(ContentJustifyLabel, largeLabelWidth);
                }
                else
                {
                    GUILayout.Label(ContentJustifyLabel);
                }
                GUILayout.BeginVertical(CSG_GUIStyleUtility.ContentEmpty);
                {
                    GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                    {
                        if (GUILayout.Button(ContentJustifyUpLeft, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayout(selectedBrushSurfaces, -1, -1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyUpLeft);
                        if (GUILayout.Button(ContentJustifyUp, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayoutY(selectedBrushSurfaces, -1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyUp);
                        if (GUILayout.Button(ContentJustifyUpRight, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayout(selectedBrushSurfaces, 1, -1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyUpRight);
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                    {
                        if (GUILayout.Button(ContentJustifyLeft, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayoutX(selectedBrushSurfaces, -1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyLeft);
                        if (GUILayout.Button(ContentJustifyCenter, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayout(selectedBrushSurfaces, 0, 0);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyCenter);
                        if (GUILayout.Button(ContentJustifyRight, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayoutX(selectedBrushSurfaces, 1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyRight);
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal(CSG_GUIStyleUtility.ContentEmpty);
                    {
                        if (GUILayout.Button(ContentJustifyDownLeft, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayout(selectedBrushSurfaces, -1, 1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyDownLeft);
                        if (GUILayout.Button(ContentJustifyDown, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayoutY(selectedBrushSurfaces, 1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyDown);
                        if (GUILayout.Button(ContentJustifyDownRight, justifyButtonLayout))
                        {
                            SurfaceUtility.JustifyLayout(selectedBrushSurfaces, 1, 1);
                        }
                        TooltipUtility.SetToolTip(ToolTipJustifyDownRight);
                    }
                    GUILayout.EndHorizontal();
                }
                GUILayout.EndVertical();

                if (!isSceneGUI)
                {
                    GUILayout.EndHorizontal();
                }
            }
            GUILayout.EndVertical();
        }
Esempio n. 23
0
        public override void Invalidate(bool polygonsChanged)
        {
            ////////////////////////////////////////////////////////////////////
            // a little hack to detect the user manually resizing the bounds. //
            // we use this to automatically add steps for barnaby.            //
            // it's probably good to build a more 'official' way to detect    //
            // user scaling events in compound brushes sometime.              //
            if (m_LastKnownExtents != localBounds.extents)                    //
            {                                                                 //
                // undo any position movement.                                //
                transform.localPosition = m_LastKnownPosition;                //
            }                                                                 //
            ////////////////////////////////////////////////////////////////////
            Bounds csgBounds = new Bounds();

            // nothing to do except copy csg information to our child brushes.
            if (!isDirty)
            {
                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;
                    generatedBrushes[i].Invalidate(true);
                    csgBounds.Encapsulate(generatedBrushes[i].GetBounds());
                }
                // apply the generated csg bounds.
                localBounds         = csgBounds;
                m_LastKnownExtents  = localBounds.extents;
                m_LastKnownPosition = transform.localPosition;
                return;
            }

            base.Invalidate(polygonsChanged);
            isDirty = false;

            // build the polygons from the project.
            if (m_LastBuiltPolygons == null)
            {
                m_LastBuiltPolygons = BuildConvexPolygons();
            }

            // iterate through the brushes we received:
            int brushCount = BrushCount;

            // force nocsg when creating a flat polygon sheet as sabrecsg doesn't support it.
            if (extrudeMode == ExtrudeMode.CreatePolygon)
            {
                this.IsNoCSG = true;
            }

            for (int i = 0; i < brushCount; i++)
            {
                // copy our csg information to our child brushes.
                generatedBrushes[i].Mode         = this.Mode;
                generatedBrushes[i].IsNoCSG      = this.IsNoCSG;
                generatedBrushes[i].IsVisible    = this.IsVisible;
                generatedBrushes[i].HasCollision = this.HasCollision;

                // local variables.
                Quaternion rot;
                Polygon[]  outputPolygons;

                switch (extrudeMode)
                {
                // generate a flat 2d polygon.
                case ExtrudeMode.CreatePolygon:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    GenerateUvCoordinates(m_LastBuiltPolygons[i], false);
                    Polygon poly1 = m_LastBuiltPolygons[i].DeepCopy();
                    poly1.Flip();
                    generatedBrushes[i].SetPolygons(new Polygon[] { poly1 });
                    break;

                // generate 3d cube-ish shapes that revolve around the pivot.
                case ExtrudeMode.RevolveShape:
                    int labpIndex = i % m_LastBuiltPolygons.Count;

                    Polygon poly2 = m_LastBuiltPolygons[labpIndex].DeepCopy();
                    poly2.Flip();
                    GenerateUvCoordinates(poly2, false);
                    foreach (Vertex v in poly2.Vertices)
                    {
                        float step = 360.0f / project.revolve360;
                        v.Position = RotatePointAroundPivot(v.Position, new Vector3(((project.revolveDistance / 8.0f) * project.extrudeScale.x) + ((project.revolveRadius * project.extrudeScale.x) / 8.0f), 0.0f, 0.0f), new Vector3(0.0f, (project.revolveDirection ? 0 : 180) + ((i / m_LastBuiltPolygons.Count) * step), 0.0f));
                    }
                    Polygon nextPoly = m_LastBuiltPolygons[labpIndex].DeepCopy();
                    nextPoly.Flip();
                    foreach (Vertex v in nextPoly.Vertices)
                    {
                        float step = 360.0f / project.revolve360;
                        v.Position = RotatePointAroundPivot(v.Position, new Vector3(((project.revolveDistance / 8.0f) * project.extrudeScale.x) + ((project.revolveRadius * project.extrudeScale.x) / 8.0f), 0.0f, 0.0f), new Vector3(0.0f, (project.revolveDirection ? 0 : 180) + (((i / m_LastBuiltPolygons.Count) * step) + step), 0.0f));
                    }
                    GenerateNormals(poly2);
                    List <Polygon> polygons = new List <Polygon>()
                    {
                        poly2
                    };
                    List <Vertex> backPolyVertices = new List <Vertex>();
                    Edge[]        myEdges          = poly2.GetEdges();
                    Edge[]        nextEdges        = nextPoly.GetEdges();
                    for (int j = 0; j < myEdges.Length; j++)
                    {
                        Edge myEdge   = myEdges[j];
                        Edge nextEdge = nextEdges[j];

                        Polygon newPoly = new Polygon(new Vertex[] {
                            new Vertex(myEdge.Vertex1.Position, Vector3.zero, Vector2.zero),
                            new Vertex(nextEdge.Vertex1.Position, Vector3.zero, Vector2.zero),
                            new Vertex(nextEdge.Vertex2.Position, Vector3.zero, Vector2.zero),
                            new Vertex(myEdge.Vertex2.Position, Vector3.zero, Vector2.zero),
                        }, null, false, false);

                        backPolyVertices.Add(nextEdge.Vertex1);
                        GenerateNormals(newPoly);
                        if (newPoly.Plane.normal == Vector3.zero)
                        {
                            continue;                                           // discard single line, can happen in the center of the shape.
                        }
                        GenerateUvCoordinates(newPoly, false);
                        polygons.Add(newPoly);
                    }

                    Polygon backPoly = new Polygon(backPolyVertices.ToArray(), null, false, false);

                    backPoly.Flip();
                    GenerateNormals(backPoly);
                    GenerateUvCoordinates(backPoly, false);
                    polygons.Add(backPoly);

                    generatedBrushes[i].SetPolygons(polygons.ToArray());
                    break;

                // generate a 3d cube-ish shape.
                case ExtrudeMode.ExtrudeShape:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    SurfaceUtility.ExtrudePolygon(m_LastBuiltPolygons[i], project.extrudeDepth, out outputPolygons, out rot);
                    foreach (Polygon poly in outputPolygons)
                    {
                        GenerateUvCoordinates(poly, false);
                    }
                    generatedBrushes[i].SetPolygons(outputPolygons);
                    break;

                // generate a 3d cone-ish shape.
                case ExtrudeMode.ExtrudePoint:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    ExtrudePolygonToPoint(m_LastBuiltPolygons[i], project.extrudeDepth, new Vector2((project.globalPivot.position.x * project.extrudeScale.x) / 8.0f, -(project.globalPivot.position.y * project.extrudeScale.y) / 8.0f), out outputPolygons, out rot);
                    foreach (Polygon poly in outputPolygons)
                    {
                        GenerateUvCoordinates(poly, false);
                    }
                    generatedBrushes[i].SetPolygons(outputPolygons);
                    break;

                // generate a 3d trapezoid-ish shape.
                case ExtrudeMode.ExtrudeBevel:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    ExtrudePolygonBevel(m_LastBuiltPolygons[i], project.extrudeDepth, project.extrudeClipDepth / project.extrudeDepth, new Vector2((project.globalPivot.position.x * project.extrudeScale.x) / 8.0f, -(project.globalPivot.position.y * project.extrudeScale.y) / 8.0f), out outputPolygons, out rot);
                    foreach (Polygon poly in outputPolygons)
                    {
                        GenerateUvCoordinates(poly, false);
                    }
                    generatedBrushes[i].SetPolygons(outputPolygons);
                    break;
                }

                generatedBrushes[i].Invalidate(true);
                csgBounds.Encapsulate(generatedBrushes[i].GetBounds());
            }

            // apply the generated csg bounds.
            localBounds         = csgBounds;
            m_LastKnownExtents  = localBounds.extents;
            m_LastKnownPosition = transform.localPosition;
        }
Esempio n. 24
0
        public override void Invalidate(bool polygonsChanged)
        {
            ////////////////////////////////////////////////////////////////////
            // a little hack to detect the user manually resizing the bounds. //
            // we use this to automatically add steps for barnaby.            //
            // it's probably good to build a more 'official' way to detect    //
            // user scaling events in compound brushes sometime.              //
            if (m_LastKnownExtents != localBounds.extents)                    //
            {                                                                 //
                // undo any position movement.                                //
                transform.localPosition = m_LastKnownPosition;                //
            }                                                                 //
            ////////////////////////////////////////////////////////////////////
            Bounds csgBounds = new Bounds();

            // force nocsg when creating a flat polygon sheet as sabrecsg doesn't support it.
            if (extrudeMode == ExtrudeMode.CreatePolygon)
            {
                this.IsNoCSG = true;
            }

            // force nocsg when revolving with a sloped spiral as there are non-planar polygons.
            if (extrudeMode == ExtrudeMode.RevolveShape && project.revolveSpiralSloped && project.globalPivot.position.y != 0)
            {
                this.IsNoCSG = true;
            }

            // nothing to do except copy csg information to our child brushes.
            if (!isDirty)
            {
                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;
                    generatedBrushes[i].Invalidate(true);
                    csgBounds.Encapsulate(generatedBrushes[i].GetBounds());
                }
                // apply the generated csg bounds.
                localBounds         = csgBounds;
                m_LastKnownExtents  = localBounds.extents;
                m_LastKnownPosition = transform.localPosition;
                return;
            }

            base.Invalidate(polygonsChanged);
            isDirty = false;

            // build the polygons from the project.
            if (m_LastBuiltPolygons == null)
            {
                m_LastBuiltPolygons = BuildConvexPolygons();
            }

            // iterate through the brushes we received:
            int brushCount = BrushCount;

            for (int i = 0; i < brushCount; i++)
            {
                // copy our csg information to our child brushes.
                generatedBrushes[i].Mode         = this.Mode;
                generatedBrushes[i].IsNoCSG      = this.IsNoCSG;
                generatedBrushes[i].IsVisible    = this.IsVisible;
                generatedBrushes[i].HasCollision = this.HasCollision;

                // local variables.
                Quaternion rot;
                Polygon[]  outputPolygons;

                switch (extrudeMode)
                {
                // generate a flat 2d polygon.
                case ExtrudeMode.CreatePolygon:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    GenerateUvCoordinates(m_LastBuiltPolygons[i], false);
                    Polygon poly1 = m_LastBuiltPolygons[i].DeepCopy();
                    poly1.Flip();
                    generatedBrushes[i].SetPolygons(new Polygon[] { poly1 });
                    break;

                // generate 3d cube-ish shapes that revolve around the pivot and spirals up or down.
                case ExtrudeMode.RevolveShape:
                    float spiralHeight = ((((project.globalPivot.position.y * project.extrudeScale.y) / 8.0f) * (i / m_LastBuiltPolygons.Count)) / project.revolve360) * (project.revolve360 / project.revolveSteps);
                    float spiralStep   = ((((project.globalPivot.position.y * project.extrudeScale.y) / 8.0f)) / project.revolve360) * (project.revolve360 / project.revolveSteps);
                    int   labpIndex    = i % m_LastBuiltPolygons.Count;

                    Polygon poly2 = m_LastBuiltPolygons[labpIndex].DeepCopy();
                    poly2.Flip();
                    GenerateUvCoordinates(poly2, false);
                    foreach (Vertex v in poly2.Vertices)
                    {
                        float step = 360.0f / project.revolve360;
                        v.Position = new Vector3(0, -spiralHeight, 0) + RotatePointAroundPivot(v.Position, new Vector3(((project.revolveDistance / 8.0f) * project.extrudeScale.x) + ((project.revolveRadius * project.extrudeScale.x) / 8.0f), 0.0f, 0.0f), new Vector3(0.0f, ((i / m_LastBuiltPolygons.Count) * step), 0.0f));
                    }
                    GenerateNormals(poly2);

                    Polygon nextPoly = m_LastBuiltPolygons[labpIndex].DeepCopy();
                    nextPoly.Flip();
                    foreach (Vertex v in nextPoly.Vertices)
                    {
                        float step = 360.0f / project.revolve360;
                        v.Position = new Vector3(0, -spiralHeight - (project.revolveSpiralSloped ? spiralStep : 0), 0) + RotatePointAroundPivot(v.Position, new Vector3(((project.revolveDistance / 8.0f) * project.extrudeScale.x) + ((project.revolveRadius * project.extrudeScale.x) / 8.0f), 0.0f, 0.0f), new Vector3(0.0f, (((i / m_LastBuiltPolygons.Count) * step) + step), 0.0f));
                    }
                    List <Polygon> polygons = new List <Polygon>()
                    {
                        poly2
                    };
                    List <Vertex> backPolyVertices = new List <Vertex>();
                    Edge[]        myEdges          = poly2.GetEdges();
                    Edge[]        nextEdges        = nextPoly.GetEdges();
                    for (int j = 0; j < myEdges.Length; j++)
                    {
                        Edge myEdge   = myEdges[j];
                        Edge nextEdge = nextEdges[j];

                        Polygon newPoly = new Polygon(new Vertex[] {
                            new Vertex(myEdge.Vertex1.Position, Vector3.zero, Vector2.zero),
                            new Vertex(nextEdge.Vertex1.Position, Vector3.zero, Vector2.zero),
                            new Vertex(nextEdge.Vertex2.Position, Vector3.zero, Vector2.zero),
                            new Vertex(myEdge.Vertex2.Position, Vector3.zero, Vector2.zero),
                        }, null, false, false);

                        backPolyVertices.Add(nextEdge.Vertex1);
                        GenerateNormals(newPoly);
                        if (newPoly.Plane.normal == Vector3.zero)
                        {
                            continue;                                           // discard single line, can happen in the center of the shape.
                        }
                        GenerateUvCoordinates(newPoly, false);
                        polygons.Add(newPoly);
                    }

                    Polygon backPoly = new Polygon(backPolyVertices.ToArray(), null, false, false);

                    backPoly.Flip();
                    GenerateNormals(backPoly);
                    GenerateUvCoordinates(backPoly, false);
                    polygons.Add(backPoly);

                    generatedBrushes[i].SetPolygons(polygons.ToArray());
                    break;

                // generate a 3d cube-ish shape.
                case ExtrudeMode.ExtrudeShape:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    SurfaceUtility.ExtrudePolygon(m_LastBuiltPolygons[i], project.extrudeDepth, out outputPolygons, out rot);
                    foreach (Polygon poly in outputPolygons)
                    {
                        GenerateUvCoordinates(poly, false);
                    }
                    generatedBrushes[i].SetPolygons(outputPolygons);
                    break;

                // generate a 3d cone-ish shape.
                case ExtrudeMode.ExtrudePoint:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    ExtrudePolygonToPoint(m_LastBuiltPolygons[i], project.extrudeDepth, new Vector2((project.globalPivot.position.x * project.extrudeScale.x) / 8.0f, -(project.globalPivot.position.y * project.extrudeScale.y) / 8.0f), out outputPolygons, out rot);
                    foreach (Polygon poly in outputPolygons)
                    {
                        GenerateUvCoordinates(poly, false);
                    }
                    generatedBrushes[i].SetPolygons(outputPolygons);
                    break;

                // generate a 3d trapezoid-ish shape.
                case ExtrudeMode.ExtrudeBevel:
                    GenerateNormals(m_LastBuiltPolygons[i]);
                    ExtrudePolygonBevel(m_LastBuiltPolygons[i], project.extrudeDepth, project.extrudeClipDepth / project.extrudeDepth, new Vector2((project.globalPivot.position.x * project.extrudeScale.x) / 8.0f, -(project.globalPivot.position.y * project.extrudeScale.y) / 8.0f), out outputPolygons, out rot);
                    foreach (Polygon poly in outputPolygons)
                    {
                        GenerateUvCoordinates(poly, false);
                    }
                    generatedBrushes[i].SetPolygons(outputPolygons);
                    break;
                }

                // we invalidate every brush after hidden surface removal.
            }

            // we exclude hidden faces automatically.
            // this step will automatically optimize NoCSG output the same way additive brushes would have.
            // it also excludes a couple faces that CSG doesn't exclude due to floating point precision errors.
            // the latter is especially noticable with complex revolved shapes.

            // compare each brush to another brush:
            for (int i = 0; i < brushCount; i++)
            {
                for (int j = 0; j < brushCount; j++)
                {
                    // can't check for hidden faces on the same brush.
                    if (i == j)
                    {
                        continue;
                    }

                    // compare each polygon on brush i to each polygon on brush j:
                    foreach (Polygon pa in generatedBrushes[i].GetPolygons())
                    {
                        foreach (Polygon pb in generatedBrushes[j].GetPolygons())
                        {
                            // check they both have this polygon:
                            bool identical = true;
                            foreach (Vertex va in pa.Vertices)
                            {
                                if (!pb.Vertices.Any(vb => vb.Position == va.Position))
                                {
                                    identical = false;
                                    break;
                                }
                            }
                            // identical polygons on both brushes means it can be excluded:
                            if (identical)
                            {
                                pa.UserExcludeFromFinal = true;
                                pb.UserExcludeFromFinal = true;
                            }
                        }
                    }
                }

                // invalidate every brush.
                generatedBrushes[i].Invalidate(true);
                csgBounds.Encapsulate(generatedBrushes[i].GetBounds());
            }

            // apply the generated csg bounds.
            localBounds         = csgBounds;
            m_LastKnownExtents  = localBounds.extents;
            m_LastKnownPosition = transform.localPosition;
            // update the generated name in the hierarchy.
            UpdateGeneratedHierarchyName();
        }