コード例 #1
0
        void RestoreMaterials(SelectedBrushSurface[] hoverBrushSurfaces)
        {
            if (hoverBrushSurfaces == null)
            {
                return;
            }

            var updateModels  = new HashSet <CSGModel>();
            var updateBrushes = new HashSet <CSGBrush>();

            for (int i = 0; i < hoverBrushSurfaces.Length; i++)
            {
                var brush       = hoverBrushSurfaces[i].brush;
                var brush_cache = InternalCSGModelManager.GetBrushCache(brush);
                if (brush_cache == null ||
                    brush_cache.childData == null ||
                    brush_cache.childData.Model == null)
                {
                    continue;
                }

                try
                {
                    var model = brush_cache.childData.Model;
                    updateModels.Add(model);
                    if (updateBrushes.Add(brush))
                    {
                        InternalCSGModelManager.UnregisterMaterials(model, brush.Shape, false);

                        System.Array.Copy(previousMaterials[i], brush.Shape.Materials, brush.Shape.Materials.Length);
                    }
                }
                finally { }
            }
            UpdateBrushMeshes(updateBrushes, updateModels);
        }
コード例 #2
0
        public virtual void Cancel()
        {
            ResetVisuals();

            CleanupGrid();

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

            Cleanup();
            Reset();

            if (shapeCancelled != null)
            {
                shapeCancelled();
            }
        }
コード例 #3
0
        void DisableVisualObjects()
        {
            //Debug.Log("DisableVisualObjects");

            if (visualDragGameObject != null)
            {
                for (int i = visualDragGameObject.Count - 1; i >= 0; i--)
                {
                    var obj = visualDragGameObject[i];
                    if (obj == null || !obj)
                    {
                        continue;
                    }
                    if (obj.activeSelf)
                    {
                        obj.SetActive(false);
                    }
                }

                InternalCSGModelManager.CheckTransformChanged();
                InternalCSGModelManager.OnHierarchyModified();
                InternalCSGModelManager.UpdateRemoteMeshes();
            }
        }
コード例 #4
0
        static void RunEditorUpdate()
        {
            if (!RealtimeCSG.CSGSettings.EnableRealtimeCSG)
            {
                return;
            }

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

            try
            {
                ColorSettings.Update();
                InternalCSGModelManager.Refresh(forceHierarchyUpdate: false);
                TooltipUtility.CleanCache();
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
            }
        }
コード例 #5
0
        public static CSGBrush CreateBrushInstanceInScene(MenuCommand command)
        {
#if EVALUATION
            if (NativeMethodBindings.BrushesAvailable() <= 0)
            {
                return(null);
            }
#endif
            var parent = GetTransformForMenu(command);

            var lastUsedModelTransform = !SelectionUtility.LastUsedModel ? null : SelectionUtility.LastUsedModel.transform;
            if (lastUsedModelTransform == null && !parent)
            {
                lastUsedModelTransform = CreateModelInstanceInScene(parent).transform;
                parent = lastUsedModelTransform;
            }
            else
            if (!parent)
            {
                parent = lastUsedModelTransform;
            }

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

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

            UnityEditor.Selection.activeGameObject = gameObject;
            Undo.RegisterCreatedObjectUndo(gameObject, "Created brush");
            InternalCSGModelManager.CheckForChanges();
            InternalCSGModelManager.UpdateMeshes();
            return(brush);
        }
コード例 #6
0
 void UndoRedoPerformed()
 {
     InternalCSGModelManager.UndoRedoPerformed();
 }
