public static void Export(CSGModel model, ExportType exportType, bool exportColliders)
        {
            string typeName;
            string extension;

            switch (exportType)
            {
            case ExportType.FBX: typeName = "FBX"; extension = @"fbx"; break;

            default:
                //case ExportType.UnityMesh:
                typeName = "Mesh"; extension = @"prefab"; exportType = ExportType.UnityMesh; break;
            }
            var newPath = model.exportPath;

            if (exportType != ExportType.UnityMesh)
            {
                newPath = UnityFBXExporter.ExporterMenu.GetNewPath(model.gameObject, typeName, extension, model.exportPath);
                if (string.IsNullOrEmpty(newPath))
                {
                    return;
                }
            }

            model.ShowGeneratedMeshes = false;
            var foundModels = model.GetComponentsInChildren <CSGModel>(true);

            for (var index = 0; index < foundModels.Length; index++)
            {
                if (!foundModels[index].ShowGeneratedMeshes)
                {
                    continue;
                }
                foundModels[index].ShowGeneratedMeshes = false;
                UpdateGeneratedMeshesVisibility(foundModels[index]);
            }

            GameObject tempExportObject;

            if (!string.IsNullOrEmpty(model.exportPath))
            {
                tempExportObject = new GameObject(System.IO.Path.GetFileNameWithoutExtension(model.exportPath));
                if (string.IsNullOrEmpty(tempExportObject.name))
                {
                    tempExportObject.name = model.name;
                }
            }
            else
            {
                tempExportObject = new GameObject(model.name);
            }

            tempExportObject.transform.position   = MathConstants.zeroVector3;
            tempExportObject.transform.rotation   = MathConstants.identityQuaternion;
            tempExportObject.transform.localScale = MathConstants.oneVector3;

            int colliderCounter      = 1;
            int shadowOnlyCounter    = 1;
            var materialMeshCounters = new Dictionary <Material, int>();

            var currentScene        = model.gameObject.scene;
            var foundMeshContainers = SceneQueryUtility.GetAllComponentsInScene <GeneratedMeshes>(currentScene);
            var bounds = new AABB();

            bounds.Reset();
            var foundMeshFilters   = new List <MeshFilter>();
            var foundMeshColliders = new List <MeshCollider>();

            AssetDatabase.StartAssetEditing(); // We might be modifying a prefab, in which case we need to store a mesh inside it
            try
            {
                foreach (var meshContainer in foundMeshContainers)
                {
                    var owner = meshContainer.owner;
                    if (!owner || !ArrayUtility.Contains(foundModels, owner))
                    {
                        continue;
                    }

                    if (!meshContainer || meshContainer.meshInstanceLookup == null)
                    {
                        continue;
                    }

                    var instances = meshContainer.meshInstanceLookup.Values;
                    foreach (var instance in instances)
                    {
                        if (!instance)
                        {
                            continue;
                        }

                        Refresh(instance, model, postProcessScene: true, skipAssetDatabaseUpdate: true);

                        var surfaceType = GetSurfaceType(instance.MeshDescription, owner.Settings);
                        if (surfaceType != RenderSurfaceType.Normal &&
                            surfaceType != RenderSurfaceType.ShadowOnly &&
                            surfaceType != RenderSurfaceType.Collider)
                        {
                            continue;
                        }

                        int counter = 0;
                        if (instance.RenderMaterial)
                        {
                            if (!materialMeshCounters.TryGetValue(instance.RenderMaterial, out counter))
                            {
                                counter = 1;
                            }
                            else
                            {
                                counter++;
                            }
                        }

                        var mesh = instance.SharedMesh;
                        if (!mesh.isReadable)
                        {
                            //bounds.Extend(mesh.bounds.min);
                            //bounds.Extend(mesh.bounds.max);
                        }
                        else
                        {
                            var vertices = mesh.vertices;
                            for (int v = 0; v < vertices.Length; v++)
                            {
                                bounds.Extend(vertices[v]);
                            }
                        }


                        var subObj = UnityEngine.Object.Instantiate(instance.gameObject, MathConstants.zeroVector3, MathConstants.identityQuaternion) as GameObject;
                        subObj.hideFlags            = HideFlags.None;
                        subObj.transform.position   = owner.transform.position;
                        subObj.transform.rotation   = owner.transform.rotation;
                        subObj.transform.localScale = owner.transform.localScale;
                        subObj.transform.SetParent(tempExportObject.transform, false);

                        var genMeshInstance = subObj.GetComponent <GeneratedMeshInstance>();

                        UnityEngine.Object.DestroyImmediate(genMeshInstance);

                        if (surfaceType == RenderSurfaceType.Collider)
                        {
                            subObj.name = "no-material Mesh (" + colliderCounter + ") COLLIDER"; colliderCounter++;
                        }
                        else
                        {
                            if (surfaceType == RenderSurfaceType.ShadowOnly)
                            {
                                subObj.name = "shadow-only Mesh (" + shadowOnlyCounter + ")"; shadowOnlyCounter++;
                                var meshRenderer = subObj.GetComponent <MeshRenderer>();
                                if (meshRenderer)
                                {
                                    meshRenderer.sharedMaterial = MaterialUtility.DefaultMaterial;
                                }
                            }
                            else
                            {
                                Material renderMaterial = instance.RenderMaterial;
                                if (!renderMaterial)
                                {
                                    renderMaterial = MaterialUtility.DefaultMaterial;
                                    subObj.name    = "missing-material Mesh (" + counter + ")"; counter++;
                                }
                                else
                                {
                                    subObj.name = renderMaterial.name + " Mesh (" + counter + ")";
                                } counter++;
                                materialMeshCounters[instance.RenderMaterial] = counter;
                            }

                            var meshFilter = subObj.GetComponent <MeshFilter>();
                            if (meshFilter)
                            {
                                foundMeshFilters.Add(meshFilter);
                            }
                        }

                        var meshCollider = subObj.GetComponent <MeshCollider>();
                        if (meshCollider)
                        {
                            foundMeshColliders.Add(meshCollider);
                        }
                    }
                }
            }
            finally { AssetDatabase.StopAssetEditing(); }

            Undo.IncrementCurrentGroup();
            var groupIndex = Undo.GetCurrentGroup();

            Undo.SetCurrentGroupName("Exported model");
            try
            {
                Vector3 position = model.transform.position;
                if (float.IsInfinity(position.x) || float.IsNaN(position.x))
                {
                    position.x = 0;
                }
                if (float.IsInfinity(position.y) || float.IsNaN(position.y))
                {
                    position.y = 0;
                }
                if (float.IsInfinity(position.z) || float.IsNaN(position.z))
                {
                    position.z = 0;
                }

                Vector3 center = bounds.Center;
                switch (model.originType)
                {
                default:
                case OriginType.ModelCenter:    center = bounds.Center + position; break;

                case OriginType.ModelPivot:             center = position; break;

                case OriginType.WorldSpace:             center = Vector3.zero; break;
                }
                if (float.IsInfinity(center.x) || float.IsNaN(center.x))
                {
                    center.x = 0;
                }
                if (float.IsInfinity(center.y) || float.IsNaN(center.y))
                {
                    center.y = 0;
                }
                if (float.IsInfinity(center.z) || float.IsNaN(center.z))
                {
                    center.z = 0;
                }

                var modifiedMeshes = new Dictionary <Mesh, Mesh>();
                foreach (var meshFilter in foundMeshFilters)
                {
                    var mesh = meshFilter.sharedMesh;
                    if (!mesh.isReadable)
                    {
                        continue;
                    }

                    Mesh newMesh;
                    if (!modifiedMeshes.TryGetValue(mesh, out newMesh))
                    {
                        newMesh = (Mesh)UnityEngine.Object.Instantiate(mesh);
                        var vertices = mesh.vertices;
                        for (int v = 0; v < vertices.Length; v++)
                        {
                            vertices[v] += position;
                            vertices[v] -= center;
                        }
                        newMesh.vertices = vertices;
                        newMesh.RecalculateBounds();
                        modifiedMeshes[mesh] = newMesh;
                    }
                    meshFilter.sharedMesh         = newMesh;
                    meshFilter.transform.position = Vector3.zero;
                }

                foreach (var meshCollider in foundMeshColliders)
                {
                    var mesh = meshCollider.sharedMesh;
                    if (!mesh.isReadable)
                    {
                        continue;
                    }

                    Mesh newMesh;
                    if (!modifiedMeshes.TryGetValue(mesh, out newMesh))
                    {
                        newMesh = (Mesh)UnityEngine.Object.Instantiate(mesh);
                        var vertices = mesh.vertices;
                        for (int v = 0; v < vertices.Length; v++)
                        {
                            vertices[v] += position;
                            vertices[v] -= center;
                        }
                        newMesh.vertices = vertices;
                        newMesh.RecalculateBounds();
                        modifiedMeshes[mesh] = newMesh;
                    }
                    meshCollider.sharedMesh         = newMesh;
                    meshCollider.transform.position = Vector3.zero;
                }

                UnityEngine.GameObject prefabObj;
                GameObject             modelGameObject;
                switch (exportType)
                {
                case ExportType.FBX:
                {
                    if (!UnityFBXExporter.FBXExporter.ExportGameObjToFBX(tempExportObject, newPath, exportColliders: exportColliders))
                    {
                        //InternalCSGModelManager.ClearMeshInstances();
                        EditorUtility.DisplayDialog("Warning", "Failed to export the FBX file.", "Ok");
                        return;
                    }
                    prefabObj = AssetDatabase.LoadAssetAtPath <UnityEngine.GameObject>(newPath);

                    modelGameObject = CSGPrefabUtility.Instantiate(prefabObj);

                    foreach (var renderer in modelGameObject.GetComponentsInChildren <MeshRenderer>())
                    {
                        var gameObject = renderer.gameObject;
                        if (gameObject.name.EndsWith("COLLIDER"))
                        {
                            var filter       = gameObject.GetComponent <MeshFilter>();
                            var meshCollider = gameObject.AddComponent <MeshCollider>();
                            meshCollider.sharedMesh = filter.sharedMesh;
                            UnityEngine.Object.DestroyImmediate(renderer);
                            UnityEngine.Object.DestroyImmediate(filter);
                        }
                    }
                    model.exportPath = newPath;
                    break;
                }

                default:
                    //case ExportType.UnityMesh:
                {
                    prefabObj       = tempExportObject;                      // AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(newPath);
                    modelGameObject = tempExportObject;

                    foreach (var meshFilter in tempExportObject.GetComponentsInChildren <MeshFilter>())
                    {
                        var mesh = meshFilter.sharedMesh;
                        mesh.name       = tempExportObject.name;
                        meshFilter.mesh = mesh;
                    }
                    break;
                }
                }


                model.exportPath = newPath;

                if (exportType == ExportType.FBX && prefabObj)
                {
                    foreach (var meshRenderer in prefabObj.GetComponentsInChildren <MeshRenderer>())
                    {
                        if (meshRenderer.sharedMaterials.Length != 1)
                        {
                            continue;
                        }

                        var gameObject = meshRenderer.gameObject;
                        var nameSplit  = gameObject.name.Split('|');
                        if (nameSplit.Length == 1)
                        {
                            continue;
                        }

                        int instanceId;
                        if (!int.TryParse(nameSplit[1], out instanceId))
                        {
                            continue;
                        }

                        var realMaterial = EditorUtility.InstanceIDToObject(instanceId) as Material;
                        if (!realMaterial)
                        {
                            continue;
                        }

                        meshRenderer.sharedMaterial = realMaterial;
                        gameObject.name             = nameSplit[0];
                    }
                }


                var staticFlags = GameObjectUtility.GetStaticEditorFlags(model.gameObject);
                var modelLayer  = model.gameObject.layer;
                foreach (var transform in modelGameObject.GetComponentsInChildren <Transform>())
                {
                    var gameObject = transform.gameObject;
                    GameObjectUtility.SetStaticEditorFlags(gameObject, staticFlags);
                    gameObject.layer = modelLayer;
                }

                modelGameObject.transform.SetParent(model.transform, true);
                modelGameObject.transform.SetSiblingIndex(0);
                modelGameObject.tag = model.gameObject.tag;

                modelGameObject.transform.localPosition = center - position;


                Undo.RegisterCreatedObjectUndo(modelGameObject, "Instantiated model");


                var exported = model.gameObject.AddComponent <CSGModelExported>();
                exported.containedModel         = null;
                exported.containedExportedModel = modelGameObject;
                exported.disarm = true;
                Undo.RegisterCreatedObjectUndo(exported, "Created CSGModelExported");
                Undo.RegisterCompleteObjectUndo(exported, "Created CSGModelExported");


                var foundBrushes    = model.GetComponentsInChildren <CSGBrush>(true);
                var foundOperations = model.GetComponentsInChildren <CSGOperation>(true);
                var foundContainers = model.GetComponentsInChildren <GeneratedMeshes>(true);

                var foundBehaviours = new HashSet <MonoBehaviour>();

                foreach (var foundBrush         in foundBrushes)
                {
                    foundBehaviours.Add(foundBrush);
                }
                foreach (var foundOperation in foundOperations)
                {
                    foundBehaviours.Add(foundOperation);
                }
                foreach (var foundModel         in foundModels)
                {
                    foundBehaviours.Add(foundModel);
                }
                foreach (var foundContainer in foundContainers)
                {
                    foundBehaviours.Add(foundContainer);
                }


                exported.hiddenComponents = new HiddenComponentData[foundBehaviours.Count];
                var index = 0;
                foreach (var foundBehaviour in foundBehaviours)
                {
                    Undo.RegisterCompleteObjectUndo(foundBehaviour, "Hide component");
                    exported.hiddenComponents[index] = new HiddenComponentData {
                        behaviour = foundBehaviour
                    };
                    index++;
                }

                for (var i = 0; i < exported.hiddenComponents.Length; i++)
                {
                    exported.hiddenComponents[i].hideFlags = exported.hiddenComponents[i].behaviour.hideFlags;
                    exported.hiddenComponents[i].enabled   = exported.hiddenComponents[i].behaviour.enabled;
                }

                for (var i = 0; i < exported.hiddenComponents.Length; i++)
                {
                    exported.hiddenComponents[i].behaviour.hideFlags = exported.hiddenComponents[i].behaviour.hideFlags | ComponentHideFlags;
                    exported.hiddenComponents[i].behaviour.enabled   = false;
                }

                EditorSceneManager.MarkSceneDirty(currentScene);
                Undo.CollapseUndoOperations(groupIndex);
                groupIndex      = 0;
                exported.disarm = false;
            }
            finally
            {
                switch (exportType)
                {
                case ExportType.FBX:
                {
                    UnityEngine.Object.DestroyImmediate(tempExportObject);
                    break;
                }
                }
                if (groupIndex != 0)
                {
                    Undo.CollapseUndoOperations(groupIndex);
                }
            }
        }
