功能:在预制体编辑窗口选择带有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;
}
}