コード例 #7
0
        public static void HideUnselectedObjects()
        {
            Undo.IncrementCurrentGroup();
            var undoGroupIndex = Undo.GetCurrentGroup();

            var selected    = Selection.gameObjects.ToList();
            var selectedIDs = new HashSet <int>();

            var models = InternalCSGModelManager.Models;

            for (var i = 0; i < models.Length; i++)
            {
                var model = models[i];
                if (!model)
                {
                    continue;
                }

                var modelCache = InternalCSGModelManager.GetModelCache(model);
                if (modelCache == null ||
                    !modelCache.GeneratedMeshes)
                {
                    continue;
                }

                var meshContainerChildren = modelCache.GeneratedMeshes.GetComponentsInChildren <Transform>();
                //for (int s = 0; s < MeshInstanceManager.SceneStates.Count; s++)
                //{
                //var sceneState		= MeshInstanceManager.SceneStates[s];
                //if (!sceneState.ParentMeshContainer)
                //	continue;
                //var meshContainerChildren = sceneState.ParentMeshContainer.GetComponentsInChildren<Transform>();
                foreach (var child in meshContainerChildren)
                {
                    selected.Add(child.gameObject);
                }
            }

            for (int i = 0; i < selected.Count; i++)             // we keep adding parents, and their parents until we hit the root-objects
            {
                selectedIDs.Add(selected[i].GetInstanceID());
                var transform = selected[i].transform;
                var parent    = transform.parent;
                if (parent == null)
                {
                    continue;
                }
                selected.Add(parent.gameObject);
            }

            for (var sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++)
            {
                var activeScene     = SceneManager.GetSceneAt(sceneIndex);
                var rootGameObjects = activeScene.GetRootGameObjects();
                for (var i = 0; i < rootGameObjects.Length; i++)
                {
                    var children = rootGameObjects[i].GetComponentsInChildren <Transform>();
                    for (var c = 0; c < children.Length; c++)
                    {
                        var transform  = children[c];
                        var gameObject = transform.gameObject;
                        if (!gameObject.activeInHierarchy || (gameObject.hideFlags != HideFlags.None))
                        {
                            continue;
                        }

                        if (selectedIDs.Contains(gameObject.GetInstanceID()))
                        {
                            continue;
                        }

                        Undo.RecordObject(gameObject, "Hiding Object");
                        gameObject.SetActive(false);
                    }
                }
            }

            Undo.CollapseUndoOperations(undoGroupIndex);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
ファイル: CSGModelManager.cs プロジェクト: Xaunaught/Gavin
 public static void EnsureBuildFinished()
 {
     InternalCSGModelManager.Refresh(true);
 }
コード例 #10
0
        protected override void HandleCreateShapeEvents(Rect sceneRect)
        {
            if (settings.vertices.Length < 2)
            {
                if (editMode == EditMode.ExtrudeShape ||
                    editMode == EditMode.EditShape)
                {
                    editMode = EditMode.CreatePlane;
                }
            }

            bool     pointOnEdge      = false;
            bool     havePlane        = false;
            bool     vertexOnGeometry = false;
            CSGBrush vertexOnBrush    = null;

            CSGPlane hoverBuildPlane = buildPlane;
            var      sceneView       = SceneView.currentDrawingSceneView; //(SceneView.currentDrawingSceneView != null) ? SceneView.currentDrawingSceneView : SceneView.lastActiveSceneView;
            var      camera          = (sceneView == null) ? null : sceneView.camera;

            if (camera != null &&
                camera.pixelRect.Contains(Event.current.mousePosition))
            {
                if (!hoverDefaultPlane.HasValue ||
                    settings.vertices.Length == 0)
                {
                    bool forceGrid = RealtimeCSG.CSGGrid.ForceGrid;
                    RealtimeCSG.CSGGrid.ForceGrid = false;
                    hoverDefaultPlane             = RealtimeCSG.CSGGrid.CurrentGridPlane;
                    RealtimeCSG.CSGGrid.ForceGrid = forceGrid;
                    firstSnappedEdges             = null;
                    firstSnappedBrush             = null;
                    firstSnappedPlanes            = null;
                    base.geometryModel            = null;
                }
                if (editMode == EditMode.CreatePlane)
                {
                    BrushIntersection intersection;
                    if (!IgnoreDepthForRayCasts(sceneView) && !havePlane &&
                        SceneQueryUtility.FindWorldIntersection(Event.current.mousePosition, out intersection))
                    {
                        worldPosition = intersection.worldIntersection;
                        if (intersection.surfaceInverted)
                        {
                            hoverBuildPlane = intersection.plane.Negated();
                        }
                        else
                        {
                            hoverBuildPlane = intersection.plane;
                        }
                        vertexOnBrush = intersection.brush;

                        vertexOnGeometry = true;
                    }
                    else
                    {
                        hoverBuildPlane = hoverDefaultPlane.Value;
                        vertexOnBrush   = null;

                        var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
                        worldPosition    = hoverBuildPlane.Intersection(mouseRay);
                        vertexOnGeometry = false;
                    }

                    ResetVisuals();
                    if (snapFunction != null)
                    {
                        CSGBrush snappedOnBrush;
                        worldPosition = snapFunction(worldPosition, hoverBuildPlane, ref visualSnappedEdges, out snappedOnBrush, generatedBrushes);
                        if (snappedOnBrush != null)
                        {
                            pointOnEdge = (visualSnappedEdges != null &&
                                           visualSnappedEdges.Count > 0);
                            vertexOnBrush    = snappedOnBrush;
                            vertexOnGeometry = true;
                        }
                    }

                    if (settings.vertices.Length == 1)
                    {
                        if (hoverBuildPlane.normal != MathConstants.zeroVector3)
                        {
                            editMode  = EditMode.CreateShape;
                            havePlane = true;
                        }
                    }
                    else
                    if (settings.vertices.Length == 2)
                    {
                        onLastPoint = true;
                    }
                }
                else
                {
                    var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
                    worldPosition = hoverBuildPlane.Intersection(mouseRay);

                    ResetVisuals();
                    if (snapFunction != null)
                    {
                        CSGBrush snappedOnBrush;
                        worldPosition = snapFunction(worldPosition, hoverBuildPlane, ref visualSnappedEdges, out snappedOnBrush, generatedBrushes);
                        if (snappedOnBrush != null)
                        {
                            pointOnEdge = (visualSnappedEdges != null &&
                                           visualSnappedEdges.Count > 0);
                            vertexOnBrush = snappedOnBrush;
                        }
                    }
                }

                if (geometryModel == null && vertexOnBrush != null)
                {
                    var brush_cache = InternalCSGModelManager.GetBrushCache(vertexOnBrush);
                    if (brush_cache != null && brush_cache.childData != null && brush_cache.childData.Model)
                    {
                        geometryModel = brush_cache.childData.Model;
                    }
                }

                if (worldPosition != prevWorldPosition)
                {
                    prevWorldPosition = worldPosition;
                    if (Event.current.type != EventType.Repaint)
                    {
                        SceneView.RepaintAll();
                    }
                }

                visualSnappedGrid  = RealtimeCSG.CSGGrid.FindAllGridEdgesThatTouchPoint(worldPosition);
                visualSnappedBrush = vertexOnBrush;
            }

            RealtimeCSG.CSGGrid.SetForcedGrid(hoverBuildPlane);


            if (!SceneDragToolManager.IsDraggingObjectInScene &&
                Event.current.type == EventType.Repaint)
            {
                PaintSnapVisualisation();
                PaintShape(base.shapeId);
            }


            var type = Event.current.GetTypeForControl(base.shapeId);

            switch (type)
            {
            case EventType.Layout:
            {
                return;
            }

            case EventType.ValidateCommand:
            case EventType.KeyDown:
            {
                if (GUIUtility.hotControl == base.shapeId)
                {
                    if (Keys.PerformActionKey.IsKeyPressed() ||
                        Keys.DeleteSelectionKey.IsKeyPressed() ||
                        Keys.CancelActionKey.IsKeyPressed())
                    {
                        Event.current.Use();
                    }
                }
                return;
            }

            case EventType.KeyUp:
            {
                if (GUIUtility.hotControl == base.shapeId)
                {
                    if (Keys.BoxBuilderMode.IsKeyPressed() ||
                        Keys.PerformActionKey.IsKeyPressed())
                    {
                        HotKeyReleased();
                        Event.current.Use();
                        return;
                    }
                    if (Keys.DeleteSelectionKey.IsKeyPressed() ||
                        Keys.CancelActionKey.IsKeyPressed())
                    {
                        Cancel();
                        Event.current.Use();
                        return;
                    }
                }
                return;
            }

            case EventType.MouseDown:
            {
                if (!sceneRect.Contains(Event.current.mousePosition))
                {
                    break;
                }
                if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan)
                {
                    return;
                }
                if ((GUIUtility.hotControl != 0 && GUIUtility.hotControl != shapeEditId && GUIUtility.hotControl != base.shapeId) ||
                    Event.current.button != 0)
                {
                    return;
                }

                Event.current.Use();
                if (settings.vertices.Length == 0)
                {
                    if ((GUIUtility.hotControl == 0 ||
                         GUIUtility.hotControl == base.shapeEditId) && base.shapeId != -1)
                    {
                        base.CalculateWorldSpaceTangents();
                        GUIUtility.hotControl             = base.shapeId;
                        GUIUtility.keyboardControl        = base.shapeId;
                        EditorGUIUtility.editingTextField = false;
                    }
                }

                if (GUIUtility.hotControl == base.shapeId && settings.vertices.Length < 2)
                {
                    if (!float.IsNaN(worldPosition.x) && !float.IsInfinity(worldPosition.x) &&
                        !float.IsNaN(worldPosition.y) && !float.IsInfinity(worldPosition.y) &&
                        !float.IsNaN(worldPosition.z) && !float.IsInfinity(worldPosition.z))
                    {
                        if (hoverBuildPlane.normal.sqrMagnitude != 0)
                        {
                            buildPlane = hoverBuildPlane;
                        }
                        CalculateWorldSpaceTangents();

                        if (settings.vertices.Length == 0)
                        {
                            if (pointOnEdge)
                            {
                                firstSnappedEdges  = visualSnappedEdges.ToArray();
                                firstSnappedBrush  = visualSnappedBrush;
                                firstSnappedPlanes = null;
                            }
                            else
                            {
                                firstSnappedBrush  = null;
                                firstSnappedEdges  = null;
                                firstSnappedPlanes = null;
                            }
                            geometryPlane   = buildPlane;
                            planeOnGeometry = vertexOnGeometry;
                        }
                        else
                        {
                            if (firstSnappedEdges != null)
                            {
                                if (firstSnappedPlanes == null)
                                {
                                    CreateSnappedPlanes();
                                }

                                bool outside = true;
                                for (int i = 0; i < firstSnappedPlanes.Length; i++)
                                {
                                    if (firstSnappedPlanes[i].Distance(worldPosition) <= MathConstants.DistanceEpsilon)
                                    {
                                        outside = false;
                                        break;
                                    }
                                }

                                planeOnGeometry = !outside;
                            }

                            if (vertexOnGeometry)
                            {
                                var plane    = hoverDefaultPlane.Value;
                                var distance = plane.Distance(worldPosition);
                                if (float.IsInfinity(distance) || float.IsNaN(distance))
                                {
                                    distance = 1.0f;
                                }
                                plane.d          += distance;
                                hoverDefaultPlane = plane;

                                for (int i = 0; i < settings.vertices.Length; i++)
                                {
                                    if (!settings.onGeometryVertices[i])
                                    {
                                        settings.vertices[i]           = GeometryUtility.ProjectPointOnPlane(plane, settings.vertices[i]);
                                        settings.onGeometryVertices[i] = true;
                                    }
                                }
                            }
                        }
                        ArrayUtility.Add(ref settings.onGeometryVertices, vertexOnGeometry);
                        settings.AddPoint(worldPosition);
                        SceneView.RepaintAll();
                        if (settings.vertices.Length == 2)
                        {
                            HotKeyReleased();
                        }
                    }
                }
                return;
            }

            case EventType.MouseDrag:
            {
                if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan)
                {
                    break;
                }
                if (GUIUtility.hotControl == base.shapeId && Event.current.button == 0)
                {
                    Event.current.Use();
                }
                return;
            }

            case EventType.MouseUp:
            {
                if (GUIUtility.hotControl != base.shapeId)
                {
                    return;
                }
                if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan)
                {
                    return;
                }
                if (Event.current.button == 0)
                {
                    Event.current.Use();

                    ResetVisuals();
                    if (onLastPoint)
                    {
                        GUIUtility.hotControl             = 0;
                        GUIUtility.keyboardControl        = 0;
                        EditorGUIUtility.editingTextField = false;

                        editMode = EditMode.CreateShape;
                        HotKeyReleased();
                    }
                }
                return;
            }
            }
            return;
        }
コード例 #11
0
        // returns true on success
        internal static bool AddNode(HierarchyItem node, ParentNodeData top)
        {
            if (node.Parent != null)
            {
                //Debug.Log("node.parent != null");
                return(false);
            }

            if (!top.Transform)
            {
//				var top_transform_name	= (top.transform == null) ? "null" : top.transform.name;
//				var node_transform_name = (node.transform == null) ? "null" : node.transform.name;
//				Debug.Log("!top.transform (top.transform=" + top_transform_name + ", node.transform = " + node_transform_name + ")", node.transform);
                return(false);
            }

            var ancestors = new List <Transform>();

            var leafTransform = node.Transform;

            if (leafTransform == null)
            {
                //Debug.Log("node.transform == null");
                return(false);
            }
            var iterator = leafTransform.parent;

            while (iterator != null &&
                   iterator != top.Transform)
            {
                ancestors.Add(iterator);
                iterator = iterator.parent;
            }

            var defaultModel = InternalCSGModelManager.GetDefaultCSGModelForObject(iterator);

            if (!defaultModel)
            {
                return(false);
            }

            var defaultModelTransform = defaultModel.transform;

            if (iterator == null || top.Transform == null ||
                top.Transform == defaultModelTransform)
            {
                iterator = defaultModelTransform;
            }

            if (iterator == null)
            {
                node.Reset();
                top.Reset();
                //Debug.Log("iterator == null");
                return(false);
            }
            if (iterator != top.Transform)
            {
                //Debug.Log("iterator != top.transform");
                return(false);
            }

//			var currentLoopCount = CurrentLoopCount;

            HierarchyItem lastParent    = top;
            var           ancestorDepth = ancestors.Count - 1;

            while (ancestorDepth >= 0)
            {
                var ancestor = ancestors[ancestorDepth];
                int childIndex;
                if (!lastParent.FindSiblingIndex(ancestor, ancestor.GetSiblingIndex(), ancestor.GetInstanceID(), out childIndex))
                {
                    break;
                }

                lastParent = lastParent.ChildNodes[childIndex];
                ancestorDepth--;
            }
            while (ancestorDepth >= 0)
            {
                var newAncestor = new HierarchyItem();
                newAncestor.Transform   = ancestors[ancestorDepth];
                newAncestor.TransformID = newAncestor.Transform.GetInstanceID();
                newAncestor.Parent      = lastParent;

                if (!lastParent.AddChildItem(newAncestor))
                {
                    return(false);
                }

                lastParent = newAncestor;
                ancestorDepth--;
            }

            node.Parent          = lastParent;
            top.ChildrenModified = true;
            return(lastParent.AddChildItem(node));
        }
