public static void DoStrip(ProBuilderMesh pb) { try { GameObject go = pb.gameObject; Renderer ren = go.GetComponent <Renderer>(); if (ren != null) { EditorUtility.SetSelectionRenderState(ren, EditorSelectedRenderState.Highlight | EditorSelectedRenderState.Wireframe); } if (EditorUtility.IsPrefabAsset(go)) { return; } EditorUtility.SynchronizeWithMeshFilter(pb); if (pb.mesh == null) { DestroyProBuilderMeshAndDependencies(go, pb, false); return; } string cachedMeshPath; Mesh cachedMesh; // if meshes are assets and the mesh cache is valid don't duplicate the mesh to an instance. if (Experimental.meshesAreAssets && EditorMeshUtility.GetCachedMesh(pb, out cachedMeshPath, out cachedMesh)) { DestroyProBuilderMeshAndDependencies(go, pb, true); } else { Mesh m = UnityEngine.ProBuilder.MeshUtility.DeepCopy(pb.mesh); DestroyProBuilderMeshAndDependencies(go, pb); go.GetComponent <MeshFilter>().sharedMesh = m; if (go.TryGetComponent(out MeshCollider meshCollider)) { meshCollider.sharedMesh = m; } } } catch {} }
internal static void TryCacheMesh(ProBuilderMesh pb) { Mesh mesh = pb.mesh; // check for an existing mesh in the mesh cache and update or create a new one so // as not to clutter the scene yaml. string meshAssetPath = AssetDatabase.GetAssetPath(mesh); // if mesh is already an asset any changes will already have been applied since // pb_Object is directly modifying the mesh asset if (string.IsNullOrEmpty(meshAssetPath)) { // at the moment the asset_guid is only used to name the mesh something unique string guid = pb.assetGuid; if (string.IsNullOrEmpty(guid)) { guid = Guid.NewGuid().ToString("N"); pb.assetGuid = guid; } string meshCacheDirectory = GetMeshCacheDirectory(true); string path = string.Format("{0}/{1}.asset", meshCacheDirectory, guid); Mesh m = AssetDatabase.LoadAssetAtPath <Mesh>(path); // a mesh already exists in the cache for this pb_Object if (m != null) { if (mesh != m) { // prefab instances should always point to the same mesh if (EditorUtility.IsPrefabInstance(pb.gameObject) || EditorUtility.IsPrefabAsset(pb.gameObject)) { // Debug.Log("reconnect prefab to mesh"); // use the most recent mesh iteration (when undoing for example) UnityEngine.ProBuilder.MeshUtility.CopyTo(mesh, m); UnityEngine.Object.DestroyImmediate(mesh); pb.gameObject.GetComponent <MeshFilter>().sharedMesh = m; // also set the MeshCollider if it exists pb.Refresh(RefreshMask.Collisions); return; } else { // duplicate mesh // Debug.Log("create new mesh in cache from disconnect"); pb.assetGuid = Guid.NewGuid().ToString("N"); path = string.Format("{0}/{1}.asset", meshCacheDirectory, pb.assetGuid); } } else { Debug.LogWarning("Mesh found in cache and scene mesh references match, but pb.asset_guid doesn't point to asset. Please report the circumstances leading to this event to Karl."); } } AssetDatabase.CreateAsset(mesh, path); } }
/// <summary> /// Ensure that this object has a valid mesh reference, and the geometry is current. If it is not valid, this function will attempt to repair the sync state. /// </summary> /// <param name="mesh">The component to test.</param> /// <seealso cref="ProBuilderMesh.meshSyncState"/> public static void SynchronizeWithMeshFilter(ProBuilderMesh mesh) { if (mesh == null) { throw new ArgumentNullException("mesh"); } Mesh oldMesh = mesh.mesh; MeshSyncState state = mesh.meshSyncState; bool meshesAreAssets = Experimental.meshesAreAssets; if (state != MeshSyncState.InSync) { if (state == MeshSyncState.Null) { mesh.Rebuild(); mesh.Optimize(); } else /** * If the mesh ID doesn't match the gameObject Id, it could mean two things - * 1. The object was just duplicated, and then made unique * 2. The scene was reloaded, and gameObject ids were recalculated. * If the latter, we need to clean up the old mesh. If the former, * the old mesh needs to *not* be destroyed. */ if (oldMesh) { int meshNo = -1; int.TryParse(oldMesh.name.Replace("pb_Mesh", ""), out meshNo); UnityEngine.Object dup = UnityEditor.EditorUtility.InstanceIDToObject(meshNo); GameObject go = dup as GameObject; if (go == null) { // Debug.Log("scene reloaded - false positive."); mesh.mesh.name = "pb_Mesh" + mesh.id; } else { // Debug.Log("duplicate mesh"); if (!meshesAreAssets || !(EditorUtility.IsPrefabAsset(mesh.gameObject) || IsPrefabInstance(mesh.gameObject))) { // deep copy arrays & ToMesh/Refresh mesh.MakeUnique(); mesh.Optimize(); } } } else { // old mesh didn't exist, so this is probably a prefab being instanced if (EditorUtility.IsPrefabAsset(mesh.gameObject)) { mesh.mesh.hideFlags = (HideFlags)(1 | 2 | 4 | 8); } mesh.Optimize(); } } else { if (meshesAreAssets) { EditorMeshUtility.TryCacheMesh(mesh); } } }
public static void DoStrip(ProBuilderMesh pb) { try { GameObject go = pb.gameObject; Renderer ren = go.GetComponent <Renderer>(); if (ren != null) { EditorUtility.SetSelectionRenderState(ren, EditorUtility.GetSelectionRenderState()); } if (EditorUtility.IsPrefabAsset(go)) { return; } EditorUtility.SynchronizeWithMeshFilter(pb); if (pb.mesh == null) { DestroyImmediate(pb); if (go.GetComponent <Entity>()) { DestroyImmediate(go.GetComponent <Entity>()); } return; } string cachedMeshPath; Mesh cachedMesh; // if meshes are assets and the mesh cache is valid don't duplicate the mesh to an instance. if (Experimental.meshesAreAssets && EditorMeshUtility.GetCachedMesh(pb, out cachedMeshPath, out cachedMesh)) { pb.preserveMeshAssetOnDestroy = true; DestroyImmediate(pb); if (go.GetComponent <Entity>()) { DestroyImmediate(go.GetComponent <Entity>()); } } else { Mesh m = UnityEngine.ProBuilder.MeshUtility.DeepCopy(pb.mesh); DestroyImmediate(pb); if (go.GetComponent <Entity>()) { DestroyImmediate(go.GetComponent <Entity>()); } go.GetComponent <MeshFilter>().sharedMesh = m; if (go.GetComponent <MeshCollider>()) { go.GetComponent <MeshCollider>().sharedMesh = m; } } } catch {} }