This commit is contained in:
Perfare 2018-12-24 04:25:55 +08:00
parent ff550b457f
commit 54d78d55a0
6 changed files with 266 additions and 359 deletions

View File

@ -9,7 +9,7 @@ namespace AssetStudio
{ {
public PPtr<Avatar> m_Avatar; public PPtr<Avatar> m_Avatar;
public PPtr<RuntimeAnimatorController> m_Controller; public PPtr<RuntimeAnimatorController> m_Controller;
public bool m_HasTransformHierarchy; public bool m_HasTransformHierarchy = true;
public Animator(ObjectReader reader) : base(reader) public Animator(ObjectReader reader) : base(reader)
{ {

View File

@ -303,18 +303,6 @@ namespace AssetStudio
} }
} }
public string FindBoneName(uint hash)
{
foreach (var pair in m_TOS)
{
if (pair.Key == hash)
{
return pair.Value.Substring(pair.Value.LastIndexOf('/') + 1);
}
}
return null;
}
public string FindBonePath(uint hash) public string FindBonePath(uint hash)
{ {
return m_TOS.FirstOrDefault(pair => pair.Key == hash).Value; return m_TOS.FirstOrDefault(pair => pair.Key == hash).Value;

View File

@ -16,7 +16,7 @@ namespace AssetStudio
List<ImportedMorph> MorphList { get; } List<ImportedMorph> MorphList { get; }
} }
public class ImportedFrame : IEnumerable<ImportedFrame> public class ImportedFrame
{ {
public string Name { get; set; } public string Name { get; set; }
public Vector3 LocalRotation { get; set; } public Vector3 LocalRotation { get; set; }
@ -47,20 +47,82 @@ namespace AssetStudio
children.Remove(frame); children.Remove(frame);
} }
public IEnumerator<ImportedFrame> GetEnumerator() public ImportedFrame FindFrameByPath(string path)
{ {
return children.GetEnumerator(); var splitPath = path.Split('/');
if (Name != splitPath[0])
throw new Exception($"Couldn't find path {path}");
var curFrame = this;
for (int i = 1; i < splitPath.Length; i++)
{
curFrame = curFrame.FindChild(splitPath[i], false);
if (curFrame == null)
{
throw new Exception($"Couldn't find path {path}");
}
}
return curFrame;
} }
IEnumerator IEnumerable.GetEnumerator() public ImportedFrame FindFrame(string name)
{ {
return GetEnumerator(); if (Name == name)
{
return this;
}
foreach (var child in children)
{
var frame = child.FindFrame(name);
if (frame != null)
{
return frame;
}
}
return null;
}
public ImportedFrame FindChild(string name, bool recursive = true)
{
foreach (var child in children)
{
if (recursive)
{
var frame = child.FindFrame(name);
if (frame != null)
{
return frame;
}
}
else
{
if (child.Name == name)
{
return child;
}
}
}
return null;
}
public IEnumerable<ImportedFrame> FindChilds(string name)
{
if (Name == name)
{
yield return this;
}
foreach (var child in children)
{
foreach (var item in child.FindChilds(name))
{
yield return item;
}
}
} }
} }
public class ImportedMesh public class ImportedMesh
{ {
public string Name { get; set; } public string Path { get; set; }
public List<ImportedSubmesh> SubmeshList { get; set; } public List<ImportedSubmesh> SubmeshList { get; set; }
public List<ImportedBone> BoneList { get; set; } public List<ImportedBone> BoneList { get; set; }
} }
@ -94,7 +156,7 @@ namespace AssetStudio
public class ImportedBone public class ImportedBone
{ {
public string Name { get; set; } public string Path { get; set; }
public Matrix Matrix { get; set; } public Matrix Matrix { get; set; }
} }
@ -129,12 +191,12 @@ namespace AssetStudio
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; } public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
public ImportedAnimationKeyframedTrack FindTrack(string name) public ImportedAnimationKeyframedTrack FindTrack(string path)
{ {
var track = TrackList.Find(x => x.Name == name); var track = TrackList.Find(x => x.Path == path);
if (track == null) if (track == null)
{ {
track = new ImportedAnimationKeyframedTrack { Name = name }; track = new ImportedAnimationKeyframedTrack { Path = path };
TrackList.Add(track); TrackList.Add(track);
} }
@ -144,11 +206,10 @@ namespace AssetStudio
public class ImportedAnimationKeyframedTrack public class ImportedAnimationKeyframedTrack
{ {
public string Name { get; set; } public string Path { get; set; }
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>(); public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>(); public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>(); public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
public List<ImportedKeyframe<float>> Curve = new List<ImportedKeyframe<float>>();
} }
public class ImportedKeyframe<T> public class ImportedKeyframe<T>
@ -167,7 +228,7 @@ namespace AssetStudio
public class ImportedMorph public class ImportedMorph
{ {
public string Name { get; set; } public string Path { get; set; }
public string ClipName { get; set; } public string ClipName { get; set; }
public List<Tuple<float, int, int>> Channels { get; set; } public List<Tuple<float, int, int>> Channels { get; set; }
public List<ImportedMorphKeyframe> KeyframeList { get; set; } public List<ImportedMorphKeyframe> KeyframeList { get; set; }
@ -184,45 +245,11 @@ namespace AssetStudio
public static class ImportedHelpers public static class ImportedHelpers
{ {
public static ImportedFrame FindFrame(string name, ImportedFrame root) public static ImportedMesh FindMesh(string path, List<ImportedMesh> importedMeshList)
{
if (root.Name == name)
{
return root;
}
foreach (var child in root)
{
var frame = FindFrame(name, child);
if (frame != null)
{
return frame;
}
}
return null;
}
public static ImportedFrame FindChildOrRoot(string name, ImportedFrame root)
{
foreach (var child in root)
{
var frame = FindFrame(name, child);
if (frame != null)
{
return frame;
}
}
if (root.Name == name)
{
return root;
}
return null;
}
public static ImportedMesh FindMesh(string frameName, List<ImportedMesh> importedMeshList)
{ {
foreach (var mesh in importedMeshList) foreach (var mesh in importedMeshList)
{ {
if (mesh.Name == frameName) if (mesh.Path == path)
{ {
return mesh; return mesh;
} }
@ -243,7 +270,7 @@ namespace AssetStudio
foreach (var mesh in importedMeshList) foreach (var mesh in importedMeshList)
{ {
if (mesh.Name == framePath) if (mesh.Path == framePath)
{ {
return mesh; return mesh;
} }

View File

@ -76,6 +76,7 @@ namespace AssetStudio {
void SetJointsFromImportedMeshes(bool allBones); void SetJointsFromImportedMeshes(bool allBones);
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame); void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals); void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals);
FbxNode* FindNodeByPath(String ^ path, bool recursive);
FbxFileTexture* ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh); FbxFileTexture* ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh);
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween); void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween); void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);

View File

@ -228,9 +228,10 @@ namespace AssetStudio
{ {
for (int i = 0; i < boneList->Count; i++) for (int i = 0; i < boneList->Count; i++)
{ {
if (!exportFrames->Contains(boneList[i]->Name)) String^ boneName = boneList[i]->Path->Substring(boneList[i]->Path->LastIndexOf('/') + 1);
if (!exportFrames->Contains(boneName))
{ {
ImportedFrame^ boneParent = ImportedHelpers::FindChildOrRoot(boneList[i]->Name, imported->RootFrame); ImportedFrame^ boneParent = imported->RootFrame->FindFrameByPath(boneList[i]->Path);
while (boneParent != nullptr) while (boneParent != nullptr)
{ {
exportFrames->Add(boneParent->Name); exportFrames->Add(boneParent->Name);
@ -263,7 +264,7 @@ namespace AssetStudio
for (int j = 0; j < boneList->Count; j++) for (int j = 0; j < boneList->Count; j++)
{ {
ImportedBone^ bone = boneList[j]; ImportedBone^ bone = boneList[j];
boneNames->Add(bone->Name); boneNames->Add(bone->Path);
} }
} }
} }
@ -307,8 +308,8 @@ namespace AssetStudio
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals) void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList, bool normals)
{ {
int lastSlash = meshList->Name->LastIndexOf('/'); int lastSlash = meshList->Path->LastIndexOf('/');
String^ frameName = lastSlash < 0 ? meshList->Name : meshList->Name->Substring(lastSlash + 1); String^ frameName = lastSlash < 0 ? meshList->Path : meshList->Path->Substring(lastSlash + 1);
List<ImportedBone^>^ boneList = meshList->BoneList; List<ImportedBone^>^ boneList = meshList->BoneList;
bool hasBones; bool hasBones;
if (exportSkins && boneList != nullptr) if (exportSkins && boneList != nullptr)
@ -330,22 +331,8 @@ namespace AssetStudio
for (int i = 0; i < boneList->Count; i++) for (int i = 0; i < boneList->Count; i++)
{ {
ImportedBone^ bone = boneList[i]; ImportedBone^ bone = boneList[i];
String^ boneName = bone->Name; FbxNode* lFrame = FindNodeByPath(bone->Path, false);
char* pBoneName = NULL; pBoneNodeList->Add(lFrame);
try
{
pBoneName = StringToCharArray(boneName);
FbxNode* foundNode = pScene->GetRootNode()->FindChild(pBoneName);
if (foundNode == NULL)
{
throw gcnew Exception(gcnew String("Couldn't find frame ") + boneName + gcnew String(" used by the bone"));
}
pBoneNodeList->Add(foundNode);
}
finally
{
Marshal::FreeHGlobal((IntPtr)pBoneName);
}
} }
} }
@ -628,6 +615,41 @@ namespace AssetStudio
} }
} }
FbxNode* Fbx::Exporter::FindNodeByPath(String ^ path, bool recursive)
{
array<String^>^ splitPath = path->Split('/');
FbxNode* lNode = pScene->GetRootNode();
for (int i = 0; i < splitPath->Length; i++)
{
String^ frameName = splitPath[i];
char* pNodeName = NULL;
try
{
pNodeName = StringToCharArray(frameName);
FbxNode* foundNode;
if (recursive && i == 0)
{
foundNode = lNode->FindChild(pNodeName);
}
else
{
foundNode = lNode->FindChild(pNodeName, false);
}
if (foundNode == NULL)
{
//throw gcnew Exception(gcnew String("Couldn't find path ") + path);
return NULL;
}
lNode = foundNode;
}
finally
{
Marshal::FreeHGlobal((IntPtr)pNodeName);
}
}
return lNode;
}
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh) FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex, FbxMesh* pMesh)
{ {
FbxFileTexture* pTex = NULL; FbxFileTexture* pTex = NULL;
@ -749,25 +771,8 @@ namespace AssetStudio
for (int j = 0; j < pAnimationList->Count; j++) for (int j = 0; j < pAnimationList->Count; j++)
{ {
ImportedAnimationKeyframedTrack^ keyframeList = pAnimationList[j]; ImportedAnimationKeyframedTrack^ keyframeList = pAnimationList[j];
String^ name = keyframeList->Name; FbxNode* pNode = FindNodeByPath(keyframeList->Path, true);
int dotPos = name->IndexOf('.'); if (pNode != nullptr)
if (dotPos >= 0 && !ImportedHelpers::FindChildOrRoot(name, imported->RootFrame))
{
name = name->Substring(0, dotPos);
}
FbxNode* pNode = NULL;
char* pName = NULL;
try
{
pName = StringToCharArray(name);
pNode = pScene->GetRootNode()->FindChild(pName);
}
finally
{
Marshal::FreeHGlobal((IntPtr)pName);
}
if (pNode != NULL)
{ {
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true); FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true); FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
@ -836,99 +841,6 @@ namespace AssetStudio
eulerFilter->SetQualityTolerance(filterPrecision); eulerFilter->SetQualityTolerance(filterPrecision);
eulerFilter->Apply(lCurve, 3); eulerFilter->Apply(lCurve, 3);
} }
if (keyframeList->Curve->Count > 0)
{
FbxNode* pMeshNode = pNode->GetChild(0);
FbxMesh* pMesh = pMeshNode ? pMeshNode->GetMesh() : NULL;
if (pMesh)
{
name = keyframeList->Name->Substring(dotPos + 1);
int numBlendShapes = pMesh->GetDeformerCount(FbxDeformer::eBlendShape);
for (int bsIdx = 0; bsIdx < numBlendShapes; bsIdx++)
{
FbxBlendShape* lBlendShape = (FbxBlendShape*)pMesh->GetDeformer(bsIdx, FbxDeformer::eBlendShape);
int numChannels = lBlendShape->GetBlendShapeChannelCount();
float flatMinStrength = 0, flatMaxStrength;
String^ shapeName = nullptr;
for (int chnIdx = 0; chnIdx < numChannels; chnIdx++)
{
FbxBlendShapeChannel* lChannel = lBlendShape->GetBlendShapeChannel(chnIdx);
String^ keyframeName;
if (!flatInbetween)
{
keyframeName = gcnew String(lChannel->GetName());
}
else
{
shapeName = gcnew String(lChannel->GetTargetShape(0)->GetName());
keyframeName = shapeName->Substring(0, shapeName->LastIndexOf("_"));
}
if (keyframeName == name)
{
FbxAnimCurve* lCurve = lChannel->DeformPercent.GetCurve(lAnimLayer, true);
if (flatInbetween)
{
FbxProperty weightProp;
WITH_MARSHALLED_STRING
(
weightName,
shapeName + ".Weight",
weightProp = pMesh->FindProperty(weightName);
);
if (weightProp.IsValid())
{
flatMaxStrength = (float)weightProp.Get<double>();
}
else
{
flatMaxStrength = 100;
}
}
lCurve->KeyModifyBegin();
for each (auto Curve in keyframeList->Curve)
{
lTime.SetSecondDouble(Curve->time);
auto keySetIndex = lCurve->KeyAdd(lTime);
if (!flatInbetween)
{
lCurve->KeySet(keySetIndex, lTime, Curve->value);
}
else
{
float val = Curve->value;
if (val >= flatMinStrength && val <= flatMaxStrength)
{
val = (val - flatMinStrength) * 100 / (flatMaxStrength - flatMinStrength);
}
else if (val < flatMinStrength)
{
val = 0;
}
else if (val > flatMaxStrength)
{
val = 100;
}
lCurve->KeySet(keySetIndex, lTime, val);
}
}
lCurve->KeyModifyEnd();
if (!flatInbetween)
{
bsIdx = numBlendShapes;
break;
}
else
{
flatMinStrength = flatMaxStrength;
}
}
}
}
}
}
} }
} }
} }
@ -953,7 +865,7 @@ namespace AssetStudio
{ {
framePath = gcnew String(rootNode->GetName()) + "/" + framePath; framePath = gcnew String(rootNode->GetName()) + "/" + framePath;
} }
if (framePath == meshList->Name) if (framePath == meshList->Path)
{ {
pBaseNode = pMeshNode; pBaseNode = pMeshNode;
break; break;
@ -966,7 +878,7 @@ namespace AssetStudio
for each (ImportedMorph^ morph in imported->MorphList) for each (ImportedMorph^ morph in imported->MorphList)
{ {
if (morph->Name != meshList->Name) if (morph->Path != meshList->Path)
{ {
continue; continue;
} }

View File

@ -18,10 +18,10 @@ namespace AssetStudio
public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>(); public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>();
private Avatar avatar; private Avatar avatar;
private Dictionary<uint, string> morphChannelInfo = new Dictionary<uint, string>();
private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>(); private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>(); private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>(); private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
private Dictionary<Transform, ImportedFrame> transformDictionary = new Dictionary<Transform, ImportedFrame>();
public ModelConverter(GameObject m_GameObject) public ModelConverter(GameObject m_GameObject)
{ {
@ -183,9 +183,10 @@ namespace AssetStudio
} }
} }
private static ImportedFrame ConvertTransform(Transform trans) private ImportedFrame ConvertTransform(Transform trans)
{ {
var frame = new ImportedFrame(trans.m_Children.Length); var frame = new ImportedFrame(trans.m_Children.Length);
transformDictionary.Add(trans, frame);
trans.m_GameObject.TryGet(out var m_GameObject); trans.m_GameObject.TryGet(out var m_GameObject);
frame.Name = m_GameObject.m_Name; frame.Name = m_GameObject.m_Name;
SetFrame(frame, trans.m_LocalPosition, trans.m_LocalRotation, trans.m_LocalScale); SetFrame(frame, trans.m_LocalPosition, trans.m_LocalRotation, trans.m_LocalScale);
@ -232,7 +233,7 @@ namespace AssetStudio
return; return;
var iMesh = new ImportedMesh(); var iMesh = new ImportedMesh();
meshR.m_GameObject.TryGet(out var m_GameObject2); meshR.m_GameObject.TryGet(out var m_GameObject2);
iMesh.Name = GetMeshPath(m_GameObject2.m_Transform); iMesh.Path = GetTransformPath(m_GameObject2.m_Transform);
iMesh.SubmeshList = new List<ImportedSubmesh>(); iMesh.SubmeshList = new List<ImportedSubmesh>();
var subHashSet = new HashSet<int>(); var subHashSet = new HashSet<int>();
var combine = false; var combine = false;
@ -358,46 +359,37 @@ namespace AssetStudio
iMesh.SubmeshList.Add(iSubmesh); iMesh.SubmeshList.Add(iSubmesh);
} }
//Bone
iMesh.BoneList = new List<ImportedBone>();
if (mesh.m_BindPose?.Length > 0 && mesh.m_BoneNameHashes?.Length > 0 && mesh.m_BindPose.Length == mesh.m_BoneNameHashes.Length)
{
for (int i = 0; i < mesh.m_BindPose.Length; i++)
{
var bone = new ImportedBone();
var boneHash = mesh.m_BoneNameHashes[i];
bone.Name = GetNameFromBonePathHashes(boneHash);
if (string.IsNullOrEmpty(bone.Name))
{
bone.Name = avatar?.FindBoneName(boneHash);
}
if (string.IsNullOrEmpty(bone.Name))
{
//throw new Exception("A Bone could neither be found by hash in Avatar nor by index in SkinnedMeshRenderer.");
continue;
}
var convert = Matrix.Scaling(new Vector3(-1, 1, 1));
bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert;
iMesh.BoneList.Add(bone);
}
}
if (meshR is SkinnedMeshRenderer sMesh) if (meshR is SkinnedMeshRenderer sMesh)
{ {
//Bone for 4.3 down and other //Bone
if (iMesh.BoneList.Count == 0) if (sMesh.m_Bones.Length > 0)
{ {
iMesh.BoneList = new List<ImportedBone>(sMesh.m_Bones.Length);
for (int i = 0; i < sMesh.m_Bones.Length; i++) for (int i = 0; i < sMesh.m_Bones.Length; i++)
{ {
var bone = new ImportedBone(); var bone = new ImportedBone();
if (sMesh.m_Bones[i].TryGet(out var m_Transform)) if (sMesh.m_Bones[i].TryGet(out var m_Transform))
{ {
if (m_Transform.m_GameObject.TryGet(out var m_GameObject)) bone.Path = GetTransformPath(m_Transform);
}
if (!string.IsNullOrEmpty(bone.Path))
{ {
bone.Name = m_GameObject.m_Name; var convert = Matrix.Scaling(new Vector3(-1, 1, 1));
bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert;
iMesh.BoneList.Add(bone);
} }
} }
if (!string.IsNullOrEmpty(bone.Name)) }
else if (mesh.m_BindPose.Length > 0 && mesh.m_BoneNameHashes?.Length > 0 && mesh.m_BindPose.Length == mesh.m_BoneNameHashes.Length)
{
iMesh.BoneList = new List<ImportedBone>(mesh.m_BoneNameHashes.Length);
for (int i = 0; i < mesh.m_BoneNameHashes.Length; i++)
{
var bone = new ImportedBone();
var boneHash = mesh.m_BoneNameHashes[i];
var path = GetPathFromHash(boneHash);
bone.Path = FixBonePath(path);
if (!string.IsNullOrEmpty(bone.Path))
{ {
var convert = Matrix.Scaling(new Vector3(-1, 1, 1)); var convert = Matrix.Scaling(new Vector3(-1, 1, 1));
bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert; bone.Matrix = convert * Matrix.Transpose(mesh.m_BindPose[i]) * convert;
@ -407,12 +399,8 @@ namespace AssetStudio
} }
//Morphs //Morphs
if (mesh.m_Shapes?.channels != null) if (mesh.m_Shapes?.shapes != null)
{ {
foreach (var channel in mesh.m_Shapes.channels)
{
morphChannelInfo[channel.nameHash] = channel.name;
}
if (mesh.m_Shapes.shapes.Length > 0) if (mesh.m_Shapes.shapes.Length > 0)
{ {
ImportedMorph morph = null; ImportedMorph morph = null;
@ -424,7 +412,7 @@ namespace AssetStudio
{ {
morph = new ImportedMorph(); morph = new ImportedMorph();
MorphList.Add(morph); MorphList.Add(morph);
morph.Name = iMesh.Name; morph.Path = iMesh.Path;
morph.ClipName = group; morph.ClipName = group;
morph.Channels = new List<Tuple<float, int, int>>(mesh.m_Shapes.channels.Length); morph.Channels = new List<Tuple<float, int, int>>(mesh.m_Shapes.channels.Length);
morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Length); morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Length);
@ -470,7 +458,7 @@ namespace AssetStudio
if (combine) if (combine)
{ {
meshR.m_GameObject.TryGet(out var m_GameObject); meshR.m_GameObject.TryGet(out var m_GameObject);
var frame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, RootFrame); var frame = RootFrame.FindChild(m_GameObject.m_Name);
frame.LocalPosition = RootFrame.LocalPosition; frame.LocalPosition = RootFrame.LocalPosition;
frame.LocalRotation = RootFrame.LocalRotation; frame.LocalRotation = RootFrame.LocalRotation;
while (frame.Parent != null) while (frame.Parent != null)
@ -508,26 +496,43 @@ namespace AssetStudio
return null; return null;
} }
private string GetMeshPath(Transform meshTransform) private string GetTransformPath(Transform transform)
{ {
meshTransform.m_GameObject.TryGet(out var m_GameObject); var frame = transformDictionary[transform];
var curFrame = ImportedHelpers.FindChildOrRoot(m_GameObject.m_Name, RootFrame); return GetFramePath(frame);
var path = curFrame.Name;
while (curFrame.Parent != null)
{
curFrame = curFrame.Parent;
path = curFrame.Name + "/" + path;
} }
private static string GetFramePath(ImportedFrame frame)
{
var path = frame.Name;
while (frame.Parent != null)
{
frame = frame.Parent;
path = frame.Name + "/" + path;
}
return path; return path;
} }
private static string GetTransformPath(Transform transform) private string FixBonePath(string path)
{
var name = path.Substring(path.LastIndexOf('/') + 1);
foreach (var frame in RootFrame.FindChilds(name))
{
var fullPath = GetFramePath(frame);
if (fullPath.EndsWith(path))
{
return fullPath;
}
}
return null;
}
private static string GetTransformPathByFather(Transform transform)
{ {
transform.m_GameObject.TryGet(out var m_GameObject); transform.m_GameObject.TryGet(out var m_GameObject);
if (transform.m_Father.TryGet(out var father)) if (transform.m_Father.TryGet(out var father))
{ {
return GetTransformPath(father) + "/" + m_GameObject.m_Name; return GetTransformPathByFather(father) + "/" + m_GameObject.m_Name;
} }
return m_GameObject.m_Name; return m_GameObject.m_Name;
@ -680,9 +685,7 @@ namespace AssetStudio
{ {
foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves) foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves)
{ {
var path = m_CompressedRotationCurve.m_Path; var track = iAnim.FindTrack(m_CompressedRotationCurve.m_Path);
var boneName = path.Substring(path.LastIndexOf('/') + 1);
var track = iAnim.FindTrack(boneName);
var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems; var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems;
var data = m_CompressedRotationCurve.m_Times.UnpackInts(); var data = m_CompressedRotationCurve.m_Times.UnpackInts();
@ -704,9 +707,7 @@ namespace AssetStudio
} }
foreach (var m_RotationCurve in animationClip.m_RotationCurves) foreach (var m_RotationCurve in animationClip.m_RotationCurves)
{ {
var path = m_RotationCurve.path; var track = iAnim.FindTrack(m_RotationCurve.path);
var boneName = path.Substring(path.LastIndexOf('/') + 1);
var track = iAnim.FindTrack(boneName);
foreach (var m_Curve in m_RotationCurve.curve.m_Curve) foreach (var m_Curve in m_RotationCurve.curve.m_Curve)
{ {
var value = Fbx.QuaternionToEuler(new Quaternion(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z, m_Curve.value.W)); var value = Fbx.QuaternionToEuler(new Quaternion(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z, m_Curve.value.W));
@ -715,9 +716,7 @@ namespace AssetStudio
} }
foreach (var m_PositionCurve in animationClip.m_PositionCurves) foreach (var m_PositionCurve in animationClip.m_PositionCurves)
{ {
var path = m_PositionCurve.path; var track = iAnim.FindTrack(m_PositionCurve.path);
var boneName = path.Substring(path.LastIndexOf('/') + 1);
var track = iAnim.FindTrack(boneName);
foreach (var m_Curve in m_PositionCurve.curve.m_Curve) foreach (var m_Curve in m_PositionCurve.curve.m_Curve)
{ {
track.Translations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(-m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z))); track.Translations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(-m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
@ -725,9 +724,7 @@ namespace AssetStudio
} }
foreach (var m_ScaleCurve in animationClip.m_ScaleCurves) foreach (var m_ScaleCurve in animationClip.m_ScaleCurves)
{ {
var path = m_ScaleCurve.path; var track = iAnim.FindTrack(m_ScaleCurve.path);
var boneName = path.Substring(path.LastIndexOf('/') + 1);
var track = iAnim.FindTrack(boneName);
foreach (var m_Curve in m_ScaleCurve.curve.m_Curve) foreach (var m_Curve in m_ScaleCurve.curve.m_Curve)
{ {
track.Scalings.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z))); track.Scalings.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
@ -737,25 +734,21 @@ namespace AssetStudio
{ {
foreach (var m_EulerCurve in animationClip.m_EulerCurves) foreach (var m_EulerCurve in animationClip.m_EulerCurves)
{ {
var path = m_EulerCurve.path; var track = iAnim.FindTrack(m_EulerCurve.path);
var boneName = path.Substring(path.LastIndexOf('/') + 1);
var track = iAnim.FindTrack(boneName);
foreach (var m_Curve in m_EulerCurve.curve.m_Curve) foreach (var m_Curve in m_EulerCurve.curve.m_Curve)
{ {
track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z))); track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z)));
} }
} }
} }
foreach (var m_FloatCurve in animationClip.m_FloatCurves) /*foreach (var m_FloatCurve in animationClip.m_FloatCurves)
{ {
var path = m_FloatCurve.path; var track = iAnim.FindTrack(m_FloatCurve.path);
var boneName = path.Substring(path.LastIndexOf('/') + 1);
var track = iAnim.FindTrack(boneName);
foreach (var m_Curve in m_FloatCurve.curve.m_Curve) foreach (var m_Curve in m_FloatCurve.curve.m_Curve)
{ {
track.Curve.Add(new ImportedKeyframe<float>(m_Curve.time, m_Curve.value)); track.Curve.Add(new ImportedKeyframe<float>(m_Curve.time, m_Curve.value));
} }
} }*/
} }
else else
{ {
@ -810,8 +803,8 @@ namespace AssetStudio
curveIndex++; curveIndex++;
return; return;
} }
var boneName = GetNameFromHashes(binding.path, binding.attribute);
var track = iAnim.FindTrack(boneName); var track = iAnim.FindTrack(GetPathFromHash(binding.path));
switch (binding.attribute) switch (binding.attribute)
{ {
@ -850,37 +843,23 @@ namespace AssetStudio
))); )));
break; break;
default: default:
track.Curve.Add(new ImportedKeyframe<float>(time, data[curveIndex++])); //track.Curve.Add(new ImportedKeyframe<float>(time, data[curveIndex++]));
curveIndex++;
break; break;
} }
} }
private string GetNameFromHashes(uint path, uint attribute) private string GetPathFromHash(uint hash)
{ {
var boneName = GetNameFromBonePathHashes(path); bonePathHash.TryGetValue(hash, out var boneName);
if (string.IsNullOrEmpty(boneName)) if (string.IsNullOrEmpty(boneName))
{ {
boneName = avatar?.FindBoneName(path); boneName = avatar?.FindBonePath(hash);
} }
if (string.IsNullOrEmpty(boneName)) if (string.IsNullOrEmpty(boneName))
{ {
boneName = "unknown " + path; boneName = "unknown " + hash;
} }
if (attribute > 4)
{
if (morphChannelInfo.TryGetValue(attribute, out var morphChannel))
{
return boneName + "." + morphChannel;
}
return boneName + ".unknown_morphChannel " + attribute;
}
return boneName;
}
private string GetNameFromBonePathHashes(uint path)
{
if (bonePathHash.TryGetValue(path, out var boneName))
boneName = boneName.Substring(boneName.LastIndexOf('/') + 1);
return boneName; return boneName;
} }
@ -922,7 +901,7 @@ namespace AssetStudio
private void CreateBonePathHash(Transform m_Transform) private void CreateBonePathHash(Transform m_Transform)
{ {
var name = GetTransformPath(m_Transform); var name = GetTransformPathByFather(m_Transform);
var crc = new SevenZip.CRC(); var crc = new SevenZip.CRC();
var bytes = Encoding.UTF8.GetBytes(name); var bytes = Encoding.UTF8.GetBytes(name);
crc.Update(bytes, 0, (uint)bytes.Length); crc.Update(bytes, 0, (uint)bytes.Length);
@ -971,13 +950,13 @@ namespace AssetStudio
{ {
transformName = strs.Last(); transformName = strs.Last();
var parentFrameName = strs[strs.Length - 2]; var parentFrameName = strs[strs.Length - 2];
parentFrame = ImportedHelpers.FindChildOrRoot(parentFrameName, RootFrame); parentFrame = RootFrame.FindChild(parentFrameName);
} }
var skeletonPose = avatar.m_Avatar.m_DefaultPose; var skeletonPose = avatar.m_Avatar.m_DefaultPose;
var xform = skeletonPose.m_X[i]; var xform = skeletonPose.m_X[i];
var frame = ImportedHelpers.FindChildOrRoot(transformName, RootFrame); var frame = RootFrame.FindChild(transformName);
if (frame != null) if (frame != null)
{ {
SetFrame(frame, xform.t, xform.q, xform.s); SetFrame(frame, xform.t, xform.q, xform.s);