コード例 #12
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();
            }
        }
コード例 #13
0
        internal override bool CreateControlMeshForBrushIndex(CSGModel parentModel, CSGBrush brush, ShapePolygon polygon, Matrix4x4 localToWorld, float height, out ControlMesh newControlMesh, out Shape newShape)
        {
            bool smooth            = settings.circleSmoothShading;
            bool singleSurfaceEnds = settings.circleSingleSurfaceEnds;
            var  direction         = haveForcedDirection ? forcedDirection : buildPlane.normal;

            if (!ShapePolygonUtility.GenerateControlMeshFromVertices(polygon,
                                                                     localToWorld,
                                                                     GeometryUtility.RotatePointIntoPlaneSpace(buildPlane, direction),
                                                                     height,

                                                                     new TexGen(),

                                                                     smooth,
                                                                     singleSurfaceEnds,
                                                                     out newControlMesh,
                                                                     out newShape))
            {
                return(false);
            }

            brush.Shape       = newShape;
            brush.ControlMesh = newControlMesh;
            InternalCSGModelManager.ValidateBrush(brush, true);
            ControlMeshUtility.RebuildShape(brush);

            var   vertices      = polygon.Vertices;
            float circumference = 0.0f;

            for (int j = vertices.Length - 1, i = 0; i < vertices.Length; j = i, i++)
            {
                circumference += (vertices[j] - vertices[i]).magnitude;
            }

            var shape = brush.Shape;

            float desiredTextureLength = Mathf.Max(1.0f, Mathf.Round(circumference));
            float scalar = desiredTextureLength / circumference;

            shape.TexGens[0].Scale.x       = scalar;
            shape.TexGens[0].Scale.y       = shape.TexGens[0].Scale.y;
            shape.TexGens[0].Translation.x = 0;

            var count = vertices.Length;

            if (!singleSurfaceEnds)
            {
                GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, 0, count);
                GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, 0, count + count);
                for (int j = 0, i = 1; i < count; j = i, i++)
                {
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, j, i);
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, i, i + count);
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, i, i + count + count);
                }
            }
            else
            {
                for (int j = 0, i = 1; i < count; j = i, i++)
                {
                    GeometryUtility.ContinueTexGenFromSurfaceToSurface(brush, j, i);
                }
            }

            return(true);
        }
コード例 #14
0
        //void OnSceneGUI() <- paints -everything- again for every selected brush
        public static void OnSceneGUI(SceneView sceneView)
        {
            if (EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }


            /*
             * int prevHotControl		= GUIUtility.hotControl;
             * int prevKeyboardControl = GUIUtility.keyboardControl;
             *
             * // make it impossible for the tool to click in the bottom bar area
             * int bottomBarId	 = GUIUtility.GetControlID (BottomBarInputHash, FocusType.Passive);
             * bool forceRevert = false;
             * //if (GUIUtility.hotControl == 0)
             * {
             *      var bottomBarRect = sceneView.position;
             *      var min = bottomBarRect.min;
             *      var max = bottomBarRect.max;
             *
             *      min.y = max.y - (GUIStyleUtility.BottomToolBarHeight + 18);
             *
             *      bottomBarRect.min = min;
             *      bottomBarRect.max = max;
             *
             *      if (bottomBarRect.Contains(Event.current.mousePosition))
             *      {
             *              GUIUtility.hotControl	   = bottomBarId;
             *              GUIUtility.keyboardControl = bottomBarId;
             *              forceRevert = true;
             *      }
             * }
             */
            SelectionUtility.HandleEvents();
            InitTools();

            HandleBuilderEvents();
            //HandleYMode();
            {
                UpdateTool();

                if (instance.activeTool != null)
                {
                    if (RealtimeCSG.CSGSettings.EnableRealtimeCSG)
                    {
                        // handle the tool
                        var sceneSize = sceneView.position.size;
                        var sceneRect = new Rect(0, 0, sceneSize.x, sceneSize.y - ((GUIStyleUtility.BottomToolBarHeight + 4) + 17));
                        //var originalEventType = Event.current.type;
                        //if (originalEventType == EventType.MouseMove ||
                        //	originalEventType == EventType.MouseUp)
                        //	holdingDownMouse = false;

                        //var mousePos = Event.current.mousePosition;
                        //if (originalEventType == EventType.Layout ||
                        //	originalEventType == EventType.Repaint ||
                        //	sceneRect.Contains(mousePos) ||
                        //	holdingDownMouse)
                        instance.activeTool.HandleEvents(sceneRect);

                        //if (originalEventType == EventType.MouseDown ||
                        //	originalEventType == EventType.MouseDrag)
                        //	holdingDownMouse = true;
                    }
                    else
                    {
                        if (Event.current.type == EventType.Repaint)
                        {
                            var brushes      = instance.filteredSelection.BrushTargets;
                            var wireframes   = new List <GeometryWireframe>(brushes.Length);
                            var translations = new List <Vector3>(brushes.Length);
                            for (int i = 0; i < brushes.Length; i++)
                            {
                                var brush = brushes[i];
                                if (!brush)
                                {
                                    continue;
                                }

                                var brushCache = InternalCSGModelManager.GetBrushCache(brush);
                                if (brushCache == null ||
                                    brushCache.childData == null ||
                                    !brushCache.childData.Model)
                                {
                                    continue;
                                }

                                var brushTranslation = brushCache.compareTransformation.modelLocalPosition + brushCache.childData.ModelTransform.position;

                                wireframes.Add(BrushOutlineManager.GetBrushOutline(brushes[i].brushID));
                                translations.Add(brushTranslation);
                            }
                            if (wireframes.Count > 0)
                            {
                                CSGRenderer.DrawSelectedBrushes(instance.zTestLineMeshManager, instance.noZTestLineMeshManager,
                                                                wireframes.ToArray(), translations.ToArray(),
                                                                ColorSettings.SelectedOutlines, ToolConstants.thickLineScale);
                            }
                            MaterialUtility.LineDashMultiplier      = 1.0f;
                            MaterialUtility.LineThicknessMultiplier = 1.0f;
                            MaterialUtility.LineAlphaMultiplier     = 1.0f;
                            instance.zTestLineMeshManager.Render(MaterialUtility.ZTestGenericLine);
                            instance.zTestLineMeshManager.Render(MaterialUtility.ZTestGenericLine);
                        }
                    }
                }
            }

            /*
             * // reset the control so the bottom bar can take over
             * if (forceRevert)
             * {
             *      GUIUtility.hotControl		= prevHotControl;
             *      GUIUtility.keyboardControl	= prevKeyboardControl;
             * }
             */

            int sceneWindowId   = GUIUtility.GetControlID(SceneWindowHash, FocusType.Passive);
            var sceneWindowType = Event.current.GetTypeForControl(sceneWindowId);

            if (sceneWindowType == EventType.Repaint)
            {
                if (currentEditorWindows.Count > 0)
                {
                    for (int i = 0; i < currentEditorWindows.Count; i++)
                    {
                        currentEditorWindows[i].Repaint();
                    }
                    return;
                }
            }

            if (sceneWindowType == EventType.MouseMove)
            {
                SceneTools.IsDraggingObjectInScene = false;
            }

            if (RealtimeCSG.CSGSettings.EnableRealtimeCSG)
            {
                if (sceneView != null && sceneWindowType != EventType.Used && !SceneTools.IsDraggingObjectInScene)
                {
                    if (currentEditorWindows.Count == 0)
                    {
                        try
                        {
                            Handles.BeginGUI();
                            Rect windowRect = new Rect(Vector2.zero, sceneView.position.size);
                            CSGBrushEditorGUI.HandleWindowGUI(windowRect);
                        }
                        finally
                        {
                            Handles.EndGUI();
                        }
                    }
                }
            }
        }
コード例 #15
0
 public static void ForceRebuild()
 {
     InternalCSGModelManager.Rebuild();
 }
コード例 #16
0
        protected bool GenerateBrushObjects(int brushObjectCount, bool inGridSpace = true)
        {
            Undo.IncrementCurrentGroup();
            undoGroupIndex = Undo.GetCurrentGroup();

            var lastUsedModel = SelectionUtility.LastUsedModel;

            if (!ModelTraits.IsModelEditable(lastUsedModel))
            {
                lastUsedModel = null;
            }
            var lastUsedModelTransform = !lastUsedModel ? null : lastUsedModel.transform;

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

                        if (!brush)
                        {
                            continue;
                        }

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

                        if (brush.ChildData == null ||
                            brush.ChildData.ModelTransform == null)
                        {
                            continue;
                        }

                        var model = brush.ChildData.Model;
                        if (!model ||
                            !model.isActiveAndEnabled)
                        {
                            continue;
                        }

                        lastUsedModelTransform = brush.ChildData.ModelTransform;
                        break;
                    }
                }
            }

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

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

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

                //DebugEditorWindow.PrintDebugInfo();

                if (lastUsedModelTransform == null)
                {
                    parentGameObject = OperationsUtility.CreateGameObject(lastUsedModelTransform, "Model", true);
                    InternalCSGModelManager.CreateCSGModel(parentGameObject);
                    parentModel = parentGameObject.GetComponent <CSGModel>();
                    Undo.RegisterCreatedObjectUndo(parentGameObject, "Created model");

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

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

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


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

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

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

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


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

            return(generatedBrushes != null && generatedBrushes.Length > 0 && generatedBrushes.Length == brushObjectCount);
        }
