From 1e4f1aace099995428931d1334bd0ffbbaa26d2a Mon Sep 17 00:00:00 2001 From: Kamzik123 Date: Tue, 28 Nov 2023 23:54:33 +0100 Subject: [PATCH] XML support improvements - Added ability to export/import Translokator to/from XML - XML Reflection -> Objects will now use their correct type converters when converting to/from XML - HashName now exports/imports to/from XML correctly --- .../Forms/TranslokatorEditor.Designer.cs | 23 ++++++++- Mafia2Libs/Forms/TranslokatorEditor.cs | 42 +++++++++++++-- .../FileTypes/Translokator/Translokator.cs | 51 +++++++++++++++---- .../Helpers/Reflection/ReflectionHelpers.cs | 31 ++++++++++- Mafia2Libs/Utils/Types/Types.cs | 5 +- 5 files changed, 132 insertions(+), 20 deletions(-) diff --git a/Mafia2Libs/Forms/TranslokatorEditor.Designer.cs b/Mafia2Libs/Forms/TranslokatorEditor.Designer.cs index 626d92d1..a7b45d66 100644 --- a/Mafia2Libs/Forms/TranslokatorEditor.Designer.cs +++ b/Mafia2Libs/Forms/TranslokatorEditor.Designer.cs @@ -44,6 +44,8 @@ private void InitializeComponent() this.SaveToolButton = new System.Windows.Forms.ToolStripMenuItem(); this.ReloadButton = new System.Windows.Forms.ToolStripMenuItem(); this.ExitButton = new System.Windows.Forms.ToolStripMenuItem(); + this.Button_ExportXml = new System.Windows.Forms.ToolStripMenuItem(); + this.Button_ImportXml = new System.Windows.Forms.ToolStripMenuItem(); this.ToolsButton = new System.Windows.Forms.ToolStripDropDownButton(); this.ViewNumInstButton = new System.Windows.Forms.ToolStripMenuItem(); this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); @@ -191,7 +193,9 @@ private void InitializeComponent() // this.ToolsButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; this.ToolsButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.ViewNumInstButton}); + this.ViewNumInstButton, + this.Button_ExportXml, + this.Button_ImportXml}); this.ToolsButton.Image = ((System.Drawing.Image)(resources.GetObject("ToolsButton.Image"))); this.ToolsButton.ImageTransparentColor = System.Drawing.Color.Magenta; this.ToolsButton.Name = "ToolsButton"; @@ -204,6 +208,21 @@ private void InitializeComponent() this.ViewNumInstButton.Size = new System.Drawing.Size(180, 22); this.ViewNumInstButton.Text = "$VIEW_NUM_INST"; this.ViewNumInstButton.Click += new System.EventHandler(this.ViewNumInstButton_Click); + // + // + // Button_ExportXml + // + this.Button_ExportXml.Name = "Button_ExportXml"; + this.Button_ExportXml.Size = new System.Drawing.Size(180, 22); + this.Button_ExportXml.Text = "$EXPORT_XML"; + this.Button_ExportXml.Click += new System.EventHandler(this.Button_ExportXml_OnClick); + // + // Button_ExportXml + // + this.Button_ImportXml.Name = "Button_ImportXml"; + this.Button_ImportXml.Size = new System.Drawing.Size(180, 22); + this.Button_ImportXml.Text = "$IMPORT_XML"; + this.Button_ImportXml.Click += new System.EventHandler(this.Button_ImportXml_OnClick); // // openFileDialog1 // @@ -240,6 +259,8 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem SaveToolButton; private System.Windows.Forms.ToolStripMenuItem ReloadButton; private System.Windows.Forms.ToolStripMenuItem ExitButton; + private System.Windows.Forms.ToolStripMenuItem Button_ExportXml; + private System.Windows.Forms.ToolStripMenuItem Button_ImportXml; private System.Windows.Forms.ToolStripMenuItem AddObject; private System.Windows.Forms.ToolStripMenuItem Delete; private System.Windows.Forms.ToolStripMenuItem CopyButton; diff --git a/Mafia2Libs/Forms/TranslokatorEditor.cs b/Mafia2Libs/Forms/TranslokatorEditor.cs index d40ce48e..0d306c36 100644 --- a/Mafia2Libs/Forms/TranslokatorEditor.cs +++ b/Mafia2Libs/Forms/TranslokatorEditor.cs @@ -1,9 +1,8 @@ -using System; +using ResourceTypes.Translokator; +using System; using System.IO; -using ResourceTypes.Translokator; using System.Windows.Forms; using Utils.Language; -using Utils.Helpers; namespace Mafia2Tool.Forms { @@ -43,6 +42,12 @@ private void Localise() private void LoadFile() { translokator = new TranslokatorLoader(file); + + LoadData(); + } + + private void LoadData() + { TranslokatorTree.Nodes.Clear(); TreeNode headerData = new TreeNode("Header Data"); @@ -402,6 +407,35 @@ private void ReloadButton_Click(object sender, EventArgs e) private void CopyButton_Click(object sender, EventArgs e) => Copy(); private void PasteButton_Click(object sender, EventArgs e) => Paste(); private void SaveToolButton_Click(object sender, EventArgs e) => SaveFile(); - private void ExitButton_Click(object sender, EventArgs e) => Close(); + private void ExitButton_Click(object sender, EventArgs e) => Close(); + private void Button_ExportXml_OnClick(object sender, System.EventArgs e) + { + SaveFileDialog saveFile = new SaveFileDialog(); + saveFile.Filter = "XML|*.XML"; + + if (saveFile.ShowDialog() == DialogResult.OK) + { + translokator.ConvertToXML(saveFile.FileName); + } + } + + private void Button_ImportXml_OnClick(object sender, EventArgs e) + { + OpenFileDialog openFileDialog = new OpenFileDialog(); + openFileDialog.Filter = "XML|*.XML"; + openFileDialog.Multiselect = false; + openFileDialog.CheckFileExists = true; + + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + string FileToOpen = openFileDialog.FileName; + if (File.Exists(FileToOpen)) + { + translokator.ConvertFromXML(FileToOpen); + + LoadData(); + } + } + } } } diff --git a/Mafia2Libs/ResourceTypes/FileTypes/Translokator/Translokator.cs b/Mafia2Libs/ResourceTypes/FileTypes/Translokator/Translokator.cs index 2bd18f2d..4084b37f 100644 --- a/Mafia2Libs/ResourceTypes/FileTypes/Translokator/Translokator.cs +++ b/Mafia2Libs/ResourceTypes/FileTypes/Translokator/Translokator.cs @@ -1,15 +1,16 @@ -using System; -using System.Numerics; +using ResourceTypes.Actors; +using System; using System.ComponentModel; -using System.Diagnostics; using System.IO; -using Vortice.Mathematics; +using System.Numerics; +using System.Xml.Linq; using Utils.Extensions; -using Utils.VorticeUtils; +using Utils.Helpers.Reflection; +using Utils.Logging; using Utils.StringHelpers; using Utils.Types; -using Utils.Logging; -using ResourceTypes.Actors; +using Utils.VorticeUtils; +using Vortice.Mathematics; namespace ResourceTypes.Translokator { @@ -139,7 +140,7 @@ public class Object int numInstances; Instance[] instances; - [Browsable(false)] + [Browsable(false), PropertyIgnoreByReflector] public short NumInstance2 { get { return numInstance2; } set { numInstance2 = value; } @@ -165,7 +166,7 @@ public float GridMin { get { return gridMin; } set { gridMin = value; } } - [Browsable(false)] + [Browsable(false), PropertyIgnoreByReflector] public int NumInstances { get { return numInstances; } set { numInstances = value; } @@ -216,8 +217,8 @@ public struct ObjectGroupMetaInfo public class TranslokatorLoader { - public Grid[] Grids; - public ObjectGroup[] ObjectGroups; + public Grid[] Grids { get; set; } + public ObjectGroup[] ObjectGroups { get; set; } int version; int unk1; @@ -236,11 +237,17 @@ public short Unk2 { get { return unk2; } set { unk2 = value; } } + [PropertyIgnoreByReflector] public BoundingBox Bounds { get { return bounds; } set { bounds = value; } } + public TranslokatorLoader() + { + + } + public TranslokatorLoader(FileInfo info) { using (BinaryReader reader = new BinaryReader(File.Open(info.FullName, FileMode.Open))) @@ -686,6 +693,8 @@ private void InternalWriteToFile(BinaryWriter writer) for (int x = 0; x < objectGroup.Objects.Length; x++) { Object obj = objectGroup.Objects[x]; + obj.NumInstance2 = (short)obj.Instances.Length; + obj.NumInstances = obj.Instances.Length; writer.Write(obj.NumInstance2); writer.Write(obj.Unk02); writer.Write(obj.Name.Hash); @@ -711,5 +720,25 @@ private void InternalWriteToFile(BinaryWriter writer) ObjectGroups[i] = objectGroup; } } + + public void ConvertToXML(string Filename) + { + XElement Root = ReflectionHelpers.ConvertPropertyToXML(this); + Root.Save(Filename); + } + + public void ConvertFromXML(string Filename) + { + XElement LoadedDoc = XElement.Load(Filename); + TranslokatorLoader FileContents = ReflectionHelpers.ConvertToPropertyFromXML(LoadedDoc); + + // Copy data taken from loaded XML + Grids = FileContents.Grids; + ObjectGroups = FileContents.ObjectGroups; + Version = FileContents.Version; + Unk1 = FileContents.Unk1; + Unk2 = FileContents.Unk2; + Bounds = FileContents.Bounds; + } } } diff --git a/Mafia2Libs/Utils/Helpers/Reflection/ReflectionHelpers.cs b/Mafia2Libs/Utils/Helpers/Reflection/ReflectionHelpers.cs index e8c054ac..2cfda64d 100644 --- a/Mafia2Libs/Utils/Helpers/Reflection/ReflectionHelpers.cs +++ b/Mafia2Libs/Utils/Helpers/Reflection/ReflectionHelpers.cs @@ -1,9 +1,11 @@ using ResourceTypes.Prefab.Vehicle; using System; +using System.ComponentModel; using System.Globalization; using System.Linq; using System.Reflection; using System.Xml.Linq; +using static System.Resources.ResXFileRef; namespace Utils.Helpers.Reflection { @@ -157,7 +159,17 @@ public static T ConvertToPropertyFromXML(XElement Node) } else { - Info.SetValue(TypedObject, Convert.ChangeType(NodeContent, Info.PropertyType)); + var props = TypeDescriptor.GetProperties(TypedObject); + var converter = props[Info.Name].Converter; + + if (converter.CanConvertFrom(NodeContent.GetType())) + { + Info.SetValue(TypedObject, converter.ConvertFromInvariantString(NodeContent)); + } + else + { + Info.SetValue(TypedObject, Convert.ChangeType(NodeContent, Info.PropertyType)); + } } } } @@ -279,7 +291,17 @@ private static object InternalConvertProperty(XElement Node, Type ElementType) } else { - Info.SetValue(TypedObject, Convert.ChangeType(NodeContent, Info.PropertyType)); + var props = TypeDescriptor.GetProperties(TypedObject); + var converter = props[Info.Name].Converter; + + if (converter.CanConvertFrom(NodeContent.GetType())) + { + Info.SetValue(TypedObject, converter.ConvertFromInvariantString(NodeContent)); + } + else + { + Info.SetValue(TypedObject, Convert.ChangeType(NodeContent, Info.PropertyType)); + } } } } @@ -366,11 +388,16 @@ private static void ConvertObject(XElement Element, TObject PropertyDat } else { + var props = TypeDescriptor.GetProperties(PropertyData); + var converter = props[Info.Name].Converter; + object info = PropertyData.GetType().GetProperty(Info.Name).GetValue(PropertyData); // Sanity check for null info = (info != null ? info : ""); + info = converter.ConvertToString(info); + if (bForceAsAttribute) { Element.Add(new XAttribute(Info.Name, info)); diff --git a/Mafia2Libs/Utils/Types/Types.cs b/Mafia2Libs/Utils/Types/Types.cs index b18df6ea..5eb966bc 100644 --- a/Mafia2Libs/Utils/Types/Types.cs +++ b/Mafia2Libs/Utils/Types/Types.cs @@ -6,10 +6,11 @@ using Utils.StringHelpers; using Utils.Models; using System; +using Utils.Helpers.Reflection; namespace Utils.Types { - [TypeConverter(typeof(ExpandableObjectConverter))] + [TypeConverter(typeof(ExpandableObjectConverter)), PropertyClassAllowReflection] public class HashName { ulong hash; @@ -24,7 +25,7 @@ public string String { set { Set(value); } } - [ReadOnly(true)] + [ReadOnly(true), PropertyIgnoreByReflector] public string Hex { get { return string.Format("{0:X}", hash); } }