unity中通过预制体生成Png图片

功能:在预制体编辑窗口选择带有MeshFilter的物体,预览窗口会显示截图按钮,可以将当前预览窗口中的图片保存为透明背景的Png格式图片

目前存在的问题:1.不能对整个预制体预览截图
2.灯光效果,不能像编辑器内置的那样跟随旋转(或者不应该转动相机)

在这里插入图片描述
在这里插入图片描述

using UnityEngine;
using UnityEditor;
using System.IO;

[CustomEditor(typeof(MeshFilter))]
[CanEditMultipleObjects]
public class MeshFilterPreview : Editor
{
    private PreviewRenderUtility m_PreviewRenderUtility;
    private MeshFilter m_TargetMeshFilter;
    private MeshRenderer m_TargetMeshRenderer;
    private static int sliderHash = "Slider".GetHashCode();
    private Vector2 m_Drag;
    Texture result_render;

    private void ValidateData()
    {
        if (m_PreviewRenderUtility == null)
        {
            m_PreviewRenderUtility = new PreviewRenderUtility();

            m_PreviewRenderUtility.camera.transform.position = new Vector3(0, 0, -6);
            m_PreviewRenderUtility.camera.transform.rotation = Quaternion.identity;
        }

        m_TargetMeshFilter = target as MeshFilter;       
        m_TargetMeshRenderer = m_TargetMeshFilter.GetComponent<MeshRenderer>();
    }

    public override bool HasPreviewGUI()
    {
        ValidateData();

        return true;
    }

    public override void OnPreviewGUI(Rect r, GUIStyle background)
    {
        m_Drag = Drag2D(m_Drag, r);

        if (Event.current.type == EventType.Repaint)
        {
            if (m_TargetMeshRenderer == null)
            {
                EditorGUI.DropShadowLabel(r, "Mesh Renderer Required");
            }
            else
            {
                m_PreviewRenderUtility.BeginPreview(r, background);

                m_PreviewRenderUtility.DrawMesh(m_TargetMeshFilter.sharedMesh, Matrix4x4.identity, m_TargetMeshRenderer.sharedMaterial, 0);


                var mesh = m_TargetMeshFilter.sharedMesh;
                var bounds = mesh.bounds;                           
                var cameraPos = bounds.center;

                m_PreviewRenderUtility.camera.transform.position = Vector2.zero;
                m_PreviewRenderUtility.camera.transform.rotation = Quaternion.Euler(new Vector3(-m_Drag.y, -m_Drag.x, 0));

                float cameraDis = bounds.center.y / Mathf.Tan(Mathf.Deg2Rad * 4);               

                m_PreviewRenderUtility.camera.transform.position = m_PreviewRenderUtility.camera.transform.forward * -cameraDis + Vector3.up*mesh.bounds.center.y;
                m_PreviewRenderUtility.camera.Render();

                result_render = m_PreviewRenderUtility.EndPreview();
                GUI.DrawTexture(r, result_render, ScaleMode.StretchToFill, false);
            }
        }
    }

    public override void OnPreviewSettings()
    {
        if (GUILayout.Button("Reset Camera", EditorStyles.miniButtonLeft))
        {
            m_Drag = Vector2.zero;
        }
        else if (GUILayout.Button("截图", EditorStyles.miniButtonRight))
        {
            PreviewShot();
        }
    }

    private void OnDisable()
    {
        if (m_PreviewRenderUtility != null)
        {
            m_PreviewRenderUtility.Cleanup();
        }
    }

    public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
    {
        int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
        Event current = Event.current;
        switch (current.GetTypeForControl(controlID))
        {
            case EventType.MouseDown:
                if (position.Contains(current.mousePosition) && position.width > 50f)
                {
                    GUIUtility.hotControl = controlID;
                    current.Use();
                    EditorGUIUtility.SetWantsMouseJumping(1);
                }

                break;
            case EventType.MouseDrag:
                if (GUIUtility.hotControl == controlID)
                {
                    scrollPosition -= current.delta * ((!current.shift) ? 1 : 3) / Mathf.Min(position.width, position.height) * 140f;
                    current.Use();
                    GUI.changed = true;
                }

                break;
            case EventType.MouseUp:
                if (GUIUtility.hotControl == controlID)
                {
                    GUIUtility.hotControl = 0;
                }

                EditorGUIUtility.SetWantsMouseJumping(0);
                break;
        }

        return scrollPosition;
    }

