using UnityEngine; using UnityEngine.Polybrush; namespace UnityEditor.Polybrush { /// /// Handle mesh preview. Use it to load a static preview from a native Unity Mesh, /// PolybrushMesh or ProBuilderMesh. /// /// /// Launch page public class MeshPreview { /// /// Preview default size. /// static readonly Vector2Int k_PreviewSize = new Vector2Int(128, 128); internal enum State { Loading, Loaded, Cannot_Load } /// /// Returns the loaded preview texture. /// If there's none, returns a white texture as fallback. /// internal Texture2D previewTexture { get { if (m_previewState == State.Loaded && m_PreviewTexture != null) return m_PreviewTexture; return Texture2D.whiteTexture; } } /// /// Current preview state. /// internal State CurrentPreviewState { get { return m_previewState; } } /// /// Instance current state. /// State m_previewState = State.Loading; /// /// Loaded preview texture. /// Texture2D m_PreviewTexture; /// /// Reference to the asset associated to this preview. /// Object m_Asset = null; internal MeshPreview(Object asset) { m_Asset = asset; m_PreviewTexture = Texture2D.whiteTexture; SetState(State.Loading); } /// /// Update the current state of the mesh preview. /// As AssetPreview API is asynchronous, we need to keep requesting the asset preview /// until we have it. Once texture is loaded, current state of the instance moves /// to Status.Loaded. /// internal void UpdatePreview() { switch (m_previewState) { case State.Loading: if (ProBuilderBridge.ProBuilderExists() && ProBuilderInterface.IsProBuilderObject(m_Asset as GameObject)) m_PreviewTexture = GenerateProBuilderPreview(); else if (PolyEditorUtility.IsPolybrushObject(m_Asset as GameObject)) m_PreviewTexture = GeneratePreview(); else m_PreviewTexture = AssetPreview.GetAssetPreview(m_Asset); if (previewTexture != null) SetState(State.Loaded); break; case State.Loaded: // Failsafe as AssetPreview can return white textures while loading // and erase that texture from memory once the right texture is available. if (m_PreviewTexture == null) SetState(State.Loading); break; } } /// /// Generate a static preview for a PolybrushMesh. /// A mesh is generated from a PolybrushMesh then feed to a default Mesh editor. /// /// Static preview of the given PolybrushMesh. internal Texture2D GeneratePreview() { PolybrushMesh castTarget = (m_Asset as GameObject).GetComponent(); Mesh mesh = castTarget.storedMesh; Editor meshEditor = Editor.CreateEditor(mesh); Texture2D preview = meshEditor.RenderStaticPreview(null, null, k_PreviewSize.x, k_PreviewSize.y); ScriptableObject.DestroyImmediate(meshEditor); return preview; } /// /// Generate a static preview for a ProBuilderMesh. /// /// Static preview of the given ProBuilderMesh. internal Texture2D GenerateProBuilderPreview() { GameObject copy = GameObject.Instantiate(m_Asset as GameObject); copy.hideFlags = HideFlags.HideAndDontSave; ProBuilderBridge.ToMesh(copy); ProBuilderBridge.Refresh(copy); MeshFilter mf = copy.GetComponent(); Editor meshEditor = Editor.CreateEditor(mf.sharedMesh); Texture2D preview = meshEditor.RenderStaticPreview(null, null, k_PreviewSize.x, k_PreviewSize.y); ScriptableObject.DestroyImmediate(meshEditor); ScriptableObject.DestroyImmediate(copy); return preview; } private void SetState(State newState) { m_previewState = newState; } } }