public static bool UpdateMesh(GeneratedMeshContents generatedMesh,
                                      GeneratedMeshDescription inputMeshDescription,
                                      RenderSurfaceType renderSurfaceType,
                                      ref bool outputHasGeneratedNormals,
                                      ref Mesh sharedMesh)
        {
            var startUpdateMeshTime = EditorApplication.timeSinceStartup;

            {
                MeshInstanceManager.ClearMesh(ref outputHasGeneratedNormals, ref sharedMesh);

                // finally, we start filling our (sub)meshes using the C# arrays
                sharedMesh.vertices = generatedMesh.positions;
                if (generatedMesh.normals != null)
                {
                    sharedMesh.normals = generatedMesh.normals;
                }
                if (generatedMesh.tangents != null)
                {
                    sharedMesh.tangents = generatedMesh.tangents;
                }
//				if (generatedMesh.colors   != null) sharedMesh.colors	= generatedMesh.colors;
                if (generatedMesh.uv0 != null)
                {
                    sharedMesh.uv = generatedMesh.uv0;
                }

                // fill the mesh with the given indices
                sharedMesh.SetTriangles(generatedMesh.indices, 0, calculateBounds: true);
                //sharedMesh.RecalculateBounds();
                //sharedMesh.bounds = generatedMesh.bounds; // why doesn't this work?
            }
            updateMeshTime += EditorApplication.timeSinceStartup - startUpdateMeshTime;

            if (renderSurfaceType != RenderSurfaceType.Normal)
            {
                outputHasGeneratedNormals = ((inputMeshDescription.meshQuery.UsedVertexChannels & VertexChannelFlags.Normal) != 0);
            }
            return(true);
        }
Example #2
0
        private void Draw(Rect rect)
        {
            var allVisibleSurfaces = (int)HelperSurfaceFlags.ShowVisibleSurfaces;
            var allHelperSurfaces  = s_Flags.allSurfaces & ~allVisibleSurfaces;

            var drawPos = new Rect(kFrameWidth, kFrameWidth, rect.width - 2 * kFrameWidth, kLineHeight);

            var helperSurfaces = (int)RealtimeCSG.CSGSettings.VisibleHelperSurfaces;

            EditorGUI.BeginChangeCheck();
            GUI.Toggle(drawPos, helperSurfaces == allVisibleSurfaces, s_Flags.onlyVisibleContent, CSG_GUIStyleUtility.Skin.menuItem);
            if (EditorGUI.EndChangeCheck())
            {
                RealtimeCSG.CSGSettings.VisibleHelperSurfaces = (HelperSurfaceFlags)allVisibleSurfaces;
                MeshInstanceManager.UpdateHelperSurfaceVisibility();
                RealtimeCSG.CSGSettings.Save();
                CSG_EditorGUIUtility.UpdateSceneViews();
            }
            drawPos.y += kLineHeight;

            EditorGUI.BeginChangeCheck();
            GUI.Toggle(drawPos, helperSurfaces == allHelperSurfaces, s_Flags.allHelperContent, CSG_GUIStyleUtility.Skin.menuItem);
            if (EditorGUI.EndChangeCheck())
            {
                RealtimeCSG.CSGSettings.VisibleHelperSurfaces = (HelperSurfaceFlags)allHelperSurfaces;
                MeshInstanceManager.UpdateHelperSurfaceVisibility();
                RealtimeCSG.CSGSettings.Save();
                CSG_EditorGUIUtility.UpdateSceneViews();
            }
            drawPos.y += kLineHeight;

            drawPos.y += 4;

            for (int i = 0; i < s_Flags.helperSurfaceFlagContent.Length; i++)
            {
                var flag = s_Flags.helperSurfaceFlagValues[i];
                DrawListElement(drawPos, s_Flags.helperSurfaceFlagContent[i], helperSurfaces, flag);
                drawPos.y += kLineHeight;
            }
        }