コード例 #17
0
        protected bool UpdateExtrudedShape(bool registerUndo = true)
        {
            if (polygons == null || polygons.Length == 0)
            {
                return(false);
            }

            bool failures          = false;
            bool modifiedHierarchy = false;

            if (HaveExtrusion)
            {
                UpdateBrushOperation();

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

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

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

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

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

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


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

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

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

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

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

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

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

            return(!failures);
        }
コード例 #18
0
        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
        }
コード例 #19
0
        // returns true when modified
        internal static bool UpdateNodePosition(HierarchyItem node, ParentNodeData top)
        {
            // on each level, compare sibling position to nodes before and after it.
            // if it's different, remove self and find new position in array.
            // continue to next parent.
            var iteratorParent = node.Parent;

            if (iteratorParent == null)
            {
                AddNode(node, top);
                top.ChildrenModified = true;
                return(true);
            }

            var currentLoopCount = CurrentLoopCount;

            var iterator = node;

            while (iteratorParent != null)
            {
                var iteratorTransformID = iterator.TransformID;

                if (iteratorTransformID == 0)
                {
                    Debug.Log("iterator_transform == null");
                }
                else
                if (iterator.LastLoopCount != currentLoopCount)
                {
                    var iteratorTransform         = iterator.Transform;
                    var iteratorParentTransformID = iteratorTransform.parent == null ? 0 : iteratorTransform.parent.GetInstanceID();
                    // Compare the unity parent transform to the stored parent transform
                    if (iteratorParent.TransformID != iteratorParentTransformID)
                    {
                        var defaultCSGInstanceID = 0;
                        var defaultCSGModel      = InternalCSGModelManager.GetDefaultCSGModelForObject(iteratorTransform);
                        if (defaultCSGModel != null &&
                            defaultCSGModel.transform != null)
                        {
                            defaultCSGInstanceID = defaultCSGModel.transform.GetInstanceID();
                        }
                        if (defaultCSGInstanceID == 0 || defaultCSGInstanceID != iteratorParent.TransformID)
                        {
                            RemoveNode(node, top);
                            AddNode(node, top);
                            top.ChildrenModified = true;
                            return(true);
                        }
                    }

                    if (iterator.LastLoopCount != currentLoopCount)
                    {
                        iterator.CachedTransformSiblingIndex = iteratorTransform.GetSiblingIndex();
                        iterator.LastLoopCount = currentLoopCount;
                    }

                    // Does the child even exist in the parent transform?
                    int iteratorChildIndex;
                    if (!iteratorParent.FindSiblingIndex(iteratorTransform, iterator.CachedTransformSiblingIndex, iteratorTransformID, out iteratorChildIndex))
                    {
                        RemoveNode(node, top);
                        AddNode(node, top);
                        top.ChildrenModified = true;
                        return(true);
                    }

                    // See if the position of the child has changed ..
                    if (iteratorChildIndex != iterator.SiblingIndex)
                    {
                        iterator.SiblingIndex = iteratorChildIndex;
                        RemoveNode(node, top);
                        AddNode(node, top);
                        top.ChildrenModified = true;
                        return(true);
                    }

                    // Compare the child index to the one before and after it ..
                    var iteratorParentChildNodes = iteratorParent.ChildNodes;
                    var iteratorSiblingIndex     = iteratorTransform.GetSiblingIndex();
                    if (iteratorChildIndex > 0)
                    {
                        var prevTransform = iteratorParentChildNodes[iteratorChildIndex - 1].Transform;
                        if (!prevTransform)
                        {
                            return(false);
                        }
                        var iteratorPrevSiblingIndex = prevTransform.GetSiblingIndex();
                        if (iteratorPrevSiblingIndex >= iteratorSiblingIndex)
                        {
                            RemoveNode(node, top);
                            AddNode(node, top);
                            top.ChildrenModified = true;
                            return(true);
                        }
                    }
                    else
                    if (iteratorChildIndex < iteratorParentChildNodes.Length - 1)
                    {
                        var nextTransform = iteratorParentChildNodes[iteratorChildIndex + 1].Transform;
                        if (!nextTransform)
                        {
                            return(false);
                        }
                        var iteratorNextSiblingIndex = nextTransform.GetSiblingIndex();
                        if (iteratorNextSiblingIndex <= iteratorSiblingIndex)
                        {
                            RemoveNode(node, top);
                            AddNode(node, top);
                            top.ChildrenModified = true;
                            return(true);
                        }
                    }
                }

                iterator       = iteratorParent;
                iteratorParent = iterator.Parent;
            }

            return(false);
        }
コード例 #20
0
        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();
        }
コード例 #21
0
        protected override void HandleEditShapeEvents(Rect sceneRect)
        {
            if (settings.vertices.Length < 2)
            {
                if (editMode == EditMode.ExtrudeShape ||
                    editMode == EditMode.EditShape)
                {
                    editMode = EditMode.CreatePlane;
                }
            }

            if (!SceneDragToolManager.IsDraggingObjectInScene &&
                Event.current.type == EventType.Repaint)
            {
                if (visualSnappedEdges != null)
                {
                    PaintUtility.DrawLines(visualSnappedEdges.ToArray(), ToolConstants.oldThickLineScale, ColorSettings.SnappedEdges);
                }

                if (visualSnappedGrid != null)
                {
                    var _origMatrix = Handles.matrix;
                    Handles.matrix = MathConstants.identityMatrix;
                    PaintUtility.DrawDottedLines(visualSnappedGrid.ToArray(), ColorSettings.SnappedEdges);
                    Handles.matrix = _origMatrix;
                }

                if (visualSnappedBrush != null)
                {
                    var brush_cache = InternalCSGModelManager.GetBrushCache(visualSnappedBrush);
                    if (brush_cache != null &&
                        brush_cache.compareTransformation != null &&
                        brush_cache.childData != null &&
                        brush_cache.childData.ModelTransform != null &&
                        brush_cache.childData.ModelTransform)
                    {
                        var brush_translation = brush_cache.compareTransformation.modelLocalPosition + brush_cache.childData.ModelTransform.position;
                        CSGRenderer.DrawOutlines(visualSnappedBrush.brushID, brush_translation, ColorSettings.SelectedOutlines, ColorSettings.SelectedOutlines, ColorSettings.SelectedOutlines, ColorSettings.SelectedOutlines);
                    }
                }

                var origMatrix = Handles.matrix;
                Handles.matrix = MathConstants.identityMatrix;
                PaintBounds();
                Handles.matrix = origMatrix;
            }

            HandleHeightHandles(sceneRect, false);

            for (int i = 0; i < settings.vertices.Length; i++)
            {
                var id         = settings.vertexIDs[i];
                var point_type = Event.current.GetTypeForControl(id);
                switch (point_type)
                {
                case EventType.Repaint:
                {
                    if (SceneDragToolManager.IsDraggingObjectInScene)
                    {
                        break;
                    }

                    bool isSelected = id == GUIUtility.keyboardControl;
                    var  temp       = Handles.color;
                    var  origMatrix = Handles.matrix;

                    Handles.matrix = MathConstants.identityMatrix;
                    var rotation = Camera.current.transform.rotation;


                    if (isSelected)
                    {
                        Handles.color = ColorSettings.PointInnerStateColor[3];
                    }
                    else
                    if (HandleUtility.nearestControl == id)
                    {
                        Handles.color = ColorSettings.PointInnerStateColor[1];
                    }
                    else
                    {
                        Handles.color = ColorSettings.PointInnerStateColor[0];
                    }

                    float handleSize       = CSG_HandleUtility.GetHandleSize(settings.vertices[i]);
                    float scaledHandleSize = handleSize * ToolConstants.handleScale;
                    PaintUtility.SquareDotCap(id, settings.vertices[i], rotation, scaledHandleSize);

                    Handles.matrix = origMatrix;
                    Handles.color  = temp;
                    break;
                }

                case EventType.Layout:
                {
                    if ((Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan))
                    {
                        break;
                    }

                    var origMatrix = Handles.matrix;
                    Handles.matrix = MathConstants.identityMatrix;
                    float handleSize       = CSG_HandleUtility.GetHandleSize(settings.vertices[i]);
                    float scaledHandleSize = handleSize * ToolConstants.handleScale;
                    HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(settings.vertices[i], scaledHandleSize));
                    Handles.matrix = origMatrix;

                    break;
                }

                case EventType.ValidateCommand:
                case EventType.KeyDown:
                {
                    if (GUIUtility.hotControl == id)
                    {
                        if (Keys.CancelActionKey.IsKeyPressed())
                        {
                            Event.current.Use();
                            break;
                        }
                    }
                    break;
                }

                case EventType.KeyUp:
                {
                    if (GUIUtility.hotControl == id)
                    {
                        if (Keys.CancelActionKey.IsKeyPressed())
                        {
                            GUIUtility.hotControl             = 0;
                            GUIUtility.keyboardControl        = 0;
                            EditorGUIUtility.editingTextField = false;
                            Event.current.Use();
                            break;
                        }
                    }
                    break;
                }

                case EventType.MouseDown:
                {
                    if (!sceneRect.Contains(Event.current.mousePosition))
                    {
                        break;
                    }
                    if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan)
                    {
                        break;
                    }
                    if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == id && Event.current.button == 0)
                    {
                        GUIUtility.hotControl             = id;
                        GUIUtility.keyboardControl        = id;
                        EditorGUIUtility.editingTextField = false;
                        EditorGUIUtility.SetWantsMouseJumping(1);
                        Event.current.Use();
                        break;
                    }
                    break;
                }

                case EventType.MouseDrag:
                {
                    if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan)
                    {
                        break;
                    }
                    if (GUIUtility.hotControl == id && Event.current.button == 0)
                    {
                        Undo.RecordObject(this, "Modify shape");

                        var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
                        RealtimeCSG.CSGGrid.SetForcedGrid(buildPlane);
                        var alignedPlane  = new CSGPlane(RealtimeCSG.CSGGrid.CurrentWorkGridPlane.normal, settings.vertices[0]);
                        var worldPosition = buildPlane.Project(alignedPlane.Intersection(mouseRay));
                        if (float.IsInfinity(worldPosition.x) || float.IsNaN(worldPosition.x) ||
                            float.IsInfinity(worldPosition.y) || float.IsNaN(worldPosition.y) ||
                            float.IsInfinity(worldPosition.z) || float.IsNaN(worldPosition.z))
                        {
                            worldPosition = settings.vertices[i];
                        }

                        ResetVisuals();
                        if (snapFunction != null)
                        {
                            CSGBrush snappedOnBrush;
                            worldPosition = snapFunction(worldPosition, buildPlane, ref base.visualSnappedEdges, out snappedOnBrush, generatedBrushes);
                        }

                        base.visualSnappedGrid = RealtimeCSG.CSGGrid.FindAllGridEdgesThatTouchPoint(worldPosition);

                        settings.vertices[i] = worldPosition;

                        CenterExtrusionPoints(buildPlane);
                        UpdateBaseShape();

                        if (editMode == EditMode.ExtrudeShape)
                        {
                            StartExtrudeMode();
                            UpdateBaseShape();
                        }
                        UpdateExtrudedShape();

                        GUI.changed = true;
                        Event.current.Use();
                        break;
                    }
                    break;
                }

                case EventType.MouseUp:
                {
                    if (GUIUtility.hotControl != id)
                    {
                        break;
                    }
                    if (Tools.viewTool != ViewTool.None && Tools.viewTool != ViewTool.Pan)
                    {
                        break;
                    }
                    if (Event.current.button == 0)
                    {
                        GUIUtility.hotControl             = 0;
                        GUIUtility.keyboardControl        = 0;
                        EditorGUIUtility.editingTextField = false;
                        EditorGUIUtility.SetWantsMouseJumping(0);
                        Event.current.Use();

                        ResetVisuals();
                        //if (Length == 0 || Width == 0)
                        //{
                        //	Cancel();
                        //}
                        break;
                    }
                    break;
                }
                }
            }
        }
