mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-25 16:32:55 +08:00
YPDB/XML conversion
This commit is contained in:
parent
12750ff595
commit
520eee6f81
@ -2,6 +2,8 @@
|
||||
using System.IO;
|
||||
using TC = System.ComponentModel.TypeConverterAttribute;
|
||||
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace CodeWalker.GameFiles
|
||||
{
|
||||
@ -137,25 +139,66 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
w.Write(Signature);
|
||||
}
|
||||
|
||||
|
||||
public void WriteXml(StringBuilder sb, int indent)
|
||||
{
|
||||
//YpdbXml.ValueTag(sb, indent, "SerializerVersion", SerializerVersion.ToString());
|
||||
//YpdbXml.ValueTag(sb, indent, "PoseMatcherVersion", PoseMatcherVersion.ToString());
|
||||
YpdbXml.ValueTag(sb, indent, "Signature", Signature.ToString());
|
||||
//YpdbXml.ValueTag(sb, indent, "Unk7", FloatUtil.ToString(Unk7));
|
||||
//YpdbXml.ValueTag(sb, indent, "Unk8", Unk8.ToString());
|
||||
YpdbXml.WriteRawArray(sb, BoneTags, indent, "BoneTags", "");
|
||||
WeightSet?.WriteXml(sb, indent);
|
||||
YpdbXml.WriteItemArray(sb, Samples, indent, "Samples");
|
||||
}
|
||||
public void ReadXml(XmlNode node)
|
||||
{
|
||||
SerializerVersion = 2;// Xml.GetChildIntAttribute(node, "SerializerVersion");
|
||||
PoseMatcherVersion = 0;// Xml.GetChildIntAttribute(node, "PoseMatcherVersion");
|
||||
Signature = Xml.GetChildUIntAttribute(node, "Signature");
|
||||
Unk7 = 0.033333f;// Xml.GetChildFloatAttribute(node, "Unk7");
|
||||
Unk8 = 1;// Xml.GetChildIntAttribute(node, "Unk8");
|
||||
BoneTags = Xml.GetChildRawUshortArray(node, "BoneTags");
|
||||
BoneTagsCount = (BoneTags?.Length ?? 0);
|
||||
WeightSet = new PoseMatcherWeightSet(node);
|
||||
Samples = XmlMeta.ReadItemArray<PoseMatcherMatchSample>(node, "Samples");
|
||||
SamplesCount = (Samples?.Length ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))]
|
||||
public class PoseMatcherMatchSample
|
||||
[TC(typeof(EXP))] public class PoseMatcherMatchSample : IMetaXmlItem
|
||||
{
|
||||
// rage::crPoseMatcherData::MatchSample
|
||||
public MetaHash ClipSet { get; set; } // from clip_sets.ymt/xml
|
||||
public MetaHash Clip { get; set; }
|
||||
public float Unk3 { get; set; }
|
||||
public float Offset { get; set; }//probably time offset, allows for multiple samples per clip
|
||||
public PoseMatcherPointCloud PointCloud { get; set; }
|
||||
|
||||
public PoseMatcherMatchSample()
|
||||
{ }
|
||||
public PoseMatcherMatchSample(DataReader r)
|
||||
{
|
||||
ClipSet = r.ReadUInt32();
|
||||
Clip = r.ReadUInt32();
|
||||
|
||||
Unk3 = r.ReadSingle();
|
||||
Offset = r.ReadSingle();
|
||||
|
||||
PointCloud = new PoseMatcherPointCloud(r);
|
||||
|
||||
switch (Offset)
|
||||
{
|
||||
case 0:
|
||||
case 0.266f:
|
||||
case 0.576f:
|
||||
case 0.366933f:
|
||||
case 0.599466f:
|
||||
case 0.506333f:
|
||||
case 1.09f:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(DataWriter w)
|
||||
@ -163,29 +206,56 @@ namespace CodeWalker.GameFiles
|
||||
w.Write(ClipSet);
|
||||
w.Write(Clip);
|
||||
|
||||
w.Write(Unk3);
|
||||
w.Write(Offset);
|
||||
|
||||
PointCloud.Write(w);
|
||||
}
|
||||
|
||||
public void WriteXml(StringBuilder sb, int indent)
|
||||
{
|
||||
YpdbXml.StringTag(sb, indent, "ClipSet", YpdbXml.HashString(ClipSet));
|
||||
YpdbXml.StringTag(sb, indent, "Clip", YpdbXml.HashString(Clip));
|
||||
YpdbXml.ValueTag(sb, indent, "Offset", FloatUtil.ToString(Offset));
|
||||
PointCloud?.WriteXml(sb, indent);
|
||||
}
|
||||
public void ReadXml(XmlNode node)
|
||||
{
|
||||
ClipSet = XmlMeta.GetHash(Xml.GetChildInnerText(node, "ClipSet"));
|
||||
Clip = XmlMeta.GetHash(Xml.GetChildInnerText(node, "Clip"));
|
||||
Offset = Xml.GetChildFloatAttribute(node, "Offset");
|
||||
PointCloud = new PoseMatcherPointCloud(node);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ClipSet}, {Clip}";
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))]
|
||||
public class PoseMatcherPointCloud
|
||||
[TC(typeof(EXP))] public class PoseMatcherPointCloud
|
||||
{
|
||||
// rage::crpmPointCloud
|
||||
public int PointsCount { get; set; }
|
||||
public Vector3[] Points { get; set; }
|
||||
public int Unk2_Count { get; set; } // == PointsCount
|
||||
public float[] Unk2_Items { get; set; }
|
||||
public int WeightsCount { get; set; } // == PointsCount
|
||||
public float[] Weights { get; set; }
|
||||
public Vector3 BoundsMin { get; set; }
|
||||
public Vector3 BoundsMax { get; set; }
|
||||
public float Unk5 { get; set; }
|
||||
public float WeightsSum { get; set; }
|
||||
|
||||
public PoseMatcherPointCloud(XmlNode n)
|
||||
{
|
||||
BoundsMin = Xml.GetChildVector3Attributes(n, "BoundsMin");
|
||||
BoundsMax = Xml.GetChildVector3Attributes(n, "BoundsMax");
|
||||
Points = Xml.GetChildRawVector3Array(n, "Points");
|
||||
PointsCount = (Points?.Length ?? 0);
|
||||
Weights = Xml.GetChildRawFloatArray(n, "Weights");
|
||||
WeightsCount = (Weights?.Length ?? 0);
|
||||
|
||||
var sum = 0.0f;
|
||||
if (Weights != null) foreach (var v in Weights) sum += v;
|
||||
WeightsSum = sum;
|
||||
}
|
||||
public PoseMatcherPointCloud(DataReader r)
|
||||
{
|
||||
PointsCount = r.ReadInt32();
|
||||
@ -197,22 +267,27 @@ namespace CodeWalker.GameFiles
|
||||
Points[i] = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
}
|
||||
|
||||
Unk2_Count = r.ReadInt32();
|
||||
if (Unk2_Count > 0)
|
||||
WeightsCount = r.ReadInt32();
|
||||
if (WeightsCount > 0)
|
||||
{
|
||||
Unk2_Items = new float[Unk2_Count];
|
||||
Weights = new float[WeightsCount];
|
||||
|
||||
for (int i = 0; i < Unk2_Count; i++)
|
||||
Unk2_Items[i] = r.ReadSingle();
|
||||
for (int i = 0; i < WeightsCount; i++)
|
||||
Weights[i] = r.ReadSingle();
|
||||
}
|
||||
|
||||
BoundsMin = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
BoundsMax = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
|
||||
|
||||
Unk5 = r.ReadSingle();
|
||||
WeightsSum = r.ReadSingle();
|
||||
|
||||
if (PointsCount != Unk2_Count)
|
||||
if (PointsCount != WeightsCount)
|
||||
{ } // no hit
|
||||
|
||||
//var sum = 0.0f;
|
||||
//if (Weights != null) foreach (var v in Weights) sum += v;
|
||||
//if (WeightsSum != sum)
|
||||
//{ } //no hit
|
||||
}
|
||||
|
||||
public void Write(DataWriter w)
|
||||
@ -224,22 +299,29 @@ namespace CodeWalker.GameFiles
|
||||
w.Write(point);
|
||||
}
|
||||
|
||||
w.Write(Unk2_Count);
|
||||
if (Unk2_Count > 0)
|
||||
w.Write(WeightsCount);
|
||||
if (WeightsCount > 0)
|
||||
{
|
||||
foreach (var entry in Unk2_Items)
|
||||
foreach (var entry in Weights)
|
||||
w.Write(entry);
|
||||
}
|
||||
|
||||
w.Write(BoundsMin);
|
||||
w.Write(BoundsMax);
|
||||
|
||||
w.Write(Unk5);
|
||||
w.Write(WeightsSum);
|
||||
}
|
||||
|
||||
public void WriteXml(StringBuilder sb, int indent)
|
||||
{
|
||||
YpdbXml.SelfClosingTag(sb, indent, "BoundsMin " + FloatUtil.GetVector3XmlString(BoundsMin));
|
||||
YpdbXml.SelfClosingTag(sb, indent, "BoundsMax " + FloatUtil.GetVector3XmlString(BoundsMax));
|
||||
YpdbXml.WriteRawArray(sb, Points, indent, "Points", "", YpdbXml.FormatVector3, 1);
|
||||
YpdbXml.WriteRawArray(sb, Weights, indent, "Weights", "", FloatUtil.ToString);
|
||||
}
|
||||
}
|
||||
|
||||
[TC(typeof(EXP))]
|
||||
public class PoseMatcherWeightSet
|
||||
[TC(typeof(EXP))] public class PoseMatcherWeightSet
|
||||
{
|
||||
// rage::crWeightSet
|
||||
public int WeightsCount { get; set; }
|
||||
@ -256,6 +338,11 @@ namespace CodeWalker.GameFiles
|
||||
Weights[i] = r.ReadSingle();
|
||||
}
|
||||
}
|
||||
public PoseMatcherWeightSet(XmlNode n)
|
||||
{
|
||||
Weights = Xml.GetChildRawFloatArray(n, "Weights");
|
||||
WeightsCount = (Weights?.Length ?? 0);
|
||||
}
|
||||
|
||||
public void Write(DataWriter w)
|
||||
{
|
||||
@ -266,5 +353,59 @@ namespace CodeWalker.GameFiles
|
||||
w.Write(weight);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteXml(StringBuilder sb, int indent)
|
||||
{
|
||||
YpdbXml.WriteRawArray(sb, Weights, indent, "Weights", "", FloatUtil.ToString);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class YpdbXml : MetaXmlBase
|
||||
{
|
||||
|
||||
public static string GetXml(YpdbFile ypdb)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine(XmlHeader);
|
||||
|
||||
if ((ypdb != null) && (ypdb.WeightSet != null))
|
||||
{
|
||||
var name = "PoseMatcher";
|
||||
|
||||
OpenTag(sb, 0, name);
|
||||
|
||||
ypdb.WriteXml(sb, 1);
|
||||
|
||||
CloseTag(sb, 0, name);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class XmlYpdb
|
||||
{
|
||||
|
||||
public static YpdbFile GetYpdb(string xml)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(xml);
|
||||
return GetYpdb(doc);
|
||||
}
|
||||
|
||||
public static YpdbFile GetYpdb(XmlDocument doc)
|
||||
{
|
||||
YpdbFile ypdb = new YpdbFile();
|
||||
ypdb.ReadXml(doc.DocumentElement);
|
||||
return ypdb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -4546,7 +4546,12 @@ namespace CodeWalker.GameFiles
|
||||
if (ypdb != null)
|
||||
{
|
||||
var odata = entry.File.ExtractFile(entry as RpfFileEntry);
|
||||
var ndata = ypdb.Save();
|
||||
//var ndata = ypdb.Save();
|
||||
|
||||
var xml = YpdbXml.GetXml(ypdb);
|
||||
var ypdb2 = XmlYpdb.GetYpdb(xml);
|
||||
var ndata = ypdb2.Save();
|
||||
|
||||
if (ndata.Length == odata.Length)
|
||||
{
|
||||
for (int i = 0; i < ndata.Length; i++)
|
||||
|
@ -122,6 +122,11 @@ namespace CodeWalker.GameFiles
|
||||
YvrFile yvr = RpfFile.GetFile<YvrFile>(e, data);
|
||||
return GetXml(yvr, out filename);
|
||||
}
|
||||
else if (fnl.EndsWith(".ypdb"))
|
||||
{
|
||||
YpdbFile ypdb = RpfFile.GetFile<YpdbFile>(e, data);
|
||||
return GetXml(ypdb, out filename);
|
||||
}
|
||||
else if (fnl.EndsWith(".awc"))
|
||||
{
|
||||
AwcFile awc = RpfFile.GetFile<AwcFile>(e, data);
|
||||
@ -274,6 +279,12 @@ namespace CodeWalker.GameFiles
|
||||
filename = fn + ".xml";
|
||||
return YvrXml.GetXml(yvr);
|
||||
}
|
||||
public static string GetXml(YpdbFile ypdb, out string filename)
|
||||
{
|
||||
var fn = (ypdb?.Name) ?? "";
|
||||
filename = fn + ".xml";
|
||||
return YpdbXml.GetXml(ypdb);
|
||||
}
|
||||
public static string GetXml(AwcFile awc, out string filename, string outputfolder)
|
||||
{
|
||||
var fn = (awc?.Name) ?? "";
|
||||
@ -2207,6 +2218,7 @@ namespace CodeWalker.GameFiles
|
||||
Yvr = 18,
|
||||
Awc = 19,
|
||||
Heightmap = 20,
|
||||
Ypdb = 21,
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,6 +55,8 @@ namespace CodeWalker.GameFiles
|
||||
return GetCacheFileData(doc);
|
||||
case MetaFormat.Heightmap:
|
||||
return GetHeightmapData(doc);
|
||||
case MetaFormat.Ypdb:
|
||||
return GetYpdbData(doc);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -178,6 +180,12 @@ namespace CodeWalker.GameFiles
|
||||
if (hmf.MaxHeights == null) return null;
|
||||
return hmf.Save();
|
||||
}
|
||||
public static byte[] GetYpdbData(XmlDocument doc)
|
||||
{
|
||||
var ypdb = XmlYpdb.GetYpdb(doc);
|
||||
if (ypdb.WeightSet == null) return null;
|
||||
return ypdb.Save();
|
||||
}
|
||||
|
||||
|
||||
public static string GetXMLFormatName(MetaFormat mformat)
|
||||
@ -204,6 +212,7 @@ namespace CodeWalker.GameFiles
|
||||
case MetaFormat.Awc: return "AWC XML";
|
||||
case MetaFormat.CacheFile: return "CacheFile XML";
|
||||
case MetaFormat.Heightmap: return "Heightmap XML";
|
||||
case MetaFormat.Ypdb: return "YPDB XML";
|
||||
default: return "XML";
|
||||
}
|
||||
}
|
||||
@ -294,6 +303,10 @@ namespace CodeWalker.GameFiles
|
||||
{
|
||||
mformat = MetaFormat.Heightmap;
|
||||
}
|
||||
if (fnamel.EndsWith(".ypdb.xml"))
|
||||
{
|
||||
mformat = MetaFormat.Ypdb;
|
||||
}
|
||||
return mformat;
|
||||
}
|
||||
|
||||
|
@ -309,7 +309,7 @@ namespace CodeWalker
|
||||
InitFileType(".awc", "Audio Wave Container", 22, FileTypeAction.ViewAwc, true);
|
||||
InitFileType(".rel", "Audio Data (REL)", 23, FileTypeAction.ViewRel, true);
|
||||
InitFileType(".nametable", "Name Table", 5, FileTypeAction.ViewNametable);
|
||||
InitFileType(".ypdb", "Pose Matcher Database", 9, FileTypeAction.ViewYpdb);
|
||||
InitFileType(".ypdb", "Pose Matcher Database", 9, FileTypeAction.ViewYpdb, true);
|
||||
|
||||
InitSubFileType(".dat", "cache_y.dat", "Cache File", 6, FileTypeAction.ViewCacheDat, true);
|
||||
InitSubFileType(".dat", "heightmap.dat", "Heightmap", 6, FileTypeAction.ViewHeightmap, true);
|
||||
@ -1813,9 +1813,9 @@ namespace CodeWalker
|
||||
private void ViewYpdb(string name, string path, byte[] data, RpfFileEntry e)
|
||||
{
|
||||
var ypdb = RpfFile.GetFile<YpdbFile>(e, data);
|
||||
GenericForm f = new GenericForm(this);
|
||||
MetaForm f = new MetaForm(this);
|
||||
f.Show();
|
||||
f.LoadFile(ypdb, ypdb.RpfFileEntry);
|
||||
f.LoadMeta(ypdb);
|
||||
}
|
||||
|
||||
private RpfFileEntry CreateFileEntry(string name, string path, ref byte[] data)
|
||||
|
@ -374,6 +374,20 @@ namespace CodeWalker.Forms
|
||||
metaFormat = MetaFormat.Heightmap;
|
||||
}
|
||||
}
|
||||
public void LoadMeta(YpdbFile ypdb)
|
||||
{
|
||||
var fn = ((ypdb?.RpfFileEntry?.Name) ?? "") + ".xml";
|
||||
Xml = MetaXml.GetXml(ypdb, out fn);
|
||||
FileName = fn;
|
||||
RawPropertyGrid.SelectedObject = ypdb;
|
||||
rpfFileEntry = ypdb?.RpfFileEntry;
|
||||
modified = false;
|
||||
metaFormat = MetaFormat.XML;
|
||||
if (ypdb?.RpfFileEntry != null)
|
||||
{
|
||||
metaFormat = MetaFormat.Ypdb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user