diff --git a/Assets/VRM/UniVRM/Editor/Format/RecordDisposer.cs b/Assets/VRM/UniVRM/Editor/Format/RecordDisposer.cs
index a824ac8bc..cc3f0557d 100644
--- a/Assets/VRM/UniVRM/Editor/Format/RecordDisposer.cs
+++ b/Assets/VRM/UniVRM/Editor/Format/RecordDisposer.cs
@@ -1,11 +1,13 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
using UnityEditor;
-using UnityEngine;
namespace VRM
{
+ ///
+ /// UndoをGroupを開始して、DisposeでUndoする。
+ /// using で使うのを想定。
+ /// using ブロック内で Undo されるべき操作をする。
+ ///
public struct RecordDisposer : IDisposable
{
int _group;
@@ -20,128 +22,5 @@ namespace VRM
{
Undo.RevertAllDownToGroup(_group);
}
-
- ///
- /// VRMを構成するコンポーネントをコピーする。
- ///
- /// コピー元
- /// コピー先
- /// コピー元とコピー先の対応関係
- public static void CopyVRMComponents(GameObject go, GameObject root,
- Dictionary map)
- {
- {
- // blendshape
- var src = go.GetComponent();
- if (src != null)
- {
- var dst = root.AddComponent();
- dst.BlendShapeAvatar = src.BlendShapeAvatar;
- }
- }
-
- {
- var secondary = go.transform.Find("secondary");
- if (secondary == null)
- {
- secondary = go.transform;
- }
-
- var dstSecondary = root.transform.Find("secondary");
- if (dstSecondary == null)
- {
- dstSecondary = new GameObject("secondary").transform;
- dstSecondary.SetParent(root.transform, false);
- }
-
- // 揺れモノ
- foreach (var src in go.transform.GetComponentsInChildren())
- {
- var dst = map[src.transform];
- var dstColliderGroup = dst.gameObject.AddComponent();
- dstColliderGroup.Colliders = src.Colliders.Select(y =>
- {
- var offset = dst.worldToLocalMatrix.MultiplyPoint(src.transform.localToWorldMatrix.MultiplyPoint(y.Offset));
- return new VRMSpringBoneColliderGroup.SphereCollider
- {
- Offset = offset,
- Radius = y.Radius
- };
- }).ToArray();
- }
-
- foreach (var src in go.transform.GetComponentsInChildren())
- {
- // Copy VRMSpringBone
- var dst = dstSecondary.gameObject.AddComponent();
- dst.m_comment = src.m_comment;
- dst.m_stiffnessForce = src.m_stiffnessForce;
- dst.m_gravityPower = src.m_gravityPower;
- dst.m_gravityDir = src.m_gravityDir;
- dst.m_dragForce = src.m_dragForce;
- if (src.m_center != null)
- {
- dst.m_center = map[src.m_center];
- }
-
- dst.RootBones = src.RootBones.Select(x => map[x]).ToList();
- dst.m_hitRadius = src.m_hitRadius;
- if (src.ColliderGroups != null)
- {
- dst.ColliderGroups = src.ColliderGroups
- .Select(x => map[x.transform].GetComponent()).ToArray();
- }
- }
- }
-
-#pragma warning disable 0618
- {
- // meta(obsolete)
- var src = go.GetComponent();
- if (src != null)
- {
- src.CopyTo(root);
- }
- }
-#pragma warning restore 0618
-
- {
- // meta
- var src = go.GetComponent();
- if (src != null)
- {
- var dst = root.AddComponent();
- dst.Meta = src.Meta;
- }
- }
-
- {
- // firstPerson
- var src = go.GetComponent();
- if (src != null)
- {
- src.CopyTo(root, map);
- }
- }
-
- {
- // humanoid
- var dst = root.AddComponent();
- var src = go.GetComponent();
- if (src != null)
- {
- dst.Avatar = src.Avatar;
- dst.Description = src.Description;
- }
- else
- {
- var animator = go.GetComponent();
- if (animator != null)
- {
- dst.Avatar = animator.avatar;
- }
- }
- }
- }
}
}
diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs b/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs
index 0386f89eb..98f7ddac9 100644
--- a/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs
+++ b/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs
@@ -86,7 +86,7 @@ namespace VRM
var normals = new Vector3[vCount];
var tangents = new Vector3[vCount];
mesh.GetBlendShapeFrameVertices(i, 0, vertices, normals, tangents);
-
+
copyMesh.AddBlendShapeFrame(name, 100f, vertices, normals, tangents);
}
@@ -109,28 +109,26 @@ namespace VRM
smr.sharedMesh = copyMesh;
}
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 作業が終わったらDestoryするべき一時オブジェクト
static void Export(string path, VRMExportSettings settings, List destroy)
{
var target = settings.Source;
- if (IsPrefab(target))
- {
- using (new RecordDisposer(settings.Source.transform.Traverse().ToArray(), "before normalize"))
- {
- target = GameObject.Instantiate(target);
- destroy.Add(target);
- }
- }
+
+ // 常にコピーする。シーンを変化させない
+ target = GameObject.Instantiate(target);
+ destroy.Add(target);
// 正規化
if (settings.PoseFreeze)
{
- using (new RecordDisposer(target.transform.Traverse().ToArray(), "before normalize"))
- {
- var normalized = BoneNormalizer.Execute(target, settings.ForceTPose, false);
- RecordDisposer.CopyVRMComponents(target, normalized.Root, normalized.BoneMap);
- target = normalized.Root;
- destroy.Add(target);
- }
+ // BoneNormalizer.Execute は Copy を作って正規化する。UNDO無用
+ target = BoneNormalizer.Execute(target, settings.ForceTPose, false);
+ destroy.Add(target);
}
// 元のBlendShapeClipに変更を加えないように複製
diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMHumanoidNormalizerMenu.cs b/Assets/VRM/UniVRM/Editor/Format/VRMHumanoidNormalizerMenu.cs
index fbb6d8a32..b02b6ce4e 100644
--- a/Assets/VRM/UniVRM/Editor/Format/VRMHumanoidNormalizerMenu.cs
+++ b/Assets/VRM/UniVRM/Editor/Format/VRMHumanoidNormalizerMenu.cs
@@ -48,14 +48,8 @@ namespace VRM
{
var go = Selection.activeObject as GameObject;
- GameObject normalizedRoot = null;
- using (new RecordDisposer(go.transform.Traverse().ToArray(), "before normalize"))
- {
- var normalized = BoneNormalizer.Execute(go, true, false);
- RecordDisposer.CopyVRMComponents(go, normalized.Root, normalized.BoneMap);
- normalizedRoot = normalized.Root;
- }
- Selection.activeGameObject = normalizedRoot;
+ // BoneNormalizer.Execute はコピーを正規化する。UNDO無用
+ Selection.activeGameObject = BoneNormalizer.Execute(go, true, false);
}
}
}
diff --git a/Assets/VRM/UniVRM/Scripts/SkinnedMeshUtility/BoneNormalizer.cs b/Assets/VRM/UniVRM/Scripts/SkinnedMeshUtility/BoneNormalizer.cs
index 513ed38dd..295561774 100644
--- a/Assets/VRM/UniVRM/Scripts/SkinnedMeshUtility/BoneNormalizer.cs
+++ b/Assets/VRM/UniVRM/Scripts/SkinnedMeshUtility/BoneNormalizer.cs
@@ -181,9 +181,10 @@ namespace VRM
var indexMap =
srcBones
.Select((x, i) => new { i, x })
- .Select(x => {
+ .Select(x =>
+ {
Transform dstBone;
- if(boneMap.TryGetValue(x.x, out dstBone))
+ if (boneMap.TryGetValue(x.x, out dstBone))
{
return dstBones.IndexOf(dstBone);
}
@@ -191,7 +192,7 @@ namespace VRM
{
return -1;
}
- })
+ })
.ToArray();
for (int i = 0; i < srcBones.Length; ++i)
@@ -322,14 +323,14 @@ namespace VRM
var mesh = srcMesh.Copy(false);
mesh.name = srcMesh.name + ".baked";
srcRenderer.BakeMesh(mesh);
-
- var blendShapeValues = new Dictionary();
+
+ var blendShapeValues = new Dictionary();
for (int i = 0; i < srcMesh.blendShapeCount; i++)
{
var val = srcRenderer.GetBlendShapeWeight(i);
if (val > 0) blendShapeValues.Add(i, val);
}
-
+
mesh.boneWeights = MapBoneWeight(srcMesh.boneWeights, boneMap, srcRenderer.bones, dstBones); // restore weights. clear when BakeMesh
// recalc bindposes
@@ -385,7 +386,7 @@ namespace VRM
srcRenderer.SetBlendShapeWeight(i, value);
Vector3[] vertices = blendShapeMesh.vertices;
-
+
for (int j = 0; j < vertices.Length; ++j)
{
if (originalBlendShapePositions[j] == Vector3.zero)
@@ -404,7 +405,7 @@ namespace VRM
if (originalBlendShapeNormals[j] == Vector3.zero)
{
normals[j] = Vector3.zero;
-
+
}
else
{
@@ -428,7 +429,7 @@ namespace VRM
#endif
var frameCount = srcMesh.GetBlendShapeFrameCount(i);
- for(int f=0; f対象モデルのルート
/// 強制的にT-Pose化するか
/// 正規化済みのモデル
- public static NormalizedResult Execute(GameObject go, bool forceTPose, bool clearBlendShapeBeforeNormalize)
+ public static GameObject Execute(GameObject go, bool forceTPose, bool clearBlendShapeBeforeNormalize)
{
Dictionary boneMap = new Dictionary();
@@ -564,11 +565,137 @@ namespace VRM
NormalizeNoneSkinnedMesh(src, dst);
}
- return new NormalizedResult
+ CopyVRMComponents(go, normalized, boneMap);
+
+ // return new NormalizedResult
+ // {
+ // Root = normalized,
+ // BoneMap = boneMap
+ // };
+ return normalized;
+ }
+
+ ///
+ /// VRMを構成するコンポーネントをコピーする。
+ ///
+ /// コピー元
+ /// コピー先
+ /// コピー元とコピー先の対応関係
+ static void CopyVRMComponents(GameObject go, GameObject root,
+ Dictionary map)
+ {
{
- Root = normalized,
- BoneMap = boneMap
- };
+ // blendshape
+ var src = go.GetComponent();
+ if (src != null)
+ {
+ var dst = root.AddComponent();
+ dst.BlendShapeAvatar = src.BlendShapeAvatar;
+ }
+ }
+
+ {
+ var secondary = go.transform.Find("secondary");
+ if (secondary == null)
+ {
+ secondary = go.transform;
+ }
+
+ var dstSecondary = root.transform.Find("secondary");
+ if (dstSecondary == null)
+ {
+ dstSecondary = new GameObject("secondary").transform;
+ dstSecondary.SetParent(root.transform, false);
+ }
+
+ // 揺れモノ
+ foreach (var src in go.transform.GetComponentsInChildren())
+ {
+ var dst = map[src.transform];
+ var dstColliderGroup = dst.gameObject.AddComponent();
+ dstColliderGroup.Colliders = src.Colliders.Select(y =>
+ {
+ var offset = dst.worldToLocalMatrix.MultiplyPoint(src.transform.localToWorldMatrix.MultiplyPoint(y.Offset));
+ return new VRMSpringBoneColliderGroup.SphereCollider
+ {
+ Offset = offset,
+ Radius = y.Radius
+ };
+ }).ToArray();
+ }
+
+ foreach (var src in go.transform.GetComponentsInChildren())
+ {
+ // Copy VRMSpringBone
+ var dst = dstSecondary.gameObject.AddComponent();
+ dst.m_comment = src.m_comment;
+ dst.m_stiffnessForce = src.m_stiffnessForce;
+ dst.m_gravityPower = src.m_gravityPower;
+ dst.m_gravityDir = src.m_gravityDir;
+ dst.m_dragForce = src.m_dragForce;
+ if (src.m_center != null)
+ {
+ dst.m_center = map[src.m_center];
+ }
+
+ dst.RootBones = src.RootBones.Select(x => map[x]).ToList();
+ dst.m_hitRadius = src.m_hitRadius;
+ if (src.ColliderGroups != null)
+ {
+ dst.ColliderGroups = src.ColliderGroups
+ .Select(x => map[x.transform].GetComponent()).ToArray();
+ }
+ }
+ }
+
+#pragma warning disable 0618
+ {
+ // meta(obsolete)
+ var src = go.GetComponent();
+ if (src != null)
+ {
+ src.CopyTo(root);
+ }
+ }
+#pragma warning restore 0618
+
+ {
+ // meta
+ var src = go.GetComponent();
+ if (src != null)
+ {
+ var dst = root.AddComponent();
+ dst.Meta = src.Meta;
+ }
+ }
+
+ {
+ // firstPerson
+ var src = go.GetComponent();
+ if (src != null)
+ {
+ src.CopyTo(root, map);
+ }
+ }
+
+ {
+ // humanoid
+ var dst = root.AddComponent();
+ var src = go.GetComponent();
+ if (src != null)
+ {
+ dst.Avatar = src.Avatar;
+ dst.Description = src.Description;
+ }
+ else
+ {
+ var animator = go.GetComponent();
+ if (animator != null)
+ {
+ dst.Avatar = animator.avatar;
+ }
+ }
+ }
}
}
}