Example #2
0
        internal static GameObject PickModel(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out CSGModel model, out Material material)
        {
            model    = null;
            material = null;
            var        flagState       = CSGGeneratedComponentManager.BeginPicking();
            GameObject gameObject      = null;
            bool       foundGameObject = false;

            try
            {
                int materialIndex = -1;
                if (pickClosestGO == null ||
                    pickClosestGameObjectDelegate == null)
                {
                    gameObject = HandleUtility.PickGameObject(pickposition, ignore, out materialIndex);
                }
                else
                {
                    gameObject = pickClosestGO(camera, layers, pickposition, ignore, filter, out materialIndex);
                }
            }
            finally
            {
                foundGameObject = CSGGeneratedComponentManager.EndPicking(flagState, gameObject, out model) && model;
            }
            if (object.Equals(gameObject, null))
            {
                return(null);
            }

            if (!foundGameObject)
            {
                return(gameObject);
            }

            var renderer = gameObject.GetComponent <Renderer>();

            if (renderer)
            {
                material = renderer.sharedMaterial;
                if (!material)
                {
                    material = null;
                }
            }
            return(gameObject);
        }
Example #3
0
        internal static GameObject PickNodeOrGameObject(Camera camera, Vector2 pickposition, int layers, ref GameObject[] ignore, ref GameObject[] filter, out CSGModel model, out CSGNode node, out CSGTreeBrushIntersection intersection)
        {
TryNextSelection:
            intersection = new CSGTreeBrushIntersection {
                surfaceID = -1, brushUserID = -1
            };

            model = null;
            node  = null;
            Material sharedMaterial;
            var      gameObject = PickModel(camera, pickposition, layers, ref ignore, ref filter, out model, out sharedMaterial);

            if (object.Equals(gameObject, null))
            {
                return(null);
            }

            if (model)
            {
                int filterLayerParameter0 = (sharedMaterial) ? sharedMaterial.GetInstanceID() : 0;
                {
                    var worldRay       = camera.ScreenPointToRay(pickposition);
                    var worldRayStart  = worldRay.origin;
                    var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane));
                    var worldRayEnd    = worldRayStart + worldRayVector;

                    CSGTreeBrushIntersection tempIntersection;
                    if (CSGSceneQuery.FindFirstWorldIntersection(model, worldRayStart, worldRayEnd, filterLayerParameter0, layers, ignore, filter, out tempIntersection))
                    {
                        var clickedBrush = tempIntersection.brush;
                        node = CSGNodeHierarchyManager.FindCSGNodeByInstanceID(clickedBrush.UserID);
                        if (node)
                        {
                            if (ignore != null &&
                                ignore.Contains(node.gameObject))
                            {
                                node = null;
                                return(null);
                            }
                            intersection = tempIntersection;
                            return(node.gameObject);
                        }
                        else
                        {
                            node = null;
                        }
                    }
                }

                if (ignore == null)
                {
                    return(null);
                }

                ArrayUtility.Add(ref ignore, gameObject);
                goto TryNextSelection;
            }

            if (object.Equals(gameObject, null))
            {
                return(null);
            }

            if (ignore != null &&
                ignore.Contains(gameObject))
            {
                return(null);
            }

            return(gameObject);
        }
        public static bool FindUnityWorldIntersection(Vector2 screenPos, out GameObject foundObject)
        {
            var sceneView = SceneView.currentDrawingSceneView;            // ? SceneView.currentDrawingSceneView : SceneView.lastActiveSceneView;
            var camera    = sceneView ? sceneView.camera : Camera.current;

            foundObject = null;
            if (!camera)
            {
                return(false);
            }

            var wireframeShown = CSGSettings.IsWireframeShown(sceneView);
            var worldRay       = HandleUtility.GUIPointToWorldRay(screenPos);
            var worldRayStart  = worldRay.origin;
            var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane));
            var worldRayEnd    = worldRayStart + worldRayVector;

            CSGModel intersectionModel = null;

            LegacyBrushIntersection[] intersections;
            if (FindMultiWorldIntersection(worldRayStart, worldRayEnd, out intersections, ignoreInvisibleSurfaces: !wireframeShown))
            {
                var visibleLayers = Tools.visibleLayers;
                for (int i = 0; i < intersections.Length; i++)
                {
                    if (((1 << intersections[i].gameObject.layer) & visibleLayers) == 0)
                    {
                        continue;
                    }
                    intersectionModel = intersections[i].model;
                    break;
                }
            }

            GameObject[] modelMeshes = null;
            HideFlags[]  hideFlags   = null;
            if (intersectionModel != null)
            {
                modelMeshes = CSGModelManager.GetModelMeshes(intersectionModel);
                if (modelMeshes != null)
                {
                    hideFlags = new HideFlags[modelMeshes.Length];
                    for (var i = 0; i < modelMeshes.Length; i++)
                    {
                        hideFlags[i]             = modelMeshes[i].hideFlags;
                        modelMeshes[i].hideFlags = HideFlags.None;
                    }
                }
            }

            var gameObject = HandleUtility.PickGameObject(screenPos, false);

            if (modelMeshes != null)
            {
                for (var i = 0; i < modelMeshes.Length; i++)
                {
                    var modelMesh = modelMeshes[i];
                    if (!modelMesh)
                    {
                        continue;
                    }

                    if (gameObject == modelMesh)
                    {
                        gameObject = null;
                    }

                    modelMesh.hideFlags = hideFlags[i];
                }
            }

            if (!gameObject ||
                gameObject.GetComponent <Canvas>() ||
                gameObject.GetComponent <CSGModel>() ||
                gameObject.GetComponent <CSGBrush>() ||
                gameObject.GetComponent <CSGOperation>() ||
                gameObject.GetComponent <GeneratedMeshInstance>() ||
                gameObject.GetComponent <GeneratedMeshes>())
            {
                return(false);
            }

            foundObject = gameObject;
            return(true);
        }
