diff --git a/README.md b/README.md
index f0367960d053fabbcc90160a0cd55df66a6c8c01..6c9e5a0d69626ef26b778a101b6d7ed5fc4d3eb6 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@ UnityPreviewEditor:使用PreviewRenderUtility创建预览窗口。
Unity 版本: Unity 2020.3.18f1c1
+[toc]
### 简介
1. Example -> PreviewRenderWindow 打开
2. 效果图:
@@ -11,6 +12,9 @@ Unity 版本: Unity 2020.3.18f1c1
![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/11_21_27_21_20220111212720.png)
### 代码
+
+ 查看代码
+
```c++
// PreviewRenderWindow.cs 负责自定义管理界面
using System.Collections;
@@ -230,3 +234,322 @@ public class PreviewRenderEditor : Editor
}
}
```
+
+
+
+### Unity 预览界面
+#### 预览界面
+在Unity编辑器界面上可以看到除了Game视图、Scene视图,其他的视图也会出现绘制三维物体的地方,比如检视器的预览窗口,当选中网格时,会对网格进行预览,如下所示:
+![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/12_20_46_52_20220112204650.png)
+绘制的方法都是使用 UnityEditor 未公开文档的PreviewRenderUtility类进行的。
+#### 检视器预览界面
+资产或脚本实现预览窗口可参考Editor类的文档说明,重载带有Preview关键字的接口。
+#### 开启预览功能
+默认脚本对象的检视器窗口是没有预览窗口的,如下所示:
+![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/12_20_51_42_20220112205141.png)
+想要开启预览窗口,那么得创建自己的检视器窗口类,然后重载HasPreviewGUI接口,完整代码如下:
+```c++
+using UnityEngine;
+public class PreviewExample : MonoBehaviour
+{
+}
+using UnityEditor;
+using UnityEngine;
+[CustomEditor(typeof(PreviewExample))]
+public class PreviewExampleInspector : Editor
+{
+ public override bool HasPreviewGUI()
+ {
+ return true;
+ }
+}
+```
+可以看到有黑色的预览窗口了,如下所示:
+![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/12_21_4_19_20220112210419.png)
+#### 标题栏绘制
+默认显示的是物体的名称,重载 GetPreviewTitle 接口可以更改标题名称:
+```c++
+public override GUIContent GetPreviewTitle()
+{
+ return new GUIContent("预览");
+}
+```
+标题栏右边可以绘制其他的信息或者按钮等,重载 OnPreviewSettings 接口方便对预览窗口进行控制:
+```c++
+public override void OnPreviewSettings()
+{
+ GUILayout.Label("文本", "preLabel");
+ GUILayout.Button("按钮", "preButton");
+}
+```
+#### 预览内容的绘制
+最后预览内容的绘制,只需要重载 OnPreviewGUI 接口即可:
+```c++
+public override void OnPreviewGUI(Rect r, GUIStyle background)
+{
+ GUI.Box(r, "Preview");
+}
+```
+最后显示如下所示:
+![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/12_21_15_5_20220112211505.png)
+
+#### 摄像机渲染
+不仅仅在预览窗口进行绘制控件,还可以绘制三维物体,实质是绘制独立的摄像机所照射的信息,例如动画片段预览窗口:
+
+鼠标可以拖动旋转等,还可以看其他方向,就像操作摄像机一样。
+
+这都是通过 PreviewRenderUtility 来实现的,对于这个类没有官方文档,可以通过网上其他人的分享,还有 UnityEditor 内部的使用来学习。
+
+#### 基础绘制
+PreviewRenderUtility 的构造和销毁,还有要预览物体的构造和销毁,以及调用绘制,以 BeginPreview 和 EndAndDrawPreview 包围,在其中进行摄像机的渲染 Camera.Render 调用,代码如下:
+
+ 查看代码
+
+```c++
+using UnityEditor;
+using UnityEngine;
+[CustomEditor(typeof(PreviewExample))]
+public class PreviewExampleInspector : Editor
+{
+ private GameObject _lastGameObj;
+ private bool _canRefreshPreviewGo = false;
+
+ public override void OnInspectorGUI()
+ {
+ // target 当前操作的对象
+ PreviewExample pe = (PreviewExample) target;
+ pe.previewGo = EditorGUILayout.ObjectField("预览目标", pe.previewGo, typeof(GameObject)) as GameObject;
+ if (pe.previewGo != _lastGameObj)
+ {
+ _lastGameObj = pe.previewGo;
+ _canRefreshPreviewGo = true;
+ }
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ public override bool HasPreviewGUI()
+ {
+ return true;
+ }
+
+ public override GUIContent GetPreviewTitle()
+ {
+ return new GUIContent("预览");
+ }
+
+ public override void OnPreviewSettings()
+ {
+ GUILayout.Label("文本", "preLabel");
+ GUILayout.Button("按钮", "preButton");
+ }
+
+ public override void OnPreviewGUI(Rect r, GUIStyle background)
+ {
+ InitPreview();
+ if (Event.current.type != EventType.Repaint)
+ {
+ return;
+ }
+ _previewRenderUtility.BeginPreview(r, background);
+ Camera camera = _previewRenderUtility.camera;
+ if (_previewInstance)
+ {
+ camera.transform.position = _previewInstance.transform.position + new Vector3(0, 5f, 3f);
+ camera.transform.LookAt(_previewInstance.transform);
+ }
+ camera.Render();
+ _previewRenderUtility.EndAndDrawPreview(r);
+ }
+
+ private PreviewRenderUtility _previewRenderUtility;
+ private GameObject _previewInstance;
+
+ private void InitPreview()
+ {
+ if (_previewRenderUtility == null)
+ {
+ // 参数true代表绘制场景内的游戏对象
+ _previewRenderUtility = new PreviewRenderUtility(true);
+ // 设置摄像机的一些参数
+ _previewRenderUtility.cameraFieldOfView = 30f;
+ }
+
+ if (_canRefreshPreviewGo)
+ {
+ _canRefreshPreviewGo = false;
+ // 创建预览的游戏对象
+ CreatePreviewInstances();
+ }
+ }
+
+ private void DestroyPreview()
+ {
+ if (_previewRenderUtility != null)
+ {
+ // 务必要进行清理,才不会残留生成的摄像机对象等
+ _previewRenderUtility.Cleanup();
+ _previewRenderUtility = null;
+ }
+ }
+
+ private void CreatePreviewInstances()
+ {
+ DestroyPreviewInstances();
+
+ // 绘制预览的游戏对象
+ if (_lastGameObj)
+ {
+ _previewInstance = Instantiate(_lastGameObj);
+ _previewRenderUtility.AddSingleGO(_previewInstance);
+ }
+ }
+
+ private void DestroyPreviewInstances()
+ {
+ if (_previewInstance)
+ {
+ DestroyImmediate(_previewInstance);
+ }
+ _previewInstance = null;
+ }
+
+ void OnDestroy()
+ {
+ DestroyPreviewInstances();
+ DestroyPreview();
+ }
+}
+```
+
+
+
+最后效果如下所示:
+![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/13_10_13_40_20220113101338.png)
+
+#### 拖动旋转
+在预览窗口鼠标拖动可以旋转进行预览,就像Cube物体预览一样。要想让摄像机旋转,得知道游戏对象的中心,才能绕着它进行旋转。
+
+
+ 查看代码
+
+```c++
+private static int sliderHash = "Slider".GetHashCode();
+
+private static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
+{
+ // 每次获得独一无二的 controlID
+ int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
+ Event current = Event.current;
+ // 获取对应 controlID 的事件
+ switch (current.GetTypeForControl(controlID))
+ {
+ case EventType.MouseDown:
+ {
+ bool flag = position.Contains(current.mousePosition) && position.width > 50f;
+ if (flag)
+ {
+ // 鼠标摁住拖出预览窗口外,预览物体任然能够旋转
+ GUIUtility.hotControl = controlID;
+ // 采用事件
+ current.Use();
+ // 让鼠标可以拖动到屏幕外后,从另一边出来
+ EditorGUIUtility.SetWantsMouseJumping(1);
+ }
+
+ break;
+ }
+ case EventType.MouseUp:
+ {
+ bool flag2 = GUIUtility.hotControl == controlID;
+ if (flag2)
+ {
+ GUIUtility.hotControl = 0;
+ }
+
+ EditorGUIUtility.SetWantsMouseJumping(0);
+ break;
+ }
+ case EventType.MouseDrag:
+ {
+ bool flag3 = GUIUtility.hotControl == controlID;
+ if (flag3)
+ {
+ // shift 加速
+ scrollPosition -= current.delta * (float) (current.shift ? 3 : 1) /
+ Mathf.Min(position.width, position.height) * 140f;
+ // 以下两条缺少任意一个,会导致延迟更新,拖动过程中无法实时更新
+ // 直到 repaint事件触发才重新绘制
+ current.Use();
+ GUI.changed = true;
+ }
+
+ break;
+ }
+ }
+
+ return scrollPosition;
+}
+```
+
+
+最后效果,如下图所示:
+
+![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/13_10_48_42_20220113104841.png)
+
+#### 自定义视图的预览
+在自定义视图上的预览,可以采用类似以上的方式进行绘制,也可以创建相应的检视器类,直接调用绘制预览接口。代码如下:
+
+ 查看代码
+
+```c++
+using UnityEngine;
+using UnityEditor;
+
+public class PreviewExampleWindow : EditorWindow
+{
+ private Editor m_Editor;
+
+ [MenuItem("Example/PreviewExample")]
+ static void ShowWindow()
+ {
+ GetWindow("PreviewExample");
+ }
+
+ private void OnDestroy()
+ {
+ if (m_Editor != null)
+ {
+ DestroyImmediate(m_Editor);
+ }
+
+ m_Editor = null;
+ }
+
+ void OnGUI()
+ {
+ if (m_Editor == null)
+ {
+ // 第一个参数这里暂时没关系,因为编辑器没有取目标对象
+ m_Editor = Editor.CreateEditor(this, typeof(PreviewExampleInspector));
+ }
+
+ m_Editor.DrawPreview(GUILayoutUtility.GetRect(300, 200));
+ }
+}
+```
+
+
+打开测试窗口,如下图所示:
+
+![](https://gitcode.net/hankangwen/blog-image/-/raw/master/pictures/2022/01/13_11_3_33_20220113110332.png)
+
+### 开源代码
+[https://gitcode.net/hankangwen/unityprevieweditor](https://gitcode.net/hankangwen/unityprevieweditor)
+
+
+
+
+
+
+
+
diff --git a/UnityPreviewEditor/.idea/.idea.UnityPreviewEditor/.idea/contentModel.xml b/UnityPreviewEditor/.idea/.idea.UnityPreviewEditor/.idea/contentModel.xml
index 1ca35529c81e71c1905d09dae0a8b4d0305f7701..de7895090f55721adb0c90d51e1041969dae8cbe 100644
--- a/UnityPreviewEditor/.idea/.idea.UnityPreviewEditor/.idea/contentModel.xml
+++ b/UnityPreviewEditor/.idea/.idea.UnityPreviewEditor/.idea/contentModel.xml
@@ -6,11 +6,19 @@
+
+
+
+
+
+
+
+
diff --git a/UnityPreviewEditor/Assembly-CSharp.csproj.meta b/UnityPreviewEditor/Assembly-CSharp.csproj.meta
new file mode 100644
index 0000000000000000000000000000000000000000..8ca09b2b3458b702b537c9e3a32dc8582eb478f2
--- /dev/null
+++ b/UnityPreviewEditor/Assembly-CSharp.csproj.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 7e2b1b35abda435a9fd3f74c027625e8
+timeCreated: 1641992479
\ No newline at end of file
diff --git a/UnityPreviewEditor/Assets.meta b/UnityPreviewEditor/Assets.meta
new file mode 100644
index 0000000000000000000000000000000000000000..76c3ce4989966617e8bd03a6c186bb9513d7bee3
--- /dev/null
+++ b/UnityPreviewEditor/Assets.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5198225033f14f39bead8eb262a2f737
+timeCreated: 1641992479
\ No newline at end of file
diff --git a/UnityPreviewEditor/Assets/Editor/Example.meta b/UnityPreviewEditor/Assets/Editor/Example.meta
new file mode 100644
index 0000000000000000000000000000000000000000..e8575b5a67e0bb4aef6975e5464371923906bf24
--- /dev/null
+++ b/UnityPreviewEditor/Assets/Editor/Example.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5dd31354876b45e48aa1b5f429f363fb
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/Editor/Example/PreviewExample.cs b/UnityPreviewEditor/Assets/Editor/Example/PreviewExample.cs
new file mode 100644
index 0000000000000000000000000000000000000000..948fcfa140bc16876d6a70ecdb42a32f62123616
--- /dev/null
+++ b/UnityPreviewEditor/Assets/Editor/Example/PreviewExample.cs
@@ -0,0 +1,18 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PreviewExample : MonoBehaviour
+{
+ // Start is called before the first frame update
+ void Start()
+ {
+
+ }
+
+ // Update is called once per frame
+ void Update()
+ {
+
+ }
+}
diff --git a/UnityPreviewEditor/Assets/Editor/Example/PreviewExample.cs.meta b/UnityPreviewEditor/Assets/Editor/Example/PreviewExample.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..4ad66635f177d85e81e2fc912527757897b7258b
--- /dev/null
+++ b/UnityPreviewEditor/Assets/Editor/Example/PreviewExample.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 52e1416b880a27047b16f6098d52bde3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/Editor/Example/PreviewExampleInspector.cs b/UnityPreviewEditor/Assets/Editor/Example/PreviewExampleInspector.cs
new file mode 100644
index 0000000000000000000000000000000000000000..65a6eeff060a15436403e0b1e6103bae544a4e39
--- /dev/null
+++ b/UnityPreviewEditor/Assets/Editor/Example/PreviewExampleInspector.cs
@@ -0,0 +1,18 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class PreviewExampleInspector : MonoBehaviour
+{
+ // Start is called before the first frame update
+ void Start()
+ {
+
+ }
+
+ // Update is called once per frame
+ void Update()
+ {
+
+ }
+}
diff --git a/UnityPreviewEditor/Assets/Editor/Example/PreviewExampleInspector.cs.meta b/UnityPreviewEditor/Assets/Editor/Example/PreviewExampleInspector.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..66f1e210c2961895a1ad9df7f0d10ea7f43fa8c4
--- /dev/null
+++ b/UnityPreviewEditor/Assets/Editor/Example/PreviewExampleInspector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2f9601ed07e8b98409ad843aa4c10e2d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/Editor/PreviewRenderEditor.cs b/UnityPreviewEditor/Assets/Editor/PreviewRenderEditor.cs
index 6a5fb1e5ce74e773bea0c67eaf7a776a7044b31e..20aed68bd9e665f6fc7c882327ccd9a227c9ddae 100644
--- a/UnityPreviewEditor/Assets/Editor/PreviewRenderEditor.cs
+++ b/UnityPreviewEditor/Assets/Editor/PreviewRenderEditor.cs
@@ -83,7 +83,7 @@ public class PreviewRenderEditor : Editor
camera.nearClipPlane = 2.0f;
camera.backgroundColor = new Color(49.0f / 255.0f, 77.0f / 255.0f, 121.0f / 255.0f, 0f);
- // // 设置光源数据
+ // 设置光源数据
_previewRenderUtility.lights[0].intensity = 0.7f;
_previewRenderUtility.lights[0].transform.rotation = Quaternion.Euler(_lightRot.x, _lightRot.y, 0f);
_previewRenderUtility.lights[1].intensity = 0.7f;
@@ -101,7 +101,7 @@ public class PreviewRenderEditor : Editor
// Drag2D 来自源码
private static int sliderHash = "Slider".GetHashCode();
- public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
+ private static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
{
// 每次获得独一无二的 controlID
int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
diff --git a/UnityPreviewEditor/Assets/PreviewExample.meta b/UnityPreviewEditor/Assets/PreviewExample.meta
new file mode 100644
index 0000000000000000000000000000000000000000..11a0eedbe5172e0b3ee8c65b3985844c14f14dbd
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d3282b6a4d7bc764093a9ebdd6da1892
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/PreviewExample/Editor.meta b/UnityPreviewEditor/Assets/PreviewExample/Editor.meta
new file mode 100644
index 0000000000000000000000000000000000000000..28897ddee57b65df460d4bf4d540b7c9917ee8fd
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample/Editor.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 15a92cf5efdc18143b700a35cef9c204
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleInspector.cs b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleInspector.cs
new file mode 100644
index 0000000000000000000000000000000000000000..81d1d9ea8a51779660756fa539d82fbc993d1b49
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleInspector.cs
@@ -0,0 +1,191 @@
+using UnityEditor;
+using UnityEngine;
+[CustomEditor(typeof(PreviewExample))]
+public class PreviewExampleInspector : Editor
+{
+ private GameObject _lastGameObj;
+ private bool _canRefreshPreviewGo = false;
+ private Vector2 _drag = new Vector2(250f, -30f);
+ private Vector2 _lightRot = new Vector2(180f, 0);
+
+ public override void OnInspectorGUI()
+ {
+ // target 当前操作的对象
+ PreviewExample pe = (PreviewExample) target;
+ pe.previewGo = EditorGUILayout.ObjectField("预览目标", pe.previewGo, typeof(GameObject)) as GameObject;
+ if (pe.previewGo != _lastGameObj)
+ {
+ _lastGameObj = pe.previewGo;
+ _canRefreshPreviewGo = true;
+ }
+
+ pe.lightRot = EditorGUILayout.Vector2Field("光源角度", pe.lightRot);
+ _lightRot = pe.lightRot;
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ public override bool HasPreviewGUI()
+ {
+ return true;
+ }
+
+ public override GUIContent GetPreviewTitle()
+ {
+ return new GUIContent("预览");
+ }
+
+ public override void OnPreviewSettings()
+ {
+ GUILayout.Label("文本", "preLabel");
+ GUILayout.Button("按钮", "preButton");
+ }
+
+ public override void OnPreviewGUI(Rect r, GUIStyle background)
+ {
+ InitPreview();
+ // 获取拖拽向量
+ _drag = Drag2D(_drag, r);
+ if (Event.current.type != EventType.Repaint)
+ {
+ return;
+ }
+ _previewRenderUtility.BeginPreview(r, background);
+
+ //调整相机位置与角度
+ Camera camera = _previewRenderUtility.camera;
+ camera.clearFlags = CameraClearFlags.Skybox;
+ var cameraTran = camera.transform;
+ cameraTran.position = Vector2.zero;
+ cameraTran.rotation = Quaternion.Euler(new Vector3(-_drag.y, -_drag.x, 0));
+ cameraTran.position = cameraTran.forward * -6f;
+ var pos = cameraTran.position;
+ cameraTran.position = new Vector3(pos.x, pos.y + 0.6f, pos.z);
+
+ // 设置光源数据
+ _previewRenderUtility.lights[0].intensity = 0.7f;
+ _previewRenderUtility.lights[0].transform.rotation = Quaternion.Euler(_lightRot.x, _lightRot.y, 0f);
+ _previewRenderUtility.lights[1].intensity = 0.7f;
+ _previewRenderUtility.lights[1].transform.rotation = Quaternion.Euler(_lightRot.x, _lightRot.y, 0f);
+ _previewRenderUtility.ambientColor = new Color(0.3f, 0.3f, 0.3f, 0f);
+
+
+ camera.Render();
+ _previewRenderUtility.EndAndDrawPreview(r);
+ }
+
+ private PreviewRenderUtility _previewRenderUtility;
+ private GameObject _previewInstance;
+
+ private void InitPreview()
+ {
+ if (_previewRenderUtility == null)
+ {
+ // 参数true代表绘制场景内的游戏对象
+ _previewRenderUtility = new PreviewRenderUtility(true);
+ // 设置摄像机的一些参数
+ _previewRenderUtility.cameraFieldOfView = 30f;
+ }
+
+ if (_canRefreshPreviewGo)
+ {
+ _canRefreshPreviewGo = false;
+ // 创建预览的游戏对象
+ CreatePreviewInstances();
+ }
+ }
+
+ private void DestroyPreview()
+ {
+ if (_previewRenderUtility != null)
+ {
+ // 务必要进行清理,才不会残留生成的摄像机对象等
+ _previewRenderUtility.Cleanup();
+ _previewRenderUtility = null;
+ }
+ }
+
+ private void CreatePreviewInstances()
+ {
+ DestroyPreviewInstances();
+
+ // 绘制预览的游戏对象
+ if (_lastGameObj)
+ {
+ _previewInstance = Instantiate(_lastGameObj);
+ _previewRenderUtility.AddSingleGO(_previewInstance);
+ }
+ }
+
+ private void DestroyPreviewInstances()
+ {
+ if (_previewInstance)
+ {
+ DestroyImmediate(_previewInstance);
+ }
+ _previewInstance = null;
+ }
+
+ void OnDestroy()
+ {
+ DestroyPreviewInstances();
+ DestroyPreview();
+ }
+
+ // Drag2D 来自源码
+ private static int sliderHash = "Slider".GetHashCode();
+
+ private static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
+ {
+ // 每次获得独一无二的 controlID
+ int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
+ Event current = Event.current;
+ // 获取对应 controlID 的事件
+ switch (current.GetTypeForControl(controlID))
+ {
+ case EventType.MouseDown:
+ {
+ bool flag = position.Contains(current.mousePosition) && position.width > 50f;
+ if (flag)
+ {
+ // 鼠标摁住拖出预览窗口外,预览物体任然能够旋转
+ GUIUtility.hotControl = controlID;
+ // 采用事件
+ current.Use();
+ // 让鼠标可以拖动到屏幕外后,从另一边出来
+ EditorGUIUtility.SetWantsMouseJumping(1);
+ }
+
+ break;
+ }
+ case EventType.MouseUp:
+ {
+ bool flag2 = GUIUtility.hotControl == controlID;
+ if (flag2)
+ {
+ GUIUtility.hotControl = 0;
+ }
+
+ EditorGUIUtility.SetWantsMouseJumping(0);
+ break;
+ }
+ case EventType.MouseDrag:
+ {
+ bool flag3 = GUIUtility.hotControl == controlID;
+ if (flag3)
+ {
+ // shift 加速
+ scrollPosition -= current.delta * (float) (current.shift ? 3 : 1) /
+ Mathf.Min(position.width, position.height) * 140f;
+ // 以下两条缺少任意一个,会导致延迟更新,拖动过程中无法实时更新
+ // 直到 repaint事件触发才重新绘制
+ current.Use();
+ GUI.changed = true;
+ }
+
+ break;
+ }
+ }
+
+ return scrollPosition;
+ }
+}
diff --git a/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleInspector.cs.meta b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleInspector.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..66f1e210c2961895a1ad9df7f0d10ea7f43fa8c4
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleInspector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2f9601ed07e8b98409ad843aa4c10e2d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleWindow.cs b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleWindow.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f1de0a0ad2ab192b2829cbb998579e1fcdbc7f45
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleWindow.cs
@@ -0,0 +1,34 @@
+using UnityEngine;
+using UnityEditor;
+
+public class PreviewExampleWindow : EditorWindow
+{
+ private Editor m_Editor;
+
+ [MenuItem("Example/PreviewExample")]
+ static void ShowWindow()
+ {
+ GetWindow("PreviewExample");
+ }
+
+ private void OnDestroy()
+ {
+ if (m_Editor != null)
+ {
+ DestroyImmediate(m_Editor);
+ }
+
+ m_Editor = null;
+ }
+
+ void OnGUI()
+ {
+ if (m_Editor == null)
+ {
+ // 第一个参数这里暂时没关系,因为编辑器没有取目标对象
+ m_Editor = Editor.CreateEditor(this, typeof(PreviewExampleInspector));
+ }
+
+ m_Editor.DrawPreview(GUILayoutUtility.GetRect(300, 200));
+ }
+}
\ No newline at end of file
diff --git a/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleWindow.cs.meta b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleWindow.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..82656745927c0ff94c3818f7eab2d31dbb43df6a
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample/Editor/PreviewExampleWindow.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 30447c5b23aa946449627f4c1c58573a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/PreviewExample/PreviewExample.cs b/UnityPreviewEditor/Assets/PreviewExample/PreviewExample.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f653183971d81ac59ef4d59f603ad5126bd82cd9
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample/PreviewExample.cs
@@ -0,0 +1,6 @@
+using UnityEngine;
+public class PreviewExample : MonoBehaviour
+{
+ public GameObject previewGo;
+ public Vector2 lightRot;
+}
\ No newline at end of file
diff --git a/UnityPreviewEditor/Assets/PreviewExample/PreviewExample.cs.meta b/UnityPreviewEditor/Assets/PreviewExample/PreviewExample.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..4ad66635f177d85e81e2fc912527757897b7258b
--- /dev/null
+++ b/UnityPreviewEditor/Assets/PreviewExample/PreviewExample.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 52e1416b880a27047b16f6098d52bde3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/UnityPreviewEditor/Assets/Scenes/SampleScene.unity b/UnityPreviewEditor/Assets/Scenes/SampleScene.unity
index 2221b0455333e66659e36ff85fd4fe4bf1cfd760..ca792db33490a55f4a38b080f6528dcbebbff418 100644
--- a/UnityPreviewEditor/Assets/Scenes/SampleScene.unity
+++ b/UnityPreviewEditor/Assets/Scenes/SampleScene.unity
@@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 705507994}
- m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
+ m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
@@ -118,6 +118,8 @@ NavMeshSettings:
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
+ maxJobWorkers: 0
+ preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
@@ -125,7 +127,8 @@ NavMeshSettings:
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 705507995}
@@ -141,15 +144,18 @@ GameObject:
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 705507993}
m_Enabled: 1
- serializedVersion: 8
+ serializedVersion: 10
m_Type: 1
+ m_Shape: 0
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
+ m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
@@ -159,6 +165,24 @@ Light:
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
+ m_CullingMatrixOverride:
+ e00: 1
+ e01: 0
+ e02: 0
+ e03: 0
+ e10: 0
+ e11: 1
+ e12: 0
+ e13: 0
+ e20: 0
+ e21: 0
+ e22: 1
+ e23: 0
+ e30: 0
+ e31: 0
+ e32: 0
+ e33: 1
+ m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
@@ -166,19 +190,24 @@ Light:
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
+ m_RenderingLayerMask: 1
m_Lightmapping: 1
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
+ m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
+ m_UseBoundingSphereOverride: 0
+ m_UseViewFrustumForShadowCasterCull: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &705507995
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 705507993}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
@@ -191,7 +220,8 @@ Transform:
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 963194228}
@@ -208,23 +238,26 @@ GameObject:
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963194225}
m_Enabled: 1
--- !u!20 &963194227
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963194225}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
+ m_GateFitMode: 2
+ m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
- m_GateFitMode: 2
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
@@ -256,7 +289,8 @@ Camera:
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInternal: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 963194225}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
@@ -265,3 +299,48 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &2025848853
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 2025848854}
+ - component: {fileID: 2025848855}
+ m_Layer: 0
+ m_Name: PreviewExample
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &2025848854
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2025848853}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 2
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &2025848855
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 2025848853}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 52e1416b880a27047b16f6098d52bde3, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ previewGo: {fileID: 6569321644736967870, guid: 9982c14b1dcece344b5aa928834f2f3a, type: 3}
+ lightRot: {x: 3.08, y: 130.93}