コード例 #22
0
        static void UpdateChildrenModel(CSGModel model, Transform container)
        {
            if (External == null)
            {
                return;
            }
            if (model == null)
            {
                return;
            }

            for (int i = 0; i < container.childCount; i++)
            {
                var child   = container.GetChild(i);
                var nodeObj = child.GetComponent(TypeConstants.CSGNodeType);
                if (nodeObj)
                {
                    var op = nodeObj as CSGOperation;
                    if (op &&
                        !op.PassThrough)
                    {
                        // make sure the node has already been initialized, otherwise
                        // assume it'll still get initialized at some point, in which
                        // case we shouldn't update it's hierarchy here
                        if (!op.IsRegistered)
                        {
                            continue;
                        }

                        if (op.ChildData.Model != model)
                        {
                            if (model)                             // assume we're still initializing
                            {
                                SetCSGOperationHierarchy(op, op.ChildData.Parent, model);
                            }
                        }
                        else
                        {
                            // assume that if this operation already has the
                            // correct model, then it's children will have the same model
                            break;
                        }
                    }


                    var brush = nodeObj as CSGBrush;
                    if (brush)
                    {
                        // make sure the node has already been initialized, otherwise
                        // assume it'll still get initialized at some point, in which
                        // case we shouldn't update it's hierarchy here
                        if (!brush.IsRegistered)
                        {
                            continue;
                        }

                        if (brush.ChildData.Model != model)
                        {
                            if (model)                             // assume we're still initializing
                            {
                                SetCSGBrushHierarchy(brush, brush.ChildData.Parent, model);
                                InternalCSGModelManager.CheckSurfaceModifications(brush);
                            }
                        }
                        else
                        {
                            // assume that if this brush already has the
                            // correct model, then it's children will have the same model
                            break;
                        }
                    }
                }
                UpdateChildrenModel(model, child);
            }
        }
コード例 #23
0
        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);
        }
コード例 #24
0
        internal override bool UpdateBaseShape(bool registerUndo = true)
        {
            if (editMode == EditMode.CreatePlane)
            {
                return(false);
            }

            var length = StairsDepth;

            if (length <= 0)
            {
                InternalCSGModelManager.skipRefresh = false;
                HideGenerateBrushes();
                return(false);
            }

            var worldToLocalRotation = GetWorldToLocalRotation();
            var localToWorldRotation = Quaternion.Inverse(worldToLocalRotation);

            brushPosition = localToWorldRotation * settings.bounds.Min;

            var totalSteps = TotalSteps;

            if (!GenerateBrushObjects(totalSteps))
            {
                InternalCSGModelManager.skipRefresh = false;
                HideGenerateBrushes();
                return(false);
            }

            if (registerUndo)
            {
                Undo.RecordObjects(generatedBrushes, "Created Linear Stairs");
            }

            if (!GenerateStairs(generatedBrushes, totalSteps, StepDepth, StepHeight, StepDepth, StairsDepth, StairsWidth, StairsHeight, ExtraDepth, ExtraHeight, StairsBottom))
            {
                InternalCSGModelManager.skipRefresh = false;
                HideGenerateBrushes();
                return(false);
            }

            if (registerUndo)
            {
                MarkAllBrushesDirty();
            }


            try
            {
                InternalCSGModelManager.skipRefresh = true;
                if (registerUndo)
                {
                    EditorUtility.SetDirty(this);
                }
                InternalCSGModelManager.External.ForceModelUpdate(parentModel.modelID);
                InternalCSGModelManager.Refresh(forceHierarchyUpdate: true);
                //DebugEditorWindow.PrintDebugInfo();
            }
            finally
            {
                InternalCSGModelManager.skipRefresh = false;
            }
            return(true);
        }
コード例 #25
0
        internal override bool UpdateBaseShape(bool registerUndo = true)
		{
			if (settings.vertices == null ||
				settings.vertices.Length == 0)
				editMode = EditMode.CreatePlane;

			if (editMode == EditMode.CreatePlane)
				return false;

			float radius = SphereRadius;
			if (editMode == EditMode.CreateShape)
			{
				brushPosition = settings.vertices[0];
				//extrusionPoints[0].Vertex = settings.vertices[0];
				radius = (settings.vertices[0] - worldPosition).magnitude;
			}

            GenerateBrushObjects(1);
			
            if (radius == 0 || generatedBrushes == null || generatedBrushes.Length < 1)
			{
				InternalCSGModelManager.skipCheckForChanges = false;
                HideGenerateBrushes();
                return false;
            }
			
            //UpdateBrushOperation(height);

            bool failures = false;
            bool modifiedHierarchy = false;
            if (generatedGameObjects != null && generatedGameObjects.Length > 0)
            {
                for (int i = generatedGameObjects.Length - 1; i >= 0; i--)
                {
                    if (generatedGameObjects[i])
                        continue;
                    ArrayUtility.RemoveAt(ref generatedGameObjects, i);
                }
            }
            if (generatedGameObjects == null || generatedGameObjects.Length == 0)
            {
                Cancel();
                return false;
            }
            if (generatedGameObjects != null && generatedGameObjects.Length > 0)
            {
                if (registerUndo)
                    Undo.RecordObjects(generatedGameObjects, "Created Sphere");
                
                var brush = generatedBrushes[0];
                if (brush && brush.gameObject)
                {
                    ControlMesh newControlMesh;
                    Shape newShape;
                    if (GenerateSphere(radius, settings.sphereSplits, parentModel, brush, out newControlMesh, out newShape))
                    {
                        if (!brush.gameObject.activeSelf)
                        {
                            modifiedHierarchy = true;
                            brush.gameObject.SetActive(true);
                        }
						
						brush.Shape = newShape;
						brush.ControlMesh = newControlMesh;
						if (registerUndo)
							EditorUtility.SetDirty(brush);
						ControlMeshUtility.UpdateBrushMesh(brush, brush.ControlMesh, brush.Shape);
                    } else
                    {
                        failures = true;
                        if (brush.gameObject.activeSelf)
                        {
                            modifiedHierarchy = true;
                            brush.gameObject.SetActive(false);
                        }
                    }
                }
            }

            try
            {
                InternalCSGModelManager.skipCheckForChanges = true;
                if (registerUndo)
                    EditorUtility.SetDirty(this);
                //CSGModelManager.External.SetDirty(parentModel.modelNodeID); 
                InternalCSGModelManager.CheckForChanges(forceHierarchyUpdate: modifiedHierarchy);
            }
            finally
            {
                InternalCSGModelManager.skipCheckForChanges = false;
            }
            return !failures;
		}