Example #5
0
 public PlaneIntersection(CSGTreeBrushIntersection brushIntersection, CSGNode node, CSGModel model)
 {
     this.point = brushIntersection.surfaceIntersection.worldIntersection;
     this.plane = brushIntersection.surfaceIntersection.worldPlane;
     this.node  = node;
     this.model = model;
 }
        public static bool FindUnityWorldIntersection(Camera camera, Vector2 screenPos, out GameObject foundObject, bool ignoreInvisibleSurfaces = true)
        {
            foundObject = null;
            if (!camera)
            {
                return(false);
            }

            var wireframeShown = CSGSettings.IsWireframeShown(camera);
            var worldRay       = HandleUtility.GUIPointToWorldRay(screenPos);
            var worldRayStart  = worldRay.origin;
            var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane));
            var worldRayEnd    = worldRayStart + worldRayVector;

            CSGModel intersectionModel = null;

            LegacyBrushIntersection[] intersections;
            if (FindMultiWorldIntersection(worldRayStart, worldRayEnd, out intersections, ignoreInvisibleSurfaces: ignoreInvisibleSurfaces && !wireframeShown))
            {
                var visibleLayers = Tools.visibleLayers;
                for (int i = 0; i < intersections.Length; i++)
                {
                    if (((1 << intersections[i].gameObject.layer) & visibleLayers) == 0)
                    {
                        continue;
                    }
                    intersectionModel = intersections[i].model;
                    break;
                }
            }

            /*
             * GameObject[] modelMeshes = null;
             * HideFlags[] hideFlags = null;
             * if (intersectionModel != null)
             * {
             *      modelMeshes = CSGModelManager.GetModelMeshes(intersectionModel);
             *      if (modelMeshes != null)
             *      {
             *              hideFlags = new HideFlags[modelMeshes.Length];
             *              for (var i = 0; i < modelMeshes.Length; i++)
             *              {
             *                      hideFlags[i] = modelMeshes[i].hideFlags;
             *                      modelMeshes[i].hideFlags = HideFlags.None;
             *              }
             *      }
             * }
             */


            CSGModel   foundModel;
            GameObject gameObject = null;
            var        flagState  = BeginPicking(null);

            try { gameObject = HandleUtility.PickGameObject(screenPos, false, null); }
            finally
            {
                foundModel = EndPicking(flagState, gameObject);
            }
            if (foundModel == intersectionModel && intersectionModel)
            {
                return(false);
            }

            /*
             * var gameObject = HandleUtility.PickGameObject(screenPos, false);
             *
             * if (modelMeshes != null)
             * {
             *      for (var i = 0; i < modelMeshes.Length; i++)
             *      {
             *              var modelMesh = modelMeshes[i];
             *              if (!modelMesh)
             *                      continue;
             *
             *              if (gameObject == modelMesh)
             *                      gameObject = null;
             *
             *              modelMesh.hideFlags = hideFlags[i];
             *      }
             * }
             */
            if (!gameObject ||
                gameObject.GetComponent <Canvas>() ||
                gameObject.GetComponent <CSGModel>() ||
                gameObject.GetComponent <CSGBrush>() ||
                gameObject.GetComponent <CSGOperation>() ||
                gameObject.GetComponent <GeneratedMeshInstance>() ||
                gameObject.GetComponent <GeneratedMeshes>())
            {
                return(false);
            }

            foundObject = gameObject;
            return(true);
        }
        public static bool FindClickWorldIntersection(Vector2 screenPos, out GameObject foundObject)
        {
            var sceneView = SceneView.currentDrawingSceneView;// ? SceneView.currentDrawingSceneView : SceneView.lastActiveSceneView;
            var camera    = sceneView ? sceneView.camera : Camera.current;

            foundObject = null;
            if (!camera)
            {
                return(false);
            }

            var worldRay       = HandleUtility.GUIPointToWorldRay(screenPos);
            var worldRayStart  = worldRay.origin;
            var worldRayVector = (worldRay.direction * (camera.farClipPlane - camera.nearClipPlane));
            var worldRayEnd    = worldRayStart + worldRayVector;

            CSGModel intersectionModel = null;

            if (_prevSceenPos == screenPos && _prevSceneView == sceneView && _deepClickIntersections != null)
            {
                var prevIntersection = (_deepIndex > 0 && _deepIndex < _deepClickIntersections.Length) ? _deepClickIntersections[_deepIndex] : null;
                if (_deepClickIntersections.Length > 1)
                {
                    var visibleLayers = Tools.visibleLayers;
                    for (var i = _deepClickIntersections.Length - 1; i >= 0; i--)
                    {
                        if (((1 << _deepClickIntersections[i].gameObject.layer) & visibleLayers) == 0)
                        {
                            continue;
                        }

                        if (_deepClickIntersections[i].brush)
                        {
                            continue;
                        }
                        ArrayUtility.RemoveAt(ref _deepClickIntersections, i);
                        if (i <= _deepIndex)
                        {
                            _deepIndex--;
                        }
                    }
                }

                if (_deepClickIntersections.Length <= 1)
                {
                    ResetDeepClick();
                }
                else
                {
                    _deepIndex = (_deepIndex + 1) % _deepClickIntersections.Length;
                    var currentIntersection = (_deepIndex > 0 && _deepIndex < _deepClickIntersections.Length) ? _deepClickIntersections[_deepIndex] : null;
                    if (currentIntersection != prevIntersection &&
                        currentIntersection != null)
                    {
                        foundObject       = currentIntersection.gameObject;
                        _prevSceenPos     = screenPos;
                        _prevSceneView    = sceneView;
                        intersectionModel = currentIntersection.model;
                    }
                    else
                    {
                        ResetDeepClick();
                    }
                }
            }

            if (_prevSceenPos != screenPos)
            {
                var wireframeShown = CSGSettings.IsWireframeShown(sceneView);
                if (FindMultiWorldIntersection(worldRayStart, worldRayEnd, out _deepClickIntersections, ignoreInvisibleSurfaces: !wireframeShown, ignoreUnrenderables: !wireframeShown))
                {
                    var visibleLayers = Tools.visibleLayers;
                    for (int i = 0; i < _deepClickIntersections.Length; i++)
                    {
                        if (((1 << _deepClickIntersections[i].gameObject.layer) & visibleLayers) == 0)
                        {
                            continue;
                        }

                        _deepIndex = 0;
                        var intersection = _deepClickIntersections[i];
                        foundObject       = intersection.gameObject;
                        _prevSceenPos     = screenPos;
                        _prevSceneView    = sceneView;
                        intersectionModel = intersection.model;
                        break;
                    }
                }
                else
                {
                    ResetDeepClick();
                }
            }

            GameObject[] modelMeshes = null;
            if (intersectionModel != null)
            {
                modelMeshes = CSGModelManager.GetModelMeshes(intersectionModel);
            }

            HideFlags[] hideFlags = null;
            if (modelMeshes != null)
            {
                hideFlags = new HideFlags[modelMeshes.Length];
                for (var i = 0; i < modelMeshes.Length; i++)
                {
                    hideFlags[i] = modelMeshes[i].hideFlags;
                    if (modelMeshes[i].hideFlags != HideFlags.None)
                    {
                        modelMeshes[i].hideFlags = HideFlags.None;
                    }
                }
            }

            var gameObject = HandleUtility.PickGameObject(screenPos, true);

            if (modelMeshes != null)
            {
                for (var i = 0; i < modelMeshes.Length; i++)
                {
                    var modelMesh = modelMeshes[i];
                    if (!modelMesh)
                    {
                        continue;
                    }

                    if (gameObject == modelMesh)
                    {
                        gameObject = null;
                    }

                    if (modelMesh.hideFlags != hideFlags[i])
                    {
                        modelMesh.hideFlags = hideFlags[i];
                    }
                }
            }

            if (!gameObject ||
                gameObject.GetComponent <CSGModel>() ||
                gameObject.GetComponent <CSGBrush>() ||
                gameObject.GetComponent <CSGOperation>() ||
                gameObject.GetComponent <GeneratedMeshInstance>() ||
                gameObject.GetComponent <GeneratedMeshes>())
            {
                return(foundObject != null);
            }

            foundObject = gameObject;
            return(true);
        }
