예제 #1
0
        void Shutdown(bool finalizing = false)
        {
            if (editor != this)
            {
                return;
            }

            editor = null;
            CSGSceneManagerRedirector.Interface = null;
            if (!initialized)
            {
                return;
            }

            EditorApplication.update -= OnFirstUpdate;
            EditorApplication.hierarchyWindowChanged   -= OnHierarchyWindowChanged;
            EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemOnGUI;
            SceneView.onSceneGUIDelegate -= OnScene;
            Undo.undoRedoPerformed       -= UndoRedoPerformed;

            initialized = false;

            // make sure the C++ side of things knows to clear the method pointers
            // so that we don't accidentally use them while closing unity
            CSGBindings.ClearUnityMethods();
            CSGBindings.ClearExternalMethods();

            if (!finalizing)
            {
                SceneTools.Cleanup();
            }
        }
예제 #2
0
        public static CSGBrush CreateBrushInstanceInScene()
        {
#if DEMO
            if (CSGBindings.BrushesAvailable() <= 0)
            {
                return(null);
            }
#endif
            var lastUsedModelTransform = !SelectionUtility.LastUsedModel ? null : SelectionUtility.LastUsedModel.transform;
            if (lastUsedModelTransform == null)
            {
                lastUsedModelTransform = CreateModelInstanceInScene().transform;
            }

            var name       = UnityEditor.GameObjectUtility.GetUniqueNameForSibling(lastUsedModelTransform, "Brush");
            var gameObject = new GameObject(name);
            var brush      = gameObject.AddComponent <CSGBrush>();

            gameObject.transform.SetParent(lastUsedModelTransform, true);
            gameObject.transform.position = new Vector3(0.5f, 0.5f, 0.5f);             // this aligns it's vertices to the grid
            BrushFactory.CreateCubeControlMesh(out brush.ControlMesh, out brush.Shape, Vector3.one);

            UnityEditor.Selection.activeGameObject = gameObject;
            Undo.RegisterCreatedObjectUndo(gameObject, "Created brush");
            InternalCSGModelManager.Refresh();
            InternalCSGModelManager.UpdateMeshes();
            return(brush);
        }
 public static void ForceRebuild()
 {
     InternalCSGModelManager.Rebuild();
     InternalCSGModelManager.OnHierarchyModified();
     CSGBindings.RebuildAll();
     InternalCSGModelManager.UpdateMeshes();
 }
예제 #4
0
        void OnGUI()
        {
            EditorGUILayout.Space();
            EditorGUILayout.Space();
            if (GUILayout.Button("Log Diagnostics"))
            {
                Debug.Log("--[C++ side]--\n");
                CSGBindings.LogDiagnostics();

                Debug.Log("--[C# side (registered)]--\n");
                Debug.Log(string.Format("models {0} brushes {1} operations {2}\n", InternalCSGModelManager.models.Length, InternalCSGModelManager.brushes.Length, InternalCSGModelManager.operations.Length));
                foreach (var model in InternalCSGModelManager.models)
                {
                    Debug.Log(string.Format("\tmodel \"{0}\" node-id: {1} model-id: {2} \n", model.name, model.nodeID, model.modelID));
                }
                foreach (var operation in InternalCSGModelManager.operations)
                {
                    Debug.Log(string.Format("\toperation \"{0}\" node-id: {1} operation-id: {2} \n", operation.name, operation.nodeID, operation.operationID));
                }
                foreach (var brush in InternalCSGModelManager.brushes)
                {
                    Debug.Log(string.Format("\tbrush \"{0}\" node-id: {1} brush-id: {2} \n", brush.name, brush.nodeID, brush.brushID));
                }

                Debug.Log("--[C# side (unregistered)]--\n");

                var nodes      = CSGSceneUtility.FindComponentsInScene <CSGNode>(EditorSceneManager.GetActiveScene());
                var models     = (from node in nodes where node is CSGModel select node as CSGModel).ToArray();
                var operations = (from node in nodes where node is CSGOperation select node as CSGOperation).ToArray();
                var brushes    = (from node in nodes where node is CSGBrush select node as CSGBrush).ToArray();

                Debug.Log(string.Format("models {0} brushes {1} operations {2}\n", models.Length, brushes.Length, operations.Length));
                foreach (var model in models)
                {
                    if (InternalCSGModelManager.models.Contains(model))
                    {
                        continue;
                    }
                    Debug.Log(string.Format("\tmodel \"{0}\" node-id: {1} model-id: {2} \n", model.name, model.nodeID, model.modelID));
                }
                foreach (var operation in operations)
                {
                    if (InternalCSGModelManager.operations.Contains(operation))
                    {
                        continue;
                    }
                    Debug.Log(string.Format("\toperation \"{0}\" node-id: {1} operation-id: {2} \n", operation.name, operation.nodeID, operation.operationID));
                }
                foreach (var brush in brushes)
                {
                    if (InternalCSGModelManager.brushes.Contains(brush))
                    {
                        continue;
                    }
                    Debug.Log(string.Format("\tbrush \"{0}\" node-id: {1} brush-id: {2} \n", brush.name, brush.nodeID, brush.brushID));
                }
            }
        }
예제 #5
0
        public static GameObject CreateBrush(ControlMesh controlMesh, Shape shape, Transform parent, string name, bool worldPositionStays)
        {
#if DEMO
            if (CSGBindings.BrushesAvailable() <= 0)
            {
                return(null);
            }
#endif
            var gameObject = CreateGameObject(parent, name, worldPositionStays);
            var brush      = gameObject.AddComponent <CSGBrush>();
            brush.ControlMesh = controlMesh;
            brush.Shape       = shape;
            gameObject.SetActive(shape != null && controlMesh != null);
            Undo.RegisterCreatedObjectUndo(gameObject, "Created brush");
            InternalCSGModelManager.Refresh();
            return(gameObject);
        }
예제 #6
0
        // Delegate for generic updates
        void OnFirstUpdate()
        {
            had_first_update          = true;
            EditorApplication.update -= OnFirstUpdate;
            RealtimeCSG.CSGSettings.Reload();

            GetReflectedData();

            // register unity methods in the c++ code so that some unity functions
            // (such as debug.log) can be called from within the c++ code.
            CSGBindings.RegisterUnityMethods();

            // register dll methods so we can use them
            CSGBindings.RegisterExternalMethods();

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

#if DEMO
            if (CSGBindings.BrushesAvailable() < polygons.Length)
            {
                Debug.Log("Demo brush limit hit (" + CSGBindings.BrushesAvailable() + " available, " + polygons.Length + " required), for the ability to create more brushes please purchase Realtime - CSG");
                return(false);
            }
#endif

            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.skipRefresh = 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.skipRefresh = true;
                if (registerUndo)
                {
                    EditorUtility.SetDirty(this);
                }
                //CSGModelManager.External.ForceModelUpdate(parentModel.modelID);
                InternalCSGModelManager.Refresh(forceHierarchyUpdate: modifiedHierarchy);
            }
            finally
            {
                InternalCSGModelManager.skipRefresh = 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.brushID != -1)
                        {
                            if (lastBrush && lastBrush.brushID != -1)
                            {
                                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);
        }