コード例 #26
0
        static public void OnInspectorGUI(Editor editor, UnityEngine.Object[] targets)
        {
            TooltipUtility.InitToolTip(editor);
            try
            {
                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);
                    }
                }

                CSG_GUIStyleUtility.InitStyles();
                ShowRealtimeCSGDisabledMessage();

                if (models.Length > 0 && models.Length == targets.Length)
                {
                    CSGModelComponentInspectorGUI.OnInspectorGUI(targets);
                    return;
                }

                var filteredSelection = EditModeManager.FilteredSelection;
                var targetNodes       = filteredSelection.NodeTargets;
                var targetModels      = filteredSelection.ModelTargets;
                var targetBrushes     = filteredSelection.BrushTargets;
                var targetOperations  = filteredSelection.OperationTargets;
                if (targetNodes == null)
                {
                    return;
                }



                bool?isPrefab = false;
                PrefabInstantiateBehaviour?prefabBehaviour            = PrefabInstantiateBehaviour.Reference;
                PrefabSourceAlignment?     prefabSourceAlignment      = PrefabSourceAlignment.AlignedTop;
                PrefabDestinationAlignment?prefabDestinationAlignment = PrefabDestinationAlignment.AlignToSurface;

                if (targetNodes.Length > 0)
                {
                    var gameObject = targetNodes[0].gameObject;
                    isPrefab                   = CSGPrefabUtility.IsPrefabAsset(gameObject);
                    prefabBehaviour            = targetNodes[0].PrefabBehaviour;
                    prefabSourceAlignment      = targetNodes[0].PrefabSourceAlignment;
                    prefabDestinationAlignment = targetNodes[0].PrefabDestinationAlignment;
                    for (int i = 1; i < targetNodes.Length; i++)
                    {
                        gameObject = targetNodes[i].gameObject;

                        var currentIsPrefab                   = CSGPrefabUtility.IsPrefabAsset(gameObject);
                        var currentPrefabBehaviour            = targetNodes[i].PrefabBehaviour;
                        var currentPrefabSourceAlignment      = targetNodes[i].PrefabSourceAlignment;
                        var currentPrefabDestinationAlignment = targetNodes[i].PrefabDestinationAlignment;
                        if (isPrefab.HasValue && isPrefab.Value != currentIsPrefab)
                        {
                            isPrefab = null;
                        }
                        if (prefabBehaviour.HasValue && prefabBehaviour.Value != currentPrefabBehaviour)
                        {
                            prefabBehaviour = null;
                        }
                        if (prefabSourceAlignment.HasValue && prefabSourceAlignment.Value != currentPrefabSourceAlignment)
                        {
                            prefabSourceAlignment = null;
                        }
                        if (prefabDestinationAlignment.HasValue && prefabDestinationAlignment.Value != currentPrefabDestinationAlignment)
                        {
                            prefabDestinationAlignment = null;
                        }
                    }
                }

                GUILayout.BeginVertical(GUI.skin.box);
                {
                    if (isPrefab.HasValue && isPrefab.Value)
                    {
                        EditorGUILayout.LabelField(PrefabLabelContent);
                    }
                    else
                    {
                        EditorGUILayout.LabelField(RaySnappingLabelContent);
                        TooltipUtility.SetToolTip(RaySnappingBehaviourTooltip);
                    }

                    EditorGUI.indentLevel++;
                    {
                        if (isPrefab.HasValue && isPrefab.Value)
                        {
                            EditorGUI.showMixedValue = !prefabBehaviour.HasValue;
                            var prefabBehavour = prefabBehaviour.HasValue ? prefabBehaviour.Value : PrefabInstantiateBehaviour.Reference;
                            EditorGUI.BeginChangeCheck();
                            {
                                prefabBehavour = (PrefabInstantiateBehaviour)EditorGUILayout.EnumPopup(PrefabInstantiateBehaviourContent, prefabBehavour);
                                TooltipUtility.SetToolTip(PrefabInstantiateBehaviourTooltip);
                            }
                            if (EditorGUI.EndChangeCheck())
                            {
                                Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes");
                                for (int i = 0; i < targetNodes.Length; i++)
                                {
                                    targetNodes[i].PrefabBehaviour = prefabBehavour;
                                }
                            }
                            EditorGUI.showMixedValue = false;
                        }


                        EditorGUI.showMixedValue = !prefabDestinationAlignment.HasValue;
                        var destinationAlignment = prefabDestinationAlignment.HasValue ? prefabDestinationAlignment.Value : PrefabDestinationAlignment.AlignToSurface;
                        EditorGUI.BeginChangeCheck();
                        {
                            destinationAlignment = (PrefabDestinationAlignment)EditorGUILayout.EnumPopup(DestinationAlignmentContent, destinationAlignment);
                            TooltipUtility.SetToolTip(DestinationAlignmentTooltip);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes");
                            for (int i = 0; i < targetNodes.Length; i++)
                            {
                                targetNodes[i].PrefabDestinationAlignment = destinationAlignment;
                            }
                        }
                        EditorGUI.showMixedValue = false;


                        EditorGUI.showMixedValue = !prefabSourceAlignment.HasValue;
                        var sourceAlignment = prefabSourceAlignment.HasValue ? prefabSourceAlignment.Value : PrefabSourceAlignment.AlignedFront;
                        EditorGUI.BeginChangeCheck();
                        {
                            sourceAlignment = (PrefabSourceAlignment)EditorGUILayout.EnumPopup(SourceAlignmentContent, sourceAlignment);
                            TooltipUtility.SetToolTip(SourceAlignmentTooltip);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes");
                            for (int i = 0; i < targetNodes.Length; i++)
                            {
                                targetNodes[i].PrefabSourceAlignment = sourceAlignment;
                            }
                        }
                        EditorGUI.showMixedValue = false;
                    }
                    EditorGUI.indentLevel--;
                }
                GUILayout.EndVertical();
                GUILayout.Space(10);


                if (targetModels.Length == 0)
                {
                    int              invalidOperationType = 999;
                    bool?            handleAsOne          = null;
                    bool             selMixedValues       = false;
                    CSGOperationType operationType        = (CSGOperationType)invalidOperationType;
                    bool             opMixedValues        = false;
                    if (targetBrushes.Length > 0)
                    {
                        operationType = targetBrushes[0].OperationType;
                    }
                    for (int b = 1; b < targetBrushes.Length; b++)
                    {
                        var brush = targetBrushes[b];
                        if (operationType != brush.OperationType)
                        {
                            opMixedValues = true;
                        }
                    }
                    foreach (var operation in targetOperations)
                    {
                        if (operationType == (CSGOperationType)invalidOperationType)
                        {
                            operationType = operation.OperationType;
                        }
                        else
                        if (operationType != operation.OperationType)
                        {
                            opMixedValues = true;
                        }

                        if (!handleAsOne.HasValue)
                        {
                            handleAsOne = operation.HandleAsOne;
                        }
                        else
                        if (handleAsOne.Value != operation.HandleAsOne)
                        {
                            selMixedValues = true;
                        }
                    }
                    GUILayout.BeginVertical(GUI.skin.box);
                    {
                        bool passThroughValue = false;
                        if (targetBrushes.Length == 0 && targetOperations.Length > 0)                         // only operations
                        {
                            bool?passThrough = targetOperations[0].PassThrough;
                            for (int i = 1; i < targetOperations.Length; i++)
                            {
                                if (passThrough.HasValue && passThrough.Value != targetOperations[i].PassThrough)
                                {
                                    passThrough = null;
                                    break;
                                }
                            }

                            opMixedValues = !passThrough.HasValue || passThrough.Value;

                            var ptMixedValues = !passThrough.HasValue;
                            passThroughValue = passThrough.HasValue ? passThrough.Value : false;
                            if (CSG_EditorGUIUtility.PassThroughButton(passThroughValue, ptMixedValues))
                            {
                                Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes");
                                foreach (var operation in targetOperations)
                                {
                                    operation.PassThrough = true;
                                }
                                InternalCSGModelManager.CheckForChanges();
                                EditorApplication.RepaintHierarchyWindow();
                            }

                            if (passThroughValue)
                            {
                                operationType = (CSGOperationType)255;
                            }
                        }
                        EditorGUI.BeginChangeCheck();
                        {
                            operationType = CSG_EditorGUIUtility.ChooseOperation(operationType, opMixedValues);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            Undo.RecordObjects(targetNodes, "Changed CSG operation of nodes");
                            foreach (var brush in targetBrushes)
                            {
                                brush.OperationType = operationType;
                            }
                            foreach (var operation in targetOperations)
                            {
                                operation.PassThrough   = false;
                                operation.OperationType = operationType;
                            }
                            InternalCSGModelManager.CheckForChanges();
                            EditorApplication.RepaintHierarchyWindow();
                        }
                    }
                    GUILayout.EndVertical();

                    if (targetOperations.Length == 0 && targetModels.Length == 0)
                    {
                        GUILayout.Space(10);
                        if (targetBrushes.Length == 1)
                        {
                            GUILayout.BeginVertical(GUI.skin.box);
                            {
                                EditorGUI.indentLevel++;
                                OpenSurfaces = EditorGUILayout.Foldout(OpenSurfaces, SurfacesContent);
                                EditorGUI.indentLevel--;
                                if (OpenSurfaces)
                                {
                                    var targetShape     = targetBrushes[0].Shape;
                                    var texGens         = targetShape.TexGens;
                                    var texGenFlagArray = targetShape.TexGenFlags;
                                    for (int t = 0; t < texGens.Length; t++)
                                    {
                                        GUILayout.Space(2);

                                        var texGenFlags = texGenFlagArray[t];
                                        var material    = targetShape.TexGens[t].RenderMaterial;
                                        var physicsMat  = targetShape.TexGens[t].PhysicsMaterial;
                                        EditorGUI.BeginChangeCheck();
                                        {
                                            GUILayout.BeginHorizontal();
                                            {
                                                GUILayout.Space(4);
                                                material = CSG_EditorGUIUtility.MaterialImage(material);
                                                GUILayout.Space(2);
                                                GUILayout.BeginVertical();
                                                {
                                                    //EditorGUI.BeginDisabledGroup(texGenFlags != TexGenFlags.None);
                                                    {
                                                        material = EditorGUILayout.ObjectField(material, typeof(Material), true) as Material;
                                                    }
                                                    //EditorGUI.EndDisabledGroup();
                                                    physicsMat = EditorGUILayout.ObjectField(physicsMat, typeof(PhysicMaterial), true) as PhysicMaterial;

                                                    texGenFlags = EditModeCommonGUI.OnSurfaceFlagButtons(texGenFlags);
                                                }
                                                GUILayout.EndVertical();
                                                GUILayout.Space(4);
                                            }
                                            GUILayout.EndHorizontal();
                                        }
                                        if (EditorGUI.EndChangeCheck())
                                        {
                                            var selectedBrushSurfaces = new []
                                            {
                                                new SelectedBrushSurface(targetBrushes[0], t)
                                            };
                                            using (new UndoGroup(selectedBrushSurfaces, "discarding surface"))
                                            {
                                                texGenFlagArray[t] = texGenFlags;
                                                targetShape.TexGens[t].RenderMaterial  = material;
                                                targetShape.TexGens[t].PhysicsMaterial = physicsMat;
                                            }
                                        }
                                        GUILayout.Space(4);
                                    }
                                }
                            }
                            GUILayout.EndVertical();
                        }
                    }

                    if (handleAsOne.HasValue)
                    {
                        EditorGUI.BeginChangeCheck();
                        {
                            EditorGUI.showMixedValue = selMixedValues;
                            handleAsOne = EditorGUILayout.Toggle(HandleAsOneLabel, handleAsOne.Value);
                        }
                        if (EditorGUI.EndChangeCheck())
                        {
                            Undo.RecordObjects(targetNodes, "Changed CSG operation 'Handle as one object'");
                            foreach (var operation in targetOperations)
                            {
                                operation.HandleAsOne = handleAsOne.Value;
                            }
                            EditorApplication.RepaintHierarchyWindow();
                        }
                    }
                }