Example #8
0
        public static ShapeExtrusionState Do(Rect dragArea, out Curve2D shape, out float height, out CSGModel modelBeneathCursor, out Matrix4x4 transformation, Axis axis)
        {
            try
            {
                if (!s_ExtrusionMode)
                {
                    // TODO: handle snapping against own points
                    // TODO: handle ability to 'commit'
                    PointDrawing.PointDrawHandle(dragArea, ref s_Points, out s_Transformation, out s_ModelBeneathCursor, UnitySceneExtensions.SceneHandles.OutlinedDotHandleCap);

                    if (s_Points.Count <= 1)
                    {
                        return(ShapeExtrusionState.HoverMode);
                    }

                    if (s_Points.Count <= 3)
                    {
                        return(ShapeExtrusionState.ShapeMode);
                    }

                    if ((s_Points[s_Points.Count - 2] - s_Points[0]).sqrMagnitude < kDistanceEpsilon)
                    {
                        s_ExtrusionMode = true;
                        s_Points[s_Points.Count - 1] = s_Points[0];
                        return(ShapeExtrusionState.Create);
                    }
                    return(ShapeExtrusionState.ShapeMode);
                }
                else
                {
                    var tempPoint = s_Points[s_Points.Count - 1];
                    var oldMatrix = UnityEditor.Handles.matrix;
                    UnityEditor.Handles.matrix = UnityEditor.Handles.matrix * s_Transformation;
                    var extrusionState = ExtrusionHandle.DoHandle(dragArea, ref tempPoint, axis);
                    UnityEditor.Handles.matrix   = oldMatrix;
                    s_Points[s_Points.Count - 1] = tempPoint;

                    switch (extrusionState)
                    {
                    case ExtrusionState.Cancel:             { s_ExtrusionMode = false; return(ShapeExtrusionState.Cancel); }

                    case ExtrusionState.Commit:             { s_ExtrusionMode = false; return(ShapeExtrusionState.Commit); }

                    case ExtrusionState.Modified:   { return(ShapeExtrusionState.Modified); }
                    }
                    return(ShapeExtrusionState.ExtrusionMode);
                }
            }
            finally
            {
                modelBeneathCursor = s_ModelBeneathCursor;
                transformation     = s_Transformation;
                shape  = GetShape();
                height = GetHeight(axis);
            }
        }
        static bool FindWorldIntersection(CSGModel model, Vector3 worldRayStart, Vector3 worldRayEnd, out LegacyBrushIntersection[] intersections, bool ignoreInvisibleSurfaces = true, bool ignoreUnrenderables = true, CSGBrush[] ignoreBrushes = null)
        {
            intersections = null;
            if (InternalCSGModelManager.External == null ||
                InternalCSGModelManager.External.RayCastIntoModelMulti == null)
            {
                return(false);
            }

            var foundIntersections = new Dictionary <CSGNode, LegacyBrushIntersection>();

            var visibleLayers = Tools.visibleLayers;

            ignoreInvisibleSurfaces = ignoreInvisibleSurfaces && !CSGSettings.ShowCulledSurfaces;
            if (!ModelTraits.IsModelSelectable(model))
            {
                return(false);
            }

            if (ignoreUnrenderables && !ModelTraits.WillModelRender(model) &&
                !Selection.Contains(model.gameObject.GetInstanceID()))
            {
                return(false);
            }

            LegacyBrushIntersection[] modelIntersections;
            if (!InternalCSGModelManager.External.RayCastIntoModelMulti(model,
                                                                        worldRayStart,
                                                                        worldRayEnd,
                                                                        ignoreInvisibleSurfaces,
                                                                        out modelIntersections,
                                                                        ignoreBrushes: ignoreBrushes))
            {
                return(false);
            }

            for (var i = 0; i < modelIntersections.Length; i++)
            {
                var intersection = modelIntersections[i];
                var brush        = intersection.gameObject.GetComponent <CSGBrush>();
                if (BrushTraits.IsSurfaceUnselectable(brush, intersection.surfaceIndex, brush.ChildData.Model.IsTrigger, ignoreSurfaceFlags: !ignoreInvisibleSurfaces))
                {
                    continue;
                }

                var currentNode = GetTopMostGroupForNode(brush);
                LegacyBrushIntersection other;
                if (foundIntersections.TryGetValue(currentNode, out other) &&
                    other.distance <= intersection.distance)
                {
                    continue;
                }

                intersection.brush = brush;
                intersection.model = model;

                foundIntersections[currentNode] = modelIntersections[i];
            }

            if (foundIntersections.Count == 0)
            {
                return(false);
            }

            var sortedIntersections = foundIntersections.Values.ToArray();

            Array.Sort(sortedIntersections, (x, y) => (int)Mathf.Sign(x.distance - y.distance));

            intersections = sortedIntersections;
            return(true);
        }
