Unity 框架

PreviewInspector.cs 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using UnityEngine;
  2. using UnityEditor;
  3. namespace TFramework
  4. {
  5. public class PreviewInspector : Editor
  6. {
  7. private PreviewRenderUtility m_PreviewUtility;
  8. private GameObject m_PreviewInstance;
  9. private Bounds m_PreviewBounds;
  10. private Vector2 m_PreviewDir = new Vector2(120f, -20f);
  11. public Texture2D PreviewTexture { get; private set; }
  12. public override bool HasPreviewGUI() => true;
  13. private void AddSingleGO(GameObject go)
  14. {
  15. #if UNITY_2017_1_OR_NEWER
  16. m_PreviewUtility.AddSingleGO(go);
  17. #endif
  18. }
  19. public override void OnPreviewGUI(Rect r, GUIStyle background)
  20. {
  21. InitPreview();
  22. m_PreviewDir = Drag2D(m_PreviewDir, r);
  23. if (Event.current.type != EventType.Repaint) return;
  24. m_PreviewUtility.BeginPreview(r, background);
  25. Camera camera = m_PreviewUtility.camera;
  26. float num = Mathf.Max(m_PreviewBounds.extents.magnitude, 0.0001f);
  27. float num2 = num * 2.8f;
  28. Quaternion quaternion = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0f);
  29. Vector3 position = m_PreviewBounds.center - quaternion * (Vector3.forward * num2);
  30. camera.transform.position = position;
  31. camera.transform.rotation = quaternion;
  32. camera.nearClipPlane = num2 - num * 1.1f;
  33. camera.farClipPlane = num2 + num * 1.1f;
  34. m_PreviewUtility.lights[0].intensity = .7f;
  35. m_PreviewUtility.lights[0].transform.rotation = quaternion * Quaternion.Euler(40f, 40f, 0);
  36. m_PreviewUtility.lights[1].intensity = .7f;
  37. m_PreviewUtility.lights[1].transform.rotation = quaternion * Quaternion.Euler(340, 218, 177);
  38. m_PreviewUtility.ambientColor = new Color(.1f, .1f, .1f, 0);
  39. SetEnabledRecursive(m_PreviewInstance, true);
  40. camera.Render();
  41. SetTexture(camera, new Vector2Int(512, 512));
  42. SetEnabledRecursive(m_PreviewInstance, false);
  43. m_PreviewUtility.EndAndDrawPreview(r);
  44. }
  45. private void InitPreview()
  46. {
  47. if (m_PreviewUtility == null)
  48. {
  49. m_PreviewUtility = new PreviewRenderUtility(true);
  50. m_PreviewUtility.cameraFieldOfView = 60f;
  51. CreatePreviewInstances();
  52. }
  53. m_PreviewUtility.camera.cullingMask = 1 << kPreviewCullingLayer;
  54. }
  55. private void DestroyPreview()
  56. {
  57. m_PreviewUtility?.Cleanup();
  58. m_PreviewUtility = null;
  59. }
  60. private void DestroyPreviewInstances()
  61. {
  62. if (m_PreviewInstance != null)
  63. {
  64. DestroyImmediate(m_PreviewInstance);
  65. }
  66. m_PreviewInstance = null;
  67. }
  68. void OnDestroy()
  69. {
  70. DestroyPreviewInstances();
  71. DestroyPreview();
  72. }
  73. private void OnDisable()
  74. {
  75. DestroyPreviewInstances();
  76. DestroyPreview();
  77. }
  78. private void CreatePreviewInstances()
  79. {
  80. DestroyPreviewInstances();
  81. // Ҫ���Ƶ���Ϸ����
  82. m_PreviewInstance = Selection.activeGameObject;
  83. if (m_PreviewInstance == null)
  84. {
  85. return;
  86. }
  87. // ʵ��������
  88. m_PreviewInstance = Instantiate(m_PreviewInstance, Vector3.zero, Quaternion.identity) as GameObject;
  89. m_PreviewInstance.transform.localScale = 100 * Vector3.one;
  90. // �ݹ��������ر�־�Ͳ�
  91. InitInstantiatedPreviewRecursive(m_PreviewInstance);
  92. // �رն�����Ⱦ
  93. SetEnabledRecursive(m_PreviewInstance, false);
  94. m_PreviewBounds = new Bounds(m_PreviewInstance.transform.position, Vector3.zero);
  95. GetRenderableBoundsRecurse(ref m_PreviewBounds, m_PreviewInstance);
  96. AddSingleGO(m_PreviewInstance);
  97. }
  98. public static void GetRenderableBoundsRecurse(ref Bounds bounds, GameObject go)
  99. {
  100. MeshRenderer meshRenderer = go.GetComponent(typeof(MeshRenderer)) as MeshRenderer;
  101. MeshFilter meshFilter = go.GetComponent(typeof(MeshFilter)) as MeshFilter;
  102. if (meshRenderer && meshFilter && meshFilter.sharedMesh)
  103. {
  104. if (bounds.extents == Vector3.zero)
  105. {
  106. bounds = meshRenderer.bounds;
  107. }
  108. else
  109. {
  110. // ��չ��Χ�У����ð�Χ���ܹ�������һ����Χ��
  111. bounds.Encapsulate(meshRenderer.bounds);
  112. }
  113. }
  114. SkinnedMeshRenderer skinnedMeshRenderer = go.GetComponent(typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer;
  115. if (skinnedMeshRenderer && skinnedMeshRenderer.sharedMesh)
  116. {
  117. if (bounds.extents == Vector3.zero)
  118. {
  119. bounds = skinnedMeshRenderer.bounds;
  120. }
  121. else
  122. {
  123. bounds.Encapsulate(skinnedMeshRenderer.bounds);
  124. }
  125. }
  126. foreach (Transform transform in go.transform)
  127. {
  128. GetRenderableBoundsRecurse(ref bounds, transform.gameObject);
  129. }
  130. }
  131. public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
  132. {
  133. int controlID = GUIUtility.GetControlID("Slider".GetHashCode(), FocusType.Passive);
  134. Event current = Event.current;
  135. switch (current.GetTypeForControl(controlID))
  136. {
  137. case EventType.MouseDown:
  138. if (position.Contains(current.mousePosition) && position.width > 50f)
  139. {
  140. GUIUtility.hotControl = controlID;
  141. current.Use();
  142. // ���������϶�����Ļ��󣬴���һ�߳���
  143. EditorGUIUtility.SetWantsMouseJumping(1);
  144. }
  145. break;
  146. case EventType.MouseUp:
  147. if (GUIUtility.hotControl == controlID)
  148. {
  149. GUIUtility.hotControl = 0;
  150. }
  151. EditorGUIUtility.SetWantsMouseJumping(0);
  152. break;
  153. case EventType.MouseDrag:
  154. if (GUIUtility.hotControl == controlID)
  155. {
  156. // ��ס Shift ���󣬿��Լӿ���ת
  157. scrollPosition -= current.delta * (float)((!current.shift) ? 1 : 3) / Mathf.Min(position.width, position.height) * 140f;
  158. scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
  159. current.Use();
  160. GUI.changed = true;
  161. }
  162. break;
  163. }
  164. return scrollPosition;
  165. }
  166. // Ԥ��������Ļ��Ʋ� Camera.PreviewCullingLayer
  167. // Ϊ�˷�ֹ������ģ�����ͨ�������ȡ������ֱ��дֵ
  168. private const int kPreviewCullingLayer = 31;
  169. private static void InitInstantiatedPreviewRecursive(GameObject go)
  170. {
  171. go.hideFlags = HideFlags.HideAndDontSave;
  172. go.layer = kPreviewCullingLayer;
  173. foreach (Transform transform in go.transform)
  174. {
  175. InitInstantiatedPreviewRecursive(transform.gameObject);
  176. }
  177. }
  178. public static void SetEnabledRecursive(GameObject go, bool enabled)
  179. {
  180. Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>();
  181. for (int i = 0; i < componentsInChildren.Length; i++)
  182. {
  183. Renderer renderer = componentsInChildren[i];
  184. renderer.enabled = enabled;
  185. }
  186. }
  187. public void SetTexture(Camera camera, Vector2Int size)
  188. {
  189. if (camera == null) return;
  190. PreviewTexture = new Texture2D(size.x, size.y, TextureFormat.RGB24, false);
  191. var scrRenderTexture = new RenderTexture(PreviewTexture.width, PreviewTexture.height, 24);
  192. var camRenderTexture = camera.targetTexture;
  193. camera.targetTexture = scrRenderTexture;
  194. camera.Render();
  195. camera.targetTexture = camRenderTexture;
  196. RenderTexture.active = scrRenderTexture;
  197. PreviewTexture.ReadPixels(new Rect(0, 0, PreviewTexture.width, PreviewTexture.height), 0, 0);
  198. PreviewTexture.Apply();
  199. }
  200. }
  201. }