利用SceneView
之前做过一个通过scene截图来实现预览的效果,这次加上窗口内的鼠标平移旋转缩放的常见效果。
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEngine;
public class ScreenShotPreview : EditorWindow
{
private bool bIsStartPreviewMouseEvent = false;
private MouseCursor previewMouseCursor = MouseCursor.Arrow;
[MenuItem("Tools/截图预览窗口")]
static void Open()
{
CreateWindow<ScreenShotPreview>();
}
void OnGUI()
{
// 接收按键
if (Event.current.type == EventType.Repaint)
Repaint(); // 保证窗口实时刷新
Camera cam = SceneView.GetAllSceneCameras()[0];
int pixWidth = cam.pixelWidth;
int pixHeight = cam.pixelHeight;
RenderTexture tex = new RenderTexture(pixWidth, pixHeight, 1, RenderTextureFormat.DefaultHDR);
RenderTexture lastTex = cam.targetTexture;
cam.targetTexture = tex;
cam.Render();
cam.targetTexture = lastTex;
float width = pixWidth;
float height = pixHeight;
Rect rect = new Rect(0, 0, width, height);
GUI.DrawTexture(rect, tex);
HandleKey(rect,SceneView.lastActiveSceneView);
}
private void HandleKey(Rect rect, SceneView view)
{
Event evt = Event.current;
switch (evt.type)
{
case EventType.MouseDown:
if (rect.Contains(evt.mousePosition))
{
switch (evt.button)
{
case 1:
case 2:
bIsStartPreviewMouseEvent = true;
// 让鼠标可以拖动到屏幕外后,从另一边出来
EditorGUIUtility.SetWantsMouseJumping(1);
break;
}
}
break;
case EventType.MouseUp:
bIsStartPreviewMouseEvent = false;
previewMouseCursor = MouseCursor.Arrow;
EditorGUIUtility.SetWantsMouseJumping(0);
break;
case EventType.MouseDrag:
if (bIsStartPreviewMouseEvent)
{
switch (evt.button)
{
case 1:
previewMouseCursor = MouseCursor.Orbit;
Quaternion rotation = view.rotation;
rotation = Quaternion.AngleAxis(evt.delta.y * .003f * Mathf.Rad2Deg, rotation * Vector3.right) * rotation;
rotation = Quaternion.AngleAxis(evt.delta.x * .003f * Mathf.Rad2Deg, Vector3.up) * rotation;
view.rotation = rotation;
break;
case 2:
previewMouseCursor = MouseCursor.Pan;
Vector2 screenDelta = evt.delta;
Vector3 worldDelta = ScreenToWorldDistance(view, new Vector2(-screenDelta.x, screenDelta.y));
if (!evt.shift)
worldDelta *= 4;
view.pivot += worldDelta;
break;
}
}
break;
case EventType.ScrollWheel:
if (rect.Contains(evt.mousePosition))
{
float zoomDelta = -HandleUtility.niceMouseDeltaZoom * (evt.shift ? 3 : 9);
if (view.orthographic)
{
view.size = Mathf.Max(.0001f, view.size * (1 + zoomDelta * .001f));
}
else
{
var s_StartZoom = view.size;
var s_ZoomSpeed = Mathf.Max(Mathf.Abs(s_StartZoom), .3f);
view.size = view.size + zoomDelta * s_ZoomSpeed * .003f;
}
}
break;
}
EditorGUIUtility.AddCursorRect(rect, previewMouseCursor);
evt.Use();
}
private Vector3 ScreenToWorldDistance(SceneView view,Vector2 sceneDelta)
{
var camera = view.camera;
Vector3 screenPos = camera.WorldToScreenPoint(view.pivot);
screenPos += new Vector3(sceneDelta.x, sceneDelta.y, 0);
Vector3 worldDelta = camera.ScreenToWorldPoint(screenPos) - view.pivot;
worldDelta *= EditorGUIUtility.pixelsPerPoint;
return worldDelta;
}
}
相关业务实际上也可以看这个面板相关的源码学习。