public static void RebuildFigaTree(string path, string outpath) { HSDRawFile file = new HSDRawFile(path); var oldTree = file.Roots[0].Data as HSD_FigaTree; HSDRawFile newFile = new HSDRawFile(); HSD_FigaTree newTree = new HSD_FigaTree(); newTree.FrameCount = oldTree.FrameCount; newFile.Roots = new List <HSDRootNode>(); newFile.Roots.Add(new HSDRootNode() { Name = file.Roots[0].Name, Data = newTree }); var newtracks = new List <FigaTreeNode>(); foreach (var tracks in oldTree.Nodes) { var newt = new List <HSD_Track>(); foreach (var track in tracks.Tracks) { HSD_Track newtrack = new HSD_Track(); newtrack.FOBJ = FOBJFrameEncoder.EncodeFrames(track.GetKeys(), track.FOBJ.JointTrackType); newt.Add(newtrack); } newtracks.Add(new FigaTreeNode() { Tracks = newt }); } newTree.Nodes = newtracks; newFile.Save(outpath); }
/// <summary> /// /// </summary> /// <returns></returns> public HSD_FigaTree ToFigaTree() { List <FigaTreeNode> nodes = new List <FigaTreeNode>(); foreach (var v in jobjToTrack) { FigaTreeNode node = new FigaTreeNode(); CreateTrack(node, JointTrackType.HSD_A_J_TRAX, v.Value.X.Keys, v.Key.TX); CreateTrack(node, JointTrackType.HSD_A_J_TRAY, v.Value.Y.Keys, v.Key.TY); CreateTrack(node, JointTrackType.HSD_A_J_TRAZ, v.Value.Z.Keys, v.Key.TZ); CreateTrack(node, JointTrackType.HSD_A_J_ROTX, v.Value.RX.Keys, v.Key.RX); CreateTrack(node, JointTrackType.HSD_A_J_ROTY, v.Value.RY.Keys, v.Key.RY); CreateTrack(node, JointTrackType.HSD_A_J_ROTZ, v.Value.RZ.Keys, v.Key.RZ); CreateTrack(node, JointTrackType.HSD_A_J_SCAX, v.Value.SX.Keys, v.Key.SX); CreateTrack(node, JointTrackType.HSD_A_J_SCAY, v.Value.SY.Keys, v.Key.SY); CreateTrack(node, JointTrackType.HSD_A_J_SCAZ, v.Value.SZ.Keys, v.Key.SZ); nodes.Add(node); } HSD_FigaTree tree = new HSD_FigaTree(); tree.Type = 1; tree.FrameCount = FrameCount; tree.Nodes = nodes; return(tree); }
/// <summary> /// /// </summary> /// <param name="figatree"></param> /// <param name="jobjFrom"></param> /// <param name="jobjTo"></param> /// <param name="bmFrom"></param> /// <param name="bmTo"></param> /// <returns></returns> public static HSD_FigaTree Port(HSD_FigaTree figatree, HSD_JOBJ jobjFrom, HSD_JOBJ jobjTo, BoneMap bmFrom, BoneMap bmTo) { AnimationPlayer sourceAnim = new AnimationPlayer(jobjFrom, figatree); AnimationPlayer targetAnim = new AnimationPlayer(jobjTo, figatree.FrameCount); int jobjIndex = 0; foreach (var to in jobjTo.BreathFirstList) { var name = bmTo.GetName(jobjIndex); var index = bmFrom.GetIndex(name); FigaTreeNode node = new FigaTreeNode(); if (index != -1) { var jfrom = jobjFrom.BreathFirstList[index]; if (targetAnim.PortBoneTo(to, sourceAnim, jfrom)) { Debug.WriteLine($"Retargeting {name}"); } } jobjIndex++; } return(targetAnim.ToFigaTree());; }
/// <summary> /// /// </summary> /// <param name="jobj"></param> /// <param name="figatree"></param> public AnimationPlayer(HSD_JOBJ jobj, HSD_FigaTree figatree) { FrameCount = (int)figatree.FrameCount; int jobjIndex = 0; foreach (var j in jobj.BreathFirstList) { TrackNode t = new TrackNode(j); var node = figatree.Nodes[jobjIndex]; foreach (var track in node.Tracks) { var fobj = track.ToFOBJ(); switch (fobj.JointTrackType) { case JointTrackType.HSD_A_J_TRAX: t.X.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_TRAY: t.Y.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_TRAZ: t.Z.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_ROTX: t.RX.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_ROTY: t.RY.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_ROTZ: t.RZ.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_SCAX: t.SX.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_SCAY: t.SY.Keys = fobj.GetDecodedKeys(); break; case JointTrackType.HSD_A_J_SCAZ: t.SZ.Keys = fobj.GetDecodedKeys(); break; } } jobjToTrack.Add(j, t); jobjIndex++; } LoadParents(jobj); }
/// <summary> /// /// </summary> /// <param name="tree"></param> /// <returns></returns> public void FromFigaTree(HSD_FigaTree tree) { if (tree == null) { return; } FrameCount = tree.FrameCount; Nodes = new List <AnimNode>(); foreach (var tracks in tree.Nodes) { AnimNode n = new AnimNode(); foreach (HSD_Track t in tracks.Tracks) { n.Tracks.Add(new FOBJ_Player(t.TrackType, t.GetKeys())); } Nodes.Add(n); } }
/// <summary> /// /// </summary> public void SetFigaTree(HSD_FigaTree tree) { Nodes.Clear(); if (tree == null) { return; } foreach (var tracks in tree.Nodes) { AnimNode n = new AnimNode(); foreach (HSD_Track t in tracks.Tracks) { AnimTrack track = new AnimTrack(); track.TrackType = t.FOBJ.AnimationType; track.Keys = t.GetKeys(); n.Tracks.Add(track); } Nodes.Add(n); } }
/// <summary> /// /// </summary> /// <param name="nodes"></param> /// <param name="frameCount"></param> /// <returns></returns> public HSD_FigaTree ToFigaTree(float error = 0.0001f) { HSD_FigaTree tree = new HSD_FigaTree(); tree.FrameCount = FrameCount; tree.Type = 1; tree.Nodes = Nodes.Select(e => { var fn = new FigaTreeNode(); foreach (var t in e.Tracks) { HSD_Track track = new HSD_Track(); HSD_FOBJ fobj = t.ToFobj(error); track.FromFOBJ(fobj); fn.Tracks.Add(track); } return(fn); }).ToList(); return(tree); }
/// <summary> /// /// </summary> /// <param name="nodes"></param> /// <param name="frameCount"></param> /// <returns></returns> public HSD_FigaTree ToFigaTree() { HSD_FigaTree tree = new HSD_FigaTree(); tree.FrameCount = FrameCount; tree.Type = 1; tree.Nodes = Nodes.Select(e => { var fn = new FigaTreeNode(); foreach (var t in e.Tracks) { HSD_Track track = new HSD_Track(); HSD_FOBJ fobj = new HSD_FOBJ(); fobj.SetKeys(t.Keys, t.JointTrackType); track.FOBJ = fobj; fn.Tracks.Add(track); } return(fn); }).ToList(); return(tree); }
public static HSD_FigaTree RemapFigatree(RemapSettings settings, HSD_FigaTree from, int newBoneCount, JointMap mapFrom, JointMap mapTo) { var sourceNodes = from.Nodes; var targetNodes = new List <FigaTreeNode>(); for (int i = 0; i < newBoneCount; i++) { FigaTreeNode node = new FigaTreeNode(); targetNodes.Add(node); var remapIndex = mapFrom.IndexOf(mapTo[i]); if (remapIndex != -1) { // port tracks node.Tracks.AddRange(sourceNodes[remapIndex].Tracks); if (settings.IgnoreTranslation) { node.Tracks.RemoveAll( e => e.JointTrackType == JointTrackType.HSD_A_J_TRAX || e.JointTrackType == JointTrackType.HSD_A_J_TRAY || e.JointTrackType == JointTrackType.HSD_A_J_TRAZ); } } } var newft = new HSD_FigaTree(); newft.Type = 1; newft.FrameCount = from.FrameCount; newft.Nodes = targetNodes; return(newft); }
/// <summary> /// /// </summary> public JointAnimManager(HSD_FigaTree tree) { FromFigaTree(tree); }
/// <summary> /// /// </summary> /// <param name="filePath"></param> public static HSD_FigaTree ImportFromMayaAnim(string filePath, BoneMap jointMap) { var mayaFile = new MayaAnim(); mayaFile.Open(filePath); HSD_FigaTree animation = new HSD_FigaTree(); animation.FrameCount = mayaFile.header.endTime - mayaFile.header.startTime; List <FigaTreeNode> nodes = new List <FigaTreeNode>(); var nodeCount = jointMap == null || jointMap.Count == 0 ? mayaFile.Nodes.Count : Math.Max(mayaFile.Nodes.Count, jointMap.Count); for (int i = 0; i < nodeCount; i++) { nodes.Add(new FigaTreeNode()); } // process and encode FOBJ keys int index = 0; foreach (var mNode in mayaFile.Nodes) { var node = animation.Nodes[index++]; //Debug.WriteLine(mNode.name); if (jointMap != null) { var nodeIndex = jointMap.GetIndex(mNode.name); if (nodeIndex != -1) { node = animation.Nodes[nodeIndex]; } } foreach (var mTrack in mNode.atts) { FOBJ_Player t = new FOBJ_Player(); t.Keys = new List <FOBJKey>(); t.JointTrackType = jointTrackToMayaTrack.FirstOrDefault(e => e.Value == mTrack.type).Key; //Debug.WriteLine("\t" + mTrack.type); var degrees = mayaFile.header.angularUnit == "deg"; var trackUnit = (mTrack.IsAngular() && degrees); for (int i = 0; i < mTrack.keys.Count; i++) { var mKey = mTrack.keys[i]; var mKeyNext = i + 1 < mTrack.keys.Count ? mTrack.keys[i + 1] : mTrack.keys[i]; var k = new FOBJKey(); k.Frame = mKey.input - mayaFile.header.startTime; k.Value = trackUnit ? (float)(mKey.output * Math.PI / 180) : mKey.output; switch (mKey.outtan) { case "auto": case "linear": k.InterpolationType = GXInterpolationType.HSD_A_OP_LIN; t.Keys.Add(k); break; case "step": if (mTrack.keys.Count == 1) { k.InterpolationType = GXInterpolationType.HSD_A_OP_KEY; } else { k.InterpolationType = GXInterpolationType.HSD_A_OP_CON; } t.Keys.Add(k); break; case "fixed": case "spline": k.InterpolationType = GXInterpolationType.HSD_A_OP_SPL; k.Tan = AngleToTan(mKey.t1, degrees); if ((mKeyNext.input - mKey.input) <= 1) // optimization { //k.InterpolationType = GXInterpolationType.HSD_A_OP_LIN; t.Keys.Add(k); } else if (mKey.t2 == 0) { k.InterpolationType = GXInterpolationType.HSD_A_OP_SPL0; t.Keys.Add(k); } else if (mKey.t1 != mKey.t2) { t.Keys.Add(k); var slp = new FOBJKey(); slp.Frame = mKeyNext.input - 1; slp.InterpolationType = GXInterpolationType.HSD_A_OP_SLP; slp.Tan = AngleToTan(mKey.t2, degrees); t.Keys.Add(slp); } else { t.Keys.Add(k); } break; default: Console.WriteLine(mKey.outtan + " not supported!"); break; } if (mTrack.keys.Count == 1) { k.InterpolationType = GXInterpolationType.HSD_A_OP_KEY; } //foreach (var key in t.Keys) // Debug.WriteLine($"\t\t{key.Frame} {key.Value}"); } var track = new HSD_Track(); track.FromFOBJ(t.ToFobj()); node.Tracks.Add(track); } } animation.Nodes = nodes; animation.Type = 1; return(animation); }
/// <summary> /// Opens dat file from stream /// </summary> /// <param name="stream"></param> public void Open(Stream stream) { using (BinaryReaderExt r = new BinaryReaderExt(stream)) { r.BigEndian = true; // Parse Header ----------------------------- var fsize = r.ReadInt32(); // dat size int relocOffset = r.ReadInt32() + 0x20; int relocCount = r.ReadInt32(); int rootCount = r.ReadInt32(); int refCount = r.ReadInt32(); VersionChars = r.ReadChars(4); // Parse Relocation Table ----------------------------- List <int> Offsets = new List <int>(); HashSet <int> OffsetContain = new HashSet <int>(); Dictionary <int, int> relocOffsets = new Dictionary <int, int>(); Offsets.Add(relocOffset); r.BaseStream.Position = relocOffset; for (int i = 0; i < relocCount; i++) { int offset = r.ReadInt32() + 0x20; var temp = r.BaseStream.Position; r.BaseStream.Position = offset; var objectOff = r.ReadInt32() + 0x20; // if we need to read past end of file then we need to include filesize as an offset // this fixes files that had previously been manually relocated to end of file if (objectOff > relocOffset && !Offsets.Contains(fsize)) { Offsets.Add(fsize); } // if (objectOff < 0) { r.BaseStream.Position = temp; continue; } relocOffsets.Add(offset, objectOff); if (!OffsetContain.Contains(objectOff)) { OffsetContain.Add(objectOff); Offsets.Add(objectOff); } r.BaseStream.Position = temp; } // Parse Roots--------------------------------- List <int> rootOffsets = new List <int>(); List <string> rootStrings = new List <string>(); List <int> refOffsets = new List <int>(); List <string> refStrings = new List <string>(); var stringStart = r.BaseStream.Position + (refCount + rootCount) * 8; for (int i = 0; i < rootCount; i++) { rootOffsets.Add(r.ReadInt32() + 0x20); rootStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1)); } for (int i = 0; i < refCount; i++) { var refp = r.ReadInt32() + 0x20; refOffsets.Add(refp); refStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1)); var temp = r.Position; var special = refp; while (true) { r.Seek((uint)special); special = r.ReadInt32(); if (special == 0 || special == -1) { break; } special += 0x20; relocOffsets.Add(refp, special); refp = special; if (!OffsetContain.Contains(special)) { OffsetContain.Add(special); Offsets.Add(special); } } r.Seek(temp); } foreach (var v in rootOffsets) { if (!OffsetContain.Contains(v)) { OffsetContain.Add(v); Offsets.Add(v); } } foreach (var v in refOffsets) { if (!OffsetContain.Contains(v)) { OffsetContain.Add(v); Offsets.Add(v); } } // Split Raw Struct Data-------------------------- Offsets.Sort(); Dictionary <int, HSDStruct> offsetToStruct = new Dictionary <int, HSDStruct>(); Dictionary <int, List <int> > offsetToOffsets = new Dictionary <int, List <int> >(); Dictionary <int, List <int> > offsetToInnerOffsets = new Dictionary <int, List <int> >(); var relockeys = relocOffsets.Keys.ToList(); for (int i = 0; i < Offsets.Count - 1; i++) { r.BaseStream.Position = Offsets[i]; byte[] data = r.ReadBytes(Offsets[i + 1] - Offsets[i]); if (!offsetToOffsets.ContainsKey(Offsets[i])) { var relocKets = relockeys.FindAll(e => e >= Offsets[i] && e < Offsets[i + 1]); var list = new List <int>(); foreach (var k in relocKets) { list.Add(relocOffsets[k]); } offsetToOffsets.Add(Offsets[i], list); offsetToInnerOffsets.Add(Offsets[i], relocKets); } if (!offsetToStruct.ContainsKey(Offsets[i])) { var struture = new HSDStruct(data); offsetToStruct.Add(Offsets[i], struture); } } // set references------------------------- foreach (var str in offsetToStruct) { var offsets = offsetToOffsets[str.Key]; var innerOffsets = offsetToInnerOffsets[str.Key]; for (int i = 0; i < offsets.Count; i++) { if (offsetToStruct.ContainsKey(offsets[i]) && str.Value.Length >= innerOffsets[i] - str.Key + 4) { str.Value.SetReferenceStruct(innerOffsets[i] - str.Key, offsetToStruct[offsets[i]]); } } _structCache.Add(str.Value); _structCacheToOffset.Add(str.Value, str.Key); } // set roots for (int i = 0; i < rootOffsets.Count; i++) { HSDStruct str = offsetToStruct[rootOffsets[i]]; HSDAccessor a = new HSDAccessor(); a._s = str; if (rootStrings[i].EndsWith("shapeanim_joint")) { var acc = new HSDAccessor(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("matanim_joint")) { var acc = new HSD_MatAnimJoint(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("_joint")) { var jobj = new HSD_JOBJ(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_animjoint")) { var jobj = new HSD_AnimJoint(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_texanim")) { var jobj = new HSD_TexAnim(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_figatree")) { var jobj = new HSD_FigaTree(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_scene_models") || rootStrings[i].Equals("Stc_rarwmdls") || rootStrings[i].Equals("Stc_scemdls") || rootStrings[i].Equals("lupe") || rootStrings[i].Equals("tdsce")) { var jobj = new HSDNullPointerArrayAccessor <HSD_JOBJDesc>(); jobj._s = str; a = jobj; } else if (rootStrings[i].StartsWith("ftData")) { var acc = new SBM_PlayerData(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("MnSelectChrDataTable")) { var acc = new SBM_SelectChrDataTable(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("MnSelectStageDataTable")) { var acc = new SBM_MnSelectStageDataTable(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("coll_data")) { var acc = new SBM_Coll_Data(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("scene_data") || rootStrings[i].Equals("pnlsce") || rootStrings[i].Equals("flmsce") || (rootStrings[i].StartsWith("Sc") && str.Length == 0x10)) { var acc = new HSD_SOBJ(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("map_plit")) { var acc = new HSDNullPointerArrayAccessor <HSD_Light>(); acc._s = str; a = acc; } /*else * if (rootStrings[i].StartsWith("grGroundParam")) * { * var acc = new SBM_GroundParam(); * acc._s = str; * a = acc; * }*/ else if (rootStrings[i].StartsWith("map_head")) { var acc = new SBM_Map_Head(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grGroundParam")) { var acc = new SBM_GroundParam(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("vcDataStar")) { var acc = new KAR_vcDataStar(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("vcDataWheel")) { var acc = new KAR_vcDataWheel(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grModelMotion")) { var acc = new KAR_grModelMotion(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grModel")) { var acc = new KAR_grModel(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grData")) { var acc = new KAR_grData(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("_texg")) { var acc = new HSD_TEXGraphicBank(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("_ptcl")) { var acc = new HSD_ParticleGroup(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("eff")) { var acc = new SBM_EffectTable(); acc._s = str; a = acc; } Roots.Add(new HSDRootNode() { Name = rootStrings[i], Data = a }); } // set references for (int i = 0; i < refOffsets.Count; i++) { HSDStruct str = offsetToStruct[refOffsets[i]]; HSDAccessor a = new HSDAccessor(); a._s = str; References.Add(new HSDRootNode() { Name = refStrings[i], Data = a }); } } }
public bool DoIt(string[] args) { if (args.Length >= 3) { // parse args var plxxfile = Path.GetFullPath(args[1]); var plxxajfile = Path.GetFullPath(args[2]); var plxxnrfile = Path.GetFullPath(args[3]); var anim_pathfile = Path.GetFullPath(args[4]); var symbol = args[5]; HSD_FigaTree anim_to_inject = null; // rendering files not loaded if (string.IsNullOrEmpty(plxxfile) || string.IsNullOrEmpty(plxxajfile) || string.IsNullOrEmpty(anim_pathfile)) { return(false); } // check if anim is maya anim if (Path.GetExtension(anim_pathfile).ToLower().Contains("anim")) { // todo: joint map anim_to_inject = Tools.ConvMayaAnim.ImportFromMayaAnim(anim_pathfile, null); // optimize var nodes = anim_to_inject.Nodes; var joints = (new HSDRawFile(plxxnrfile).Roots[0].Data as HSD_JOBJ).BreathFirstList; int nodeIndex = 0; foreach (var n in nodes) { var joint = joints[nodeIndex]; var tracks = n.Tracks.Select(e => new FOBJ_Player(e.ToFOBJ())).ToList(); AnimationKeyCompressor.OptimizeJointTracks(joint, ref tracks); n.Tracks = tracks.Select(e => { var tr = new HSD_Track(); tr.FromFOBJ(e.ToFobj()); return(tr); }).ToList(); nodeIndex++; } anim_to_inject.Nodes = nodes; } else { // check if anim if figatree try { HSDRawFile f = new HSDRawFile(anim_pathfile); if (f.Roots.Count < 1) { return(false); } if (f.Roots[0].Data is HSD_FigaTree ani) { anim_to_inject = ani; } else { return(false); } } catch { return(false); } } // make sure anim isn't null if (anim_to_inject == null) { return(false); } try { var plxx = new HSDRawFile(plxxfile); FighterAJManager animManager = new FighterAJManager(); animManager.ScanAJFile(plxxajfile); var newAnim = new HSDRawFile(); newAnim.Roots.Add(new HSDRootNode() { Name = symbol, Data = anim_to_inject }); using (MemoryStream stream = new MemoryStream()) { // set new animation newAnim.Save(stream); animManager.SetAnimation(symbol, stream.ToArray()); var ftdata = plxx.Roots[0].Data as SBM_FighterData; var commands = ftdata.FighterActionTable.Commands; var symbols = commands.Select(e => e.SymbolName.Value).ToArray(); var rebuild = animManager.RebuildAJFile(symbols, true); foreach (var c in commands) { if (c.SymbolName != null && !string.IsNullOrEmpty(c.SymbolName.Value)) { var sizeoffset = animManager.GetOffsetSize(c.SymbolName.Value); c.AnimationOffset = sizeoffset.Item1; c.AnimationSize = sizeoffset.Item2; } } // save files plxx.Save(plxxfile); File.WriteAllBytes(plxxajfile, rebuild); } } catch { return(false); } return(true); } return(false); }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> private void ExportFigaTree(string FileName, SBAnimation animation, SBSkeleton skeleton) { HSDRawFile file = new HSDRawFile(); HSDRootNode root = new HSDRootNode(); if (HSDSettings.RootName == "" || HSDSettings.RootName == null) { HSDSettings.RootName = System.IO.Path.GetFileNameWithoutExtension(FileName); } if (HSDSettings.RootName == "" || HSDSettings.RootName == null) { HSDSettings.RootName = animation.Name; } root.Name = HSDSettings.RootName; if (root.Name == null || !root.Name.EndsWith("_figatree")) { System.Windows.Forms.MessageBox.Show($"Warning, the root name does not end with \"_figatree\"\n{root.Name}"); } file.Roots.Add(root); var nodes = new List <FigaTreeNode>(); int boneIndex = -1; foreach (var skelnode in skeleton.Bones) { FigaTreeNode animNode = new FigaTreeNode(); nodes.Add(animNode); boneIndex++; // skip trans n and rotn tracks if (boneIndex == 0) { continue; } var node = animation.TransformNodes.Find(e => e.Name == skelnode.Name); if (node == null) { continue; } foreach (var track in node.Tracks) { HSD_Track animTrack = new HSD_Track(); animTrack.FOBJ = EncodeFOBJ(track); animTrack.DataLength = (short)animTrack.FOBJ.Buffer.Length; animNode.Tracks.Add(animTrack); } } HSD_FigaTree tree = new HSD_FigaTree(); tree.FrameCount = animation.FrameCount; tree.Type = 1; tree.Nodes = nodes; root.Data = tree; file.Save(FileName); }
/// <summary> /// /// </summary> private void LoadFigaTree(string treeSymbol, HSD_FigaTree tree) { // clear animation JointManager.SetFigaTree(null); ThrowDummyManager.SetFigaTree(null); // create new action var name = new Action() { Symbol = treeSymbol }.ToString(); // load figatree to manager and anim editor JointManager.SetFigaTree(tree); _animEditor.SetJoint(JointManager.GetJOBJ(0), JointManager.Animation); // set backup anim BackupAnim = new JointAnimManager(); BackupAnim.FromFigaTree(tree); // set frame viewport.MaxFrame = tree.FrameCount; // enable shield display if (FighterData != null && name.Equals("Guard")) { DisplayShieldSize = FighterData.Attributes.ShieldSize / 2; } // load throw dummy for thrown animations if (name.Contains("Throw") && !name.Contains("Taro")) { // find thrown anim Action throwAction = null; foreach (Action a in actionList.Items) { if (a.Symbol != null && a.Symbol.Contains("Taro") && a.Symbol.Contains(name) && !a.Symbol.Equals(treeSymbol)) { throwAction = a; break; } } // if throw animation is found if (throwAction != null && throwAction.Symbol != null) { var throwData = AJManager.GetAnimationData(throwAction.Symbol); if (throwData != null) { // load throw animation var tanim = new HSDRawFile(throwData); if (tanim.Roots[0].Data is HSD_FigaTree tree2) { ThrowDummyManager.SetFigaTree(tree2); if (ThrowDummyLookupTable.Count > 0) { ThrowDummyManager.Animation.EnableBoneLookup = true; ThrowDummyManager.Animation.BoneLookup = ThrowDummyLookupTable; } } } } } }
/// <summary> /// /// </summary> /// <param name="args"></param> /// <returns></returns> public bool DoIt(string[] args) { if (args.Length >= 6) { // parse args var targetAnimFile = Path.GetFullPath(args[1]); var destAnimFile = Path.GetFullPath(args[2]); var newSymbol = args[3]; var boneIniTarget = Path.GetFullPath(args[4]); var boneInitDest = Path.GetFullPath(args[5]); // load bone inis var target = new BoneMap(boneIniTarget); var dest = new BoneMap(boneInitDest); SkeletonPorter port = null; List <HSD_JOBJ> jobjsFrom = null; List <HSD_JOBJ> jobjsTo = null; if (args.Length >= 8) { jobjsFrom = (new HSDRawFile(args[6]).Roots[0].Data as HSD_JOBJ).BreathFirstList; jobjsTo = (new HSDRawFile(args[7]).Roots[0].Data as HSD_JOBJ).BreathFirstList; port = new SkeletonPorter( new HSDRawFile(args[6]).Roots[0].Data as HSD_JOBJ, new HSDRawFile(args[7]).Roots[0].Data as HSD_JOBJ, target, dest); } // retarget animation HSDRawFile inputAnim = new HSDRawFile(targetAnimFile); var targetTree = inputAnim.Roots[0].Data as HSD_FigaTree; List <FigaTreeNode> newNodes = new List <FigaTreeNode>(); for (int i = 0; i < dest.Count; i++) { newNodes.Add(new FigaTreeNode()); } int nodeIndex = 0; foreach (var n in targetTree.Nodes) { string boneName = ""; boneName = target.GetName(nodeIndex); var ind = dest.GetIndex(boneName); if (ind != -1) { //System.Diagnostics.Debug.WriteLine($"{boneName} {nodeIndex} {ind}"); if (port != null && port.HasBone(boneName)) { var jobj = jobjsFrom[nodeIndex]; FOBJ_Player rx = new FOBJ_Player(); rx.Keys.Add(new FOBJKey() { Value = jobj.RX, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); FOBJ_Player ry = new FOBJ_Player(); ry.Keys.Add(new FOBJKey() { Value = jobj.RY, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); FOBJ_Player rz = new FOBJ_Player(); rz.Keys.Add(new FOBJKey() { Value = jobj.RZ, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); HSD_Track rotXTrack = new HSD_Track(); HSD_Track rotYTrack = new HSD_Track(); HSD_Track rotZTrack = new HSD_Track(); foreach (var track in n.Tracks) { var fobj = track.ToFOBJ(); var keys = fobj.GetDecodedKeys(); switch (fobj.JointTrackType) { case JointTrackType.HSD_A_J_ROTX: rx.Keys = keys; break; case JointTrackType.HSD_A_J_ROTY: ry.Keys = keys; break; case JointTrackType.HSD_A_J_ROTZ: rz.Keys = keys; break; default: //newNodes[ind].Tracks.Add(track); break; } } rotXTrack.FromFOBJ(OrientTrack(boneName, port, rx.Keys, JointTrackType.HSD_A_J_ROTX, jobj, jobjsTo[nodeIndex])); rotYTrack.FromFOBJ(OrientTrack(boneName, port, ry.Keys, JointTrackType.HSD_A_J_ROTY, jobj, jobjsTo[nodeIndex])); rotZTrack.FromFOBJ(OrientTrack(boneName, port, rz.Keys, JointTrackType.HSD_A_J_ROTZ, jobj, jobjsTo[nodeIndex])); newNodes[ind].Tracks.Add(rotXTrack); newNodes[ind].Tracks.Add(rotYTrack); newNodes[ind].Tracks.Add(rotZTrack); foreach (var track in newNodes[ind].Tracks) { //System.Diagnostics.Debug.WriteLine(track.FOBJ.JointTrackType + " " + track.FOBJ.GetDecodedKeys().Count); } } else if (ind < newNodes.Count && ind >= 0) { newNodes[ind] = n; } } nodeIndex++; } // save new file HSD_FigaTree figatree = new HSD_FigaTree(); figatree.FrameCount = targetTree.FrameCount; figatree.Type = targetTree.Type; figatree.Nodes = newNodes; System.Console.WriteLine(destAnimFile); HSDRawFile file = new HSDRawFile(); file.Roots.Add(new HSDRootNode() { Name = newSymbol, Data = figatree }); file.Save(destAnimFile); return(true); } return(false); }