Skip to content

Commit

Permalink
Merge pull request #7 from dwango/work_v035
Browse files Browse the repository at this point in the history
Work v035
  • Loading branch information
ousttrue authored Apr 20, 2018
2 parents d77470d + ec8a122 commit d2df01b
Show file tree
Hide file tree
Showing 17 changed files with 420 additions and 334 deletions.
29 changes: 20 additions & 9 deletions Scripts/BlendShape/BlendShapeClip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,26 @@ public struct MaterialValueBinding
[CreateAssetMenu(menuName = "VRM/BlendShapeClip")]
public class BlendShapeClip : ScriptableObject
{
[SerializeField]
GameObject m_prefab;
public GameObject Prefab
{
set { m_prefab = value; }
get {
#if UNITY_EDITOR
if (m_prefab == null)
{
var assetPath = UnityEditor.AssetDatabase.GetAssetPath(this);
if (!string.IsNullOrEmpty(assetPath))
{
m_prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
}
}
#endif
return m_prefab;
}
}

[SerializeField]
public string BlendShapeName = "";

Expand Down Expand Up @@ -74,14 +94,5 @@ public void Apply(Transform root, float value)
}
*/
}

public static BlendShapeClip Create(BlendShapePreset preset)
{
var clip = ScriptableObject.CreateInstance<BlendShapeClip>();
clip.Preset = preset;
clip.BlendShapeName = preset.ToString();
clip.name = preset.ToString();
return clip;
}
}
}
236 changes: 236 additions & 0 deletions Scripts/BlendShape/BlendShapeMerger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UnityEngine;