Example #10
0
        /// <summary>
        /// Imports the specified map into the SabreCSG model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="map">The map to be imported.</param>
        /// <param name="scale">The scale modifier.</param>
        public static void Import(CSGModel model, T3dMap map, int scale = 64)
        {
            try
            {
                model.BeginUpdate();

                List <T3dActor> brushes      = map.Brushes;
                Brush[]         sabreBrushes = new Brush[brushes.Count];

                // iterate through all brush actors.
                for (int k = 0; k < brushes.Count; k++)
                {
                    // get the underlying brush data.
                    T3dActor tactor = brushes[k];
                    T3dBrush tbrush = tactor.Brush;
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Unreal Gold Map", "Converting Unreal Brushes To SabreCSG Brushes (" + (k + 1) + " / " + brushes.Count + ")...", k / (float)brushes.Count);
#endif
                    // iterate through the brush polygons.
                    Polygon[] polygons = new Polygon[tbrush.Polygons.Count];
                    for (int i = 0; i < tbrush.Polygons.Count; i++)
                    {
                        T3dPolygon tpolygon = tbrush.Polygons[i];

                        // find the material in the unity project automatically.
                        Material material = FindMaterial(tpolygon.Texture);

                        Vertex[] vertices = new Vertex[tpolygon.Vertices.Count];
                        for (int j = 0; j < tpolygon.Vertices.Count; j++)
                        {
                            // main-scale
                            // scale around pivot point.
                            Vector3 vertexPosition = ToVector3(tpolygon.Vertices[j]);
                            Vector3 pivot          = ToVector3(tactor.PrePivot);
                            Vector3 difference     = vertexPosition - pivot;
                            vertexPosition = difference.Multiply(ToVector3Raw(tactor.MainScale)) + pivot;

                            // post-scale
                            vertices[j] = new Vertex(vertexPosition.Multiply(ToVector3Raw(tactor.PostScale)) / (float)scale, ToVector3(tpolygon.Normal), GenerateUV(tpolygon, j, material));
                        }

                        // detect the polygon flags.
                        bool userExcludeFromFinal = false;
                        if ((tpolygon.Flags & T3dPolygonFlags.Invisible) > 0)
                        {
                            userExcludeFromFinal = true;
                        }

                        polygons[i] = new Polygon(vertices, material, false, userExcludeFromFinal);
                    }

                    // position and rotate the brushes around their pivot point.
                    Transform transform = model.CreateCustomBrush(polygons).transform;
                    transform.position = (ToVector3(tactor.Location) / (float)scale) - (ToVector3(tactor.PrePivot) / (float)scale);
                    Vector3 axis;
                    float   angle;
                    T3dRotatorToQuaternion(tactor.Rotation).ToAngleAxis(out angle, out axis);
                    transform.RotateAround(transform.position + (ToVector3(tactor.PrePivot) / (float)scale), axis, angle);

                    PrimitiveBrush brush = transform.GetComponent <PrimitiveBrush>();
                    sabreBrushes[k] = brush;

                    object value;
                    // detect the brush mode (additive, subtractive).
                    if (tactor.Properties.TryGetValue("CsgOper", out value))
                    {
                        brush.Mode = (string)value == "CSG_Add" ? CSGMode.Add : CSGMode.Subtract;
                    }
                    // detect special brush flags.
                    if (tactor.Properties.TryGetValue("PolyFlags", out value))
                    {
                        T3dBrushFlags flags = (T3dBrushFlags)value;
                        if ((flags & T3dBrushFlags.Invisible) > 0)
                        {
                            brush.IsVisible = false;
                        }
                        if ((flags & T3dBrushFlags.NonSolid) > 0)
                        {
                            brush.HasCollision = false;
                        }
                        if ((flags & T3dBrushFlags.SemiSolid) > 0)
                        {
                            brush.IsNoCSG = true;
                        }
                    }
                    // detect single polygons.
                    if (polygons.Length == 1)
                    {
                        brush.IsNoCSG = true;
                    }
                }

                // add all new brushes to a group.
                string title = "Unreal Gold Map";
                if (map.Title != "")
                {
                    title += " '" + map.Title + "'";
                }
                if (map.Author != "")
                {
                    title += " (" + map.Author + ")";
                }

                GroupBrush groupBrush = new GameObject(title).AddComponent <GroupBrush>();
                groupBrush.transform.SetParent(model.transform);
                for (int i = 0; i < sabreBrushes.Length; i++)
                {
                    sabreBrushes[i].transform.SetParent(groupBrush.transform);
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                model.EndUpdate();
            }
        }
        public static BoxExtrusionState Do(Rect dragArea, out Bounds bounds, out float height, out CSGModel modelBeneathCursor, out Matrix4x4 transformation, BoxExtrusionFlags flags, Axis axis, float?snappingSteps = null)
        {
            try
            {
                if (Tools.viewTool != ViewTool.None &&
                    Tools.viewTool != ViewTool.Pan)
                {
                    return(BoxExtrusionState.None);
                }

                if (s_Points.Count <= 2)
                {
                    PointDrawing.PointDrawHandle(dragArea, ref s_Points, out s_Transformation, out s_ModelBeneathCursor, UnitySceneExtensions.SceneHandles.OutlinedDotHandleCap);

                    if (s_Points.Count <= 1)
                    {
                        return(BoxExtrusionState.HoverMode);
                    }

                    if (s_Points.Count > 2)
                    {
                        s_Points[2] = s_Points[0];
                        return(BoxExtrusionState.Create);
                    }

                    return(BoxExtrusionState.SquareMode);
                }
                else
                {
                    var tempPoint = s_Points[2];
                    var oldMatrix = UnityEditor.Handles.matrix;
                    UnityEditor.Handles.matrix = UnityEditor.Handles.matrix * s_Transformation;
                    var extrusionState = ExtrusionHandle.DoHandle(dragArea, ref tempPoint, axis, snappingSteps: snappingSteps);
                    UnityEditor.Handles.matrix = oldMatrix;
                    s_Points[2] = tempPoint;

                    switch (extrusionState)
                    {
                    case ExtrusionState.Cancel:             { return(BoxExtrusionState.Cancel); }

                    case ExtrusionState.Commit:             { return(BoxExtrusionState.Commit); }

                    case ExtrusionState.Modified:   { return(BoxExtrusionState.Modified); }
                    }
                    return(BoxExtrusionState.BoxMode);
                }
            }
            finally
            {
                modelBeneathCursor = s_ModelBeneathCursor;
                bounds             = GetBounds(flags, axis);
                height             = GetHeight(axis);

                var center = bounds.center;
                if ((flags & BoxExtrusionFlags.GenerateFromCenterY) != BoxExtrusionFlags.GenerateFromCenterY)
                {
                    center[(int)axis] -= height * 0.5f;
                }

                transformation = s_Transformation * Matrix4x4.TRS(center, Quaternion.identity, Vector3.one);

                center = Vector3.zero;
                if ((flags & BoxExtrusionFlags.GenerateFromCenterY) != BoxExtrusionFlags.GenerateFromCenterY)
                {
                    center[(int)axis] = height * 0.5f;
                }
                bounds.center = center;
            }
        }
        public static void Do(int id, Rect dragArea, ref List <Vector3> points, out Matrix4x4 transformation, out CSGModel modelBeneathCursor, UnitySceneExtensions.SceneHandles.CapFunction capFunction)
        {
            modelBeneathCursor = null;
            var evt  = Event.current;
            var type = evt.GetTypeForControl(id);

            switch (type)
            {
            case EventType.ValidateCommand: { if (evt.commandName == kSoftDeleteCommand)
                                              {
                                                  evt.Use(); break;
                                              }
                                              break; }

            case EventType.ExecuteCommand:  { if (evt.commandName == kSoftDeleteCommand)
                                              {
                                                  Cancel(evt, ref points); break;
                                              }
                                              break; }

            case EventType.KeyDown:                 { if (evt.keyCode == kCancelKey ||
                                                          evt.keyCode == kCommitKey)
                                                      {
                                                          evt.Use(); break;
                                                      }
                                                      break; }

            case EventType.KeyUp:                   { if (evt.keyCode == kCancelKey)
                                                      {
                                                          Cancel(evt, ref points); break;
                                                      }
                                                      else
                                                      if (evt.keyCode == kCommitKey)
                                                      {
                                                          Commit(evt, dragArea, ref points); break;
                                                      }
                                                      break; }

            case EventType.Layout:
            {
                if (Tools.current == Tool.View ||
                    Tools.current == Tool.None ||
                    evt.alt)
                {
                    break;
                }

                if (s_StartIntersection == null)
                {
                    break;
                }

                // We set the id at the maximum handle distance so that other things, such as the axis gizmo,
                // will block the click to create a point. If we don't we wouldn't be able to use the axis gizmo.
                UnityEditor.HandleUtility.AddControl(id, kMaxHandleDistance);
                break;
            }

            case EventType.Repaint:
            {
                if (s_StartIntersection == null)
                {
                    break;
                }

                if (points.Count == 0)
                {
                    break;
                }

                if (SceneHandleUtility.focusControl != id)
                {
                    break;
                }

                using (new UnityEditor.Handles.DrawingScope(Matrix4x4.identity))
                {
                    var orientation = s_StartIntersection.orientation;
                    if (capFunction != null)
                    {
                        using (new UnityEditor.Handles.DrawingScope(s_Transform))
                        {
                            for (int i = 0; i < points.Count; i++)
                            {
                                capFunction(id, points[i], orientation, UnityEditor.HandleUtility.GetHandleSize(points[i]) * kPointScale, type);
                            }
                        }
                    }

                    var selectedColor = UnityEditor.Handles.selectedColor;
                    selectedColor.a = 0.5f;
                    using (new UnityEditor.Handles.DrawingScope(selectedColor))
                    {
                        HandleRendering.RenderSnapping3D(s_Snapping2D.WorldSlideGrid, s_Snapping2D.WorldSnappedExtents, s_Snapping2D.GridSnappedPosition, s_Snapping2D.SnapResult, true);
                    }
                }
                break;
            }

            case EventType.MouseMove:
            {
                if (GUIUtility.hotControl != 0 &&
                    GUIUtility.hotControl != id)
                {
                    break;
                }

                UpdatePoints(points, GetPointAtPosition(evt.mousePosition, dragArea));
                break;
            }

            case EventType.MouseDrag:
            {
                if (GUIUtility.hotControl != id)
                {
                    break;
                }

                UpdatePoints(points, GetPointAtPosition(evt.mousePosition, dragArea));
                GUI.changed = true;
                evt.Use();
                break;
            }

            case EventType.MouseDown:
            {
                if (Tools.current == Tool.View ||
                    Tools.current == Tool.None ||
                    evt.alt)
                {
                    break;
                }

                if (GUIUtility.hotControl != 0)
                {
                    break;
                }

                if ((UnityEditor.HandleUtility.nearestControl != id || evt.button != 0) &&
                    (GUIUtility.keyboardControl != id || evt.button != 2))
                {
                    break;
                }

                if (s_StartIntersection == null)
                {
                    break;
                }

                s_CurrentPointIndex++;
                GUIUtility.hotControl = GUIUtility.keyboardControl = id;
                EditorGUIUtility.SetWantsMouseJumping(1);
                evt.Use();
                break;
            }

            case EventType.MouseUp:
            {
                if (GUIUtility.hotControl != id || (evt.button != 0 && evt.button != 2))
                {
                    break;
                }

                GUIUtility.hotControl      = 0;
                GUIUtility.keyboardControl = 0;
                evt.Use();
                EditorGUIUtility.SetWantsMouseJumping(0);

                // reset the starting position
                UpdatePoints(points, GetPointAtPosition(evt.mousePosition, dragArea));
                break;
            }
            }
            if (s_StartIntersection != null)
            {
                modelBeneathCursor = s_StartIntersection.model;
                transformation     = s_Transform;
            }
            else
            {
                transformation = Matrix4x4.identity;
            }
        }
        public static void PointDrawHandle(Rect dragArea, ref List <Vector3> points, out Matrix4x4 transformation, out CSGModel modelBeneathCursor, UnitySceneExtensions.SceneHandles.CapFunction capFunction)
        {
            var id = GUIUtility.GetControlID(s_PointDrawingHash, FocusType.Keyboard);

            PointDrawing.Do(id, dragArea, ref points, out transformation, out modelBeneathCursor, capFunction);
        }
Example #14
0
        private const float inchesInMeters = 0.03125f; // 1/32

        /// <summary>
        /// Imports the specified world into the SabreCSG model.
        /// </summary>
        /// <param name="model">The model to import into.</param>
        /// <param name="world">The world to be imported.</param>
        /// <param name="scale">The scale modifier.</param>
        public static void Import(CSGModel model, VmfWorld world)
        {
            try
            {
                model.BeginUpdate();

                // group all the brushes together.
                GroupBrush groupBrush = new GameObject("Source Engine Map").AddComponent <GroupBrush>();
                groupBrush.transform.SetParent(model.transform);

                // iterate through all world solids.
                for (int i = 0; i < world.Solids.Count; i++)
                {
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Source Engine Map", "Converting Hammer Solids To SabreCSG Brushes (" + (i + 1) + " / " + world.Solids.Count + ")...", i / (float)world.Solids.Count);
#endif
                    VmfSolid solid = world.Solids[i];

                    // don't add triggers to the scene.
                    if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material))
                    {
                        continue;
                    }

                    // build a very large cube brush.
                    var go = model.CreateBrush(PrimitiveBrushType.Cube, Vector3.zero);
                    var pr = go.GetComponent <PrimitiveBrush>();
                    BrushUtility.Resize(pr, new Vector3(8192, 8192, 8192));

                    // clip all the sides out of the brush.
                    for (int j = solid.Sides.Count; j-- > 0;)
                    {
                        VmfSolidSide side = solid.Sides[j];
                        Plane        clip = new Plane(pr.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters));
                        ClipUtility.ApplyClipPlane(pr, clip, false);

                        // find the polygons associated with the clipping plane.
                        // the normal is unique and can never occur twice as that wouldn't allow the solid to be convex.
                        var polygons = pr.GetPolygons().Where(p => p.Plane.normal == clip.normal);
                        foreach (var polygon in polygons)
                        {
                            // detect excluded polygons.
                            if (IsExcludedMaterial(side.Material))
                            {
                                polygon.UserExcludeFromFinal = true;
                            }
                            // detect collision-only brushes.
                            if (IsInvisibleMaterial(side.Material))
                            {
                                pr.IsVisible = false;
                            }
                            // try finding the material in the project.
                            polygon.Material = FindMaterial(side.Material);
                            // calculate the texture coordinates.
                            int w = 256;
                            int h = 256;
                            if (polygon.Material != null && polygon.Material.mainTexture != null)
                            {
                                w = polygon.Material.mainTexture.width;
                                h = polygon.Material.mainTexture.height;
                            }
                            CalculateTextureCoordinates(pr, polygon, w, h, side.UAxis, side.VAxis);
                        }
                    }

                    // add the brush to the group.
                    pr.transform.SetParent(groupBrush.transform);
                }

                // iterate through all entities.
                for (int e = 0; e < world.Entities.Count; e++)
                {
#if UNITY_EDITOR
                    UnityEditor.EditorUtility.DisplayProgressBar("SabreCSG: Importing Source Engine Map", "Converting Hammer Entities To SabreCSG Brushes (" + (e + 1) + " / " + world.Entities.Count + ")...", e / (float)world.Entities.Count);
#endif
                    VmfEntity entity = world.Entities[e];

                    // skip entities that sabrecsg can't handle.
                    switch (entity.ClassName)
                    {
                    case "func_areaportal":
                    case "func_areaportalwindow":
                    case "func_capturezone":
                    case "func_changeclass":
                    case "func_combine_ball_spawner":
                    case "func_dustcloud":
                    case "func_dustmotes":
                    case "func_nobuild":
                    case "func_nogrenades":
                    case "func_occluder":
                    case "func_precipitation":
                    case "func_proprespawnzone":
                    case "func_regenerate":
                    case "func_respawnroom":
                    case "func_smokevolume":
                    case "func_viscluster":
                        continue;
                    }

                    // iterate through all entity solids.
                    for (int i = 0; i < entity.Solids.Count; i++)
                    {
                        VmfSolid solid = entity.Solids[i];

                        // don't add triggers to the scene.
                        if (solid.Sides.Count > 0 && IsSpecialMaterial(solid.Sides[0].Material))
                        {
                            continue;
                        }

                        // build a very large cube brush.
                        var go = model.CreateBrush(PrimitiveBrushType.Cube, Vector3.zero);
                        var pr = go.GetComponent <PrimitiveBrush>();
                        BrushUtility.Resize(pr, new Vector3(8192, 8192, 8192));

                        // clip all the sides out of the brush.
                        for (int j = solid.Sides.Count; j-- > 0;)
                        {
                            VmfSolidSide side = solid.Sides[j];
                            Plane        clip = new Plane(pr.transform.InverseTransformPoint(new Vector3(side.Plane.P1.X, side.Plane.P1.Z, side.Plane.P1.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P2.X, side.Plane.P2.Z, side.Plane.P2.Y) * inchesInMeters), pr.transform.InverseTransformPoint(new Vector3(side.Plane.P3.X, side.Plane.P3.Z, side.Plane.P3.Y) * inchesInMeters));
                            ClipUtility.ApplyClipPlane(pr, clip, false);

                            // find the polygons associated with the clipping plane.
                            // the normal is unique and can never occur twice as that wouldn't allow the solid to be convex.
                            var polygons = pr.GetPolygons().Where(p => p.Plane.normal == clip.normal);
                            foreach (var polygon in polygons)
                            {
                                // detect excluded polygons.
                                if (IsExcludedMaterial(side.Material))
                                {
                                    polygon.UserExcludeFromFinal = true;
                                }
                                // detect collision-only brushes.
                                if (IsInvisibleMaterial(side.Material))
                                {
                                    pr.IsVisible = false;
                                }
                                // try finding the material in the project.
                                polygon.Material = FindMaterial(side.Material);
                                // calculate the texture coordinates.
                                int w = 256;
                                int h = 256;
                                if (polygon.Material != null && polygon.Material.mainTexture != null)
                                {
                                    w = polygon.Material.mainTexture.width;
                                    h = polygon.Material.mainTexture.height;
                                }
                                CalculateTextureCoordinates(pr, polygon, w, h, side.UAxis, side.VAxis);
                            }
                        }

                        // detail brushes that do not affect the CSG world.
                        if (entity.ClassName == "func_detail")
                        {
                            pr.IsNoCSG = true;
                        }
                        // collision only brushes.
                        if (entity.ClassName == "func_vehicleclip")
                        {
                            pr.IsVisible = false;
                        }

                        // add the brush to the group.
                        pr.transform.SetParent(groupBrush.transform);
                    }
                }

#if UNITY_EDITOR
                UnityEditor.EditorUtility.ClearProgressBar();
#endif
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                model.EndUpdate();
            }
        }