#if false
                if (targetNodes.Length == 1)
                {
                    var node  = targetNodes[0];
                    var brush = node as CSGBrush;
                    if (brush != null)
                    {
                        var brush_cache = CSGSceneManager.GetBrushCache(brush);
                        if (brush_cache == null ||
                            brush_cache.childData == null ||
                            brush_cache.childData.modelTransform == null)
                        {
                            EditorGUILayout.LabelField("brush-cache: null");
                        }
                        else
                        {
                            EditorGUILayout.LabelField("node-id: " + brush.brushNodeID);
                        }
                    }
                    var operation = node as CSGOperation;
                    if (operation != null)
                    {
                        var operation_cache = CSGSceneManager.GetOperationCache(operation);
                        if (operation_cache == null ||
                            operation_cache.childData == null ||
                            operation_cache.childData.modelTransform == null)
                        {
                            EditorGUILayout.LabelField("operation-cache: null");
                        }
                        else
                        {
                            EditorGUILayout.LabelField("operation-id: " + operation.operationNodeID);
                        }
                    }
                    var model = node as CSGModel;
                    if (model != null)
                    {
                        var model_cache = CSGSceneManager.GetModelCache(model);
                        if (model_cache == null ||
                            model_cache.meshContainer == null)
                        {
                            EditorGUILayout.LabelField("model-cache: null");
                        }
                        else
                        {
                            EditorGUILayout.LabelField("model-id: " + model.modelNodeID);
                        }
                    }
                }
#endif
            }
            finally
            {
                TooltipUtility.DrawToolTip(getLastRect: true, goUp: true);
            }
        }
コード例 #27
0
        public static void DoSelectionClick()
        {
            GameObject gameobject;

            SceneQueryUtility.FindClickWorldIntersection(Event.current.mousePosition, out gameobject);

            gameobject = SceneQueryUtility.GetGroupGameObjectIfObjectIsPartOfGroup(gameobject);

            var  selectedObjectsOnClick = new List <int>(Selection.instanceIDs);
            bool addedSelection         = false;

            if (EditorGUI.actionKey)
            {
                if (gameobject != null)
                {
                    var instanceID = gameobject.GetInstanceID();
                    if (selectedObjectsOnClick.Contains(instanceID))
                    {
                        selectedObjectsOnClick.Remove(instanceID);
                    }
                    else
                    {
                        selectedObjectsOnClick.Add(instanceID);
                        addedSelection = true;
                    }

                    if (selectedObjectsOnClick.Count == 0)
                    {
                        Selection.activeTransform = null;
                    }
                    else
                    {
                        Selection.instanceIDs = selectedObjectsOnClick.ToArray();
                    }
                }
            }
            else
            if (Event.current.shift)
            {
                if (gameobject != null)
                {
                    var instanceID = gameobject.GetInstanceID();
                    selectedObjectsOnClick.Add(instanceID);
                    Selection.instanceIDs = selectedObjectsOnClick.ToArray();
                    addedSelection        = true;
                }
            }
            else
            if (Event.current.alt)
            {
                if (gameobject != null)
                {
                    var instanceID = gameobject.GetInstanceID();
                    selectedObjectsOnClick.Remove(instanceID);
                    Selection.instanceIDs = selectedObjectsOnClick.ToArray();
                    return;
                }
            }
            else
            {
                Selection.activeGameObject = gameobject;
                addedSelection             = true;
            }

            if (!addedSelection)
            {
                foreach (var item in Selection.GetFiltered(typeof(CSGBrush), SelectionMode.Deep))
                {
                    var brush       = item as CSGBrush;
                    var brush_cache = InternalCSGModelManager.GetBrushCache(brush);
                    if (brush_cache == null ||
                        brush_cache.childData == null ||
                        !brush_cache.childData.Model ||
                        !brush_cache.childData.Model.isActiveAndEnabled)
                    {
                        continue;
                    }
                    SelectionUtility.LastUsedModel = brush_cache.childData.Model;
                    break;
                }
            }
            else
            if (gameobject != null)
            {
                var brush = gameobject.GetComponent <CSGBrush>();
                if (brush != null)
                {
                    var brush_cache = InternalCSGModelManager.GetBrushCache(brush);
                    if (brush_cache == null ||
                        brush_cache.childData == null ||
                        !brush_cache.childData.Model ||
                        !brush_cache.childData.Model.isActiveAndEnabled)
                    {
                        return;
                    }
                    SelectionUtility.LastUsedModel = brush_cache.childData.Model;
                }
            }
        }
コード例 #28
0
        public void UpdateTransforms(CSGBrush brush)
        {
            BrushTransform = brush.GetComponent <Transform>();
            ModelTransform = InternalCSGModelManager.FindModelTransform(BrushTransform);
//			ParentTransform = InternalCSGModelManager.FindParentTransform(BrushTransform);
        }