namespace VRM
{
/// <summary>
/// ブレンドシェイプを蓄えてまとめて適用するクラス
/// </summary>
class BlendShapeMerger
{
Dictionary<BlendShapeKey, BlendShapeClip> m_clipMap;
Dictionary<BlendShapeKey, float> m_valueMap;

class AccumulatingSetter
{
public Action<float> Setter;
float m_value;

public void AddValue(float value)
{
m_value += value;
}

public void Apply(float value)
{
Setter(value);
m_value = 0;
}

public void Apply()
{
Setter(m_value);
m_value = 0;
}

public void Clear()
{
m_value = 0;
Apply();
}
}
Dictionary<BlendShapeBinding, AccumulatingSetter> m_setterMap;
Dictionary<string, Material> m_materialMap;
Dictionary<MaterialValueBinding, AccumulatingSetter> m_materialSetterMap;

public BlendShapeMerger(IEnumerable<BlendShapeClip> clips, Transform root)
{
m_materialMap = new Dictionary<string, Material>();
foreach (var x in root.Traverse())
{
var renderer = x.GetComponent<Renderer>();
if (renderer != null)
{
foreach (var y in renderer.sharedMaterials.Where(y => y != null))
{
if (!string.IsNullOrEmpty(y.name))
{
if (!m_materialMap.ContainsKey(y.name))
{
m_materialMap.Add(y.name, y);
}
}
}
}
}

m_clipMap = clips.ToDictionary(x => BlendShapeKey.CreateFrom(x), x => x);

m_valueMap = new Dictionary<BlendShapeKey, float>();
m_setterMap = new Dictionary<BlendShapeBinding, AccumulatingSetter>();
m_materialSetterMap = new Dictionary<MaterialValueBinding, AccumulatingSetter>();
foreach (var kv in m_clipMap)
{
foreach (var binding in kv.Value.Values)
{
if (!m_setterMap.ContainsKey(binding))
{
var _target = root.Find(binding.RelativePath);
SkinnedMeshRenderer target = null;
if (_target != null)
{
target = _target.GetComponent<SkinnedMeshRenderer>();
}
if (target != null)
{
m_setterMap.Add(binding, new AccumulatingSetter
{
Setter = x =>
{
target.SetBlendShapeWeight(binding.Index, x);
}
});
}
else
{
Debug.LogWarningFormat("SkinnedMeshRenderer: {0} not found", binding.RelativePath);
}
}
}

foreach(var binding in kv.Value.MaterialValues)
{
if (!m_materialSetterMap.ContainsKey(binding))
{
Material target;
if(m_materialMap.TryGetValue(binding.MaterialName, out target))
{
m_materialSetterMap.Add(binding, new AccumulatingSetter
{
Setter = x =>
{
//target.SetBlendShapeWeight(binding.Index, x);
var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * x;
target.SetColor(binding.ValueName, propValue);
}
});
}
else
{
Debug.LogWarningFormat("material: {0} not found", binding.MaterialName);
}
}
}
}
}

public void Clear()
{
foreach (var kv in m_setterMap)
{
kv.Value.Clear();
}
}

public void Restore()
{
foreach (var kv in m_valueMap.ToArray())
{
SetValue(kv.Key, kv.Value, false);
}
}

public void Apply()
{
foreach (var kv in m_setterMap)
{
kv.Value.Apply();
}
}

public void SetValue(BlendShapeKey key, float value, bool replace)
{
m_valueMap[key] = value;

BlendShapeClip clip;
if (!m_clipMap.TryGetValue(key, out clip))
{
return;
}

foreach (var binding in clip.Values)
{
AccumulatingSetter handler;
if (m_setterMap.TryGetValue(binding, out handler))
{
if (replace)
{
// 値置き換え
handler.Apply(binding.Weight * value);
}
else
{
// 積算
handler.AddValue(binding.Weight * value);
}
}
else
{
Debug.LogWarningFormat("'{0}' not found", binding);
}
}

// materialの更新
foreach (var binding in clip.MaterialValues)
{
AccumulatingSetter handler;
if(m_materialSetterMap.TryGetValue(binding, out handler))
{
if (replace)
{
// 値置き換え
handler.Apply(value);
}
else
{
// 積算
handler.AddValue(value);
}
}
else
{
Debug.LogWarningFormat("'{0}' not found", binding);
}
}
}

public float GetValue(BlendShapeKey key)
{
float value;
if (!m_valueMap.TryGetValue(key, out value))
{
return 0;
}
return value;
}

public void RestoreMaterialInitialValues(IEnumerable<BlendShapeClip> clips)
{
if (m_materialMap != null)
{
foreach (var x in clips)
{
foreach (var y in x.MaterialValues)
{
// restore values
m_materialMap[y.MaterialName].SetColor(y.ValueName, y.BaseValue);
}
}
}
}
}
}
12 changes: 12 additions & 0 deletions Scripts/BlendShape/BlendShapeMerger.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ void AddBlendShapeClip()
Debug.LogFormat("{0}", path);
var clip = ScriptableObject.CreateInstance<BlendShapeClip>();
m_target.Clips.Add(clip);
clip.Prefab = AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GetAssetPath(m_target));
AssetDatabase.CreateAsset(clip, path);
AssetDatabase.ImportAsset(path);
}
Expand Down
6 changes: 6 additions & 0 deletions Scripts/BlendShape/Editor/BlendShapeClipEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,14 @@ public class BlendShapeClipEditor : PreviewEditor
BlendShapeClip m_target;
bool m_changed;

protected override GameObject GetPrefab()
{
return m_target.Prefab;
}

void OnPrefabChanged()
{
m_target.Prefab = Prefab;
Bake(m_target.Values, m_target.MaterialValues, 1.0f);
}

Expand Down
19 changes: 12 additions & 7 deletions Scripts/BlendShape/Editor/PreviewEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ protected PreviewSceneManager PreviewSceneManager
/// Previewシーンに表示するPrefab
/// </summary>
GameObject m_prefab;
GameObject Prefab
protected GameObject Prefab
{
get { return m_prefab; }
set
private set
{
if (m_prefab == value) return;
m_prefab = value;
Expand Down Expand Up @@ -89,15 +89,20 @@ protected void Bake(BlendShapeBinding[] values, MaterialValueBinding[] materialV
}
}

protected virtual void OnEnable()
protected virtual GameObject GetPrefab()
{
m_renderer = new PreviewFaceRenderer();
var assetPath = AssetDatabase.GetAssetPath(target);
//Debug.LogFormat("assetPath: {0}", assetPath);
if (!string.IsNullOrEmpty(assetPath))
if (string.IsNullOrEmpty(assetPath))
{
Prefab = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
return null;
}
return AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
}

protected virtual void OnEnable()
{
m_renderer = new PreviewFaceRenderer();
Prefab = GetPrefab();
}

protected virtual void OnDisable()
Expand Down
Loading

0 comments on commit d2df01b

Please sign in to comment.