Example #3
0
 void UpdateBrushMeshes(HashSet <CSGBrush> brushes, HashSet <CSGModel> models)
 {
     foreach (var brush in brushes)
     {
         try
         {
             brush.EnsureInitialized();
             ShapeUtility.CheckMaterials(brush.Shape);
         }
         finally { }
     }
     foreach (var brush in brushes)
     {
         try
         {
             InternalCSGModelManager.CheckSurfaceModifications(brush, true);
             InternalCSGModelManager.ValidateBrush(brush);
         }
         finally { }
     }
     MeshInstanceManager.UpdateHelperSurfaceVisibility(force: true);
 }
        public static GameObject[] GetModelMeshes(CSGModel model)
        {
            var meshContainer = model.generatedMeshes;
            var meshInstances = MeshInstanceManager.GetAllModelMeshInstances(meshContainer);

            if (meshInstances == null)
            {
                return(new GameObject[0]);
            }

            var gameObjects = new List <GameObject>();

            for (var i = 0; i < meshInstances.Length; i++)
            {
                if (!meshInstances[i] ||
                    meshInstances[i].RenderSurfaceType != RenderSurfaceType.Normal)
                {
                    continue;
                }
                gameObjects.Add(meshInstances[i].gameObject);
            }

            return(gameObjects.ToArray());
        }
        public bool DragUpdated(SceneView sceneView)
        {
            var camera = sceneView.camera;
            LegacyBrushIntersection intersection;
            int      highlight_surface = -1;
            CSGBrush highlight_brush   = null;

            if (!SceneQueryUtility.FindWorldIntersection(camera, Event.current.mousePosition, out intersection))
            {
                highlight_brush   = null;
                highlight_surface = -1;
            }
            else
            {
                highlight_brush   = intersection.brush;
                highlight_surface = intersection.surfaceIndex;
            }

            bool modified = true;

            if (hoverBrushSurfaces != null)
            {
                for (int i = 0; i < hoverBrushSurfaces.Length; i++)
                {
                    if (hoverBrushSurfaces[i].brush == highlight_brush &&
                        hoverBrushSurfaces[i].surfaceIndex == highlight_surface)
                    {
                        modified = false;
                        break;
                    }
                }
            }

            bool needUpdate = false;

            if (modified)
            {
                hoverOnSelectedSurfaces = false;
                if (hoverBrushSurfaces != null)
                {
                    needUpdate = true;
                    RestoreMaterials(hoverBrushSurfaces);
                }

                hoverBrushSurfaces = HoverOnBrush(new CSGBrush[1] {
                    highlight_brush
                }, highlight_surface);

                if (hoverBrushSurfaces != null)
                {
                    hoverBrushSurfaces = GetCombinedBrushes(hoverBrushSurfaces);
                    needUpdate         = true;
                    using (new UndoGroup(hoverBrushSurfaces, "Modified materials"))
                    {
                        RememberMaterials(hoverBrushSurfaces);
                        ApplyMaterial(hoverBrushSurfaces);
                    }
                }
            }
            else
            {
                bool prevSelectAllSurfaces = selectAllSurfaces;
                selectAllSurfaces = Event.current.shift;

                if (prevSelectAllSurfaces != selectAllSurfaces)
                {
                    if (hoverBrushSurfaces != null)
                    {
                        needUpdate = true;

                        using (new UndoGroup(hoverBrushSurfaces, "Modified materials"))
                        {
                            ApplyMaterial(hoverBrushSurfaces);
                        }
                    }
                }
            }

            if (needUpdate)
            {
                InternalCSGModelManager.UpdateMeshes();
                MeshInstanceManager.UpdateHelperSurfaceVisibility();
            }
            return(needUpdate);
        }
        public bool DragUpdated(Transform transformInInspector, Rect selectionRect)
        {
            var highlight_brushes = transformInInspector.GetComponentsInChildren <CSGBrush>();

            bool prevSelectAllSurfaces = selectAllSurfaces;

            selectAllSurfaces = true;
            bool modified = true;

            if (hoverBrushSurfaces != null)
            {
                if (hoverBrushSurfaces.Length != highlight_brushes.Length)
                {
                    modified = false;
                }
                else
                {
                    modified = false;
                    for (int i = 0; i < highlight_brushes.Length; i++)
                    {
                        var  find_brush = highlight_brushes[i];
                        bool found      = false;
                        for (int j = 0; j < hoverBrushSurfaces.Length; j++)
                        {
                            if (hoverBrushSurfaces[j].surfaceIndex == -1 &&
                                hoverBrushSurfaces[j].brush == find_brush)
                            {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            modified = true;
                            break;
                        }
                    }
                }
            }


            bool needUpdate = false;

            if (modified)
            {
                hoverOnSelectedSurfaces = false;
                if (hoverBrushSurfaces != null)
                {
                    needUpdate = true;
                    RestoreMaterials(hoverBrushSurfaces);
                }

                hoverBrushSurfaces = HoverOnBrush(highlight_brushes, -1);

                if (hoverBrushSurfaces != null)
                {
                    hoverBrushSurfaces = GetCombinedBrushes(hoverBrushSurfaces);
                    needUpdate         = true;
                    using (new UndoGroup(hoverBrushSurfaces, "Modified materials"))
                    {
                        RememberMaterials(hoverBrushSurfaces);
                        ApplyMaterial(hoverBrushSurfaces);
                    }
                }
            }
            else
            {
                if (prevSelectAllSurfaces != selectAllSurfaces)
                {
                    if (hoverBrushSurfaces != null)
                    {
                        needUpdate = true;
                        using (new UndoGroup(hoverBrushSurfaces, "Modified materials"))
                        {
                            ApplyMaterial(hoverBrushSurfaces);
                        }
                    }
                }
            }

            if (needUpdate)
            {
                InternalCSGModelManager.UpdateMeshes();
                MeshInstanceManager.UpdateHelperSurfaceVisibility();
            }
            return(needUpdate);
        }
        internal static void OnScene(SceneView sceneView)
        {
            if (!RealtimeCSG.CSGSettings.EnableRealtimeCSG)
            {
                return;
            }

            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }
            UpdateLoop.UpdateOnSceneChange();

            if (!RealtimeCSG.CSGSettings.EnableRealtimeCSG)
            {
                ColorSettings.isInitialized = false;
            }
            else
            if (!ColorSettings.isInitialized)
            {
                if (Event.current.type == EventType.Repaint)
                {
                    ColorSettings.Update();
                }
            }

            if (!UpdateLoop.IsActive())
            {
                UpdateLoop.ResetUpdateRoutine();
            }

            if (Event.current.type == EventType.MouseDown ||
                Event.current.type == EventType.MouseDrag)
            {
                mousePressed = true;
            }
            else if (Event.current.type == EventType.MouseUp ||
                     Event.current.type == EventType.MouseMove)
            {
                mousePressed = false;
            }

            SceneDragToolManager.OnHandleDragAndDrop(sceneView);
            RectangleSelectionManager.Update(sceneView);
            EditModeManager.InitSceneGUI(sceneView);

            if (Event.current.type == EventType.Repaint)
            {
                MeshInstanceManager.RenderHelperSurfaces(sceneView);
            }

            if (Event.current.type == EventType.Repaint)
            {
                SceneToolRenderer.OnPaint(sceneView);
            }
            else
            //if (fallbackGUI)
            {
                SceneViewBottomBarGUI.ShowGUI(sceneView);
                SceneViewInfoGUI.DrawInfoGUI(sceneView);
            }

            EditModeManager.OnSceneGUI(sceneView);

            //if (fallbackGUI)
            {
                TooltipUtility.InitToolTip(sceneView);
                if (Event.current.type == EventType.Repaint)
                {
                    SceneViewBottomBarGUI.ShowGUI(sceneView);
                    SceneViewInfoGUI.DrawInfoGUI(sceneView);
                }
                if (!mousePressed)
                {
                    Handles.BeginGUI();
                    TooltipUtility.DrawToolTip(getLastRect: false);
                    Handles.EndGUI();
                }
            }

            if (Event.current.type == EventType.Layout)
            {
                var currentFocusControl = CSGHandles.FocusControl;
                if (prevFocusControl != currentFocusControl)
                {
                    prevFocusControl = currentFocusControl;
                    HandleUtility.Repaint();
                }
            }
        }
        public override void OnInspectorGUI()
        {
            GUILayout.BeginVertical(GUI.skin.box);
            {
                GUILayout.Label("A hidden CSG model, and all it's brushes and operations, is contained by this object. This will automatically be removed at build time.", GUIStyleUtility.wrapLabel);
                GUILayout.Space(10);
                if (GUILayout.Button("Revert back to CSG model"))
                {
                    Undo.IncrementCurrentGroup();
                    var groupIndex = Undo.GetCurrentGroup();
                    Undo.SetCurrentGroupName("Reverted to former CSG model");
                    try
                    {
                        var selection    = new List <UnityEngine.Object>();
                        var updateScenes = new HashSet <Scene>();
                        foreach (var target in targets)
                        {
                            var exportedModel = target as CSGModelExported;
                            if (!exportedModel)
                            {
                                continue;
                            }

                            exportedModel.disarm    = true;
                            exportedModel.hideFlags = HideFlags.DontSaveInBuild;
                            updateScenes.Add(exportedModel.gameObject.scene);
                            if (exportedModel.containedModel)
                            {
                                Undo.RecordObject(exportedModel.containedModel, "Revert model");
                                selection.Add(exportedModel.containedModel.gameObject);
                                exportedModel.containedModel.transform.SetParent(exportedModel.transform.parent, true);
                                exportedModel.containedModel.transform.SetSiblingIndex(exportedModel.transform.GetSiblingIndex());
                                exportedModel.containedModel.gameObject.SetActive(true);
                                exportedModel.containedModel.gameObject.hideFlags = HideFlags.None;
                                EditorUtility.SetDirty(exportedModel.containedModel);
                                Undo.DestroyObjectImmediate(exportedModel);
                            }
                            else
                            {
                                MeshInstanceManager.ReverseExport(exportedModel);
                                selection.Add(exportedModel.gameObject);
                                EditorUtility.SetDirty(exportedModel);
                                Undo.DestroyObjectImmediate(exportedModel);
                            }
                        }
                        Selection.objects = selection.ToArray();

                        InternalCSGModelManager.skipRefresh = true;

                        BrushOutlineManager.ClearOutlines();
                        //CSGModelManager.Refresh(forceHierarchyUpdate: true);
                        InternalCSGModelManager.Rebuild();
                        foreach (var scene in updateScenes)
                        {
                            UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene);
                        }
                    }
                    finally
                    {
                        InternalCSGModelManager.skipRefresh = false;
                        Undo.CollapseUndoOperations(groupIndex);
                    }
                }
            }
            GUILayout.Space(30);
            if (GUILayout.Button("Remove hidden CSG model"))
            {
                Undo.IncrementCurrentGroup();
                var groupIndex = Undo.GetCurrentGroup();
                Undo.SetCurrentGroupName("Removed hidden CSG model");
                Undo.RecordObject(this, "Removed hidden CSG model");
                foreach (var target in targets)
                {
                    var exportedModel = target as CSGModelExported;
                    if (!exportedModel)
                    {
                        continue;
                    }
                    exportedModel.DestroyModel(undoable: true);
                    Undo.DestroyObjectImmediate(exportedModel);
                }
                Undo.CollapseUndoOperations(groupIndex);
            }
            GUILayout.Space(10);
            GUILayout.EndVertical();
        }