コード例 #29
0
        static void ShowCSGOperations(bool isSceneGUI, EditModePlace tool, FilteredSelection filteredSelection)
        {
            bool operations_enabled = (tool != null &&
                                       filteredSelection.NodeTargets.Length > 0 &&
                                       filteredSelection.NodeTargets.Length == (filteredSelection.BrushTargets.Length + filteredSelection.OperationTargets.Length));

            EditorGUI.BeginDisabledGroup(!operations_enabled);
            {
                bool             mixedValues   = tool == null || ((filteredSelection.BrushTargets.Length == 0) && (filteredSelection.OperationTargets.Length == 0));
                CSGOperationType operationType = CSGOperationType.Additive;
                if (tool != null)
                {
                    if (filteredSelection.BrushTargets.Length > 0)
                    {
                        operationType = filteredSelection.BrushTargets[0].OperationType;
                        for (int i = 1; i < filteredSelection.BrushTargets.Length; i++)
                        {
                            if (filteredSelection.BrushTargets[i].OperationType != operationType)
                            {
                                mixedValues = true;
                            }
                        }
                    }
                    else
                    if (filteredSelection.OperationTargets.Length > 0)
                    {
                        operationType = filteredSelection.OperationTargets[0].OperationType;
                    }

                    if (filteredSelection.OperationTargets.Length > 0)
                    {
                        for (int i = 0; i < filteredSelection.OperationTargets.Length; i++)
                        {
                            if (filteredSelection.OperationTargets[i].OperationType != operationType)
                            {
                                mixedValues = true;
                            }
                        }
                    }
                }

                GUILayout.BeginVertical(isSceneGUI ? GUI.skin.box : GUIStyle.none);
                {
                    bool passThroughValue = false;
                    if (tool != null &&
                        filteredSelection.BrushTargets.Length == 0 &&
                        filteredSelection.OperationTargets.Length > 0 &&
                        filteredSelection.OperationTargets.Length == filteredSelection.NodeTargets.Length)                         // only operations
                    {
                        bool?passThrough = filteredSelection.OperationTargets[0].PassThrough;
                        for (int i = 1; i < filteredSelection.OperationTargets.Length; i++)
                        {
                            if (passThrough.HasValue && passThrough.Value != filteredSelection.OperationTargets[i].PassThrough)
                            {
                                passThrough = null;
                                break;
                            }
                        }

                        mixedValues = !passThrough.HasValue || passThrough.Value;

                        var ptMixedValues = !passThrough.HasValue;
                        passThroughValue = passThrough.HasValue ? passThrough.Value : false;
                        if (CSG_EditorGUIUtility.PassThroughButton(passThroughValue, ptMixedValues))
                        {
                            Undo.RecordObjects(filteredSelection.OperationTargets, "Changed CSG operation of nodes");
                            foreach (var operation in filteredSelection.OperationTargets)
                            {
                                operation.PassThrough = true;
                            }
                            InternalCSGModelManager.CheckForChanges();
                            EditorApplication.RepaintHierarchyWindow();
                        }

                        if (passThroughValue)
                        {
                            operationType = (CSGOperationType)255;
                        }
                    }
                    EditorGUI.BeginChangeCheck();
                    {
                        operationType = CSG_EditorGUIUtility.ChooseOperation(operationType, mixedValues);
                    }
                    if (EditorGUI.EndChangeCheck() && tool != null)
                    {
                        Undo.RecordObjects(filteredSelection.NodeTargets, "Changed CSG operation of nodes");
                        for (int i = 0; i < filteredSelection.BrushTargets.Length; i++)
                        {
                            filteredSelection.BrushTargets[i].OperationType = operationType;
                        }
                        for (int i = 0; i < filteredSelection.OperationTargets.Length; i++)
                        {
                            filteredSelection.OperationTargets[i].PassThrough   = false;
                            filteredSelection.OperationTargets[i].OperationType = operationType;
                        }
                        InternalCSGModelManager.CheckForChanges();
                        EditorApplication.RepaintHierarchyWindow();
                    }
                }
                GUILayout.EndVertical();
            }
            EditorGUI.EndDisabledGroup();
        }
コード例 #30
0
        public bool UpdateSelection(HashSet <CSGNode> newTargetNodes, HashSet <Transform> newTargetOthers)
        {
            if (newTargetNodes == null)
            {
                newTargetNodes = new HashSet <CSGNode>();
            }
            if (newTargetOthers == null)
            {
                newTargetOthers = new HashSet <Transform>();
            }

            this.RemovedNodes  = null;
            this.RemovedOthers = null;

            this.AddedNodes  = null;
            this.AddedOthers = null;

            var foundRemovedNodes = new List <CSGNode>();

            if (this.NodeTargets != null &&
                this.NodeTargets.Length > 0)
            {
                if (newTargetNodes.Count == 0)
                {
                    foundRemovedNodes.AddRange(this.NodeTargets);
                }
                else
                {
                    for (int i = 0; i < this.NodeTargets.Length; i++)
                    {
                        if (!this.NodeTargets[i] ||
                            !newTargetNodes.Contains(this.NodeTargets[i]))
                        {
                            foundRemovedNodes.Add(this.NodeTargets[i]);
                        }
                    }
                }
            }

            var foundRemovedOthers = new List <Transform>();

            if (this.OtherTargets != null &&
                this.OtherTargets.Length > 0)
            {
                if (newTargetOthers.Count == 0)
                {
                    foundRemovedOthers.AddRange(this.OtherTargets);
                }
                else
                {
                    for (int i = 0; i < this.OtherTargets.Length; i++)
                    {
                        if (!this.OtherTargets[i] ||
                            !newTargetOthers.Contains(this.OtherTargets[i]))
                        {
                            foundRemovedOthers.Add(this.OtherTargets[i]);
                        }
                    }
                }
            }

            var originalTargetNodeCount  = (this.NodeTargets == null) ? 0 : this.NodeTargets.Length;
            var originalTargetOtherCount = (this.OtherTargets == null) ? 0 : this.OtherTargets.Length;

            // If our counts are the same and nothing is removed (and nothing could've been added), nothing has changed.
            if (newTargetNodes.Count == originalTargetNodeCount &&
                newTargetOthers.Count == originalTargetOtherCount &&
                foundRemovedNodes.Count == 0 &&
                foundRemovedOthers.Count == 0)
            {
                //Debug.Log(originalTargetNodeCount + " " + originalTargetOtherCount + " " + newTargetNodes .Count + " " + newTargetOthers .Count);
                return(false);
            }

            Validate();

            foreach (var node in foundRemovedNodes)
            {
                ArrayUtility.Remove(ref this.NodeTargets, node);

                var brush = node as CSGBrush;
                if (brush != null)
                {
                    ArrayUtility.Remove(ref this.BrushTargets, brush);
                    continue;
                }
                var operation = node as CSGOperation;
                if (node is CSGOperation)
                {
                    ArrayUtility.Remove(ref this.OperationTargets, operation);
                    continue;
                }
                var model = node as CSGModel;
                if (node is CSGModel)
                {
                    ArrayUtility.Remove(ref this.ModelTargets, model);
                    continue;
                }
            }

            foreach (var other in foundRemovedOthers)
            {
                ArrayUtility.Remove(ref this.OtherTargets, other);
            }

            var foundAddedNodes = new List <CSGNode>();

            foreach (var node in newTargetNodes)
            {
                if (this.NodeTargets != null &&
                    ArrayUtility.Contains(this.NodeTargets, node))
                {
                    continue;
                }

                if (this.NodeTargets == null)
                {
                    this.NodeTargets = new CSGNode[] { node };
                }
                else
                {
                    ArrayUtility.Add(ref this.NodeTargets, node);
                }

                foundAddedNodes.Add(node);

                if (SelectionUtility.IsPrefab(node.gameObject))
                {
                    continue;
                }

                var brush = node as CSGBrush;
                if (brush != null)
                {
                    if (this.BrushTargets == null)
                    {
                        this.BrushTargets = new CSGBrush[] { brush }
                    }
                    ;
                    else
                    {
                        ArrayUtility.Add(ref this.BrushTargets, brush);
                    }
                    continue;
                }
                var operation = node as CSGOperation;
                if (node is CSGOperation)
                {
                    if (this.OperationTargets == null)
                    {
                        this.OperationTargets = new CSGOperation[] { operation }
                    }
                    ;
                    else
                    {
                        ArrayUtility.Add(ref this.OperationTargets, operation);
                    }
                    continue;
                }
                var model = node as CSGModel;
                if (node is CSGModel)
                {
                    if (this.ModelTargets == null)
                    {
                        this.ModelTargets = new CSGModel[] { model }
                    }
                    ;
                    else
                    {
                        ArrayUtility.Add(ref this.ModelTargets, model);
                    }
                    continue;
                }
            }

            var foundAddedOthers = new List <Transform>();

            foreach (var other in newTargetOthers)
            {
                if (this.OtherTargets != null &&
                    ArrayUtility.Contains(this.OtherTargets, other))
                {
                    continue;
                }

                if (this.OtherTargets == null)
                {
                    this.OtherTargets = new Transform[] { other }
                }
                ;
                else
                {
                    ArrayUtility.Add(ref this.OtherTargets, other);
                }
                foundAddedOthers.Add(other);
            }

            for (int i = foundAddedNodes.Count - 1; i >= 0; i--)
            {
                var node  = foundAddedNodes[i];
                var brush = node as CSGBrush;
                if (brush != null)
                {
                    var brush_cache = InternalCSGModelManager.GetBrushCache(brush);
                    if (brush_cache == null ||
                        brush_cache.childData == null ||
                        brush_cache.childData.Model == null)
                    {
                        continue;
                    }

                    var childModel = brush_cache.childData.Model;
                    if (childModel &&
                        childModel.isActiveAndEnabled)
                    {
                        SelectionUtility.LastUsedModel = childModel;
                    }
                    break;
                }
                var operation = node as CSGOperation;
                if (operation != null)
                {
                    var operation_cache = InternalCSGModelManager.GetOperationCache(operation);
                    if (operation_cache == null ||
                        operation_cache.ChildData == null ||
                        operation_cache.ChildData.Model == null)
                    {
                        continue;
                    }

                    SelectionUtility.LastUsedModel = operation_cache.ChildData.Model;
                    break;
                }
                var model = node as CSGModel;
                if (model &&
                    model.isActiveAndEnabled)
                {
                    SelectionUtility.LastUsedModel = model;
                    break;
                }
            }

            this.RemovedNodes  = foundRemovedNodes.ToArray();
            this.RemovedOthers = foundRemovedOthers.ToArray();

            this.AddedNodes  = foundAddedNodes.ToArray();
            this.AddedOthers = foundAddedOthers.ToArray();

            return(foundAddedNodes.Count > 0 || foundRemovedNodes.Count > 0 || foundAddedOthers.Count > 0 || foundRemovedOthers.Count > 0);
        }