BlendShape thumbnail

This commit is contained in:
ousttrue
2018-11-03 14:26:15 +09:00
parent 91306f4a83
commit 183ec644ba
5 changed files with 190 additions and 30 deletions

View File

@@ -10,7 +10,9 @@ namespace VRM
[CustomPropertyDrawer(typeof(BlendShapeClip))]
public class BlendShapeClipDrawer : PropertyDrawer
{
public const int Height = 72;
public const int Height = 132;
public const int ThumbnailSize = 128;
public override void OnGUI(Rect position,
SerializedProperty property, GUIContent label)
@@ -23,7 +25,7 @@ namespace VRM
var halfWidth = position.width * 0.5f;
var rect = new Rect(position.x + 64, position.y, position.width - 64, position.height);
var rect = new Rect(position.x + ThumbnailSize, position.y, position.width - ThumbnailSize, position.height);
EditorGUI.PropertyField(rect, property);
var clip = property.objectReferenceValue as BlendShapeClip;
@@ -37,8 +39,8 @@ namespace VRM
EditorGUI.ObjectField(new Rect(position)
{
width = 64,
height = 64
width = ThumbnailSize,
height = ThumbnailSize
}, thumbnail.objectReferenceValue, typeof(Texture), false);
rect.y += (EditorGUIUtility.singleLineHeight + 2);

View File

@@ -1,4 +1,6 @@
using System;
using System.IO;
using UniGLTF;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
@@ -13,6 +15,9 @@ namespace VRM
BlendShapeClip m_target;
SerializedProperty m_thumbnailProp;
SerializedProperty m_isBinaryProp;
protected override GameObject GetPrefab()
{
return m_target.Prefab;
@@ -41,6 +46,49 @@ namespace VRM
PrefabChanged -= OnPrefabChanged;
}
float m_previewSlider = 1.0f;
static Texture2D SaveResizedImage(RenderTexture rt, UnityPath path, int size)
{
var tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
RenderTexture.active = rt;
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
tex.Apply();
//TextureScale.Scale(tex, size, size);
tex = TextureScale.GetResized(tex, size, size);
byte[] bytes;
switch (path.Extension.ToLower())
{
case ".png":
bytes = tex.EncodeToPNG();
break;
case ".jpg":
bytes = tex.EncodeToJPG();
break;
default:
throw new Exception();
}
if (Application.isPlaying)
{
UnityEngine.Object.Destroy(tex);
}
else
{
UnityEngine.Object.DestroyImmediate(tex);
}
File.WriteAllBytes(path.FullPath, bytes);
path.ImportAsset();
return path.LoadAsset<Texture2D>();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
@@ -48,12 +96,57 @@ namespace VRM
if (m_serializedEditor == null)
{
m_serializedEditor = new SerializedBlendShapeEditor(serializedObject, PreviewSceneManager);
m_thumbnailProp = serializedObject.FindProperty("Thumbnail");
m_isBinaryProp = serializedObject.FindProperty("IsBinary");
}
var result = m_serializedEditor.Draw();
if (result.Changed && PreviewSceneManager != null)
EditorGUILayout.BeginHorizontal();
EditorGUILayout.ObjectField(m_thumbnailProp.objectReferenceValue, typeof(Texture), false,
GUILayout.Width(64), GUILayout.Height(64));
var changed = false;
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField("Preview Weight");
var previewSlider = EditorGUILayout.Slider(m_previewSlider, 0, 1.0f);
GUI.enabled = PreviewTexture != null;
if (GUILayout.Button("save thumbnail"))
{
PreviewSceneManager.Bake(result.BlendShapeBindings, result.MaterialValueBindings, result.Weight);
//var ext = "jpg";
var ext = "png";
var asset = UnityPath.FromAsset(target);
var path = EditorUtility.SaveFilePanel(
"save thumbnail",
asset.Parent.FullPath,
string.Format("{0}.{1}", asset.FileNameWithoutExtension, ext),
ext);
if (!string.IsNullOrEmpty(path))
{
var thumbnail = SaveResizedImage(PreviewTexture, UnityPath.FromFullpath(path),
BlendShapeClipDrawer.ThumbnailSize);
m_thumbnailProp.objectReferenceValue = thumbnail;
serializedObject.ApplyModifiedProperties();
}
}
GUI.enabled = true;
EditorGUILayout.EndVertical();
if (m_isBinaryProp.boolValue)
{
previewSlider = Mathf.Round(previewSlider);
}
if (previewSlider != m_previewSlider)
{
m_previewSlider = previewSlider;
changed = true;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
var result = m_serializedEditor.Draw();
if ((changed || result.Changed) && PreviewSceneManager != null)
{
PreviewSceneManager.Bake(result.BlendShapeBindings, result.MaterialValueBindings, m_previewSlider);
}
}

View File

@@ -237,4 +237,78 @@ namespace VRM
}
#endregion
}
/// https://gist.github.com/gszauer/7799899
public class TextureScale
{
private static Color[] texColors;
private static Color[] newColors;
private static int w;
private static float ratioX;
private static float ratioY;
private static int w2;
public static void Scale(Texture2D tex, int newWidth, int newHeight)
{
texColors = tex.GetPixels();
newColors = new Color[newWidth * newHeight];
ratioX = 1.0f / ((float)newWidth / (tex.width - 1));
ratioY = 1.0f / ((float)newHeight / (tex.height - 1));
w = tex.width;
w2 = newWidth;
BilinearScale(0, newHeight);
tex.Resize(newWidth, newHeight);
tex.SetPixels(newColors);
tex.Apply();
}
private static void BilinearScale(int start, int end)
{
for (var y = start; y < end; y++)
{
int yFloor = (int)Mathf.Floor(y * ratioY);
var y1 = yFloor * w;
var y2 = (yFloor + 1) * w;
var yw = y * w2;
for (var x = 0; x < w2; x++)
{
int xFloor = (int)Mathf.Floor(x * ratioX);
var xLerp = x * ratioX - xFloor;
newColors[yw + x] = ColorLerpUnclamped(ColorLerpUnclamped(texColors[y1 + xFloor], texColors[y1 + xFloor + 1], xLerp),
ColorLerpUnclamped(texColors[y2 + xFloor], texColors[y2 + xFloor + 1], xLerp),
y * ratioY - yFloor);
}
}
}
private static Color ColorLerpUnclamped(Color c1, Color c2, float value)
{
return new Color(c1.r + (c2.r - c1.r) * value,
c1.g + (c2.g - c1.g) * value,
c1.b + (c2.b - c1.b) * value,
c1.a + (c2.a - c1.a) * value);
}
/// http://light11.hatenadiary.com/entry/2018/04/19/194015
public static Texture2D GetResized(Texture2D texture, int width, int height)
{
// リサイズ後のサイズを持つRenderTextureを作成して書き込む
var rt = RenderTexture.GetTemporary(width, height);
Graphics.Blit(texture, rt);
// リサイズ後のサイズを持つTexture2Dを作成してRenderTextureから書き込む
var preRT = RenderTexture.active;
RenderTexture.active = rt;
var ret = new Texture2D(width, height);
ret.ReadPixels(new Rect(0, 0, width, height), 0, 0);
ret.Apply();
RenderTexture.active = preRT;
RenderTexture.ReleaseTemporary(rt);
return ret;
}
}
}

