using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
namespace ChivaXR
{
///
/// 屏幕截图管理
///
public class ScreenShot : EditorWindow
{
///
/// 目标相机,即需要用来截图的层级相机
///
public Camera targetCamera;
///
/// 最后一个截图的完整路径信息
///
public string lastScreenshot = "";
///
/// 用于保存所截图片的文件路径
///
private string folderPath = "";
///
/// 预设宽高,默认为屏幕分辨率
///
private int rectWidth = Screen.width;
private int rectHight = Screen.height;
///
/// 默认比例
///
private int scale = 1;
///
/// 图片背景是否透明,默认不透明
///
private bool isTransparent = false;
///
/// 模型是否居中
///
private bool isCenter = false;
///
/// 是否隐藏截屏图片
///
private bool takeHiResShot = false;
[MenuItem("ChivaXR/Tool/截 图/高分辨率截图")]
public static void SceneScreenShot()
{
EditorWindow editorWindow = EditorWindow.GetWindow(typeof(ScreenShot));
editorWindow.autoRepaintOnSceneChange = true;
editorWindow.Show();
editorWindow.titleContent = new GUIContent("高分辨率截图");
}
private void OnGUI()
{
GUIStyle style = new GUIStyle();
style.fontSize = 16;
style.normal.textColor = Color.white;
EditorGUILayout.LabelField("分辨率", style);
rectWidth = EditorGUILayout.IntField("宽度", rectWidth);
rectHight = EditorGUILayout.IntField("高度", rectHight);
EditorGUILayout.Space();
scale = EditorGUILayout.IntSlider("比例", scale, 1, 15);
//显示帮助信息
EditorGUILayout.HelpBox("截图的默认模式是裁剪,所以需要选择合适的宽高,而比例是在不降低质量的情况下增加或放大渲染的一个因素", MessageType.None);
EditorGUILayout.Space();
GUILayout.Label(" 保存路径", style);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.TextField(folderPath, GUILayout.ExpandWidth(true));
if (GUILayout.Button("预览", GUILayout.ExpandWidth(false)))
{
folderPath = EditorUtility.SaveFolderPanel("保存路径", folderPath, Application.dataPath);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.HelpBox("选择保存截图的文件夹", MessageType.None);
EditorGUILayout.Space();
GUILayout.Label(" 选择相机", style);
targetCamera = EditorGUILayout.ObjectField(targetCamera, typeof(Camera), true, null) as Camera;
if (targetCamera == null)
{
targetCamera = Camera.main;
}
isTransparent = EditorGUILayout.Toggle("背景是否透明", isTransparent);
EditorGUILayout.HelpBox("选择要捕捉渲染的相机,可以使用透明度选项使背景透明", MessageType.None);
EditorGUILayout.Space();
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("默认选项", style);
if (GUILayout.Button("设置为屏幕尺寸"))
{
rectWidth = (int)Handles.GetMainGameViewSize().x;
rectHight = (int)Handles.GetMainGameViewSize().y;
}
if (GUILayout.Button("默认尺寸"))
{
rectWidth = 1920;
rectHight = 1080;
scale = 1;
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
EditorGUILayout.LabelField("图片分辨率为:" + rectWidth * scale + " x " + rectHight * scale + " px", EditorStyles.boldLabel);
if (GUILayout.Button("截屏", GUILayout.MinHeight(60)))
{
if (folderPath == "")
{
folderPath = EditorUtility.SaveFolderPanel("保存路径", folderPath, Application.dataPath);
TakeHiResShot();
}
else
{
TakeHiResShot();
}
}
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("打开最后一个截图", GUILayout.MaxWidth(160), GUILayout.MinHeight(40)))
{
if (lastScreenshot != "")
{
Application.OpenURL("file://" + lastScreenshot);
}
}
if (GUILayout.Button("打开文件夹", GUILayout.MaxWidth(160), GUILayout.MinHeight(40)))
{
Application.OpenURL("file://" + folderPath);
}
EditorGUILayout.EndHorizontal();
if (takeHiResShot)
{
int width = rectWidth * scale;
int height = rectHight * scale;
RenderTexture rt = new RenderTexture(width, height, 24);
targetCamera.targetTexture = rt;
//纹理格式
TextureFormat textureFormat;
if (isTransparent)
{
textureFormat = TextureFormat.ARGB32;
}
else
{
textureFormat = TextureFormat.RGB24;
}
Texture2D screenShot = new Texture2D(width, height, textureFormat, false);
targetCamera.Render();
RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, width, height), 0, 0);
targetCamera.targetTexture = null;
RenderTexture.active = null;
byte[] bytes = screenShot.EncodeToPNG();
string filename = ScreenShotName(width, height);
File.WriteAllBytes(filename, bytes);
Application.OpenURL(filename);
takeHiResShot = false;
}
}
private void TakeHiResShot()
{
takeHiResShot = true;
}
///
/// 截图完整路径信息
///
///
///
///
public string ScreenShotName(int width, int height)
{
string strPath = string.Format(
"{0}/screen_{1}x{2}_{3}.png",
folderPath,
width,
height,
System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
lastScreenshot = strPath;
return strPath;
}
[MenuItem("GameObject/Chiva/固定视角创建预览图", priority = 0)]
public static void CreatePreview()
{
string folderPath = "";
folderPath = EditorUtility.SaveFolderPanel("保存路径", folderPath, Application.dataPath);
byte[] bytes = GetAssetPreview(Selection.activeGameObject).EncodeToPNG();
string filename = string.Format(
"{0}/screen_{1}.png",
folderPath,
System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
File.WriteAllBytes(filename, bytes);
Application.OpenURL(filename);
}
[MenuItem("GameObject/Chiva/Scene视角创建预览图", priority = 0)]
public static void CreatePreviewBySceneView()
{
string folderPath = "";
folderPath = EditorUtility.SaveFolderPanel("保存路径", folderPath, Application.dataPath);
byte[] bytes = GetAssetPreview(Selection.activeGameObject, true).EncodeToPNG();
string filename = string.Format(
"{0}/screen_{1}.png",
folderPath,
System.DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
File.WriteAllBytes(filename, bytes);
Application.OpenURL(filename);
}
private static Vector2 previewSize = new Vector2(512, 512);
///
/// 获取预览图象
///
///
/// 是否按照当前Scene视角截图
///
private static Texture2D GetAssetPreview(GameObject obj, bool sceneView = false, bool cloneObj = true)
{
GameObject clone;
Transform cloneTransform;
if (cloneObj)
{
clone = GameObject.Instantiate(obj);
cloneTransform = clone.transform;
cloneTransform.position = new Vector3(-1000, -1000, -1000);
cloneTransform.rotation = obj.transform.rotation;
}
else
{
clone = obj;
cloneTransform = clone.transform;
}
Transform[] all = clone.GetComponentsInChildren();
foreach (Transform trans in all)
{
trans.gameObject.layer = 21;
}
Bounds bounds = GetBounds(clone);
Vector3 Min = bounds.min;
Vector3 Max = bounds.max;
GameObject cameraObj = new GameObject("render camera");
Camera renderCamera = cameraObj.AddComponent();
renderCamera.backgroundColor = new Color(0.2f, 0.2f, 0.2f, 0);
renderCamera.clearFlags = CameraClearFlags.Color;
renderCamera.cullingMask = 1 << 21;
renderCamera.nearClipPlane = 0.01f;
renderCamera.fieldOfView = 30;
Vector3 center = bounds.center;
Vector3 position;
//求相机应当所处的目标位置
if (sceneView)
{
//预览图视角设置为当前Scene视角
position = center - SceneView.lastActiveSceneView.camera.transform.rotation * (bounds.extents.magnitude * 3.8f * Vector3.forward);
}
else
{
//固定视角
position = center - Quaternion.Euler(30, -30, 60) * (bounds.extents.magnitude * 3.8f * Vector3.forward);
}
// 更新位置
cameraObj.transform.position = position;
cameraObj.transform.LookAt(bounds.center);
RenderTexture texture = new RenderTexture((int)previewSize.x, (int)previewSize.y, 24, RenderTextureFormat.Default);
renderCamera.targetTexture = texture;
renderCamera.RenderDontRestore();
//纹理格式
TextureFormat textureFormat = TextureFormat.ARGB32;
Texture2D screenShot = new Texture2D((int)previewSize.x, (int)previewSize.y, textureFormat, false);
renderCamera.Render();
RenderTexture.active = texture;
screenShot.ReadPixels(new Rect(0, 0, (int)previewSize.x, (int)previewSize.y), 0, 0);
renderCamera.targetTexture = null;
RenderTexture.active = null;
if (cloneObj)
{
Object.DestroyImmediate(clone);
}
Object.DestroyImmediate(cameraObj);
return screenShot;
}
///
/// 获得某物体的空間bounds
///
///
private static Bounds GetBounds(GameObject obj)
{
Vector3 Min = new Vector3(99999, 99999, 99999);
Vector3 Max = new Vector3(-99999, -99999, -99999);
MeshRenderer[] renders = obj.GetComponentsInChildren();
for (int i = 0; i < renders.Length; i++)
{
if (renders[i].bounds.min.x < Min.x)
Min.x = renders[i].bounds.min.x;
if (renders[i].bounds.min.y < Min.y)
Min.y = renders[i].bounds.min.y;
if (renders[i].bounds.min.z < Min.z)
Min.z = renders[i].bounds.min.z;
if (renders[i].bounds.max.x > Max.x)
Max.x = renders[i].bounds.max.x;
if (renders[i].bounds.max.y > Max.y)
Max.y = renders[i].bounds.max.y;
if (renders[i].bounds.max.z > Max.z)
Max.z = renders[i].bounds.max.z;
}
Vector3 center = (Min + Max) / 2;
Vector3 size = new Vector3(Max.x - Min.x, Max.y - Min.y, Max.z - Min.z);
return new Bounds(center, size);
}
}
}