    private void PreviewShot()
    {
        var name = Selection.gameObjects[0].name;
        string path = "/Resources/PreviewShot/";

        if (!System.IO.Directory.Exists(Application.dataPath + path))
        {
            System.IO.Directory.CreateDirectory(Application.dataPath + path);
        }

        Texture2D texture2D = TextureToTexture2D(result_render);

        int offsetx = Mathf.RoundToInt((texture2D.width - 512)/2);
        int offsetY = Mathf.RoundToInt((texture2D.height - 512)/2);
        texture2D = TextureCutOut(texture2D,offsetx,offsetY,512,512);

        SaveTexture(texture2D,path,name);

        Application.OpenURL(Application.dataPath + path);       
    }

    
    private Texture2D TextureToTexture2D(Texture texture)
    {
        Texture2D texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);         
        RenderTexture currentRT = RenderTexture.active;
        RenderTexture renderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 32);
        Graphics.Blit(texture, renderTexture);

        RenderTexture.active = renderTexture;
        texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
        
        texture2D.Apply();

        RenderTexture.active = currentRT;
        RenderTexture.ReleaseTemporary(renderTexture);
        

        return texture2D;
    }

    private void SaveTexture(Texture2D texture2D,string path,string name)
    {
        //保存图片
        byte[] dataBytes = texture2D.EncodeToPNG();
        string savePath = Application.dataPath + path +name+".png";
        FileStream fileStream = File.Open(savePath, FileMode.OpenOrCreate);
        fileStream.Write(dataBytes, 0, dataBytes.Length);
        fileStream.Close();
        UnityEditor.AssetDatabase.SaveAssets();
        UnityEditor.AssetDatabase.Refresh();
    } 

    public static Texture2D TextureCutOut(Texture2D originalTexture, int offsetX, int offsetY, float originalWidth, float originalHeight)
    {
        Texture2D newTexture = new Texture2D(Mathf.CeilToInt(originalWidth), Mathf.CeilToInt(originalHeight));
        int maxX = originalTexture.width - 1;
        int maxY = originalTexture.height - 1;
        for (int y = 0; y < newTexture.height; y++)
        {
            for (int x = 0; x < newTexture.width; x++)
            {
                float targetX = x + offsetX;
                float targetY = y + offsetY;
                int x1 = Mathf.Min(maxX, Mathf.FloorToInt(targetX));
                int y1 = Mathf.Min(maxY, Mathf.FloorToInt(targetY));
                int x2 = Mathf.Min(maxX, x1 + 1);
                int y2 = Mathf.Min(maxY, y1 + 1);

                float u = targetX - x1;
                float v = targetY - y1;
                float w1 = (1 - u) * (1 - v);
                float w2 = u * (1 - v);
                float w3 = (1 - u) * v;
                float w4 = u * v;
                Color color1 = originalTexture.GetPixel(x1, y1);
                Color color2 = originalTexture.GetPixel(x2, y1);
                Color color3 = originalTexture.GetPixel(x1, y2);
                Color color4 = originalTexture.GetPixel(x2, y2);
                Color color = new Color(Mathf.Clamp01(color1.r * w1 + color2.r * w2 + color3.r * w3 + color4.r * w4),
                                        Mathf.Clamp01(color1.g * w1 + color2.g * w2 + color3.g * w3 + color4.g * w4),
                                        Mathf.Clamp01(color1.b * w1 + color2.b * w2 + color3.b * w3 + color4.b * w4),
                                        Mathf.Clamp01(color1.a * w1 + color2.a * w2 + color3.a * w3 + color4.a * w4)
                                        );
                newTexture.SetPixel(x, y, color);
            }
        }
        newTexture.anisoLevel = 2;
        newTexture.Apply();
        return newTexture;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值