diff --git a/Scripts/BlendShape/Editor/PreviewEditor.cs b/Scripts/BlendShape/Editor/PreviewEditor.cs
index 30476d1c1..e5c93cac1 100644
--- a/Scripts/BlendShape/Editor/PreviewEditor.cs
+++ b/Scripts/BlendShape/Editor/PreviewEditor.cs
@@ -1,20 +1,44 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEditor;
+using UnityEditor;
using UnityEngine;
+using UnityEditorInternal;
namespace VRM
{
+ ///
+ /// Prefabをインスタンス化してPreviewに表示する
+ ///
+ /// * https://github.com/Unity-Technologies/UnityCsReference/blob/11bcfd801fccd2a52b09bb6fd636c1ddcc9f1705/Editor/Mono/Inspector/ModelInspector.cs
+ ///
+ ///
public class PreviewEditor : Editor
{
+ ///
+ /// PreviewRenderUtilityを管理する。
+ ///
+ /// * PreviewRenderUtility.m_cameraのUnityVersionによる切り分け
+ ///
+ ///
+ PreviewFaceRenderer m_renderer;
+
+ ///
+ /// Prefabをインスタンス化したシーンを管理する。
+ ///
+ /// * BlendShapeのBake
+ /// * MaterialMorphの適用
+ /// * Previewカメラのコントロール
+ /// * Previewライティングのコントロール
+ ///
+ ///
PreviewSceneManager m_scene;
protected PreviewSceneManager PreviewSceneManager
{
get { return m_scene; }
}
- PreviewFaceRenderer m_renderer;
+ ///
+ /// Previewシーンに表示するPrefab
+ ///
GameObject m_prefab;
GameObject Prefab
{
@@ -42,6 +66,12 @@ namespace VRM
}
}
+ ///
+ /// シーンにBlendShapeとMaterialMorphを適用する
+ ///
+ ///
+ ///
+ ///
protected void Bake(BlendShapeBinding[] values, MaterialValueBinding[] materialValues, float weight)
{
if (m_scene != null)
@@ -88,6 +118,43 @@ namespace VRM
Prefab = (GameObject)EditorGUILayout.ObjectField("prefab", Prefab, typeof(GameObject), false);
}
+ private static int sliderHash = "Slider".GetHashCode();
+ public static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
+ {
+ int controlId = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
+ Event current = Event.current;
+ switch (current.GetTypeForControl(controlId))
+ {
+ case EventType.MouseDown:
+ if (position.Contains(current.mousePosition) && (double)position.width > 50.0)
+ {
+ GUIUtility.hotControl = controlId;
+ current.Use();
+ EditorGUIUtility.SetWantsMouseJumping(1);
+ break;
+ }
+ break;
+ case EventType.MouseUp:
+ if (GUIUtility.hotControl == controlId)
+ GUIUtility.hotControl = 0;
+ EditorGUIUtility.SetWantsMouseJumping(0);
+ break;
+ case EventType.MouseDrag:
+ if (GUIUtility.hotControl == controlId)
+ {
+ scrollPosition -= current.delta * (!current.shift ? 1f : 3f) / Mathf.Min(position.width, position.height) * 140f;
+ scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
+ current.Use();
+ GUI.changed = true;
+ break;
+ }
+ break;
+ }
+ return scrollPosition;
+ }
+
+ Vector2 previewDir;
+
// very important to override this, it tells Unity to render an ObjectPreview at the bottom of the inspector
public override bool HasPreviewGUI() { return true; }
@@ -99,10 +166,15 @@ namespace VRM
{
if (Event.current.type == EventType.Repaint)
{
- EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40f), "Mesh preview requires\nrender texture support");
+ EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40f),
+ "Mesh preview requires\nrender texture support");
}
return;
}
+
+ previewDir = Drag2D(previewDir, r);
+ //Debug.LogFormat("{0}", previewDir);
+
if (Event.current.type != EventType.Repaint)
{
// if we don't need to update yet, then don't
@@ -111,7 +183,7 @@ namespace VRM
if (m_renderer != null && m_scene != null)
{
- var texture = m_renderer.Render(r, background, m_scene);
+ var texture = m_renderer.Render(r, background, m_scene, previewDir);
if (texture != null)
{
// draw the RenderTexture in the ObjectPreview pane
diff --git a/Scripts/BlendShape/Editor/PreviewFaceRenderer.cs b/Scripts/BlendShape/Editor/PreviewFaceRenderer.cs
index 15c95c5e9..62c0711fd 100644
--- a/Scripts/BlendShape/Editor/PreviewFaceRenderer.cs
+++ b/Scripts/BlendShape/Editor/PreviewFaceRenderer.cs
@@ -79,7 +79,9 @@ namespace VRM
}
}
- public Texture Render(Rect r, GUIStyle background, PreviewSceneManager scene)
+ //const float FACTOR = 0.1f;
+
+ public Texture Render(Rect r, GUIStyle background, PreviewSceneManager scene, Vector2 drag)
{
if (scene == null) return null;
@@ -88,7 +90,7 @@ namespace VRM
m_previewUtility.BeginPreview(r, background); // set up the PreviewRenderUtility's mini internal scene
// setup the ObjectPreview's camera
- scene.SetupCamera(PreviewCamera);
+ scene.SetupCamera(PreviewCamera, scene.TargetPosition, -drag.x, drag.y);
foreach (var item in scene.EnumRenderItems)
{
diff --git a/Scripts/BlendShape/PreviewSceneManager.cs b/Scripts/BlendShape/PreviewSceneManager.cs
index 5f86207b2..9de0e9217 100644
--- a/Scripts/BlendShape/PreviewSceneManager.cs
+++ b/Scripts/BlendShape/PreviewSceneManager.cs
@@ -127,6 +127,16 @@ namespace VRM
.Where(x => x.SkinnedMeshRenderer != null)
.Select(x => x.Path)
.ToArray();
+
+ var animator = GetComponent();
+ if (animator != null)
+ {
+ var head = animator.GetBoneTransform(HumanBodyBones.Head);
+ if (head != null)
+ {
+ m_target = head;
+ }
+ }
}
MeshPreviewItem[] m_meshes;
@@ -186,6 +196,19 @@ namespace VRM
return item;
}
+ public Transform m_target;
+ public Vector3 TargetPosition
+ {
+ get
+ {
+ if (m_target == null)
+ {
+ return new Vector3(0, 1.4f, 0);
+ }
+ return m_target.position;
+ }
+ }
+
Bounds m_bounds;
public void Bake(BlendShapeBinding[] values=null, MaterialValueBinding[] materialValues=null, float weight=1.0f)
{
@@ -243,18 +266,28 @@ namespace VRM
/// カメラパラメーターを決める
///
///
- public void SetupCamera(Camera camera)
+ public void SetupCamera(Camera camera, Vector3 target, float yaw, float pitch)
{
- float magnitude = m_bounds.extents.magnitude * 0.5f;
- float distance = magnitude;
- camera.fieldOfView = 27f;
camera.backgroundColor = Color.gray;
camera.clearFlags = CameraClearFlags.Color;
+
+ // projection
+ //float magnitude = m_bounds.extents.magnitude * 0.5f;
+ //float distance = magnitude;
+ var distance = target.magnitude;
+
+ camera.fieldOfView = 27f;
+ camera.nearClipPlane = 0.3f;
+ camera.farClipPlane = distance /*+ magnitude*/ * 2.1f;
+
+#if false
// this used to be "-Vector3.forward * num" but I hardcoded my camera position instead
camera.transform.position = new Vector3(0f, 1.4f, distance);
camera.transform.rotation = Quaternion.Euler(0, 180f, 0);
- camera.nearClipPlane = 0.3f;
- camera.farClipPlane = distance + magnitude * 1.1f;
+#else
+ camera.transform.position = target + Quaternion.Euler(pitch, yaw, 0) * Vector3.forward * distance;
+ camera.transform.LookAt(target);
+#endif
//previewLayer のみ表示する
//camera.cullingMask = 1 << PreviewLayer;