예제 #8
0
        protected bool GenerateBrushObjects(int brushObjectCount, bool inGridSpace = true)
        {
            Undo.IncrementCurrentGroup();
            undoGroupIndex = Undo.GetCurrentGroup();

            var lastUsedModel          = SelectionUtility.LastUsedModel;
            var lastUsedModelTransform = !lastUsedModel ? null : lastUsedModel.transform;

            if (!lastUsedModelTransform ||
                !lastUsedModel.isActiveAndEnabled)
            {
                if (prevSelection != null && prevSelection.Length > 0)
                {
                    for (int i = 0; i < prevSelection.Length; i++)
                    {
                        UnityEngine.Object obj   = prevSelection[i];
                        CSGBrush           brush = obj as CSGBrush;
                        MonoBehaviour      mono  = obj as MonoBehaviour;
                        GameObject         go    = obj as GameObject;
                        if (!brush)
                        {
                            if (mono)
                            {
                                brush = mono.GetComponentInChildren <CSGBrush>();
                            }
                            if (go)
                            {
                                brush = go.GetComponentInChildren <CSGBrush>();
                            }
                        }

                        if (!brush)
                        {
                            continue;
                        }

                        if ((brush.gameObject.hideFlags & (HideFlags.HideInHierarchy | HideFlags.NotEditable | HideFlags.DontSaveInBuild)) != 0)
                        {
                            continue;
                        }

                        var brush_cache = InternalCSGModelManager.GetBrushCache(brush);
                        if (brush_cache == null ||
                            brush_cache.childData == null ||
                            brush_cache.childData.ModelTransform == null)
                        {
                            continue;
                        }

                        var model = brush_cache.childData.Model;
                        if (!model ||
                            !model.isActiveAndEnabled)
                        {
                            continue;
                        }

                        lastUsedModelTransform = brush_cache.childData.ModelTransform;
                        break;
                    }
                }
            }

            if (generatedBrushes != null && generatedBrushes.Length > 0)
            {
                for (int i = generatedBrushes.Length - 1; i >= 0; i--)
                {
                    if (generatedBrushes[i])
                    {
                        continue;
                    }
                    ArrayUtility.RemoveAt(ref generatedBrushes, i);
                }
                for (int i = generatedGameObjects.Length - 1; i >= 0; i--)
                {
                    if (generatedGameObjects[i])
                    {
                        var brush = generatedGameObjects[i].GetComponentInChildren <CSGBrush>();
                        if (brush && ArrayUtility.Contains(generatedBrushes, brush))
                        {
                            continue;
                        }
                    }
                    ArrayUtility.RemoveAt(ref generatedGameObjects, i);
                }
            }

            if (generatedGameObjects == null ||
                generatedGameObjects.Length != brushObjectCount)
            {
                if (generatedBrushes != null && generatedBrushes.Length > 0)
                {
                    for (int i = 0; i < generatedBrushes.Length; i++)
                    {
                        InternalCSGModelManager.OnDestroyed(generatedBrushes[i]);
                        GameObject.DestroyImmediate(generatedBrushes[i]);
                    }
                }
                if (generatedGameObjects != null && generatedGameObjects.Length > 0)
                {
                    for (int i = 0; i < generatedGameObjects.Length; i++)
                    {
                        GameObject.DestroyImmediate(generatedGameObjects[i]);
                    }
                }

                if (parentGameObject != null)
                {
                    GameObject.DestroyImmediate(parentGameObject);
                }

                //DebugEditorWindow.PrintDebugInfo();

#if DEMO
                if (CSGBindings.BrushesAvailable() < brushObjectCount)
                {
                    Debug.Log("Demo brush limit hit (" + CSGBindings.BrushesAvailable() + " available, " + brushObjectCount + " required), for the ability to create more brushes please purchase Realtime-CSG");
                    return(false);
                }
#endif
                if (lastUsedModelTransform == null)
                {
                    parentGameObject = OperationsUtility.CreateGameObject(lastUsedModelTransform, "Model", true);
                    InternalCSGModelManager.CreateCSGModel(parentGameObject);
                    parentModel = parentGameObject.GetComponent <CSGModel>();
                    Undo.RegisterCreatedObjectUndo(parentGameObject, "Created model");

                    if (brushObjectCount > 1)
                    {
                        operationGameObject = OperationsUtility.CreateGameObject(parentGameObject.transform, "Operation", true);
                        var transform = operationGameObject.transform;
                        SetBrushTransformation(transform);

                        var operation = operationGameObject.AddComponent <CSGOperation>();
                        if (CurrentCSGOperationType != invalidCSGOperationType)
                        {
                            operation.OperationType = CurrentCSGOperationType;
                        }
                        operation.HandleAsOne = true;
                        Undo.RegisterCreatedObjectUndo(operationGameObject, "Created operation");
                        parentTransform = operationGameObject.transform;
                    }
                    else
                    {
                        parentTransform = parentGameObject.transform;
                    }
                }
                else
                if (brushObjectCount > 1)
                {
                    parentModel      = lastUsedModelTransform.GetComponent <CSGModel>();
                    parentGameObject = OperationsUtility.CreateGameObject(lastUsedModelTransform, "Brushes", true);
                    var transform = parentGameObject.transform;
                    SetBrushTransformation(transform);

                    operationGameObject = parentGameObject;
                    var operation = operationGameObject.AddComponent <CSGOperation>();
                    if (CurrentCSGOperationType != invalidCSGOperationType)
                    {
                        operation.OperationType = CurrentCSGOperationType;
                    }
                    operation.HandleAsOne = true;
                    parentTransform       = operationGameObject.transform;
                    Undo.RegisterCreatedObjectUndo(parentGameObject, "Created brush");
                }
                else
                {
                    parentGameObject    = null;
                    operationGameObject = null;
                    parentTransform     = lastUsedModelTransform;
                    parentModel         = lastUsedModelTransform.GetComponent <CSGModel>();
                }


                generatedGameObjects = new GameObject[brushObjectCount];
                generatedBrushes     = new CSGBrush[brushObjectCount];
                for (int p = 0; p < brushObjectCount; p++)
                {
                    string name;
                    if (brushObjectCount == 1)
                    {
                        name = "Brush";
                    }
                    else
                    {
                        name = "Brush (" + p + ")";
                    }
                    var gameObject = OperationsUtility.CreateGameObject(parentTransform, name, false);
                    gameObject.SetActive(false);

                    var brushComponent = gameObject.AddComponent <CSGBrush>();

                    if (operationGameObject == null)
                    {
                        if (CurrentCSGOperationType != invalidCSGOperationType)
                        {
                            brushComponent.OperationType = CurrentCSGOperationType;
                        }
                        operationGameObject = gameObject;
                        var transform = gameObject.transform;
                        SetBrushTransformation(transform);
                    }

                    generatedBrushes[p]             = brushComponent;
                    generatedBrushes[p].ControlMesh = new ControlMesh();
                    generatedBrushes[p].Shape       = new Shape();
                    Undo.RegisterCreatedObjectUndo(gameObject, "Created brush");
                    generatedGameObjects[p] = gameObject;
                }
                //InternalCSGModelManager.Refresh(forceHierarchyUpdate: true);
                // brushes not registered at this point!??


                //DebugEditorWindow.PrintDebugInfo();
                //Selection.objects = generatedGameObjects;
            }
            else
            {
                UpdateBrushPosition();
            }

            return(generatedBrushes != null && generatedBrushes.Length > 0 && generatedBrushes.Length == brushObjectCount);
        }
        static void OnBottomBarGUI(SceneView sceneView, Rect barSize)
        {
            //if (Event.current.type == EventType.Layout)
            //	return;

            var  snapToGrid        = RealtimeCSG.CSGSettings.SnapToGrid;
            var  uniformGrid       = RealtimeCSG.CSGSettings.UniformGrid;
            var  moveSnapVector    = RealtimeCSG.CSGSettings.SnapVector;
            var  rotationSnap      = RealtimeCSG.CSGSettings.SnapRotation;
            var  scaleSnap         = RealtimeCSG.CSGSettings.SnapScale;
            var  showGrid          = RealtimeCSG.CSGSettings.GridVisible;
            var  lockAxisX         = RealtimeCSG.CSGSettings.LockAxisX;
            var  lockAxisY         = RealtimeCSG.CSGSettings.LockAxisY;
            var  lockAxisZ         = RealtimeCSG.CSGSettings.LockAxisZ;
            var  distanceUnit      = RealtimeCSG.CSGSettings.DistanceUnit;
            var  helperSurfaces    = RealtimeCSG.CSGSettings.VisibleHelperSurfaces;
            var  showWireframe     = RealtimeCSG.CSGSettings.IsWireframeShown(sceneView);
            var  skin              = GUIStyleUtility.Skin;
            var  updateSurfaces    = false;
            bool wireframeModified = false;

            var viewWidth = sceneView.position.width;

            float layoutHeight = barSize.height;
            float layoutX      = 6.0f;

            bool modified = false;

            GUI.changed = false;
            {
                currentRect.width  = 27;
                currentRect.y      = 0;
                currentRect.height = layoutHeight - currentRect.y;
                currentRect.y     += barSize.y;
                currentRect.x      = layoutX;
                layoutX           += currentRect.width;

                #region "Grid" button
                if (showGrid)
                {
                    showGrid = GUI.Toggle(currentRect, showGrid, skin.gridIconOn, EditorStyles.toolbarButton);
                }
                else
                {
                    showGrid = GUI.Toggle(currentRect, showGrid, skin.gridIcon, EditorStyles.toolbarButton);
                }
                //(x:6.00, y:0.00, width:27.00, height:18.00)
                TooltipUtility.SetToolTip(showGridTooltip, currentRect);
                #endregion

                if (viewWidth >= 800)
                {
                    layoutX += 6;                     //(x:33.00, y:0.00, width:6.00, height:6.00)
                }
                var prevBackgroundColor   = GUI.backgroundColor;
                var lockedBackgroundColor = skin.lockedBackgroundColor;
                if (lockAxisX)
                {
                    GUI.backgroundColor = lockedBackgroundColor;
                }

                #region "X" lock button
                currentRect.width  = 17;
                currentRect.y      = 0;
                currentRect.height = layoutHeight - currentRect.y;
                currentRect.y     += barSize.y;
                currentRect.x      = layoutX;
                layoutX           += currentRect.width;

                lockAxisX = !GUI.Toggle(currentRect, !lockAxisX, xLabel, skin.xToolbarButton);
                //(x:39.00, y:0.00, width:17.00, height:18.00)
                if (lockAxisX)
                {
                    TooltipUtility.SetToolTip(xTooltipOn, currentRect);
                }
                else
                {
                    TooltipUtility.SetToolTip(xTooltipOff, currentRect);
                }
                GUI.backgroundColor = prevBackgroundColor;
                #endregion

                #region "Y" lock button
                currentRect.x = layoutX;
                layoutX      += currentRect.width;

                if (lockAxisY)
                {
                    GUI.backgroundColor = lockedBackgroundColor;
                }
                lockAxisY = !GUI.Toggle(currentRect, !lockAxisY, yLabel, skin.yToolbarButton);
                //(x:56.00, y:0.00, width:17.00, height:18.00)
                if (lockAxisY)
                {
                    TooltipUtility.SetToolTip(yTooltipOn, currentRect);
                }
                else
                {
                    TooltipUtility.SetToolTip(yTooltipOff, currentRect);
                }
                GUI.backgroundColor = prevBackgroundColor;
                #endregion

                #region "Z" lock button
                currentRect.x = layoutX;
                layoutX      += currentRect.width;

                if (lockAxisZ)
                {
                    GUI.backgroundColor = lockedBackgroundColor;
                }
                lockAxisZ = !GUI.Toggle(currentRect, !lockAxisZ, zLabel, skin.zToolbarButton);
                //(x:56.00, y:0.00, width:17.00, height:18.00)
                if (lockAxisZ)
                {
                    TooltipUtility.SetToolTip(zTooltipOn, currentRect);
                }
                else
                {
                    TooltipUtility.SetToolTip(zTooltipOff, currentRect);
                }
                GUI.backgroundColor = prevBackgroundColor;
                #endregion
            }
            modified = GUI.changed || modified;

            if (viewWidth >= 800)
            {
                layoutX += 6;                 // (x:91.00, y:0.00, width:6.00, height:6.00)
            }
            #region "SnapToGrid" button
            GUI.changed = false;
            {
                currentRect.width  = 27;
                currentRect.y      = 0;
                currentRect.height = layoutHeight - currentRect.y;
                currentRect.y     += barSize.y;
                currentRect.x      = layoutX;
                layoutX           += currentRect.width;

                snapToGrid = GUI.Toggle(currentRect, snapToGrid, GUIStyleUtility.Skin.snappingIconOn, EditorStyles.toolbarButton);
                //(x:97.00, y:0.00, width:27.00, height:18.00)
                TooltipUtility.SetToolTip(snapToGridTooltip, currentRect);

                layoutX += 4;
            }
            modified = GUI.changed || modified;
            #endregion

            if (viewWidth >= 460)
            {
                if (snapToGrid)
                {
                    #region "Position" label
                    if (viewWidth >= 500)
                    {
                        if (viewWidth >= 865)
                        {
                            currentRect.width  = 44;
                            currentRect.y      = 1;
                            currentRect.height = layoutHeight - currentRect.y;
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;

                            uniformGrid = GUI.Toggle(currentRect, uniformGrid, positionLargeLabel, miniTextStyle);
                            //(x:128.00, y:2.00, width:44.00, height:16.00)

                            TooltipUtility.SetToolTip(positionTooltip, currentRect);
                        }
                        else
                        {
                            currentRect.width  = 22;
                            currentRect.y      = 1;
                            currentRect.height = layoutHeight - currentRect.y;
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;

                            uniformGrid = GUI.Toggle(currentRect, uniformGrid, positionSmallLabel, miniTextStyle);
                            //(x:127.00, y:2.00, width:22.00, height:16.00)

                            TooltipUtility.SetToolTip(positionTooltip, currentRect);
                        }
                    }
                    #endregion

                    layoutX += 2;

                    #region "Position" field
                    if (uniformGrid || viewWidth < 515)
                    {
                        EditorGUI.showMixedValue = !(moveSnapVector.x == moveSnapVector.y && moveSnapVector.x == moveSnapVector.z);
                        GUI.changed = false;
                        {
                            currentRect.width  = 70;
                            currentRect.y      = 3;
                            currentRect.height = layoutHeight - (currentRect.y - 1);
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;

                            moveSnapVector.x = Units.DistanceUnitToUnity(distanceUnit, EditorGUI.DoubleField(currentRect, Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.x), textInputStyle));                            //, MinSnapWidth, MaxSnapWidth));
                            //(x:176.00, y:3.00, width:70.00, height:16.00)
                        }
                        if (GUI.changed)
                        {
                            modified         = true;
                            moveSnapVector.y = moveSnapVector.x;
                            moveSnapVector.z = moveSnapVector.x;
                        }
                        EditorGUI.showMixedValue = false;
                    }
                    else
                    {
                        GUI.changed = false;
                        {
                            currentRect.width  = 70;
                            currentRect.y      = 3;
                            currentRect.height = layoutHeight - (currentRect.y - 1);
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;
                            layoutX++;

                            moveSnapVector.x = Units.DistanceUnitToUnity(distanceUnit, EditorGUI.DoubleField(currentRect, Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.x), textInputStyle));                            //, MinSnapWidth, MaxSnapWidth));
                            //(x:175.00, y:3.00, width:70.00, height:16.00)


                            currentRect.x = layoutX;
                            layoutX      += currentRect.width;
                            layoutX++;

                            moveSnapVector.y = Units.DistanceUnitToUnity(distanceUnit, EditorGUI.DoubleField(currentRect, Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.y), textInputStyle));                            //, MinSnapWidth, MaxSnapWidth));
                            //(x:247.00, y:3.00, width:70.00, height:16.00)


                            currentRect.x = layoutX;
                            layoutX      += currentRect.width;

                            moveSnapVector.z = Units.DistanceUnitToUnity(distanceUnit, EditorGUI.DoubleField(currentRect, Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.z), textInputStyle));                            //, MinSnapWidth, MaxSnapWidth));
                            //(x:319.00, y:3.00, width:70.00, height:16.00)
                        }
                        modified = GUI.changed || modified;
                    }
                    #endregion

                    layoutX++;

                    #region "Position" Unit
                    DistanceUnit nextUnit = Units.CycleToNextUnit(distanceUnit);
                    GUIContent   unitText = Units.GetUnitGUIContent(distanceUnit);

                    currentRect.width  = 22;
                    currentRect.y      = 2;
                    currentRect.height = layoutHeight - currentRect.y;
                    currentRect.y     += barSize.y;
                    currentRect.x      = layoutX;
                    layoutX           += currentRect.width;

                    if (GUI.Button(currentRect, unitText, miniTextStyle))                    //(x:393.00, y:2.00, width:13.00, height:16.00)
                    {
                        distanceUnit = nextUnit;
                        modified     = true;
                    }
                    #endregion

                    layoutX += 2;

                    #region "Position" +/-
                    if (viewWidth >= 700)
                    {
                        currentRect.width  = 19;
                        currentRect.y      = 2;
                        currentRect.height = layoutHeight - (currentRect.y + 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        if (GUI.Button(currentRect, positionPlusLabel, EditorStyles.miniButtonLeft))
                        {
                            GridUtility.DoubleGridSize(); moveSnapVector = RealtimeCSG.CSGSettings.SnapVector;
                        }
                        //(x:410.00, y:2.00, width:19.00, height:15.00)
                        TooltipUtility.SetToolTip(positionPlusTooltip, currentRect);

                        currentRect.width  = 17;
                        currentRect.y      = 2;
                        currentRect.height = layoutHeight - (currentRect.y + 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        if (GUI.Button(currentRect, positionMinusLabel, EditorStyles.miniButtonRight))
                        {
                            GridUtility.HalfGridSize(); moveSnapVector = RealtimeCSG.CSGSettings.SnapVector;
                        }
                        //(x:429.00, y:2.00, width:17.00, height:15.00)
                        TooltipUtility.SetToolTip(positionMinnusTooltip, currentRect);
                    }
                    #endregion

                    layoutX += 2;

                    #region "Angle" label
                    if (viewWidth >= 750)
                    {
                        if (viewWidth >= 865)
                        {
                            currentRect.width  = 31;
                            currentRect.y      = 1;
                            currentRect.height = layoutHeight - currentRect.y;
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;

                            GUI.Label(currentRect, angleLargeLabel, miniTextStyle);
                            //(x:450.00, y:2.00, width:31.00, height:16.00)
                        }
                        else
                        {
                            currentRect.width  = 22;
                            currentRect.y      = 1;
                            currentRect.height = layoutHeight - currentRect.y;
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;

                            GUI.Label(currentRect, angleSmallLabel, miniTextStyle);
                            //(x:355.00, y:2.00, width:22.00, height:16.00)
                        }
                        TooltipUtility.SetToolTip(angleTooltip, currentRect);
                    }
                    #endregion

                    layoutX += 2;

                    #region "Angle" field
                    GUI.changed = false;
                    {
                        currentRect.width  = 70;
                        currentRect.y      = 3;
                        currentRect.height = layoutHeight - (currentRect.y - 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        rotationSnap = EditorGUI.FloatField(currentRect, rotationSnap, textInputStyle);                        //, MinSnapWidth, MaxSnapWidth);
                        //(x:486.00, y:3.00, width:70.00, height:16.00)
                        if (viewWidth <= 750)
                        {
                            TooltipUtility.SetToolTip(angleTooltip, currentRect);
                        }
                    }
                    modified = GUI.changed || modified;
                    #endregion

                    layoutX++;

                    #region "Angle" Unit
                    if (viewWidth >= 370)
                    {
                        currentRect.width  = 14;
                        currentRect.y      = 1;
                        currentRect.height = layoutHeight - currentRect.y;
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        GUI.Label(currentRect, angleUnitLabel, miniTextStyle);
                    }
                    #endregion

                    layoutX += 2;

                    #region "Angle" +/-
                    if (viewWidth >= 700)
                    {
                        currentRect.width  = 19;
                        currentRect.y      = 1;
                        currentRect.height = layoutHeight - (currentRect.y + 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        if (GUI.Button(currentRect, anglePlusLabel, EditorStyles.miniButtonLeft))
                        {
                            rotationSnap *= 2.0f; modified = true;
                        }
                        //(x:573.00, y:2.00, width:19.00, height:15.00)
                        TooltipUtility.SetToolTip(anglePlusTooltip, currentRect);


                        currentRect.width  = 17;
                        currentRect.y      = 1;
                        currentRect.height = layoutHeight - (currentRect.y + 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        if (GUI.Button(currentRect, angleMinusLabel, EditorStyles.miniButtonRight))
                        {
                            rotationSnap /= 2.0f; modified = true;
                        }
                        //(x:592.00, y:2.00, width:17.00, height:15.00)
                        TooltipUtility.SetToolTip(angleMinnusTooltip, currentRect);
                    }
                    #endregion

                    layoutX += 2;

                    #region "Scale" label
                    if (viewWidth >= 750)
                    {
                        if (viewWidth >= 865)
                        {
                            currentRect.width  = 31;
                            currentRect.y      = 1;
                            currentRect.height = layoutHeight - currentRect.y;
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;

                            GUI.Label(currentRect, scaleLargeLabel, miniTextStyle);
                            //(x:613.00, y:2.00, width:31.00, height:16.00)
                        }
                        else
                        {
                            currentRect.width  = 19;
                            currentRect.y      = 1;
                            currentRect.height = layoutHeight - currentRect.y;
                            currentRect.y     += barSize.y;
                            currentRect.x      = layoutX;
                            layoutX           += currentRect.width;

                            GUI.Label(currentRect, scaleSmallLabel, miniTextStyle);
                            //(x:495.00, y:2.00, width:19.00, height:16.00)
                        }
                        TooltipUtility.SetToolTip(scaleTooltip, currentRect);
                    }
                    #endregion

                    layoutX += 2;

                    #region "Scale" field
                    GUI.changed = false;
                    {
                        currentRect.width  = 70;
                        currentRect.y      = 3;
                        currentRect.height = layoutHeight - (currentRect.y - 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        scaleSnap = EditorGUI.FloatField(currentRect, scaleSnap, textInputStyle);                        //, MinSnapWidth, MaxSnapWidth);
                        //(x:648.00, y:3.00, width:70.00, height:16.00)
                        if (viewWidth <= 750)
                        {
                            TooltipUtility.SetToolTip(scaleTooltip, currentRect);
                        }
                    }
                    modified = GUI.changed || modified;
                    #endregion

                    layoutX++;

                    #region "Scale" Unit
                    if (viewWidth >= 370)
                    {
                        currentRect.width  = 15;
                        currentRect.y      = 1;
                        currentRect.height = layoutHeight - currentRect.y;
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        GUI.Label(currentRect, scaleUnitLabel, miniTextStyle);
                        //(x:722.00, y:2.00, width:15.00, height:16.00)
                    }
                    #endregion

                    layoutX += 2;

                    #region "Scale" +/-
                    if (viewWidth >= 700)
                    {
                        currentRect.width  = 19;
                        currentRect.y      = 2;
                        currentRect.height = layoutHeight - (currentRect.y + 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        if (GUI.Button(currentRect, scalePlusLabel, EditorStyles.miniButtonLeft))
                        {
                            scaleSnap *= 10.0f; modified = true;
                        }
                        //(x:741.00, y:2.00, width:19.00, height:15.00)
                        TooltipUtility.SetToolTip(scalePlusTooltip, currentRect);


                        currentRect.width  = 17;
                        currentRect.y      = 2;
                        currentRect.height = layoutHeight - (currentRect.y + 1);
                        currentRect.y     += barSize.y;
                        currentRect.x      = layoutX;
                        layoutX           += currentRect.width;

                        if (GUI.Button(currentRect, scaleMinusLabel, EditorStyles.miniButtonRight))
                        {
                            scaleSnap /= 10.0f; modified = true;
                        }
                        //(x:760.00, y:2.00, width:17.00, height:15.00)
                        TooltipUtility.SetToolTip(scaleMinnusTooltip, currentRect);
                    }
                    #endregion
                }
            }


            var prevLayoutX = layoutX;

            layoutX = viewWidth;


            #region "Rebuild"
            currentRect.width  = 27;
            currentRect.y      = 0;
            currentRect.height = layoutHeight - currentRect.y;
            currentRect.y     += barSize.y;
            layoutX           -= currentRect.width;
            currentRect.x      = layoutX;

            if (GUI.Button(currentRect, GUIStyleUtility.Skin.rebuildIcon, EditorStyles.toolbarButton))
            {
                Debug.Log("Starting complete rebuild");

                var text = new System.Text.StringBuilder();

                InternalCSGModelManager.skipRefresh = true;
                RealtimeCSG.CSGSettings.Reload();
                SceneViewEventHandler.UpdateDefines();

                InternalCSGModelManager.registerTime        = 0.0;
                InternalCSGModelManager.validateTime        = 0.0;
                InternalCSGModelManager.updateHierarchyTime = 0.0;

                var startTime = EditorApplication.timeSinceStartup;
                InternalCSGModelManager.Rebuild();
                InternalCSGModelManager.OnHierarchyModified();
                var hierarchy_update_endTime = EditorApplication.timeSinceStartup;
                text.AppendFormat(CultureInfo.InvariantCulture, "Full hierarchy rebuild in {0:F} ms. ", (hierarchy_update_endTime - startTime) * 1000);


                CSGBindings.RebuildAll();
                var csg_endTime = EditorApplication.timeSinceStartup;
                text.AppendFormat(CultureInfo.InvariantCulture, "Full CSG rebuild done in {0:F} ms. ", (csg_endTime - hierarchy_update_endTime) * 1000);

                InternalCSGModelManager.UpdateMeshes(text);

                updateSurfaces = true;
                SceneViewEventHandler.ResetUpdateRoutine();
                RealtimeCSG.CSGSettings.Save();
                InternalCSGModelManager.skipRefresh = false;

                Debug.Log(text.ToString());
            }
            //(x:1442.00, y:0.00, width:27.00, height:18.00)
            TooltipUtility.SetToolTip(rebuildTooltip, currentRect);
            #endregion

            if (viewWidth >= 800)
            {
                layoutX -= 6;                 //(x:1436.00, y:0.00, width:6.00, height:6.00)
            }
            #region "Helper Surface Flags" Mask
            if (viewWidth >= 250)
            {
                GUI.changed = false;
                {
                    prevLayoutX += 8;                      // extra space
                    prevLayoutX += 26;                     // width of "Show wireframe" button

                    currentRect.width = Mathf.Max(20, Mathf.Min(165, (viewWidth - prevLayoutX - currentRect.width)));

                    currentRect.y      = 0;
                    currentRect.height = layoutHeight - currentRect.y;
                    currentRect.y     += barSize.y;
                    layoutX           -= currentRect.width;
                    currentRect.x      = layoutX;

                    SurfaceVisibilityPopup.Button(currentRect);

                    //(x:1267.00, y:2.00, width:165.00, height:16.00)
                    TooltipUtility.SetToolTip(helperSurfacesTooltip, currentRect);
                }
                if (GUI.changed)
                {
                    updateSurfaces = true;
                    modified       = true;
                }
            }
            #endregion

            #region "Show wireframe" button
            GUI.changed        = false;
            currentRect.width  = 26;
            currentRect.y      = 0;
            currentRect.height = layoutHeight - currentRect.y;
            currentRect.y     += barSize.y;
            layoutX           -= currentRect.width;
            currentRect.x      = layoutX;

            if (showWireframe)
            {
                showWireframe = GUI.Toggle(currentRect, showWireframe, GUIStyleUtility.Skin.wireframe, EditorStyles.toolbarButton);
                //(x:1237.00, y:0.00, width:26.00, height:18.00)
            }
            else
            {
                showWireframe = GUI.Toggle(currentRect, showWireframe, GUIStyleUtility.Skin.wireframeOn, EditorStyles.toolbarButton);
                //(x:1237.00, y:0.00, width:26.00, height:18.00)
            }
            TooltipUtility.SetToolTip(showWireframeTooltip, currentRect);
            if (GUI.changed)
            {
                wireframeModified = true;
                modified          = true;
            }
            #endregion



            #region Capture mouse clicks in empty space
            var mousePoint = Event.current.mousePosition;
            int controlID  = GUIUtility.GetControlID(BottomBarEditorOverlayHash, FocusType.Passive, barSize);
            switch (Event.current.GetTypeForControl(controlID))
            {
            case EventType.MouseDown:       { if (barSize.Contains(mousePoint))
                                              {
                                                  GUIUtility.hotControl = controlID; GUIUtility.keyboardControl = controlID; Event.current.Use();
                                              }
                                              break; }

            case EventType.MouseMove:       { if (barSize.Contains(mousePoint))
                                              {
                                                  Event.current.Use();
                                              }
                                              break; }

            case EventType.MouseUp:         { if (GUIUtility.hotControl == controlID)
                                              {
                                                  GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; Event.current.Use();
                                              }
                                              break; }

            case EventType.MouseDrag:       { if (GUIUtility.hotControl == controlID)
                                              {
                                                  Event.current.Use();
                                              }
                                              break; }

            case EventType.ScrollWheel: { if (barSize.Contains(mousePoint))
                                          {
                                              Event.current.Use();
                                          }
                                          break; }
            }
            #endregion



            #region Store modified values
            rotationSnap     = Mathf.Max(1.0f, Mathf.Abs((360 + (rotationSnap % 360))) % 360);
            moveSnapVector.x = Mathf.Max(1.0f / 1024.0f, moveSnapVector.x);
            moveSnapVector.y = Mathf.Max(1.0f / 1024.0f, moveSnapVector.y);
            moveSnapVector.z = Mathf.Max(1.0f / 1024.0f, moveSnapVector.z);

            scaleSnap = Mathf.Max(MathConstants.MinimumScale, scaleSnap);

            RealtimeCSG.CSGSettings.SnapToGrid   = snapToGrid;
            RealtimeCSG.CSGSettings.SnapVector   = moveSnapVector;
            RealtimeCSG.CSGSettings.SnapRotation = rotationSnap;
            RealtimeCSG.CSGSettings.SnapScale    = scaleSnap;
            RealtimeCSG.CSGSettings.UniformGrid  = uniformGrid;
//			RealtimeCSG.Settings.SnapVertex					= vertexSnap;
            RealtimeCSG.CSGSettings.GridVisible           = showGrid;
            RealtimeCSG.CSGSettings.LockAxisX             = lockAxisX;
            RealtimeCSG.CSGSettings.LockAxisY             = lockAxisY;
            RealtimeCSG.CSGSettings.LockAxisZ             = lockAxisZ;
            RealtimeCSG.CSGSettings.DistanceUnit          = distanceUnit;
            RealtimeCSG.CSGSettings.VisibleHelperSurfaces = helperSurfaces;

            if (wireframeModified)
            {
                RealtimeCSG.CSGSettings.SetWireframeShown(sceneView, showWireframe);
            }

            if (updateSurfaces)
            {
                MeshInstanceManager.UpdateHelperSurfaceVisibility();
            }

            if (modified)
            {
                GUI.changed = true;
                RealtimeCSG.CSGSettings.UpdateSnapSettings();
                RealtimeCSG.CSGSettings.Save();
                SceneView.RepaintAll();
            }
            #endregion
        }
예제 #10
0
        static void OnBottomBarGUI(SceneView sceneView)
        {
            var  snapToGrid        = RealtimeCSG.CSGSettings.SnapToGrid;
            var  uniformGrid       = RealtimeCSG.CSGSettings.UniformGrid;
            var  moveSnapVector    = RealtimeCSG.CSGSettings.SnapVector;
            var  rotationSnap      = RealtimeCSG.CSGSettings.SnapRotation;
            var  scaleSnap         = RealtimeCSG.CSGSettings.SnapScale;
            var  showGrid          = RealtimeCSG.CSGSettings.GridVisible;
            var  lockAxisX         = RealtimeCSG.CSGSettings.LockAxisX;
            var  lockAxisY         = RealtimeCSG.CSGSettings.LockAxisY;
            var  lockAxisZ         = RealtimeCSG.CSGSettings.LockAxisZ;
            var  distanceUnit      = RealtimeCSG.CSGSettings.DistanceUnit;
            var  helperSurfaces    = RealtimeCSG.CSGSettings.VisibleHelperSurfaces;
            var  showWireframe     = RealtimeCSG.CSGSettings.IsWireframeShown(sceneView);
            var  updateSurfaces    = false;
            bool wireframeModified = false;

            var viewWidth = sceneView.position.width;

            bool modified = false;

            EditorGUILayout.BeginHorizontal(GUIStyleUtility.ContentEmpty);
            {
                EditorGUI.BeginChangeCheck();
                {
                    var skin = GUIStyleUtility.Skin;
                    if (showGrid)
                    {
                        showGrid = GUILayout.Toggle(showGrid, skin.gridIconOn, EditorStyles.toolbarButton);
                    }
                    else
                    {
                        showGrid = GUILayout.Toggle(showGrid, skin.gridIcon, EditorStyles.toolbarButton);
                    }
                    TooltipUtility.SetToolTip(showGridTooltip);

                    if (viewWidth >= 800)
                    {
                        EditorGUILayout.Space();
                    }

                    if (viewWidth >= 200)
                    {
                        var prevBackgroundColor   = GUI.backgroundColor;
                        var lockedBackgroundColor = skin.lockedBackgroundColor;
                        if (lockAxisX)
                        {
                            GUI.backgroundColor = lockedBackgroundColor;
                        }
                        lockAxisX = !GUILayout.Toggle(!lockAxisX, xLabel, skin.xToolbarButton);
                        if (lockAxisX)
                        {
                            TooltipUtility.SetToolTip(xTooltipOn);
                        }
                        else
                        {
                            TooltipUtility.SetToolTip(xTooltipOff);
                        }
                        GUI.backgroundColor = prevBackgroundColor;

                        if (lockAxisY)
                        {
                            GUI.backgroundColor = lockedBackgroundColor;
                        }
                        lockAxisY = !GUILayout.Toggle(!lockAxisY, yLabel, skin.yToolbarButton);
                        if (lockAxisY)
                        {
                            TooltipUtility.SetToolTip(yTooltipOn);
                        }
                        else
                        {
                            TooltipUtility.SetToolTip(yTooltipOff);
                        }
                        GUI.backgroundColor = prevBackgroundColor;

                        if (lockAxisZ)
                        {
                            GUI.backgroundColor = lockedBackgroundColor;
                        }
                        lockAxisZ = !GUILayout.Toggle(!lockAxisZ, zLabel, skin.zToolbarButton);
                        if (lockAxisZ)
                        {
                            TooltipUtility.SetToolTip(zTooltipOn);
                        }
                        else
                        {
                            TooltipUtility.SetToolTip(zTooltipOff);
                        }
                        GUI.backgroundColor = prevBackgroundColor;
                    }
                }
                modified = EditorGUI.EndChangeCheck() || modified;

                if (viewWidth >= 800)
                {
                    EditorGUILayout.Space();
                }

                EditorGUI.BeginChangeCheck();
                {
                    if (viewWidth >= 475)
                    {
                        if (snapToGrid && viewWidth >= 310)
                        {
                            snapToGrid = GUILayout.Toggle(snapToGrid, GUIStyleUtility.Skin.snappingIconOn, EditorStyles.toolbarButton);
                            TooltipUtility.SetToolTip(snapToGridTooltip);
                            if (viewWidth >= 865)
                            {
                                uniformGrid = GUILayout.Toggle(uniformGrid, positionLargeLabel, miniTextStyle);
                            }
                            else
                            {
                                uniformGrid = GUILayout.Toggle(uniformGrid, positionSmallLabel, miniTextStyle);
                            }
                            TooltipUtility.SetToolTip(positionTooltip);
                        }
                        else
                        {
                            snapToGrid = GUILayout.Toggle(snapToGrid, GUIStyleUtility.Skin.snappingIcon, EditorStyles.toolbarButton);
                            TooltipUtility.SetToolTip(snapToGridTooltip);
                        }
                    }
                }
                modified = EditorGUI.EndChangeCheck() || modified;
                if (viewWidth >= 310)
                {
                    if (snapToGrid)
                    {
                        if (uniformGrid || viewWidth < 515)
                        {
                            EditorGUI.showMixedValue = !(moveSnapVector.x == moveSnapVector.y && moveSnapVector.x == moveSnapVector.z);
                            EditorGUI.BeginChangeCheck();
                            {
                                moveSnapVector.x = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.x), textInputStyle, MinSnapWidth, MaxSnapWidth));
                            }
                            if (EditorGUI.EndChangeCheck())
                            {
                                modified         = true;
                                moveSnapVector.y = moveSnapVector.x;
                                moveSnapVector.z = moveSnapVector.x;
                            }
                            EditorGUI.showMixedValue = false;
                        }
                        else
                        {
                            EditorGUI.BeginChangeCheck();
                            {
                                moveSnapVector.x = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.x), textInputStyle, MinSnapWidth, MaxSnapWidth));
                                moveSnapVector.y = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.y), textInputStyle, MinSnapWidth, MaxSnapWidth));
                                moveSnapVector.z = Units.DistanceUnitToUnity(distanceUnit, EditorGUILayout.DoubleField(Units.UnityToDistanceUnit(distanceUnit, moveSnapVector.z), textInputStyle, MinSnapWidth, MaxSnapWidth));
                            }
                            modified = EditorGUI.EndChangeCheck() || modified;
                        }
                        DistanceUnit nextUnit = Units.CycleToNextUnit(distanceUnit);
                        GUIContent   unitText = Units.GetUnitGUIContent(distanceUnit);
                        if (GUILayout.Button(unitText, miniTextStyle))
                        {
                            distanceUnit = nextUnit;
                            modified     = true;
                        }
                        if (viewWidth >= 700)
                        {
                            if (GUILayout.Button(positionPlusLabel, EditorStyles.miniButtonLeft))
                            {
                                GridUtility.DoubleGridSize(); moveSnapVector = RealtimeCSG.CSGSettings.SnapVector;
                            }
                            TooltipUtility.SetToolTip(positionPlusTooltip);
                            if (GUILayout.Button(positionMinusLabel, EditorStyles.miniButtonRight))
                            {
                                GridUtility.HalfGridSize(); moveSnapVector = RealtimeCSG.CSGSettings.SnapVector;
                            }
                            TooltipUtility.SetToolTip(positionMinnusTooltip);
                        }
                        if (viewWidth >= 750)
                        {
                            if (viewWidth >= 865)
                            {
                                GUILayout.Label(angleLargeLabel, miniTextStyle);
                            }
                            else
                            {
                                GUILayout.Label(angleSmallLabel, miniTextStyle);
                            }
                            TooltipUtility.SetToolTip(angleTooltip);
                        }
                        EditorGUI.BeginChangeCheck();
                        {
                            rotationSnap = EditorGUILayout.FloatField(rotationSnap, textInputStyle, MinSnapWidth, MaxSnapWidth);
                            if (viewWidth <= 750)
                            {
                                TooltipUtility.SetToolTip(angleTooltip);
                            }
                        }
                        modified = EditorGUI.EndChangeCheck() || modified;

                        if (viewWidth >= 370)
                        {
                            GUILayout.Label(angleUnitLabel, miniTextStyle);
                        }
                        if (viewWidth >= 700)
                        {
                            if (GUILayout.Button(anglePlusLabel, EditorStyles.miniButtonLeft))
                            {
                                rotationSnap *= 2.0f; modified = true;
                            }
                            TooltipUtility.SetToolTip(anglePlusTooltip);
                            if (GUILayout.Button(angleMinusLabel, EditorStyles.miniButtonRight))
                            {
                                rotationSnap /= 2.0f; modified = true;
                            }
                            TooltipUtility.SetToolTip(angleMinnusTooltip);
                        }

                        if (viewWidth >= 750)
                        {
                            if (viewWidth >= 865)
                            {
                                GUILayout.Label(scaleLargeLabel, miniTextStyle);
                            }
                            else
                            {
                                GUILayout.Label(scaleSmallLabel, miniTextStyle);
                            }
                            TooltipUtility.SetToolTip(scaleTooltip);
                        }
                        EditorGUI.BeginChangeCheck();
                        {
                            scaleSnap = EditorGUILayout.FloatField(scaleSnap, textInputStyle, MinSnapWidth, MaxSnapWidth);
                            if (viewWidth <= 750)
                            {
                                TooltipUtility.SetToolTip(scaleTooltip);
                            }
                        }
                        modified = EditorGUI.EndChangeCheck() || modified;
                        if (viewWidth >= 370)
                        {
                            GUILayout.Label(scaleUnitLabel, miniTextStyle);
                        }
                        if (viewWidth >= 700)
                        {
                            if (GUILayout.Button(scalePlusLabel, EditorStyles.miniButtonLeft))
                            {
                                scaleSnap *= 10.0f; modified = true;
                            }
                            TooltipUtility.SetToolTip(scalePlusTooltip);
                            if (GUILayout.Button(scaleMinusLabel, EditorStyles.miniButtonRight))
                            {
                                scaleSnap /= 10.0f; modified = true;
                            }
                            TooltipUtility.SetToolTip(scaleMinnusTooltip);
                        }
                    }
                }

                if (viewWidth >= 750)
                {
                    GUILayout.FlexibleSpace();
                }
                EditorGUI.BeginChangeCheck();
                if (showWireframe)
                {
                    showWireframe = GUILayout.Toggle(showWireframe, GUIStyleUtility.Skin.wireframe, EditorStyles.toolbarButton);
                }
                else
                {
                    showWireframe = GUILayout.Toggle(showWireframe, GUIStyleUtility.Skin.wireframeOn, EditorStyles.toolbarButton);
                }
                TooltipUtility.SetToolTip(showWireframeTooltip);
                if (EditorGUI.EndChangeCheck())
                {
                    wireframeModified = true;
                    modified          = true;
                }

                if (viewWidth >= 250)
                {
                    EditorGUI.BeginChangeCheck();
                    {
                        helperSurfaces = (HelperSurfaceFlags)EditorGUILayout.MaskField((int)helperSurfaces, helperSurfaceFlagStrings, EnumMaxWidth, EnumMinWidth);
                        TooltipUtility.SetToolTip(helperSurfacesTooltip);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        updateSurfaces = true;
                        modified       = true;
                    }
                }

                if (viewWidth >= 800)
                {
                    EditorGUILayout.Space();
                }

                if (GUILayout.Button(GUIStyleUtility.Skin.rebuildIcon, EditorStyles.toolbarButton))
                {
                    Debug.Log("Starting complete rebuild");
                    InternalCSGModelManager.skipRefresh = true;
                    RealtimeCSG.CSGSettings.Reload();
                    SceneViewEventHandler.UpdateDefines();

                    var startTime = EditorApplication.timeSinceStartup;
                    InternalCSGModelManager.Rebuild();
                    InternalCSGModelManager.OnHierarchyModified();
                    var hierarchy_update_endTime = EditorApplication.timeSinceStartup;

                    CSGBindings.RebuildAll();
                    var csg_endTime = EditorApplication.timeSinceStartup;

                    InternalCSGModelManager.UpdateMeshes();
                    MeshInstanceManager.UpdateHelperSurfaceVisibility();
                    var meshupdate_endTime = EditorApplication.timeSinceStartup;

                    updateSurfaces = true;
                    SceneViewEventHandler.ResetUpdateRoutine();
                    RealtimeCSG.CSGSettings.Save();
                    InternalCSGModelManager.skipRefresh = false;
                    Debug.Log(string.Format(CultureInfo.InvariantCulture,
                                            "Full hierarchy rebuild in {0:F} ms. Full CSG rebuild done in {1:F} ms. Mesh update done in {2:F} ms.",
                                            (hierarchy_update_endTime - startTime) * 1000,
                                            (csg_endTime - hierarchy_update_endTime) * 1000,
                                            (meshupdate_endTime - csg_endTime) * 1000
                                            ));
                }
                TooltipUtility.SetToolTip(rebuildTooltip);
            }
            EditorGUILayout.EndHorizontal();

            var mousePoint  = Event.current.mousePosition;
            var currentArea = GUILayoutUtility.GetLastRect();
            int controlID   = GUIUtility.GetControlID(BottomBarEditorOverlayHash, FocusType.Passive, currentArea);

            switch (Event.current.GetTypeForControl(controlID))
            {
            case EventType.MouseDown:       { if (currentArea.Contains(mousePoint))
                                              {
                                                  GUIUtility.hotControl = controlID; GUIUtility.keyboardControl = controlID; Event.current.Use();
                                              }
                                              break; }

            case EventType.MouseMove:       { if (currentArea.Contains(mousePoint))
                                              {
                                                  Event.current.Use();
                                              }
                                              break; }

            case EventType.MouseUp:         { if (GUIUtility.hotControl == controlID)
                                              {
                                                  GUIUtility.hotControl = 0; GUIUtility.keyboardControl = 0; Event.current.Use();
                                              }
                                              break; }

            case EventType.MouseDrag:       { if (GUIUtility.hotControl == controlID)
                                              {
                                                  Event.current.Use();
                                              }
                                              break; }

            case EventType.ScrollWheel: { if (currentArea.Contains(mousePoint))
                                          {
                                              Event.current.Use();
                                          }
                                          break; }
            }

            rotationSnap     = Mathf.Max(1.0f, Mathf.Abs((360 + (rotationSnap % 360))) % 360);
            moveSnapVector.x = Mathf.Max(1.0f / 1024.0f, moveSnapVector.x);
            moveSnapVector.y = Mathf.Max(1.0f / 1024.0f, moveSnapVector.y);
            moveSnapVector.z = Mathf.Max(1.0f / 1024.0f, moveSnapVector.z);

            scaleSnap = Mathf.Max(MathConstants.MinimumScale, scaleSnap);

            RealtimeCSG.CSGSettings.SnapToGrid   = snapToGrid;
            RealtimeCSG.CSGSettings.SnapVector   = moveSnapVector;
            RealtimeCSG.CSGSettings.SnapRotation = rotationSnap;
            RealtimeCSG.CSGSettings.SnapScale    = scaleSnap;
            RealtimeCSG.CSGSettings.UniformGrid  = uniformGrid;
//			RealtimeCSG.Settings.SnapVertex					= vertexSnap;
            RealtimeCSG.CSGSettings.GridVisible           = showGrid;
            RealtimeCSG.CSGSettings.LockAxisX             = lockAxisX;
            RealtimeCSG.CSGSettings.LockAxisY             = lockAxisY;
            RealtimeCSG.CSGSettings.LockAxisZ             = lockAxisZ;
            RealtimeCSG.CSGSettings.DistanceUnit          = distanceUnit;
            RealtimeCSG.CSGSettings.VisibleHelperSurfaces = helperSurfaces;

            if (wireframeModified)
            {
                RealtimeCSG.CSGSettings.SetWireframeShown(sceneView, showWireframe);
            }

            if (updateSurfaces)
            {
                MeshInstanceManager.UpdateHelperSurfaceVisibility();
            }

            if (modified)
            {
                GUI.changed = true;
                RealtimeCSG.CSGSettings.UpdateSnapSettings();
                RealtimeCSG.CSGSettings.Save();
                SceneView.RepaintAll();
            }
        }