Example #9
0
        static void OnScene(SceneView sceneView)
        {
            if (!RealtimeCSG.CSGSettings.EnableRealtimeCSG)
            {
                return;
            }
            UpdateOnSceneChange();
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            if (Event.current.type == EventType.Repaint &&
                !ColorSettings.isInitialized)
            {
                ColorSettings.Update();
            }

            if (!IsActive())
            {
                ResetUpdateRoutine();
            }

            if (Event.current.type == EventType.MouseDown ||
                Event.current.type == EventType.MouseDrag)
            {
                mousePressed = true;
            }
            else if (Event.current.type == EventType.MouseUp ||
                     Event.current.type == EventType.MouseMove)
            {
                mousePressed = false;
            }

            var s_RectSelectionID_instance = (int)s_RectSelectionID_field.GetValue(null);

            UpdateRectSelection(sceneView, s_RectSelectionID_instance);
            OnHandleDragAndDrop(inSceneView: true);

            var eventType = Event.current.GetTypeForControl(s_RectSelectionID_instance);

            var hotControl = GUIUtility.hotControl;

            if (hotControl == s_RectSelectionID_instance &&
                CSGBrushEditorManager.ActiveTool.IgnoreUnityRect)
            {
                hotControl            = 0;
                GUIUtility.hotControl = 0;
            }

            switch (eventType)
            {
            case EventType.MouseDown:
            {
                rectClickDown      = (Event.current.button == 0 && hotControl == s_RectSelectionID_instance);
                clickMousePosition = Event.current.mousePosition;
                mouseDragged       = false;
                break;
            }

            case EventType.MouseUp:
            {
                rectClickDown = false;
                break;
            }

            case EventType.MouseMove:
            {
                rectClickDown = false;
                break;
            }

            case EventType.Used:
            {
                if (clickMousePosition != Event.current.mousePosition)
                {
                    mouseDragged = true;
                }
                if (!mouseDragged && rectClickDown &&
                    Event.current.button == 0)
                {
                    // m_RectSelection field of SceneView
                    var m_RectSelection_instance = m_RectSelection_field.GetValue(sceneView);

                    var m_RectSelecting_instance = (bool)m_RectSelecting_field.GetValue(m_RectSelection_instance);
                    if (!m_RectSelecting_instance)
                    {
                        // make sure GeneratedMeshes are not part of our selection
                        if (Selection.gameObjects != null)
                        {
                            var selectedObjects = Selection.objects;
                            var foundObjects    = new List <UnityEngine.Object>();
                            foreach (var obj in selectedObjects)
                            {
                                var component  = obj as Component;
                                var gameObject = obj as GameObject;
                                var transform  = obj as Transform;
                                if (!(component && component.GetComponent <GeneratedMeshes>()) &&
                                    !(gameObject && gameObject.GetComponent <GeneratedMeshes>()) &&
                                    !(transform && transform.GetComponent <Transform>()))
                                {
                                    foundObjects.Add(obj);
                                }
                            }
                            if (foundObjects.Count != selectedObjects.Length)
                            {
                                Selection.objects = foundObjects.ToArray();
                            }
                        }

                        SelectionUtility.DoSelectionClick();
                        Event.current.Use();
                    }
                }
                rectClickDown = false;
                break;
            }


            case EventType.ValidateCommand:
            {
                if (Event.current.commandName == "SelectAll")
                {
                    Event.current.Use();
                    break;
                }
                if (Keys.HandleSceneValidate(CSGBrushEditorManager.CurrentTool, true))
                {
                    Event.current.Use();
                    HandleUtility.Repaint();
                }
                break;
            }

            case EventType.ExecuteCommand:
            {
                if (Event.current.commandName == "SelectAll")
                {
                    var transforms = new List <UnityEngine.Object>();
                    for (int sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++)
                    {
                        var scene = SceneManager.GetSceneAt(sceneIndex);
                        foreach (var gameObject in scene.GetRootGameObjects())
                        {
                            foreach (var transform in gameObject.GetComponentsInChildren <Transform>())
                            {
                                if ((transform.hideFlags & (HideFlags.NotEditable | HideFlags.HideInHierarchy)) == (HideFlags.NotEditable | HideFlags.HideInHierarchy))
                                {
                                    continue;
                                }
                                transforms.Add(transform.gameObject);
                            }
                        }
                    }
                    Selection.objects = transforms.ToArray();

                    Event.current.Use();
                    break;
                }
                break;
            }

            case EventType.KeyDown:
            {
                if (Keys.HandleSceneKeyDown(CSGBrushEditorManager.CurrentTool, true))
                {
                    Event.current.Use();
                    HandleUtility.Repaint();
                }
                break;
            }

            case EventType.KeyUp:
            {
                if (Keys.HandleSceneKeyUp(CSGBrushEditorManager.CurrentTool, true))
                {
                    Event.current.Use();
                    HandleUtility.Repaint();
                }
                break;
            }

            case EventType.Layout:
            {
                if (currentDragTool != null)
                {
                    currentDragTool.Layout();
                }
                break;
            }

            case EventType.Repaint:
            {
                break;
            }
            }

            //bool fallbackGUI = EditorWindow.focusedWindow != sceneView;
            //fallbackGUI =
            CSGBrushEditorManager.InitSceneGUI(sceneView);                    // || fallbackGUI;
            //fallbackGUI = true;

            /*
             * if (SceneQueryUtility._deepClickIntersections != null &&
             *      SceneQueryUtility._deepClickIntersections.Length > 0)
             * {
             *      foreach (var intersection in SceneQueryUtility._deepClickIntersections)
             *      {
             *              var triangle = intersection.triangle;
             *              Debug.DrawLine(triangle[0], triangle[1]);
             *              Debug.DrawLine(triangle[1], triangle[2]);
             *              Debug.DrawLine(triangle[2], triangle[0]);
             *      }
             * }
             */

            if (Event.current.type == EventType.Repaint)
            {
                MeshInstanceManager.RenderHelperSurfaces(sceneView);
            }

            if (Event.current.type == EventType.Repaint)
            {
                if (currentDragTool != null)
                {
                    currentDragTool.OnPaint();
                }

                SceneTools.OnPaint(sceneView);
            }
            else
            //if (fallbackGUI)
            {
                BottomBarGUI.ShowGUI(sceneView);
            }


            CSGBrushEditorManager.OnSceneGUI(sceneView);

            //if (fallbackGUI)
            {
                TooltipUtility.InitToolTip(sceneView);
                if (Event.current.type == EventType.Repaint)
                {
                    BottomBarGUI.ShowGUI(sceneView);
                }
                if (!mousePressed)
                {
                    Handles.BeginGUI();
                    TooltipUtility.DrawToolTip(getLastRect: false);
                    Handles.EndGUI();
                }
            }
        }
        static void OnBottomBarGUI(SceneView sceneView, Rect barSize)
        {
            //if (Event.current.type == EventType.Layout)
            //	return;

            var  snapMode          = RealtimeCSG.CSGSettings.SnapMode;
            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              = CSG_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 "SnapMode" 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;


                switch (snapMode)
                {
                case SnapMode.GridSnapping:
                {
                    var newValue = GUI.Toggle(currentRect, snapMode == SnapMode.GridSnapping, CSG_GUIStyleUtility.Skin.gridSnapIconOn, EditorStyles.toolbarButton);
                    if (GUI.changed)
                    {
                        snapMode = newValue ? SnapMode.GridSnapping : SnapMode.RelativeSnapping;
                    }
                    //(x:97.00, y:0.00, width:27.00, height:18.00)
                    TooltipUtility.SetToolTip(gridSnapModeTooltip, currentRect);
                    break;
                }

                case SnapMode.RelativeSnapping:
                {
                    var newValue = GUI.Toggle(currentRect, snapMode == SnapMode.RelativeSnapping, CSG_GUIStyleUtility.Skin.relSnapIconOn, EditorStyles.toolbarButton);
                    if (GUI.changed)
                    {
                        snapMode = newValue ? SnapMode.RelativeSnapping : SnapMode.None;
                    }
                    //(x:97.00, y:0.00, width:27.00, height:18.00)
                    TooltipUtility.SetToolTip(relativeSnapModeTooltip, currentRect);
                    break;
                }

                default:
                case SnapMode.None:
                {
                    var newValue = GUI.Toggle(currentRect, snapMode != SnapMode.None, CSG_GUIStyleUtility.Skin.noSnapIconOn, EditorStyles.toolbarButton);
                    if (GUI.changed)
                    {
                        snapMode = newValue ? SnapMode.GridSnapping : SnapMode.None;
                    }
                    //(x:97.00, y:0.00, width:27.00, height:18.00)
                    TooltipUtility.SetToolTip(noSnappingModeTooltip, currentRect);
                    break;
                }
                }
            }
            modified = GUI.changed || modified;
            #endregion

            if (viewWidth >= 460)
            {
                if (snapMode != SnapMode.None)
                {
                    #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, CSG_GUIStyleUtility.Skin.rebuildIcon, EditorStyles.toolbarButton))
            {
                Debug.Log("Starting complete rebuild");

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

                MaterialUtility.ResetMaterialTypeLookup();

                InternalCSGModelManager.skipCheckForChanges = true;
                RealtimeCSG.CSGSettings.Reload();
                UnityCompilerDefineManager.UpdateUnityDefines();

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

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


                NativeMethodBindings.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.RemoveForcedUpdates();                 // we already did this in rebuild all
                InternalCSGModelManager.UpdateMeshes(text, forceUpdate: true);

                updateSurfaces = true;
                UpdateLoop.ResetUpdateRoutine();
                RealtimeCSG.CSGSettings.Save();
                InternalCSGModelManager.skipCheckForChanges = false;

                var scenes = new HashSet <UnityEngine.SceneManagement.Scene>();
                foreach (var model in InternalCSGModelManager.Models)
                {
                    scenes.Add(model.gameObject.scene);
                }

                text.AppendFormat(CultureInfo.InvariantCulture, "{0} brushes. ", Foundation.CSGManager.TreeBrushCount);

                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(sceneView, 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, CSG_GUIStyleUtility.Skin.wireframe, EditorStyles.toolbarButton);
                //(x:1237.00, y:0.00, width:26.00, height:18.00)
            }
            else
            {
                showWireframe = GUI.Toggle(currentRect, showWireframe, CSG_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.SnapMode     = snapMode;
            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(force: true);
            }

            if (modified)
            {
                GUI.changed = true;
                RealtimeCSG.CSGSettings.UpdateSnapSettings();
                RealtimeCSG.CSGSettings.Save();
                CSG_EditorGUIUtility.RepaintAll();
            }
            #endregion
        }
Example #11
0
        public static void OnInspectorGUI(UnityEngine.Object[] targets)
        {
            InitReflection();
            if (!localStyles)
            {
                popupStyle = new GUIStyle(EditorStyles.popup);
                //popupStyle.padding.top += 2;
                popupStyle.margin.top += 2;
                localStyles            = true;
            }


            bool updateMeshes = false;

            var models = new CSGModel[targets.Length];

            for (int i = targets.Length - 1; i >= 0; i--)
            {
                models[i] = targets[i] as CSGModel;
                if (!models[i])
                {
                    ArrayUtility.RemoveAt(ref models, i);
                }
            }

            if (models.Length == 0)
            {
                return;
            }


            var               settings                    = models[0].Settings;
            var               vertexChannels              = models[0].VertexChannels;
            ExportType?       exportType                  = models[0].exportType;
            bool?             VertexChannelColor          = (vertexChannels & VertexChannelFlags.Color) == VertexChannelFlags.Color;
            bool?             VertexChannelTangent        = (vertexChannels & VertexChannelFlags.Tangent) == VertexChannelFlags.Tangent;
            bool?             VertexChannelNormal         = (vertexChannels & VertexChannelFlags.Normal) == VertexChannelFlags.Normal;
            bool?             VertexChannelUV0            = (vertexChannels & VertexChannelFlags.UV0) == VertexChannelFlags.UV0;
            bool?             InvertedWorld               = (settings & ModelSettingsFlags.InvertedWorld) == ModelSettingsFlags.InvertedWorld;
            bool?             NoCollider                  = (settings & ModelSettingsFlags.NoCollider) == ModelSettingsFlags.NoCollider;
            bool?             IsTrigger                   = (settings & ModelSettingsFlags.IsTrigger) == ModelSettingsFlags.IsTrigger;
            bool?             SetToConvex                 = (settings & ModelSettingsFlags.SetColliderConvex) == ModelSettingsFlags.SetColliderConvex;
            bool?             AutoGenerateRigidBody       = (settings & ModelSettingsFlags.AutoUpdateRigidBody) == ModelSettingsFlags.AutoUpdateRigidBody;
            bool?             DoNotRender                 = (settings & ModelSettingsFlags.DoNotRender) == ModelSettingsFlags.DoNotRender;
            bool?             ReceiveShadows              = !((settings & ModelSettingsFlags.DoNotReceiveShadows) == ModelSettingsFlags.DoNotReceiveShadows);
            bool?             AutoRebuildUVs              = (settings & ModelSettingsFlags.AutoRebuildUVs) == ModelSettingsFlags.AutoRebuildUVs;
            bool?             PreserveUVs                 = (settings & ModelSettingsFlags.PreserveUVs) == ModelSettingsFlags.PreserveUVs;
            bool?             ShowGeneratedMeshes         = models[0].ShowGeneratedMeshes;
            ShadowCastingMode?ShadowCastingMode           = (ShadowCastingMode)(settings & ModelSettingsFlags.ShadowCastingModeFlags);
            var               defaultPhysicsMaterial      = models[0].DefaultPhysicsMaterial;
            var               defaultPhysicsMaterialMixed = false;

            for (int i = 1; i < models.Length; i++)
            {
                settings       = models[i].Settings;
                vertexChannels = models[i].VertexChannels;
                ExportType        currExportType             = models[i].exportType;
                bool              currVertexChannelColor     = (vertexChannels & VertexChannelFlags.Color) == VertexChannelFlags.Color;
                bool              currVertexChannelTangent   = (vertexChannels & VertexChannelFlags.Tangent) == VertexChannelFlags.Tangent;
                bool              currVertexChannelNormal    = (vertexChannels & VertexChannelFlags.Normal) == VertexChannelFlags.Normal;
                bool              currVertexChannelUV0       = (vertexChannels & VertexChannelFlags.UV0) == VertexChannelFlags.UV0;
                bool              currInvertedWorld          = (settings & ModelSettingsFlags.InvertedWorld) == ModelSettingsFlags.InvertedWorld;
                bool              currNoCollider             = (settings & ModelSettingsFlags.NoCollider) == ModelSettingsFlags.NoCollider;
                bool              currIsTrigger              = (settings & ModelSettingsFlags.IsTrigger) == ModelSettingsFlags.IsTrigger;
                bool              currSetToConvex            = (settings & ModelSettingsFlags.SetColliderConvex) == ModelSettingsFlags.SetColliderConvex;
                bool              currAutoGenerateRigidBody  = (settings & ModelSettingsFlags.AutoUpdateRigidBody) == ModelSettingsFlags.AutoUpdateRigidBody;
                bool              currDoNotRender            = (settings & ModelSettingsFlags.DoNotRender) == ModelSettingsFlags.DoNotRender;
                bool              currReceiveShadows         = !((settings & ModelSettingsFlags.DoNotReceiveShadows) == ModelSettingsFlags.DoNotReceiveShadows);
                bool              currAutoRebuildUVs         = (settings & ModelSettingsFlags.AutoRebuildUVs) == ModelSettingsFlags.AutoRebuildUVs;
                bool              currPreserveUVs            = (settings & ModelSettingsFlags.PreserveUVs) == ModelSettingsFlags.PreserveUVs;
                bool              currShowGeneratedMeshes    = models[i].ShowGeneratedMeshes;
                var               currdefaultPhysicsMaterial = models[i].DefaultPhysicsMaterial;
                ShadowCastingMode currShadowCastingMode      = (ShadowCastingMode)(settings & ModelSettingsFlags.ShadowCastingModeFlags);

                if (VertexChannelColor.HasValue && VertexChannelColor.Value != currVertexChannelColor)
                {
                    VertexChannelColor = null;
                }
                if (VertexChannelTangent.HasValue && VertexChannelTangent.Value != currVertexChannelTangent)
                {
                    VertexChannelTangent = null;
                }
                if (VertexChannelNormal.HasValue && VertexChannelNormal.Value != currVertexChannelNormal)
                {
                    VertexChannelNormal = null;
                }
                if (VertexChannelUV0.HasValue && VertexChannelUV0.Value != currVertexChannelUV0)
                {
                    VertexChannelUV0 = null;
                }

                if (exportType.HasValue && exportType.Value != currExportType)
                {
                    exportType = null;
                }

                if (InvertedWorld.HasValue && InvertedWorld.Value != currInvertedWorld)
                {
                    InvertedWorld = null;
                }
                if (NoCollider.HasValue && NoCollider.Value != currNoCollider)
                {
                    NoCollider = null;
                }
                if (IsTrigger.HasValue && IsTrigger.Value != currIsTrigger)
                {
                    IsTrigger = null;
                }
                if (SetToConvex.HasValue && SetToConvex.Value != currSetToConvex)
                {
                    SetToConvex = null;
                }
                if (AutoGenerateRigidBody.HasValue && AutoGenerateRigidBody.Value != currAutoGenerateRigidBody)
                {
                    AutoGenerateRigidBody = null;
                }
                if (DoNotRender.HasValue && DoNotRender.Value != currDoNotRender)
                {
                    DoNotRender = null;
                }
                if (ReceiveShadows.HasValue && ReceiveShadows.Value != currReceiveShadows)
                {
                    ReceiveShadows = null;
                }
                if (ShadowCastingMode.HasValue && ShadowCastingMode.Value != currShadowCastingMode)
                {
                    ShadowCastingMode = null;
                }
                if (AutoRebuildUVs.HasValue && AutoRebuildUVs.Value != currAutoRebuildUVs)
                {
                    AutoRebuildUVs = null;
                }
                if (PreserveUVs.HasValue && PreserveUVs.Value != currPreserveUVs)
                {
                    PreserveUVs = null;
                }
                if (ShowGeneratedMeshes.HasValue && ShowGeneratedMeshes.Value != currShowGeneratedMeshes)
                {
                    ShowGeneratedMeshes = null;
                }

                if (defaultPhysicsMaterial != currdefaultPhysicsMaterial)
                {
                    defaultPhysicsMaterialMixed = true;
                }
            }

            GUILayout.BeginVertical(GUI.skin.box);
            {
                EditorGUILayout.LabelField("Behaviour");
                EditorGUI.indentLevel++;
                {
                    bool inverted_world = InvertedWorld.HasValue ? InvertedWorld.Value : false;
                    EditorGUI.BeginChangeCheck();
                    {
                        EditorGUI.showMixedValue = !InvertedWorld.HasValue;
                        inverted_world           = EditorGUILayout.Toggle(InvertedWorldContent, inverted_world);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        for (int i = 0; i < models.Length; i++)
                        {
                            if (inverted_world)
                            {
                                models[i].Settings |= ModelSettingsFlags.InvertedWorld;
                            }
                            else
                            {
                                models[i].Settings &= ~ModelSettingsFlags.InvertedWorld;
                            }
                        }
                        GUI.changed   = true;
                        InvertedWorld = inverted_world;
                    }
                }
                EditorGUI.indentLevel--;
            }
            GUILayout.EndVertical();
            if (models != null && models.Length == 1)
            {
                GUILayout.Space(10);
                GUILayout.BeginVertical(GUI.skin.box);
                {
                    EditorGUILayout.LabelField("Export");
                    GUILayout.BeginHorizontal();
                    {
                        EditorGUI.BeginDisabledGroup(!exportType.HasValue);
                        {
                            if (GUILayout.Button("Export to ...") && exportType.HasValue)
                            {
#if !DEMO
                                MeshInstanceManager.Export(models[0], exportType.Value);
#else
                                Debug.LogWarning("Export is disabled in demo version");
#endif
                            }
                        }
                        EditorGUI.EndDisabledGroup();
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = !exportType.HasValue;
                            exportType = (ExportType)EditorGUILayout.EnumPopup(exportType ?? ExportType.FBX, popupStyle);
                            EditorGUI.showMixedValue = false;
                        }
                        if (EditorGUI.EndChangeCheck() && exportType.HasValue)
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                models[i].exportType = exportType.Value;
                            }
                        }
                    }
                    GUILayout.EndHorizontal();
                }
                GUILayout.EndVertical();
            }
            GUILayout.Space(10);
            GUILayout.BeginVertical(GUI.skin.box);
            {
                EditorGUILayout.LabelField("Physics");
                EditorGUI.indentLevel++;
                {
                    bool collider_value = NoCollider.HasValue ? NoCollider.Value : false;
                    EditorGUI.BeginChangeCheck();
                    {
                        EditorGUI.showMixedValue = !NoCollider.HasValue;
                        collider_value           = !EditorGUILayout.Toggle(GenerateColliderContent, !collider_value);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        for (int i = 0; i < models.Length; i++)
                        {
                            if (collider_value)
                            {
                                models[i].Settings |= ModelSettingsFlags.NoCollider;
                            }
                            else
                            {
                                models[i].Settings &= ~ModelSettingsFlags.NoCollider;
                            }
                        }
                        GUI.changed  = true;
                        NoCollider   = collider_value;
                        updateMeshes = true;
                    }
                }
                var have_no_collider = NoCollider.HasValue && NoCollider.Value;
                EditorGUI.BeginDisabledGroup(have_no_collider);
                {
                    bool trigger_value_mixed = have_no_collider ? true : !IsTrigger.HasValue;
                    bool trigger_value       = IsTrigger.HasValue ? IsTrigger.Value : false;
                    {
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = trigger_value_mixed;
                            trigger_value            = EditorGUILayout.Toggle(ModelIsTriggerContent, trigger_value);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                if (trigger_value)
                                {
                                    models[i].Settings |= ModelSettingsFlags.IsTrigger;
                                }
                                else
                                {
                                    models[i].Settings &= ~ModelSettingsFlags.IsTrigger;
                                }
                            }
                            GUI.changed  = true;
                            IsTrigger    = trigger_value;
                            updateMeshes = true;
                        }
                    }
                    bool set_convex_value_mixed = have_no_collider ? true : !SetToConvex.HasValue;
                    bool set_convex_value       = have_no_collider ? false : (SetToConvex.HasValue ? SetToConvex.Value : false);
                    {
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = set_convex_value_mixed;
                            var prevColor = GUI.color;
                            if (!set_convex_value && trigger_value)
                            {
                                var color = new Color(1, 0.25f, 0.25f);
                                GUI.color = color;
                            }
                            set_convex_value = EditorGUILayout.Toggle(ColliderSetToConvexContent, set_convex_value);
                            GUI.color        = prevColor;
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                if (set_convex_value)
                                {
                                    models[i].Settings |= ModelSettingsFlags.SetColliderConvex;
                                }
                                else
                                {
                                    models[i].Settings &= ~ModelSettingsFlags.SetColliderConvex;
                                }
                            }
                            GUI.changed  = true;
                            SetToConvex  = set_convex_value;
                            updateMeshes = true;
                        }
                    }
                    {
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = defaultPhysicsMaterialMixed;
                            GUILayout.BeginHorizontal();
                            EditorGUILayout.PrefixLabel(DefaultPhysicsMaterialContent);
                            defaultPhysicsMaterial = EditorGUILayout.ObjectField(defaultPhysicsMaterial, typeof(PhysicMaterial), true) as PhysicMaterial;
                            GUILayout.EndHorizontal();
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                models[i].DefaultPhysicsMaterial = defaultPhysicsMaterial;
                            }
                            GUI.changed = true;
                            //MeshInstanceManager.Clear();
                            updateMeshes = true;
                        }
                    }
                    if (!have_no_collider && !set_convex_value && trigger_value)
                    {
                        var prevColor = GUI.color;
                        var color     = new Color(1, 0.25f, 0.25f);
                        GUI.color = color;
                        GUILayout.Label("Warning:\r\nFor performance reasons colliders need to\r\nbe convex!");

                        GUI.color = prevColor;
                    }
                }
                EditorGUI.EndDisabledGroup();
                {
                    bool autoRigidbody = (AutoGenerateRigidBody.HasValue ? AutoGenerateRigidBody.Value : false);
                    EditorGUI.BeginChangeCheck();
                    {
                        EditorGUI.showMixedValue = !AutoGenerateRigidBody.HasValue;
                        autoRigidbody            = !EditorGUILayout.Toggle(ColliderAutoRigidBodyContent, !autoRigidbody);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        for (int i = 0; i < models.Length; i++)
                        {
                            if (autoRigidbody)
                            {
                                models[i].Settings |= ModelSettingsFlags.AutoUpdateRigidBody;
                            }
                            else
                            {
                                models[i].Settings &= ~ModelSettingsFlags.AutoUpdateRigidBody;
                            }
                        }
                        GUI.changed           = true;
                        AutoGenerateRigidBody = autoRigidbody;
                    }
                }
                EditorGUI.indentLevel--;
            }
            GUILayout.EndVertical();
            GUILayout.Space(10);
            GUILayout.BeginVertical(GUI.skin.box);
            {
                ShadowCastingMode shadowcastingValue = ShadowCastingMode.HasValue ? ShadowCastingMode.Value : UnityEngine.Rendering.ShadowCastingMode.On;
                var castOnlyShadow = (shadowcastingValue == UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly);
                EditorGUILayout.LabelField("Rendering");
                EditorGUI.indentLevel++;
                EditorGUI.BeginDisabledGroup(castOnlyShadow);
                {
                    bool donotrender_value = castOnlyShadow ? true : (DoNotRender.HasValue ? DoNotRender.Value : false);
                    EditorGUI.BeginChangeCheck();
                    {
                        EditorGUI.showMixedValue = castOnlyShadow ? true : !DoNotRender.HasValue;
                        donotrender_value        = EditorGUILayout.Toggle(DoNotRenderContent, donotrender_value);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        for (int i = 0; i < models.Length; i++)
                        {
                            if (donotrender_value)
                            {
                                models[i].Settings |= ModelSettingsFlags.DoNotRender;
                            }
                            else
                            {
                                models[i].Settings &= ~ModelSettingsFlags.DoNotRender;
                            }
                        }
                        GUI.changed  = true;
                        DoNotRender  = donotrender_value;
                        updateMeshes = true;
                    }
                }
                EditorGUI.EndDisabledGroup();
                GUILayout.Space(10);
                EditorGUI.BeginDisabledGroup(DoNotRender.HasValue && DoNotRender.Value);
                {
                    EditorGUI.BeginChangeCheck();
                    {
                        EditorGUI.showMixedValue = !ShadowCastingMode.HasValue;
                        shadowcastingValue       = (ShadowCastingMode)EditorGUILayout.EnumPopup(CastShadows, shadowcastingValue);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        for (int i = 0; i < models.Length; i++)
                        {
                            settings           = models[i].Settings;
                            settings          &= ~ModelSettingsFlags.ShadowCastingModeFlags;
                            settings          |= (ModelSettingsFlags)(((int)shadowcastingValue) & (int)ModelSettingsFlags.ShadowCastingModeFlags);
                            models[i].Settings = settings;
                        }
                        GUI.changed       = true;
                        ShadowCastingMode = shadowcastingValue;
                        updateMeshes      = true;
                    }

                    var isUsingDeferredRenderingPath = false;                    //IsUsingDeferredRenderingPath();
                    EditorGUI.BeginDisabledGroup(castOnlyShadow || isUsingDeferredRenderingPath);
                    {
                        var receiveshadowsValue = !castOnlyShadow && (isUsingDeferredRenderingPath || (ReceiveShadows ?? false));
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = (castOnlyShadow || !ReceiveShadows.HasValue) && !isUsingDeferredRenderingPath;
                            receiveshadowsValue      = EditorGUILayout.Toggle(ModelInspectorGUI.ReceiveShadowsContent, receiveshadowsValue || isUsingDeferredRenderingPath);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                if (receiveshadowsValue)
                                {
                                    models[i].Settings &= ~ModelSettingsFlags.DoNotReceiveShadows;
                                }
                                else
                                {
                                    models[i].Settings |= ModelSettingsFlags.DoNotReceiveShadows;
                                }
                            }
                            GUI.changed    = true;
                            ReceiveShadows = receiveshadowsValue;
                        }
                    }
                    EditorGUI.EndDisabledGroup();
                }
                EditorGUI.EndDisabledGroup();

                EditorGUI.BeginDisabledGroup(castOnlyShadow);
                EditorGUI.showMixedValue = false;
                UpdateTargets(models);
                if (_probesInstance != null &&
                    _probesOnGUIMethod != null &&
                    _probesTargets != null &&
                    _probesInitialized)
                {
                    GUILayout.Space(10);
                    try
                    {
#if UNITY_5_6_OR_NEWER
                        _probesSerializedObject.UpdateIfRequiredOrScript();
#else
                        _probesSerializedObject.UpdateIfDirtyOrScript();
#endif
                        _probesOnGUIMethod.Invoke(_probesInstance, new System.Object[] { _probesTargets, (Renderer)_probesTargets[0], false });
                        _probesSerializedObject.ApplyModifiedProperties();
                    }
                    catch { }
                }
                EditorGUI.EndDisabledGroup();
                EditorGUI.indentLevel--;
            }
            GUILayout.EndVertical();
            GUILayout.Space(10);
            GUILayout.BeginVertical(GUI.skin.box);
            {
                EditorGUILayout.LabelField("Lighting");
                EditorGUI.indentLevel++;
                {
                    EditorGUI.indentLevel++;
                    CommonGUI.GenerateLightmapUVButton(models);
                    EditorGUI.indentLevel--;

                    EditorGUILayout.LabelField("UV Settings");
                    EditorGUI.indentLevel++;
                    {
                        var autoRebuildUvs = AutoRebuildUVs ?? false;
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = !AutoRebuildUVs.HasValue;
                            autoRebuildUvs           = EditorGUILayout.Toggle(AutoRebuildUVsContent, autoRebuildUvs);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                if (autoRebuildUvs)
                                {
                                    models[i].Settings |= ModelSettingsFlags.AutoRebuildUVs;
                                }
                                else
                                {
                                    models[i].Settings &= ~ModelSettingsFlags.AutoRebuildUVs;
                                }
                            }
                            GUI.changed    = true;
                            AutoRebuildUVs = autoRebuildUvs;
                            updateMeshes   = true;
                        }
                    }
                    {
                        var preserveUVs = PreserveUVs ?? false;
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = !PreserveUVs.HasValue;
                            preserveUVs = EditorGUILayout.Toggle(PreserveUVsContent, preserveUVs);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                if (preserveUVs)
                                {
                                    models[i].Settings |= ModelSettingsFlags.PreserveUVs;
                                }
                                else
                                {
                                    models[i].Settings &= ~ModelSettingsFlags.PreserveUVs;
                                }
                            }
                            GUI.changed  = true;
                            PreserveUVs  = preserveUVs;
                            updateMeshes = true;
                        }
                    }
                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }
            GUILayout.EndVertical();
            GUILayout.Space(10);
            GUILayout.BeginVertical(GUI.skin.box);
            {
                EditorGUILayout.LabelField("Mesh (advanced)");
                EditorGUI.indentLevel++;
                {
                    var showGeneratedMeshes = ShowGeneratedMeshes ?? false;
                    EditorGUI.BeginChangeCheck();
                    {
                        EditorGUI.showMixedValue = !ShowGeneratedMeshes.HasValue;
                        showGeneratedMeshes      = EditorGUILayout.Toggle(ShowGeneratedMeshesContent, showGeneratedMeshes);
                    }
                    if (EditorGUI.EndChangeCheck())
                    {
                        for (int i = 0; i < models.Length; i++)
                        {
                            models[i].ShowGeneratedMeshes = showGeneratedMeshes;
                            MeshInstanceManager.UpdateGeneratedMeshesVisibility(models[i]);
                        }
                    }
                    GUILayout.Space(10);

                    EditorGUILayout.LabelField("Used Vertex Channels");
                    EditorGUI.indentLevel++;
                    {
                        var vertex_channel_color   = VertexChannelColor ?? false;
                        var vertex_channel_tangent = VertexChannelTangent ?? false;
                        var vertex_channel_normal  = VertexChannelNormal ?? false;
                        var vertex_channel_UV0     = VertexChannelUV0 ?? false;
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = !VertexChannelColor.HasValue;
                            vertex_channel_color     = EditorGUILayout.Toggle(VertexChannelColorContent, vertex_channel_color);

                            EditorGUI.showMixedValue = !VertexChannelTangent.HasValue;
                            vertex_channel_tangent   = EditorGUILayout.Toggle(VertexChannelTangentContent, vertex_channel_tangent);

                            EditorGUI.showMixedValue = !VertexChannelNormal.HasValue;
                            vertex_channel_normal    = EditorGUILayout.Toggle(VertexChannelNormalContent, vertex_channel_normal);

                            EditorGUI.showMixedValue = !VertexChannelUV0.HasValue;
                            vertex_channel_UV0       = EditorGUILayout.Toggle(VertexChannelUV1Content, vertex_channel_UV0);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            for (int i = 0; i < models.Length; i++)
                            {
                                var vertexChannel = models[i].VertexChannels;
                                vertexChannel &= ~(VertexChannelFlags.Color |
                                                   VertexChannelFlags.Tangent |
                                                   VertexChannelFlags.Normal |
                                                   VertexChannelFlags.UV0);

                                if (vertex_channel_color)
                                {
                                    vertexChannel |= VertexChannelFlags.Color;
                                }
                                if (vertex_channel_tangent)
                                {
                                    vertexChannel |= VertexChannelFlags.Tangent;
                                }
                                if (vertex_channel_normal)
                                {
                                    vertexChannel |= VertexChannelFlags.Normal;
                                }
                                if (vertex_channel_UV0)
                                {
                                    vertexChannel |= VertexChannelFlags.UV0;
                                }
                                models[i].VertexChannels = vertexChannel;
                            }
                            GUI.changed = true;
                        }
                    }
                    EditorGUI.indentLevel--;
                }
                EditorGUI.indentLevel--;
            }
            GUILayout.EndVertical();
            if (models != null && models.Length == 1)
            {
                GUILayout.Space(10);

                GUILayout.BeginVertical(GUI.skin.box);
                _showDetails = EditorGUILayout.BeginToggleGroup("Statistics", _showDetails);
                if (_showDetails)
                {
                    var model_cache = InternalCSGModelManager.GetModelCache(models[0]);
                    if (model_cache == null ||
                        model_cache.GeneratedMeshes == null ||
                        !model_cache.GeneratedMeshes)
                    {
                        GUILayout.Label("Could not find model cache for this model.");
                    }
                    else
                    {
                        var meshContainer = model_cache.GeneratedMeshes;


                        var totalTriangles = 0;
                        var totalVertices  = 0;
                        var totalMeshes    = 0;

                        var materialMeshes = new Dictionary <Material, List <MeshData> >();
                        foreach (var instance in meshContainer.meshInstances.Values)
                        {
                            var mesh = instance.SharedMesh;
                            if (!MeshInstanceManager.HasVisibleMeshRenderer(instance))
                            {
                                continue;
                            }

                            List <MeshData> meshes;
                            if (!materialMeshes.TryGetValue(instance.RenderMaterial, out meshes))
                            {
                                meshes = new List <MeshData>();
                                materialMeshes[instance.RenderMaterial] = meshes;
                            }

                            var meshData = new MeshData();
                            meshData.Mesh          = mesh;
                            meshData.VertexCount   = mesh.vertexCount;
                            meshData.TriangleCount = mesh.triangles.Length / 3;
                            meshes.Add(meshData);

                            totalVertices += meshData.VertexCount;
                            totalTriangles = meshData.TriangleCount;
                            totalMeshes++;
                        }
                        EditorGUI.indentLevel++;
                        EditorGUILayout.Space();
                        EditorGUILayout.LabelField("total:");
                        EditorGUILayout.LabelField("vertices: " + totalVertices + "  triangles: " + totalTriangles + "  materials: " + materialMeshes.Count + "  meshes: " + totalMeshes);
                        GUILayout.Space(10);
                        EditorGUILayout.LabelField("meshes:");
                        foreach (var item in materialMeshes)
                        {
                            var material = item.Key;
                            var meshes   = item.Value;

                            GUILayout.BeginHorizontal();
                            {
                                EditorGUI.BeginDisabledGroup(true);
                                {
                                    EditorGUILayout.ObjectField(material, typeof(Material), true);
                                }
                                GUILayout.BeginVertical();
                                {
                                    if (meshes.Count == 1)
                                    {
                                        EditorGUILayout.ObjectField(meshes[0].Mesh, typeof(Mesh), true);
                                        EditorGUILayout.LabelField("vertices " + meshes[0].VertexCount + "  triangles " + meshes[0].TriangleCount);
                                    }
                                    else
                                    {
                                        for (int i = 0; i < meshes.Count; i++)
                                        {
                                            EditorGUILayout.ObjectField(meshes[i].Mesh, typeof(Mesh), true);
                                            EditorGUILayout.LabelField("vertices " + meshes[i].VertexCount + "  triangles " + meshes[i].TriangleCount);
                                        }
                                    }
                                }
                                GUILayout.EndVertical();
                                EditorGUI.EndDisabledGroup();
                            }
                            GUILayout.EndHorizontal();
                            EditorGUILayout.Space();
                        }
                        EditorGUI.indentLevel--;
                    }
                }
                EditorGUILayout.EndToggleGroup();
                GUILayout.EndVertical();
            }
            EditorGUI.showMixedValue = false;
            if (updateMeshes)
            {
                InternalCSGModelManager.DoForcedMeshUpdate();
                SceneViewEventHandler.ResetUpdateRoutine();
            }
        }
        public static bool UpdateMeshes(System.Text.StringBuilder text = null, bool forceUpdate = false)
        {
            if (EditorApplication.isPlaying ||
                EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return(false);
            }

            if (inUpdateMeshes)
            {
                return(false);
            }

            MeshInstanceManager.Update();

            var unityMeshUpdates       = 0.0;
            var getMeshDescriptionTime = 0.0;

            getMeshInstanceTime = 0.0;
            getModelMeshesTime  = 0.0;
            updateMeshTime      = 0.0;

            inUpdateMeshes = true;
            try
            {
                if (External == null)
                {
                    return(false);
                }

                if (forcedUpdateRequired)
                {
                    forceUpdate          = true;
                    forcedUpdateRequired = false;
                }

                var modelCount = Models.Length;
                if (modelCount == 0)
                {
                    return(false);
                }

                for (var i = 0; i < modelCount; i++)
                {
                    var model = Models[i];

                    if (!forceUpdate &&
                        !model.forceUpdate)
                    {
                        continue;
                    }

                    if (!ModelTraits.IsModelEditable(model))
                    {
                        continue;
                    }

                    External.SetDirty(model.modelNodeID);
                    model.forceUpdate = false;
                }

                // update the model meshes
                if (!External.UpdateAllModelMeshes())
                {
                    return(false);                    // nothing to do
                }
                MeshGeneration++;
                bool haveUpdates = forceUpdate;
                for (var i = 0; i < modelCount; i++)
                {
                    var model = Models[i];

                    if (!(new CSGTreeNode {
                        nodeID = model.modelNodeID
                    }.Dirty))
                    {
                        continue;
                    }

                    var meshContainer = model.generatedMeshes;
                    if (!meshContainer)
                    {
                        continue;
                    }

                    EnsureInitialized(model);

                    bool needToUpdateMeshes;
                    var  startGetMeshDescriptionTime = EditorApplication.timeSinceStartup;
                    {
                        needToUpdateMeshes = External.GetMeshDescriptions(model, ref __meshDescriptions);
                    }
                    getMeshDescriptionTime += EditorApplication.timeSinceStartup - startGetMeshDescriptionTime;


                    if (!ModelTraits.IsModelEditable(model))
                    {
                        continue;
                    }

                    if (!needToUpdateMeshes)
                    {
                        continue;
                    }

                    __foundHelperSurfaces.Clear();
                    __foundGeneratedMeshInstance.Clear();
                    __unfoundMeshInstances.Clear();
                    {
                        var startUnityMeshUpdates = EditorApplication.timeSinceStartup;
                        for (int meshIndex = 0; meshIndex < __meshDescriptions.Length; meshIndex++)
                        {
                            if (!ValidateMesh(__meshDescriptions[meshIndex]))
                            {
                                continue;
                            }

                            haveUpdates = true;
                            var renderSurfaceType = MeshInstanceManager.GetSurfaceType(__meshDescriptions[meshIndex], model.Settings);
                            if (renderSurfaceType == RenderSurfaceType.Normal ||
                                renderSurfaceType == RenderSurfaceType.ShadowOnly ||
                                renderSurfaceType == RenderSurfaceType.Collider ||
                                renderSurfaceType == RenderSurfaceType.Trigger)
                            {
                                GeneratedMeshInstance meshInstance;
                                if (TryGetMeshInstance(meshContainer, model, model.Settings, __meshDescriptions[meshIndex], renderSurfaceType, out meshInstance))
                                {
                                    if (meshInstance != null)
                                    {
                                        __foundGeneratedMeshInstance.Add(meshInstance);
                                    }
                                    else
                                    {
                                        __unfoundMeshInstances.Add(meshIndex);
                                    }
                                }
                            }
                            if (renderSurfaceType != RenderSurfaceType.Normal)
                            {
                                HelperSurfaceDescription helperSurface;
                                if (TryGetHelperSurfaceDescription(meshContainer, model, model.Settings, __meshDescriptions[meshIndex], renderSurfaceType, out helperSurface))
                                {
                                    if (helperSurface != null)
                                    {
                                        __foundHelperSurfaces.Add(helperSurface);
                                    }
                                    else
                                    {
                                        __unfoundMeshInstances.Add(meshIndex);
                                    }
                                }
                            }
                        }

                        var unusedInstances = MeshInstanceManager.FindUnusedMeshInstances(meshContainer, __foundGeneratedMeshInstance, __foundHelperSurfaces);

                        foreach (int meshIndex in __unfoundMeshInstances)
                        {
                            haveUpdates = true;
                            var renderSurfaceType = MeshInstanceManager.GetSurfaceType(__meshDescriptions[meshIndex], model.Settings);
                            if (renderSurfaceType == RenderSurfaceType.Normal ||
                                renderSurfaceType == RenderSurfaceType.ShadowOnly ||
                                renderSurfaceType == RenderSurfaceType.Collider ||
                                renderSurfaceType == RenderSurfaceType.Trigger)
                            {
                                var meshInstance = GenerateMeshInstance(meshContainer, model, model.Settings, __meshDescriptions[meshIndex], renderSurfaceType, unusedInstances);
                                if (meshInstance != null)
                                {
                                    __foundGeneratedMeshInstance.Add(meshInstance);
                                }
                            }
                            if (renderSurfaceType != RenderSurfaceType.Normal)
                            {
                                var helperSurface = GenerateHelperSurfaceDescription(meshContainer, model, model.Settings, __meshDescriptions[meshIndex], renderSurfaceType);
                                __foundHelperSurfaces.Add(helperSurface);
                            }
                        }

                        MeshInstanceManager.UpdateContainerComponents(meshContainer, __foundGeneratedMeshInstance, __foundHelperSurfaces);
                        unityMeshUpdates += (EditorApplication.timeSinceStartup - startUnityMeshUpdates);
                    }
                }

                if (haveUpdates)
                {
                    MeshInstanceManager.UpdateHelperSurfaceVisibility(force: true);
                }


                if (text != null)
                {
                    text.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
                                      "All mesh generation {0:F} ms " +
                                      "+ retrieving {1:F} ms " +
                                      "+ Unity mesh updates {2:F} ms " +
                                      "+ overhead {3:F} ms. ",
                                      getMeshDescriptionTime * 1000,
                                      getModelMeshesTime * 1000,
                                      updateMeshTime * 1000,
                                      (unityMeshUpdates - (getModelMeshesTime + updateMeshTime)) * 1000);
                }

                return(true);
            }
            finally
            {
                inUpdateMeshes = false;
            }
        }
        public static void ClearMeshInstances()
        {
            MeshInstanceManager.Reset();

            MeshInstanceManager.DestroyAllMeshInstances();
        }
        internal static void OnScene(SceneView sceneView)
        {
            if (Event.current.type == EventType.MouseMove)
            {
                sceneView.Repaint();
            }

            sceneView.cameraSettings.dynamicClip         = false;
            sceneView.cameraSettings.easingEnabled       = false;
            sceneView.cameraSettings.accelerationEnabled = false;

            //if (sceneView.orthographic)
            //{
            //    sceneView.camera.nearClipPlane = 1;
            //    sceneView.camera.farClipPlane = 1001f;

            //    var camPos = sceneView.pivot;
            //    var camForward = sceneView.camera.transform.forward;
            //    for (int i = 0; i < 3; i++)
            //    {
            //        if (!FastApproximately(camForward[i], 0, .01f))
            //        {
            //            camPos[i] = 1000;
            //        }
            //    }
            //    sceneView.pivot = camPos;
            //}

            if (sceneView.orthographic)
            {
                if (Event.current.type == EventType.KeyDown &&
                    Event.current.keyCode == KeyCode.F)
                {
                    Event.current.Use();
                    sceneView.pivot = Vector3.zero;
                    if (TryGetSelectionBounds(out Bounds bounds))
                    {
                        var sz = bounds.extents.magnitude;
                        sz = Mathf.Clamp(sz, 0.05f, 500);
                        sceneView.pivot = bounds.center;
                        sceneView.size  = sz;
                    }
                }

                if (sceneView.size > 500)
                {
                    sceneView.size = 500;
                }

                if (sceneView.size < .05f)
                {
                    sceneView.size = .05f;
                }
            }

            CSGSettings.RegisterSceneView(sceneView);

            if (!RealtimeCSG.CSGSettings.EnableRealtimeCSG ||
                EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            UpdateLoop.UpdateOnSceneChange();

            if (!RealtimeCSG.CSGSettings.EnableRealtimeCSG)
            {
                ColorSettings.isInitialized = false;
            }
            else if (!ColorSettings.isInitialized)
            {
                if (Event.current.type == EventType.Repaint)
                {
                    ColorSettings.Update();
                }
            }

            if (!UpdateLoop.IsActive())
            {
                UpdateLoop.ResetUpdateRoutine();
            }

            if (Event.current.type == EventType.MouseDown ||
                Event.current.type == EventType.MouseDrag)
            {
                mousePressed = true;
            }
            else if (Event.current.type == EventType.MouseUp ||
                     Event.current.type == EventType.MouseMove)
            {
                mousePressed = false;
            }

            SceneDragToolManager.OnHandleDragAndDrop(sceneView);
            RectangleSelectionManager.Update(sceneView);
            EditModeManager.InitSceneGUI(sceneView);

            if (Event.current.type == EventType.Repaint)
            {
                MeshInstanceManager.UpdateHelperSurfaces();
                SceneToolRenderer.OnPaint(sceneView);
            }
            else
            {
                SceneViewBottomBarGUI.ShowGUI(sceneView);
                SceneViewInfoGUI.DrawInfoGUI(sceneView);
            }

            //if(EditorWindow.mouseOverWindow == sceneView)
            {
                EditModeManager.OnSceneGUI(sceneView);

                TooltipUtility.InitToolTip(sceneView);

                if (!mousePressed)
                {
                    Handles.BeginGUI();
                    TooltipUtility.DrawToolTip(getLastRect: false);
                    Handles.EndGUI();
                }

                if (Event.current.type == EventType.Layout)
                {
                    var currentFocusControl = CSGHandles.FocusControl;
                    if (prevFocusControl != currentFocusControl)
                    {
                        prevFocusControl = currentFocusControl;
                        HandleUtility.Repaint();
                    }
                }
            }
        }
Example #15
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();
            }
        }