View File

@@ -164,11 +164,13 @@ namespace VRM
private static int sliderHash = "Slider".GetHashCode();
float m_yaw = 180.0f;
float m_pitch;
Vector3 m_position = new Vector3(0, 0, -1f);
Vector3 m_position = new Vector3(0, 0, -0.8f);
// very important to override this, it tells Unity to render an ObjectPreview at the bottom of the inspector
public override bool HasPreviewGUI() { return true; }
public RenderTexture PreviewTexture;
// the main ObjectPreview function... it's called constantly, like other IMGUI On*GUI() functions
public override void OnPreviewGUI(Rect r, GUIStyle background)
{
@@ -183,6 +185,14 @@ namespace VRM
return;
}
var src = r;
var min = Mathf.Min(r.width, r.height);
r.width = min;
r.height = min;
r.x = src.x + (src.width - min) / 2;
r.y = src.y + (src.height - min) / 2;
//previewDir = Drag2D(previewDir, r);
{
int controlId = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
@@ -260,11 +270,11 @@ namespace VRM
if (m_renderer != null && m_scene != null)
{
var texture = m_renderer.Render(r, background, m_scene, m_yaw, m_pitch, m_position);
if (texture != null)
PreviewTexture = m_renderer.Render(r, background, m_scene, m_yaw, m_pitch, m_position) as RenderTexture;
if (PreviewTexture != null)
{
// draw the RenderTexture in the ObjectPreview pane
GUI.DrawTexture(r, texture, ScaleMode.StretchToFill, false);
GUI.DrawTexture(r, PreviewTexture, ScaleMode.StretchToFill, false);
}
}
}

View File

@@ -108,7 +108,6 @@ namespace VRM
public struct DrawResult
{
public bool Changed;
public float Weight;
public BlendShapeBinding[] BlendShapeBindings;
@@ -119,36 +118,19 @@ namespace VRM
{
m_changed = false;
//EditorGUILayout.Space();
var previewSlider = EditorGUILayout.Slider("Preview Weight", m_previewSlider, 0, 1.0f);
m_serializedObject.Update();
EditorGUILayout.Space();
// ReadonlyのBlendShapeClip参照
GUI.enabled = false;
EditorGUILayout.ObjectField("Current clip",
m_targetObject, typeof(BlendShapeClip), false);
GUI.enabled = true;
m_thumbnail.objectReferenceValue = EditorGUILayout.ObjectField(m_thumbnail.objectReferenceValue, typeof(Texture), false);
EditorGUILayout.PropertyField(m_thumbnail, true);
EditorGUILayout.PropertyField(m_blendShapeNameProp, true);
EditorGUILayout.PropertyField(m_presetProp, true);
// v0.45 Added. Binary flag
EditorGUILayout.PropertyField(m_isBinaryProp, true);
if (m_isBinaryProp.boolValue)
{
previewSlider = Mathf.Round(previewSlider);
}
if (previewSlider != m_previewSlider)
{
m_previewSlider = previewSlider;
m_changed = true;
}
EditorGUILayout.Space();
//m_mode = EditorGUILayout.Popup("SourceType", m_mode, MODES);
@@ -181,7 +163,6 @@ namespace VRM
return new DrawResult
{
Changed = m_changed,
Weight = m_previewSlider,
BlendShapeBindings = m_targetObject.Values,
MaterialValueBindings = m_targetObject.MaterialValues
};