예제 #1
0
        internal static void DestroyAllMeshInstances()
        {
            if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            for (var sceneIndex = 0; sceneIndex < SceneManager.sceneCount; sceneIndex++)
            {
                var scene = SceneManager.GetSceneAt(sceneIndex);
                if (!scene.isLoaded)
                {
                    continue;
                }
                var sceneModels = SceneQueryUtility.GetAllComponentsInScene <CSGModel>(scene);
                for (int i = 0; i < sceneModels.Count; i++)
                {
                    if (!ModelTraits.IsModelEditable(sceneModels[i]))
                    {
                        continue;
                    }
                    var selfTransform = sceneModels[i].transform;
                    var transforms    = selfTransform.GetComponentsInChildren <Transform>();
                    foreach (var generateMeshesTransform in transforms)
                    {
                        if (!generateMeshesTransform || generateMeshesTransform.parent != selfTransform)
                        {
                            continue;
                        }

                        if (generateMeshesTransform.name != MeshInstanceManager.MeshContainerName)
                        {
                            continue;
                        }

                        var childTransforms = generateMeshesTransform;
                        foreach (Transform childTransform in childTransforms)
                        {
                            GameObjectExtensions.Destroy(childTransform.gameObject);
                        }
                    }
                }
            }
        }
        internal static void OnBuild()
        {
            // apparently only way to determine current scene while post processing a scene
            var randomObject = UnityEngine.Object.FindObjectOfType <Transform>();

            if (!randomObject)
            {
                return;
            }

            var currentScene = randomObject.gameObject.scene;

            var foundMeshContainers = SceneQueryUtility.GetAllComponentsInScene <GeneratedMeshes>(currentScene);

            foreach (var meshContainer in foundMeshContainers)
            {
                var model = meshContainer.owner;
                if (!model)
                {
                    UnityEngine.Object.DestroyImmediate(meshContainer.gameObject);
                    continue;
                }

                if (model.NeedAutoUpdateRigidBody)
                {
                    AutoUpdateRigidBody(meshContainer);
                }

                model.gameObject.hideFlags         = HideFlags.None;
                meshContainer.transform.hideFlags  = HideFlags.None;
                meshContainer.gameObject.hideFlags = HideFlags.None;
                meshContainer.hideFlags            = HideFlags.None;

                var instances = meshContainer.GetComponentsInChildren <GeneratedMeshInstance>(true);
                foreach (var instance in instances)
                {
                    if (!instance)
                    {
                        continue;
                    }

                    instance.gameObject.hideFlags = HideFlags.None;// HideFlags.NotEditable;
                    instance.gameObject.SetActive(true);

                    //Refresh(instance, model, postProcessScene: true);
#if SHOW_GENERATED_MESHES
                    UpdateName(instance);
#endif

                    // TODO: make sure meshes are no longer marked as dynamic!

                    if (!HasRuntimeMesh(instance))
                    {
                        UnityEngine.Object.DestroyImmediate(instance.gameObject);
                        continue;
                    }

                    var surfaceType = GetSurfaceType(instance.MeshDescription, model.Settings);
                    if (surfaceType == RenderSurfaceType.ShadowOnly)
                    {
                        var meshRenderer = instance.gameObject.GetComponent <MeshRenderer>();
                        if (meshRenderer)
                        {
                            meshRenderer.sharedMaterial = MaterialUtility.DefaultMaterial;
                            meshRenderer.enabled        = true;
                        }
                        RemoveIfEmpty(instance.gameObject);
                        continue;
                    }
                    if (surfaceType == RenderSurfaceType.Normal)
                    {
                        var meshRenderer = instance.gameObject.GetComponent <MeshRenderer>();
                        if (meshRenderer)
                        {
                            meshRenderer.enabled = true;
                        }
                    }

                    if (surfaceType == RenderSurfaceType.Collider ||
                        surfaceType == RenderSurfaceType.Trigger)
                    {
                        var meshRenderer = instance.gameObject.GetComponent <MeshRenderer>();
                        if (meshRenderer)
                        {
                            UnityEngine.Object.DestroyImmediate(meshRenderer);
                        }

                        var meshFilter = instance.gameObject.GetComponent <MeshFilter>();
                        if (meshFilter)
                        {
                            UnityEngine.Object.DestroyImmediate(meshFilter);
                        }

                        if (surfaceType == RenderSurfaceType.Trigger)
                        {
                            var oldMeshCollider = instance.gameObject.GetComponent <MeshCollider>();
                            if (oldMeshCollider)
                            {
                                var newMeshCollider = model.gameObject.AddComponent <MeshCollider>();
                                EditorUtility.CopySerialized(oldMeshCollider, newMeshCollider);
                                UnityEngine.Object.DestroyImmediate(oldMeshCollider);
                            }
                        }
                        RemoveIfEmpty(instance.gameObject);
                        continue;
                    }
                    RemoveIfEmpty(instance.gameObject);
                }

                if (!meshContainer)
                {
                    continue;
                }

                var children = meshContainer.GetComponentsInChildren <GeneratedMeshInstance>();
                foreach (var child in children)
                {
                    child.hideFlags            = HideFlags.None;
                    child.gameObject.hideFlags = HideFlags.None;
                    child.transform.hideFlags  = HideFlags.None;
                    if (child.SharedMesh && !UsesLightmapUVs(model))
                    {
                        MeshUtility.Optimize(child.SharedMesh);
                    }
                }

                UnityEngine.Object.DestroyImmediate(meshContainer);
            }


            var meshInstances = SceneQueryUtility.GetAllComponentsInScene <GeneratedMeshInstance>(currentScene);
            foreach (var meshInstance in meshInstances)
            {
                if (meshInstance)
                {
                    UnityEngine.Object.DestroyImmediate(meshInstance);
                }
            }

            var csgnodes             = new HashSet <CSGNode>(SceneQueryUtility.GetAllComponentsInScene <CSGNode>(currentScene));
            var removableGameObjects = new List <GameObject>();
            foreach (var csgnode in csgnodes)
            {
                if (!csgnode)
                {
                    continue;
                }

                var gameObject = csgnode.gameObject;
                var model      = csgnode as CSGModel;

                if (
                    (model && model.name == InternalCSGModelManager.DefaultModelName &&
                     (model.transform.childCount == 0 ||
                      (model.transform.childCount == 1 &&
                       model.transform.GetChild(0).name == MeshContainerName &&
                       model.transform.GetChild(0).childCount == 0)
                     )
                    )
                    )
                {
                    UnityEngine.Object.DestroyImmediate(gameObject);
                }
                else
                if (model)
                {
                    gameObject.tag = "Untagged";
                    AssignLayerToChildren(gameObject);
                }
                else
                if (gameObject.tag == "EditorOnly")
                {
                    removableGameObjects.Add(gameObject);
                }
                if (csgnode)
                {
                    UnityEngine.Object.DestroyImmediate(csgnode);
                }
            }

            var removableTransforms = new HashSet <Transform>();
            for (int i = 0; i < removableGameObjects.Count; i++)
            {
                var gameObject = removableGameObjects[i];
                var transform  = gameObject.transform;
                if (removableTransforms.Contains(transform))
                {
                    continue;
                }
                RemoveWithChildrenIfPossible(transform, removableTransforms);
            }
        }
        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);
                }
            }
        }