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); } } }