/// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void saveToolStripMenuItem_Click(object sender, EventArgs e) { var f = Tools.FileIO.SaveFile("HSD (*.dat,*.usd)|*.dat;*.usd", System.IO.Path.GetFileName(FilePath), "Save File As"); if (f != null) { RawHSDFile.Save(f); OpenFile(f); } }
/// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void saveToolStripMenuItem_Click(object sender, EventArgs e) { var f = Tools.FileIO.SaveFile("HSD (*.dat,*.usd)|*.dat;*.usd"); if (f != null) { RawHSDFile.Save(f); OpenFile(f); } }
/// <summary> /// /// </summary> public void SetFromFile(string filePath) { try { var figaFile = new HSDRawFile(filePath); if (figaFile.Roots.Count > 0 && figaFile.Roots[0].Data is HSD_FigaTree tree) { if (figaFile.Roots[0].Name.Equals(Name)) { Data = File.ReadAllBytes(filePath); } else { // rename symbol if necessary //if(MessageBox.Show($"The animation symbol does not match./nRename It?\n{Name}\n{figaFile.Roots[0].Name}", "Symbol Mismatch", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { figaFile.Roots[0].Name = Name; using (MemoryStream stream = new MemoryStream()) { figaFile.Save(stream); Data = stream.ToArray(); } } } } } catch { MessageBox.Show("Error replacing animation", "Animation Replace Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// /// </summary> /// <param name="FileName"></param> /// <param name="animation"></param> /// <param name="skeleton"></param> private void ExportAnimJoint(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) { System.Windows.Forms.MessageBox.Show($"Warning, the root name does not end with \"_figatree\"\n{root.Name}"); } file.Roots.Add(root); var joint = new HSD_AnimJoint(); EncodeAnimJoint(skeleton.Bones[0], joint, animation); root.Data = joint; file.Save(FileName); }
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> /// <param name="args"></param> /// <returns></returns> public bool DoIt(string[] args) { if (args.Length >= 6) { // parse args var inputjoint = Path.GetFullPath(args[1]); var inputBoneMap = new BoneMap(Path.GetFullPath(args[2])); var targetjoint = Path.GetFullPath(args[3]); var targetBoneMap = new BoneMap(Path.GetFullPath(args[4])); var inputfigatree = Path.GetFullPath(args[5]); var outputfigatree = Path.GetFullPath(args[6]); // source joint HSDRawFile inputJoint = new HSDRawFile(inputjoint); var sourceJOBJ = inputJoint.Roots[0].Data as HSD_JOBJ; // target joint HSDRawFile targetJoint = new HSDRawFile(targetjoint); var targetJOBJ = targetJoint.Roots[0].Data as HSD_JOBJ; // retarget animation HSDRawFile inputAnim = new HSDRawFile(inputfigatree); var tree = inputAnim.Roots[0].Data as HSD_FigaTree; inputAnim.Roots[0].Data = AnimationBakery.Port(tree, sourceJOBJ, targetJOBJ, inputBoneMap, targetBoneMap); inputAnim.Save(outputfigatree); return(true); } return(false); }
/// <summary> /// /// </summary> public void Save() { if (Loaded) { File.TrimData(); File.Save(FilePath); } }
public static void RemoveImageNodes(string filePath) { HSDRawFile file = new HSDRawFile(filePath); file.Roots.RemoveAll(e => e.Name.EndsWith("_image")); file.Save(filePath + "_noImage"); }
/// <summary> /// Test for rebuilding pobjs from scratch /// </summary> /// <param name="path"></param> public static void RebuildPOBJs(string path) { HSDRawFile file = new HSDRawFile(path); var rootJOBJ = (HSD_JOBJ)(file.Roots[0].Data); file.Save(path + "_rebuilt.dat"); }
public bool DoIt(string[] args) { if (args.Length >= 2) { var mapFile = args[1]; var linkFile = (args.Length >= 3) ? args[2] : null; var map = new MapFile(mapFile); LinkFile link = null; if (linkFile != null) { link = new LinkFile(linkFile); } var debug_symbol_table = new HSDStruct((map.Entries.Count + 1) * 0xC); int symbol_index = 0; foreach (var e in map.Entries) { debug_symbol_table.SetInt32(symbol_index * 0xC, (int)e.Start); debug_symbol_table.SetInt32(symbol_index * 0xC + 4, (int)e.End); if (link != null && link.TryGetAddressSymbol(e.Start, out string sym)) { debug_symbol_table.SetString(symbol_index * 0xC + 8, sym, true); } else if (!e.Symbol.StartsWith("zz_")) { debug_symbol_table.SetString(symbol_index * 0xC + 8, e.Symbol, true); } symbol_index++; } var function = new HSDAccessor() { _s = new HSDStruct(0x10) }; function._s.SetInt32(0, map.Entries.Count); function._s.SetReferenceStruct(0x04, debug_symbol_table); HSDRawFile f = new HSDRawFile(); f.Roots.Add(new HSDRootNode() { Data = function, Name = "mexDebug" }); f.Save("MxDb.dat"); return(true); } return(false); }
/// <summary> /// /// </summary> /// <param name="ftdat"></param> /// <param name="ajdat"></param> /// <param name="editAnim"></param> public static void EditFighterAnimations(string ftdat, string ajdat, EditAnimation editAnim) { FighterAJManager manager = new FighterAJManager(File.ReadAllBytes(ajdat)); foreach (var symbol in manager.GetAnimationSymbols()) { if (symbol.Contains("Taro")) { continue; } var ftFile = new HSDRawFile(manager.GetAnimationData(symbol)); if (ftFile[symbol] != null) { var ft = ftFile[symbol].Data as HSD_FigaTree; editAnim(ft, symbol); ftFile[symbol].Data = ft; using (MemoryStream stream = new MemoryStream()) { ftFile.Save(stream); manager.SetAnimation(symbol, stream.ToArray()); } } } var newAJFile = manager.RebuildAJFile(manager.GetAnimationSymbols().ToArray(), true); HSDRawFile ftfile = new HSDRawFile(ftdat); if (ftfile.Roots[0].Data is SBM_FighterData data) { var sa = data.FighterActionTable.Commands; foreach (var action in sa) { if (action.SymbolName != null && !string.IsNullOrEmpty(action.SymbolName.Value)) { var sizeOffset = manager.GetOffsetSize(action.SymbolName.Value); action.AnimationOffset = sizeOffset.Item1; action.AnimationSize = sizeOffset.Item2; } } data.FighterActionTable.Commands = sa; ftfile.TrimData(); ftfile.Save(ftdat); File.WriteAllBytes(ajdat, newAJFile); } }
/// <summary> /// /// </summary> private void SaveAnimation() { if (actionList.SelectedItem is Action action) { HSDRawFile f = new HSDRawFile(); f.Roots.Add(new HSDRootNode() { Name = action.Symbol, Data = JointManager.Animation.ToFigaTree() }); var tempFileName = Path.GetTempFileName(); f.Save(tempFileName); SymbolToAnimation[action.Symbol] = File.ReadAllBytes(tempFileName); File.Delete(tempFileName); } }
/// <summary> /// /// </summary> /// <param name="args"></param> /// <returns></returns> public bool DoIt(string[] args) { if (args.Length >= 3) { // parse args var targetAnimFile = Path.GetFullPath(args[1]); var destAnimFile = Path.GetFullPath(args[2]); // retarget animation HSDRawFile inputAnim = new HSDRawFile(targetAnimFile); var targetTree = inputAnim.Roots[0].Data as HSD_FigaTree; List <FigaTreeNode> newNodes = targetTree.Nodes; var keydecrease = 0; foreach (var n in newNodes) { foreach (var t in n.Tracks) { var fobj = t.ToFOBJ(); var keys = fobj.GetDecodedKeys(); if (keys.Count > targetTree.FrameCount * 0.8f) { var before = keys.Count; keys = Tools.LineSimplification.Simplify(keys, 0.025f); fobj.SetKeys(keys, fobj.JointTrackType); t.FromFOBJ(fobj); keydecrease += before - keys.Count; } } } Console.WriteLine("Optimized " + keydecrease + " removed"); targetTree.Nodes = newNodes; inputAnim.Save(destAnimFile); return(true); } return(false); }
public bool DoIt(string[] args) { if (args.Length >= 2) { var dat = args[1]; HSDRawFile file = new HSDRawFile(dat); foreach (var r in file.Roots) { r.Data.Optimize(); } file.Save(dat); return(true); } return(false); }
/// <summary> /// /// </summary> /// <param name="ftdat"></param> /// <param name="ajdat"></param> /// <param name="editAnim"></param> public static void EditFighterActions(string ftdat, EditSubaction editAction) { HSDRawFile ftfile = new HSDRawFile(ftdat); if (ftfile.Roots[0].Data is SBM_FighterData data) { var sa = data.FighterActionTable.Commands; foreach (var action in sa) { editAction(action); } data.FighterActionTable.Commands = sa; ftfile.TrimData(); ftfile.Save(ftdat); } }
/// <summary> /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void compressAllAnimationsToolStripMenuItem_Click(object sender, EventArgs e) { if (AJManager == null) { return; } HashSet <string> edited = new HashSet <string>(); int oldSize = 0; int newSize = 0; foreach (var a in AllActions) { if (string.IsNullOrEmpty(a.Symbol) || edited.Contains(a.Symbol)) { continue; } var anim = AJManager.GetAnimationData(a.Symbol); if (anim != null) { JointAnimManager ja = new JointAnimManager(); var animfile = new HSDRawFile(anim); ja.FromFigaTree(animfile.Roots[0].Data as HSD_FigaTree); //ja.Optimize(JointManager.GetJOBJ(0), 0.01f); animfile.Roots[0].Data = ja.ToFigaTree(0.01f); using (MemoryStream s = new MemoryStream()) { animfile.Save(s); var newfile = s.ToArray(); oldSize += anim.Length; newSize += newfile.Length; AJManager.SetAnimation(a.Symbol, newfile); } } edited.Add(a.Symbol); } Console.WriteLine($"{oldSize.ToString("X")} => {newSize.ToString("X")}"); Console.WriteLine($"Saved {(oldSize - newSize).ToString("X")} bytes"); }
/// <summary> /// /// </summary> /// <param name="filePath"></param> private void ExportFiles() { var filePath = Tools.FileIO.SaveFile("Pl**.dat (*.dat)|*.dat", Path.GetFileName(ftDataPath)); if (filePath != null) { if (AJLoaded) { var AJPath = Tools.FileIO.SaveFile("Pl**AJ.dat (*.dat)|*.dat", Path.GetFileName(ftAJPath)); if (AJPath != null) { using (BinaryWriter w = new BinaryWriter(new FileStream(AJPath, FileMode.Create))) { PlayerData.FighterActionTable.Commands = CreateAnimationFile(w, PlayerData.FighterActionTable.Commands, FightingAnimations); } } } if (ResultLoaded) { var resultPath = Tools.FileIO.SaveFile("GrRstM**.dat (*.dat)|*.dat", "GrRstM" + FighterName + ".dat"); if (resultPath != null) { HSDRawFile res = new HSDRawFile(); res.Roots.Add(new HSDRootNode() { Name = "ftDemoResultMotionFile" + FighterName, Data = new HSDAccessor() }); using (BinaryWriter w = new BinaryWriter(new MemoryStream())) { PlayerData.DemoActionTable.Commands = CreateAnimationFile(w, PlayerData.DemoActionTable.Commands, ResultAnimations); res.Roots[0].Data._s.SetData(((MemoryStream)w.BaseStream).ToArray()); } res.Save(resultPath); } } PlayerFile.Save(filePath, false, false); } }
/// <summary> /// /// </summary> private void SaveAnimationChanges() { if (actionList.SelectedItem is Action action) { HSDRawFile f = new HSDRawFile(); f.Roots.Add(new HSDRootNode() { Name = action.Symbol, Data = JointManager.Animation.ToFigaTree() }); using (MemoryStream stream = new MemoryStream()) { f.Save(stream); AJManager.SetAnimation(action.Symbol, stream.ToArray()); } BackupAnim.FromFigaTree(JointManager.Animation.ToFigaTree()); } }
/// <summary> /// /// </summary> public static void GenerateStockNode(string ifallPath) { var file = new HSDRawFile(ifallPath); var path = ifallPath; var stockSymbol = file.Roots.Find(e => e.Name.Equals("Stc_icns")); if (stockSymbol == null) { var stockModel = file.Roots.Find(e => e.Name.Equals("Stc_scemdls")).Data as HSDNullPointerArrayAccessor <HSD_JOBJDesc>; var texanim = stockModel[0].MaterialAnimations[0].Child.MaterialAnimation.TextureAnimation; file.Roots.Add(new HSDRootNode() { Name = "Stc_icns", Data = GenerateStockIconNodeFromVanilla(texanim) }); } file.TrimData(); file.Save(path + "_new.dat"); }
/// <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); }
public static void Deconstruct(string plFilePath, string ajFilePath, string outputFolder) { var plfile = new HSDRawFile(plFilePath); var path = Path.GetDirectoryName(plFilePath) + "\\" + outputFolder + "\\"; Directory.CreateDirectory(path); var data = plfile.Roots[0].Data as SBM_FighterData; if (data == null) { return; } var ajfile = new HSDRawFile(ajFilePath); foreach (var prop in data.GetType().GetProperties()) { var val = prop.GetValue(data) as HSDAccessor; if (val == null) { continue; } if (prop.PropertyType == typeof(SBM_CommonFighterAttributes)) { var attr = prop.GetValue(data) as SBM_CommonFighterAttributes; using (StreamWriter w = new StreamWriter(new FileStream(path + prop.Name + ".ini", FileMode.Create))) { foreach (var v in attr.GetType().GetProperties()) { if (v.Name.Equals("TrimmedSize")) { continue; } w.WriteLine($"{v.Name}={v.GetValue(attr)}"); } } } else if (prop.Name.Equals("SubActionTable")) { ScriptFile f = new ScriptFile(); f.Actions = new ActionGroup[val._s.Length / 0x18]; var ActionDecompiler = new ActionDecompiler(); HashSet <string> ExportedAnimations = new HashSet <string>(); for (int i = 0; i < f.Actions.Length; i++) { SBM_FighterAction subaction = new HSDRaw.Melee.Pl.SBM_FighterAction(); subaction._s = val._s.GetEmbeddedStruct(0x18 * i, 0x18); if (!ExportedAnimations.Contains(subaction.Name) && subaction.Name != null && subaction.Name != "") { ExportedAnimations.Add(subaction.Name); if (ajFilePath != null && File.Exists(ajFilePath)) { using (BinaryReaderExt r = new BinaryReaderExt(new FileStream(ajFilePath, FileMode.Open))) { var animdata = r.GetSection((uint)subaction.AnimationOffset, subaction.AnimationSize); File.WriteAllBytes(path + "Animations\\" + subaction.Name + ".dat", animdata); } } } ActionGroup g = new ActionGroup(); g.animation_name = subaction.Name; g.flags = (int)subaction.Flags; g.script = ActionDecompiler.Decompile("Func_" + i.ToString("X3"), subaction.SubAction); //g.script = g.off = subaction.AnimationOffset; g.size = subaction.AnimationSize; f.Actions[i] = g; Console.WriteLine(i + " " + subaction.Name + " " + subaction._s.GetReference <HSDAccessor>(0x0C)._s.References.Count); } XmlSerializer writer = new XmlSerializer(typeof(ScriptFile)); using (var w = new XmlTextWriter(new FileStream(path + prop.Name + ".txt", FileMode.Create), Encoding.UTF8)) { w.Formatting = Formatting.Indented; writer.Serialize(w, f); } } else { HSDRootNode root = new HSDRootNode(); root.Name = prop.Name; root.Data = val; HSDRawFile file = new HSDRawFile(); file.Roots.Add(root); file.Save(path + prop.Name + ".dat"); Console.WriteLine(prop.Name + " " + val._s.GetSubStructs().Count); } } }
public static void Reconstruct(string filepath, string animPath, string directory, string rootName) { var path = Path.GetDirectoryName(directory); HSDRawFile file = new HSDRawFile(); HSDRootNode root = new HSDRootNode(); root.Name = rootName; var ftData = new SBM_FighterData(); root.Data = ftData; file.Roots.Add(root); var prop = root.Data.GetType().GetProperties().ToList(); foreach (var f in Directory.GetFiles(directory)) { if (f.EndsWith(".dat")) { HSDRawFile chunk = new HSDRawFile(f); Console.WriteLine(f + " " + chunk.Roots.Count); var property = prop.Find(e => e.Name == chunk.Roots[0].Name); if (property != null) { var newt = Activator.CreateInstance(property.PropertyType); { var dset = newt as HSDAccessor; if (dset != null) { dset._s = chunk.Roots[0].Data._s; } } property.SetValue(root.Data, newt); } } else if (f.EndsWith(".ini")) { SBM_CommonFighterAttributes attr = new SBM_CommonFighterAttributes(); using (StreamReader r = new StreamReader(new FileStream(f, FileMode.Open))) { foreach (var v in attr.GetType().GetProperties()) { if (v.Name.Equals("TrimmedSize")) { continue; } var line = r.ReadLine().Split('='); if (line.Length < 2 || line[0] != v.Name) { throw new InvalidDataException("Invalid Attribute " + string.Join("=", line)); } if (v.PropertyType == typeof(int)) { v.SetValue(attr, int.Parse(line[1].Trim())); } if (v.PropertyType == typeof(float)) { v.SetValue(attr, float.Parse(line[1].Trim())); } } } ftData.Attributes = attr; } else if (f.EndsWith(".txt")) { XmlSerializer writer = new XmlSerializer(typeof(ScriptFile)); var script = (ScriptFile)writer.Deserialize(new FileStream(f, FileMode.Open)); Dictionary <string, Tuple <int, int> > animationToOffset = new Dictionary <string, Tuple <int, int> >(); List <SBM_FighterAction> SubActions = new List <SBM_FighterAction>(); Dictionary <SBM_FighterAction, string> subActionToScript = new Dictionary <SBM_FighterAction, string>(); Dictionary <string, HSDStruct> stringToStruct = new Dictionary <string, HSDStruct>(); using (BinaryWriter w = new BinaryWriter(new FileStream(animPath, FileMode.Create))) { foreach (var s in script.Actions) { SBM_FighterAction subaction = new SBM_FighterAction(); subaction.Flags = (uint)s.flags; if (s.animation_name != null) { if (!stringToStruct.ContainsKey(s.animation_name)) { var namestruct = new HSDStruct(); byte[] data = new byte[s.animation_name.Length + 1]; var bytes = UTF8Encoding.UTF8.GetBytes(s.animation_name); for (int i = 0; i < s.animation_name.Length; i++) { data[i] = bytes[i]; } namestruct.SetData(data); stringToStruct.Add(s.animation_name, namestruct); } subaction._s.SetReferenceStruct(0, stringToStruct[s.animation_name]); //subaction.Name = s.animation_name; if (!animationToOffset.ContainsKey(s.animation_name)) { if (File.Exists(path + "\\Animations\\" + s.animation_name + ".dat")) { var data = File.ReadAllBytes(path + "\\Animations\\" + s.animation_name + ".dat"); animationToOffset.Add(s.animation_name, new Tuple <int, int>((int)w.BaseStream.Position, data.Length)); w.Write(data); if (w.BaseStream.Length % 0x20 != 0) { var padd = new byte[0x20 - (w.BaseStream.Position % 0x20)]; for (int i = 0; i < padd.Length; i++) { padd[i] = 0xFF; } w.Write(padd); } } else { throw new FileNotFoundException("Could not find animation " + path + "\\Animations\\" + s.animation_name + ".dat"); } } subaction.AnimationOffset = animationToOffset[s.animation_name].Item1; subaction.AnimationSize = animationToOffset[s.animation_name].Item2; } if (s.script != null) { ActionCompiler.Compile(s.script); subActionToScript.Add(subaction, s.script); } SubActions.Add(subaction); } } ftData.FighterActionTable = new SBM_FighterActionTable(); ActionCompiler.LinkStructs(); ftData.FighterActionTable.Commands = SubActions.ToArray(); Console.WriteLine("recompiled count " + ftData.FighterActionTable._s.GetSubStructs().Count); } } file.Save(filepath); }
/// <summary> /// /// </summary> /// <param name="args"></param> /// <returns></returns> public bool DoIt(string[] args) { // Parse Args List <Tuple <int, List <string> > > itemInputs = new List <Tuple <int, List <string> > >(); List <string> inputs = new List <string>(); LinkFile linkFile = new LinkFile(); string output = ""; string symbolName = ""; string datFile = null; string[] fightFuncTable = null; string buildPath = null; bool quiet = true; bool yesOverwrite = false; bool disableWarnings = true; bool clean = false; bool debug = false; int opLevel = 2; List <string> includes = new List <string>(); for (int i = 0; i < args.Length; i++) { if (args[i] == "-i") { for (int j = i + 1; j < args.Length; j++) { if (File.Exists(args[j])) { inputs.Add(Path.GetFullPath(args[j])); } else { break; } } } if (args[i] == "-inc") { for (int j = i + 1; j < args.Length; j++) { if (Directory.Exists(args[j])) { includes.Add(Path.GetFullPath(args[j])); } else { break; } } } if (args[i] == "-item" && i + 2 < args.Length) { List <string> itemRefList = new List <string>(); for (int j = i + 2; j < args.Length; j++) { if (args[j] != "-item" && File.Exists(args[j])) { itemRefList.Add(Path.GetFullPath(args[j])); } else { break; } } itemInputs.Add(new Tuple <int, List <string> >(int.Parse(args[i + 1]), itemRefList)); } if (args[i] == "-op" && i + 1 < args.Length) { opLevel = int.Parse(args[i + 1]); } if (args[i] == "-o" && i + 1 < args.Length) { output = Path.GetFullPath(args[i + 1]); } if (args[i] == "-dat" && i + 1 < args.Length) { datFile = Path.GetFullPath(args[i + 1]); } if (args[i] == "-s" && i + 1 < args.Length) { symbolName = args[i + 1]; } if (args[i] == "-ow") { yesOverwrite = true; } if (args[i] == "-w") { disableWarnings = false; } if (args[i] == "-d") { debug = true; } if (args[i] == "-t" && i + 1 < args.Length) { fightFuncTable = File.ReadAllLines(args[i + 1]); } if (args[i] == "-v") { quiet = false; } if (args[i] == "-b" && i + 1 < args.Length) { buildPath = Path.GetFullPath(args[i + 1]); } if (args[i] == "-l" && i + 1 < args.Length) { linkFile.LoadLinkFile(args[i + 1]); } } // if (string.IsNullOrEmpty(symbolName)) { Console.WriteLine("Error: Symbol Required; please specify a symbol Ex:\"-s ftFunction\""); return(false); } // if output is null set the name to the symbol name if (string.IsNullOrEmpty(datFile) && string.IsNullOrEmpty(output) && !string.IsNullOrEmpty(symbolName)) { output = symbolName + ".dat"; } var symbolPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, symbolName + ".txt"); // if function table not specified attempt to get it from symbol name if (fightFuncTable == null && !string.IsNullOrEmpty(symbolName) && File.Exists(symbolPath)) { fightFuncTable = File.ReadAllLines(symbolPath); } // load link file in mex directory foreach (var f in Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory)) { if (Path.GetExtension(f).ToLower().Equals(".link")) { linkFile.LoadLinkFile(f); } } // don't allow both item tables and normal tables if (inputs.Count > 0 && itemInputs.Count > 0) { Console.WriteLine("Only -i or -ii can be used at once, not both"); return(false); } // print instruction and exit if no input if ((inputs.Count == 0 && itemInputs.Count == 0) || args.Length == 0) { Console.WriteLine("No input files were given"); return(false); } // check if symbol name is given if (string.IsNullOrEmpty(symbolName)) { symbolName = "ftFunction"; Console.WriteLine("No symbol name given, defaulting to \"ftFunction\""); } // create output path if one isn't entered if (string.IsNullOrEmpty(output) && string.IsNullOrEmpty(datFile)) { output = Path.Combine(Path.GetDirectoryName(inputs[0]), Path.GetFileName(inputs[0]).Replace(Path.GetExtension(inputs[0]), ".dat")); } // check if output already exists if (File.Exists(output) && !yesOverwrite) { Console.WriteLine(output + " already exists, overwrite? (y/n)"); if (Console.ReadLine().Trim().ToLower() != "y") { return(false); } } // compile functions HSDAccessor function = null; // create file HSDRawFile newfile = null; HSDRawFile injectfile = null; SBM_FighterData ftData = null; // create new file if (!string.IsNullOrEmpty(output)) { newfile = new HSDRawFile(); } // inject existing dat file (or create new one if not found) if (!string.IsNullOrEmpty(datFile)) { injectfile = File.Exists(datFile) ? new HSDRawFile(datFile) : new HSDRawFile(); } // find fighter data if it exists if (injectfile != null && injectfile.Roots.Count > 0 && injectfile.Roots[0].Data is SBM_FighterData ftdata) { ftData = ftdata; } // static param table var param_table = new string[] { "param_ext" }; // single table compile if (itemInputs.Count == 0) { var elfs = CompileElfs(inputs.ToArray(), disableWarnings, clean, opLevel, includes.ToArray(), buildPath, debug, quiet); //foreach (var f in Directory.GetFiles(@"C:\devkitPro\libogc\lib\cube")) //foreach (var f in Directory.GetFiles(@"C:\devkitPro\devkitPPC\powerpc-eabi\lib")) //{ // if (Path.GetExtension(f).Equals(".a")) // elfs.AddRange(FighterFunction.LibArchive.GetElfs(f)); // if (Path.GetExtension(f).Equals(".o")) // elfs.Add(new RelocELF(File.ReadAllBytes(f))); //} //elfs.AddRange(FighterFunction.LibArchive.GetElfs(@"C:\devkitPro\devkitPPC\lib\gcc\powerpc-eabi\10.2.0\libgcc.a")); //elfs.AddRange(FighterFunction.LibArchive.GetElfs(@"C:\Users\ploaj\Desktop\Modlee\libgc\MemCardDemo\libogc.a")); var lelf = GenerateLinkedElf(elfs, fightFuncTable, linkFile, quiet); // check for special attribute symbol if (ftData != null) { foreach (var elf in elfs) { if (elf.SymbolEnumerator.Any(e => e.Symbol.Equals("param_ext"))) { var special_attr = CmdGenerateDatFile.BuildDatFile(elf, param_table); if (special_attr != null && special_attr.Roots.Count > 0 && special_attr["param_ext"] != null) { // Console.WriteLine("Found Param_Ext... adding to fighter data..."); ftData.Attributes2 = special_attr["param_ext"].Data; break; } } } } function = GenerateFunctionData(lelf, linkFile, fightFuncTable, quiet, debug); } else { // item table compile function = new HSDAccessor() { _s = new HSDStruct(4) }; int count = 0; foreach (var f in itemInputs) { count = Math.Max(count, f.Item1 + 1); if (4 + 4 * (f.Item1 + 1) > function._s.Length) { function._s.Resize(4 + 4 * (f.Item1 + 1)); } var elfs = CompileElfs(f.Item2.ToArray(), disableWarnings, clean, opLevel, includes.ToArray(), buildPath, debug, quiet); var lelf = GenerateLinkedElf(elfs, fightFuncTable, linkFile, quiet); // check for special attribute symbol if (ftData != null) { foreach (var elf in elfs) { if (elf.SymbolEnumerator.Any(e => e.Symbol.Equals("param_ext"))) { var special_attr = CmdGenerateDatFile.BuildDatFile(elf, param_table); if (special_attr != null && special_attr.Roots.Count > 0 && special_attr["param_ext"] != null) { // Console.WriteLine("Found Param_Ext... adding to fighter data..."); ftData.Articles.Articles[f.Item1].ParametersExt = special_attr["param_ext"].Data; break; } } } } var relocFunc = GenerateFunctionData(lelf, linkFile, fightFuncTable, quiet, debug); function._s.SetReference(4 + 0x04 * f.Item1, relocFunc); } function._s.SetInt32(0x00, count); } // inject symbol to dat file and save if (function != null) { if (newfile != null) { DatTools.InjectSymbolIntoDat(newfile, symbolName, function); newfile.Save(output); Console.WriteLine("saving " + output + "..."); } if (injectfile != null) { DatTools.InjectSymbolIntoDat(injectfile, symbolName, function); injectfile.Save(datFile); Console.WriteLine("saving " + datFile + "..."); } // We did it boys Console.WriteLine(); Console.WriteLine("Sucessfully Compiled and Converted to DAT!"); return(true); } return(false); }
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); }
public bool DoIt(string[] args) { if (args.Length >= 3) { var dest = args[1]; var src = args[2]; bool all = false; List <string> names = new List <string>(); for (int i = 3; i < args.Length; i++) { if (args[i] == "-a") { all = true; } if (args[i] == "-s" && i + 1 < args.Length) { names.Add(args[i + 1]); } } HSDRawFile d = new HSDRawFile(dest); HSDRawFile s = new HSDRawFile(src); if (s.Roots.Count > 0) { if (all) { d.Roots.AddRange(s.Roots); } else if (names.Count > 0) { foreach (var n in names) { var sym = s.Roots.Find(e => e.Name.Equals(n)); if (sym != null) { d.Roots.Add(sym); } else { Console.WriteLine("Could not find symbol " + n); } } } else { var root = d.Roots.Find(e => e.Name == s.Roots[0].Name); if (root == null) { d.Roots.Add(s.Roots[0]); } else { root.Data = s.Roots[0].Data; } } } d.Save(dest); return(true); } return(false); }
/// <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); }
/// <summary> /// /// </summary> /// <param name="resource"></param> /// <returns></returns> public static bool InstallMEX(ImageResource resource) { // patch dol resource.SetDOL(MEXDolPatcher.ApplyPatch(resource.GetDOL(), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lib/dol.patch"))); /*using (var src = new MemoryStream(resource.GetDOL())) * using (System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider()) * { * byte[] vanillaFullHash = new byte[] { 39, 123, 108, 9, 132, 118, 2, 32, 152, 149, 208, 17, 197, 163, 163, 139 }; * byte[] vanillaDolHash = new byte[] { 135, 241, 17, 254, 252, 165, 45, 39, 50, 80, 104, 65, 216, 32, 142, 212 }; * byte[] patchedHash = new byte[] { 220, 216, 224, 150, 88, 53, 129, 175, 54, 201, 175, 176, 53, 71, 167, 40 }; * * var hash = md5.ComputeHash(src); * * if (!hash.SequenceEqual(vanillaDolHash) && !hash.SequenceEqual(vanillaFullHash) && !hash.SequenceEqual(patchedHash)) * return false; * * if (!hash.SequenceEqual(patchedHash)) * using (var dest = new MemoryStream()) * { * src.Position = 0; * GCILib.BZip2.BinaryPatchUtility.Apply(src, () => new FileStream(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lib/dol.patch"), FileMode.Open, FileAccess.Read, FileShare.Read), dest); * * dest.Position = 0; * hash = md5.ComputeHash(dest); * * if (!hash.SequenceEqual(patchedHash)) * return false; * * System.Diagnostics.Debug.WriteLine(string.Join(", ", patchedHash) + " " + hash.SequenceEqual(vanillaDolHash)); * * resource.SetDOL(dest.ToArray()); * } * }*/ // generate mex files using (MEXDOLScrubber dol = new MEXDOLScrubber(resource.GetDOL())) { var resourceFile = new HSDRawFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lib\\resource.dat")); // generate mxdt MEX_Data data = new MEX_Data(); // generate meta data data.MetaData = new MEX_Meta() { NumOfInternalIDs = 33, NumOfExternalIDs = 33, NumOfCSSIcons = 26, NumOfInternalStage = 0, NumOfExternalStage = 285, NumOfSSSIcons = 30, NumOfSSMs = 55, NumOfMusic = 98, NumOfEffects = 51, EnterScene = 2, LastMajor = 45, //? LastMinor = 45, }; // Version data.MetaData._s.SetInt16(0x00, 0x0100); // fighter table InstallFighters(dol, data, resourceFile); // kirby table InstallKirby(dol, data, resourceFile); // sound table InstallSounds(dol, data, resourceFile); // item table InstallItems(dol, data, resourceFile); // effect table data.EffectTable = new MEX_EffectData(); data.EffectTable.EffectFiles = new HSDArrayAccessor <MEX_EffectFiles>() { _s = new HSDFixedLengthPointerArrayAccessor <HSD_String>() { Array = dol.ReadStringTable(EffectStringOffset, data.MetaData.NumOfEffects * 3) }._s }; // note: this really isn't needed here because saving will regenerate anyway data.EffectTable.RuntimeUnk1 = new HSDAccessor() { _s = new HSDStruct(0x60) }; data.EffectTable.RuntimeUnk3 = new HSDAccessor() { _s = new HSDStruct(0xCC) }; data.EffectTable.RuntimeTexGrNum = new HSDAccessor() { _s = new HSDStruct(0xCC) }; data.EffectTable.RuntimeTexGrData = new HSDAccessor() { _s = new HSDStruct(0xCC) }; data.EffectTable.RuntimeUnk4 = new HSDAccessor() { _s = new HSDStruct(0xCC) }; data.EffectTable.RuntimePtclLast = new HSDAccessor() { _s = new HSDStruct(0xCC) }; data.EffectTable.RuntimePtclData = new HSDAccessor() { _s = new HSDStruct(0xCC) }; data.EffectTable.RuntimeLookup = new HSDAccessor() { _s = new HSDStruct(0xCC) }; // stage table InstallStages(dol, data, resourceFile); // scene table InstallScenes(dol, data, resourceFile); // misc table InstallMisc(dol, data, resourceFile); // generate sss and css symbols GetIconFromDOL(dol, data); var cssFile = new HSDRawFile(resource.GetFile("MnSlChr.usd")); var sssFile = new HSDRawFile(resource.GetFile("MnSlMap.usd")); var ifallFile = new HSDRawFile(resource.GetFile("IfAll.usd")); // mexSelectChr var mexMenuSymbol = GenerateMexSelectChrSymbol(cssFile.Roots[0].Data as SBM_SelectChrDataTable, data.MenuTable.CSSIconData.Icons); cssFile.Roots.RemoveAll(e => e.Name == "mexSelectChr"); cssFile.Roots.Add(new HSDRootNode() { Name = "mexSelectChr", Data = mexMenuSymbol }); // mexMapData var mexMapSymbol = LoadIconDataFromVanilla(sssFile.Roots[0].Data as SBM_MnSelectStageDataTable); sssFile.Roots.RemoveAll(e => e.Name == "mexMapData"); sssFile.Roots.Add(new HSDRootNode() { Name = "mexMapData", Data = mexMapSymbol }); // ifall data // load this from resources; don't generate if (ifallFile["bgm"] == null) { ifallFile.Roots.Add(new HSDRootNode() { Name = "bgm", Data = resourceFile["bgm"].Data }); } if (ifallFile["Eblm_matanim_joint"] == null) { ifallFile.Roots.Add(new HSDRootNode() { Name = "Eblm_matanim_joint", Data = resourceFile["Eblm_matanim_joint"].Data }); } if (ifallFile["Stc_icns"] == null) { ifallFile.Roots.Add(new HSDRootNode() { Name = "Stc_icns", Data = resourceFile["Stc_icns"].Data }); } #if DEBUG /*var mexfile2 = new HSDRawFile(); * mexfile2.Roots.Add(new HSDRootNode() { Name = "mexData", Data = data }); * mexfile2.Save("test_Mxdt.dat"); * cssFile.Save("test_CSS.dat"); * sssFile.Save("test_SSS.dat"); * ifallFile.Save("test_IfAll.dat"); * return false;*/ #endif // add files to resource resource.AddFile("codes.gct", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "lib\\codes.gct")); // null ssm file resource.AddFile("audio/us/null.ssm", resource.GetFile("audio/us/end.ssm")); using (MemoryStream dat = new MemoryStream()) { ifallFile.Save(dat); resource.AddFile("IfAll.usd", dat.ToArray()); } using (MemoryStream dat = new MemoryStream()) { cssFile.Save(dat); resource.AddFile("MnSlChr.usd", dat.ToArray()); } using (MemoryStream dat = new MemoryStream()) { sssFile.Save(dat); resource.AddFile("MnSlMap.usd", dat.ToArray()); } using (MemoryStream dat = new MemoryStream()) { var mexfile = new HSDRawFile(); mexfile.Roots.Add(new HSDRootNode() { Name = "mexData", Data = data }); mexfile.Save(dat); resource.AddFile("MxDt.dat", dat.ToArray()); } } // success return(true); }
public JOBJContextMenu() : base() { MenuItem Import = new MenuItem("Import Model From File"); Import.Click += (sender, args) => { if (MainForm.SelectedDataNode.Accessor is HSD_JOBJ root) { MainForm.SelectedDataNode.Collapse(); ModelImporter.ReplaceModelFromFile(root); } }; MenuItems.Add(Import); MenuItem GenerateMatAnimJoint = new MenuItem("Generate and Export MatAnimJoint Structure"); GenerateMatAnimJoint.Click += (sender, args) => { if (MainForm.SelectedDataNode.Accessor is HSD_JOBJ root) { var file = Tools.FileIO.SaveFile(ApplicationSettings.HSDFileFilter, "matanim_joint.dat"); if (file != null) { HSDRawFile f = new HSDRawFile(); HSDRootNode r = new HSDRootNode(); r.Name = "matanim_joint"; r.Data = GenerateMatAnimJointFromJOBJ(root); f.Roots.Add(r); f.Save(file); } } }; MenuItems.Add(GenerateMatAnimJoint); MenuItem addChild = new MenuItem("Add Child"); MenuItems.Add(addChild); MenuItem createJOBJ = new MenuItem("From Scratch"); createJOBJ.Click += (sender, args) => { if (MainForm.SelectedDataNode.Accessor is HSD_JOBJ root) { root.AddChild(new HSD_JOBJ() { SX = 1, SY = 1, SZ = 1, Flags = JOBJ_FLAG.CLASSICAL_SCALING | JOBJ_FLAG.ROOT_XLU }); MainForm.SelectedDataNode.Refresh(); } }; addChild.MenuItems.Add(createJOBJ); MenuItem createJOBJFromFile = new MenuItem("From File"); createJOBJFromFile.Click += (sender, args) => { if (MainForm.SelectedDataNode.Accessor is HSD_JOBJ root) { var f = Tools.FileIO.OpenFile(ApplicationSettings.HSDFileFilter); if (f != null) { HSDRaw.HSDRawFile file = new HSDRaw.HSDRawFile(f); var node = file.Roots[0].Data; if (node is HSD_JOBJ newchild) { root.AddChild(newchild); } } MainForm.SelectedDataNode.Refresh(); } }; addChild.MenuItems.Add(createJOBJFromFile); }
/// <summary> /// Test for rebuilding pobjs from scratch /// </summary> /// <param name="path"></param> public static void RebuildPOBJs(string path) { HSDRawFile file = new HSDRawFile(path); var rootJOBJ = (HSD_JOBJ)(file.Roots[0].Data); var compressor = new POBJ_Generator(); foreach (var jobj in rootJOBJ.BreathFirstSearch) { if (jobj.Dobj != null) { foreach (var dobj in jobj.Dobj.List) { if (dobj.Pobj != null) { GXAttribName[] attributes = null; if (attributes == null) { attributes = new GXAttribName[dobj.Pobj.Attributes.Length - 1]; for (int i = 0; i < attributes.Length; i++) { attributes[i] = dobj.Pobj.Attributes[i].AttributeName; } } List <GX_Vertex> triList = new List <GX_Vertex>(); List <HSD_JOBJ[]> bones = new List <HSD_JOBJ[]>(); List <float[]> weights = new List <float[]>(); foreach (var pobj in dobj.Pobj.List) { var dl = pobj.ToDisplayList(); int off = 0; foreach (var pri in dl.Primitives) { var strip = dl.Vertices.GetRange(off, pri.Count); if (pri.PrimitiveType == GXPrimitiveType.TriangleStrip) { TriangleConverter.StripToList(strip, out strip); } if (pri.PrimitiveType == GXPrimitiveType.Quads) { TriangleConverter.QuadToList(strip, out strip); } off += pri.Count; //if(pobj.Flags.HasFlag(POBJ_FLAG.ENVELOPE)) { triList.AddRange(strip); foreach (var v in strip) { if (dl.Envelopes.Count > 0) { var en = dl.Envelopes[v.PNMTXIDX / 3]; HSD_JOBJ[] b = en.JOBJs; float[] w = en.Weights; bones.Add(b); weights.Add(w); } else { bones.Add(new HSD_JOBJ[0]); weights.Add(new float[0]); } } } } } dobj.Pobj = compressor.CreatePOBJsFromTriangleList(triList, attributes, bones, weights); /*List<GX_Vertex> triList = new List<GX_Vertex>(); * foreach (var pobj in dobj.Pobj.List) * { * var dl = pobj.DisplayList; * var newPrimGroup = new List<GX_PrimitiveGroup>(); * int offset = 0; * foreach (var g in dl.Primitives) * { * GX_Vertex[] strip = new GX_Vertex[g.Count]; * for (int i = 0; i < g.Count; i++) * strip[i] = dl.Vertices[offset + i]; * newPrimGroup.Add(compressor.Compress(g.PrimitiveType, strip, pobj.Attributes)); * offset += g.Count; * } * dl.Primitives = newPrimGroup; * pobj.DisplayList = dl; * }*/ } } } } compressor.SaveChanges(); file.Save(path + "_rebuilt.dat"); }