2020-03-02 04:48:30 +08:00
|
|
|
|
using SharpDX;
|
|
|
|
|
using System;
|
2019-11-21 21:34:27 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
2020-03-02 04:48:30 +08:00
|
|
|
|
using System.IO;
|
2019-11-21 21:34:27 +08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
2022-01-31 16:39:42 +08:00
|
|
|
|
using TC = System.ComponentModel.TypeConverterAttribute;
|
|
|
|
|
using EXP = System.ComponentModel.ExpandableObjectConverter;
|
|
|
|
|
using System.Xml;
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Copyright(c) 2017 Neodymium
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//ruthlessly stolen
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace CodeWalker.GameFiles
|
|
|
|
|
{
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionDictionary : ResourceFileBase
|
2019-11-21 21:34:27 +08:00
|
|
|
|
{
|
|
|
|
|
// pgDictionaryBase
|
|
|
|
|
// pgDictionary<crExpressions>
|
|
|
|
|
public override long BlockLength => 0x40;
|
|
|
|
|
|
|
|
|
|
// structure data
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public uint Unknown_10h { get; set; } = 0;
|
|
|
|
|
public uint Unknown_14h { get; set; } = 0;
|
|
|
|
|
public uint Unknown_18h { get; set; } = 1;
|
|
|
|
|
public uint Unknown_1Ch { get; set; } = 0;
|
2020-03-02 04:48:30 +08:00
|
|
|
|
public ResourceSimpleList64_s<MetaHash> ExpressionNameHashes { get; set; }
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public ResourcePointerList64<Expression> Expressions { get; set; }
|
|
|
|
|
|
2020-03-06 00:02:40 +08:00
|
|
|
|
|
|
|
|
|
public Dictionary<MetaHash, Expression> ExprMap { get; set; }
|
|
|
|
|
|
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
|
|
|
|
{
|
|
|
|
|
base.Read(reader, parameters);
|
|
|
|
|
|
|
|
|
|
// read structure data
|
|
|
|
|
this.Unknown_10h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_14h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_18h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_1Ch = reader.ReadUInt32();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
this.ExpressionNameHashes = reader.ReadBlock<ResourceSimpleList64_s<MetaHash>>();
|
2019-11-21 21:34:27 +08:00
|
|
|
|
this.Expressions = reader.ReadBlock<ResourcePointerList64<Expression>>();
|
2020-03-06 00:02:40 +08:00
|
|
|
|
|
|
|
|
|
BuildMap();
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
}
|
|
|
|
|
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
|
|
|
|
{
|
|
|
|
|
base.Write(writer, parameters);
|
|
|
|
|
|
|
|
|
|
// write structure data
|
|
|
|
|
writer.Write(this.Unknown_10h);
|
|
|
|
|
writer.Write(this.Unknown_14h);
|
|
|
|
|
writer.Write(this.Unknown_18h);
|
|
|
|
|
writer.Write(this.Unknown_1Ch);
|
|
|
|
|
writer.WriteBlock(this.ExpressionNameHashes);
|
|
|
|
|
writer.WriteBlock(this.Expressions);
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (Expressions?.data_items != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var e in Expressions.data_items)
|
|
|
|
|
{
|
|
|
|
|
YedXml.OpenTag(sb, indent, "Item");
|
|
|
|
|
e.WriteXml(sb, indent + 1);
|
|
|
|
|
YedXml.CloseTag(sb, indent, "Item");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
var expressions = new List<Expression>();
|
|
|
|
|
var expressionhashes = new List<MetaHash>();
|
|
|
|
|
|
|
|
|
|
var inodes = node.SelectNodes("Item");
|
|
|
|
|
if (inodes != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (XmlNode inode in inodes)
|
|
|
|
|
{
|
|
|
|
|
var e = new Expression();
|
|
|
|
|
e.ReadXml(inode);
|
|
|
|
|
expressions.Add(e);
|
|
|
|
|
expressionhashes.Add(e.NameHash);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExpressionNameHashes = new ResourceSimpleList64_s<MetaHash>();
|
|
|
|
|
ExpressionNameHashes.data_items = expressionhashes.ToArray();
|
|
|
|
|
Expressions = new ResourcePointerList64<Expression>();
|
|
|
|
|
Expressions.data_items = expressions.ToArray();
|
|
|
|
|
|
|
|
|
|
BuildMap();
|
|
|
|
|
}
|
|
|
|
|
public static void WriteXmlNode(ExpressionDictionary d, StringBuilder sb, int indent, string name = "ExpressionDictionary")
|
|
|
|
|
{
|
|
|
|
|
if (d == null) return;
|
|
|
|
|
if ((d.Expressions?.data_items == null) || (d.Expressions.data_items.Length == 0))
|
|
|
|
|
{
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
YedXml.OpenTag(sb, indent, name);
|
|
|
|
|
d.WriteXml(sb, indent + 1);
|
|
|
|
|
YedXml.CloseTag(sb, indent, name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public static ExpressionDictionary ReadXmlNode(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
if (node == null) return null;
|
|
|
|
|
var ed = new ExpressionDictionary();
|
|
|
|
|
ed.ReadXml(node);
|
|
|
|
|
return ed;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
|
|
|
|
public override IResourceBlock[] GetReferences()
|
|
|
|
|
{
|
|
|
|
|
var list = new List<IResourceBlock>(base.GetReferences());
|
|
|
|
|
return list.ToArray();
|
|
|
|
|
}
|
|
|
|
|
public override Tuple<long, IResourceBlock>[] GetParts()
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<long, IResourceBlock>[] {
|
|
|
|
|
new Tuple<long, IResourceBlock>(0x20, ExpressionNameHashes),
|
|
|
|
|
new Tuple<long, IResourceBlock>(0x30, Expressions)
|
|
|
|
|
};
|
|
|
|
|
}
|
2020-03-06 00:02:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void BuildMap()
|
|
|
|
|
{
|
|
|
|
|
ExprMap = new Dictionary<MetaHash, Expression>();
|
|
|
|
|
|
|
|
|
|
if ((Expressions?.data_items != null) && (ExpressionNameHashes?.data_items != null))
|
|
|
|
|
{
|
|
|
|
|
var exprs = Expressions.data_items;
|
|
|
|
|
var names = ExpressionNameHashes.data_items;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < exprs.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var expr = exprs[i];
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var name = (i < names.Length) ? names[i] : (MetaHash)JenkHash.GenHash(expr?.GetShortName() ?? "");
|
|
|
|
|
expr.NameHash = name;
|
2020-03-06 00:02:40 +08:00
|
|
|
|
ExprMap[name] = expr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class Expression : ResourceSystemBlock
|
2019-11-21 21:34:27 +08:00
|
|
|
|
{
|
|
|
|
|
// pgBase
|
|
|
|
|
// crExpressions
|
|
|
|
|
public override long BlockLength => 0x90;
|
|
|
|
|
|
|
|
|
|
// structure data
|
|
|
|
|
public uint VFT { get; set; }
|
2020-03-02 04:48:30 +08:00
|
|
|
|
public uint Unknown_4h { get; set; } = 1;
|
|
|
|
|
public uint Unknown_8h { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_Ch { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_10h { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_14h { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_18h { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_1Ch { get; set; } // 0x00000000
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public ResourcePointerList64<ExpressionStream> Streams { get; set; }
|
|
|
|
|
public ResourceSimpleList64_s<ExpressionBoneTrack> BoneTracks { get; set; } // bone tags / animation tracks
|
|
|
|
|
public ResourceSimpleList64<ExpressionJiggleBlock> JiggleData { get; set; } //compiled list of jiggles data from all jiggle Stream nodes
|
|
|
|
|
public ResourceSimpleList64_s<MetaHash> ItemHashes { get; set; } // maybe variables? only for: faceinit.expr, independent_mover.expr
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public ulong NamePointer { get; set; }
|
2020-03-02 04:48:30 +08:00
|
|
|
|
public ushort NameLength { get; set; } // name len
|
|
|
|
|
public ushort NameCapacity { get; set; } // name len+1
|
|
|
|
|
public uint Unknown_6Ch { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_70h { get; set; } = 1;
|
|
|
|
|
public MetaHash Unknown_74h { get; set; } // seems to be a hash?
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public uint MaxStreamSize { get; set; } // max length of any item in Streams
|
2020-03-02 04:48:30 +08:00
|
|
|
|
public uint Unknown_7Ch { get; set; } // 3 or 2
|
|
|
|
|
public uint Unknown_80h { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_84h { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_88h { get; set; } // 0x00000000
|
|
|
|
|
public uint Unknown_8Ch { get; set; } // 0x00000000
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
|
|
|
|
// reference data
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public string_r Name { get; set; }
|
|
|
|
|
public MetaHash NameHash { get; set; }
|
2020-03-06 00:02:40 +08:00
|
|
|
|
|
|
|
|
|
public Dictionary<ExpressionBoneTrack, ExpressionBoneTrack> BoneTracksDict { get; set; }
|
|
|
|
|
|
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
|
|
|
|
{
|
|
|
|
|
// read structure data
|
|
|
|
|
this.VFT = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_4h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_8h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_Ch = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_10h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_14h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_18h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_1Ch = reader.ReadUInt32();
|
2022-01-31 16:39:42 +08:00
|
|
|
|
this.Streams = reader.ReadBlock<ResourcePointerList64<ExpressionStream>>();
|
2020-03-06 00:02:40 +08:00
|
|
|
|
this.BoneTracks = reader.ReadBlock<ResourceSimpleList64_s<ExpressionBoneTrack>>();
|
2022-01-31 16:39:42 +08:00
|
|
|
|
this.JiggleData = reader.ReadBlock<ResourceSimpleList64<ExpressionJiggleBlock>>();
|
|
|
|
|
this.ItemHashes = reader.ReadBlock<ResourceSimpleList64_s<MetaHash>>();
|
2019-11-21 21:34:27 +08:00
|
|
|
|
this.NamePointer = reader.ReadUInt64();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
this.NameLength = reader.ReadUInt16();
|
|
|
|
|
this.NameCapacity = reader.ReadUInt16();
|
2019-11-21 21:34:27 +08:00
|
|
|
|
this.Unknown_6Ch = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_70h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_74h = reader.ReadUInt32();
|
2022-01-31 16:39:42 +08:00
|
|
|
|
this.MaxStreamSize = reader.ReadUInt32();
|
2019-11-21 21:34:27 +08:00
|
|
|
|
this.Unknown_7Ch = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_80h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_84h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_88h = reader.ReadUInt32();
|
|
|
|
|
this.Unknown_8Ch = reader.ReadUInt32();
|
|
|
|
|
|
|
|
|
|
// read reference data
|
|
|
|
|
this.Name = reader.ReadBlockAt<string_r>(
|
|
|
|
|
this.NamePointer // offset
|
|
|
|
|
);
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
JenkIndex.Ensure(GetShortName());
|
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2020-03-06 00:02:40 +08:00
|
|
|
|
BuildBoneTracksDict();
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
#region testing
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
|
|
|
|
//if (Streams?.data_items != null)
|
|
|
|
|
//{ }
|
|
|
|
|
|
|
|
|
|
////if ((this.JiggleData?.data_items?.Length ?? 0) > 0)
|
|
|
|
|
//{
|
|
|
|
|
// var cnt1 = JiggleData?.data_items?.Length ?? 0;
|
|
|
|
|
// var cnt2 = 0;
|
|
|
|
|
// foreach (var stream in Streams.data_items)
|
|
|
|
|
// {
|
|
|
|
|
// foreach (var node in stream.Items)
|
|
|
|
|
// {
|
|
|
|
|
// if (node is ExpressionNodeJiggle jnode)
|
|
|
|
|
// {
|
|
|
|
|
// var trackrot = BoneTracks.data_items[jnode.BoneTrackRot];
|
|
|
|
|
// var trackpos = BoneTracks.data_items[jnode.BoneTrackPos];
|
|
|
|
|
// var jd1 = jnode.JiggleData;
|
|
|
|
|
// var jd2 = JiggleData.data_items[cnt2].JiggleData;
|
|
|
|
|
// if (!jd1.Compare(jd2))
|
|
|
|
|
// { }//no hit
|
|
|
|
|
// if (jd2.BoneTag != trackrot.BoneTag)
|
|
|
|
|
// { }//no hit
|
|
|
|
|
// cnt2++;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// if (cnt1 != cnt2)
|
|
|
|
|
// { }//no hit
|
|
|
|
|
//}
|
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
//long tlen = 0;
|
2022-01-31 16:39:42 +08:00
|
|
|
|
//if (Streams?.data_items != null) foreach (var item in Streams.data_items) tlen = Math.Max(tlen, item.BlockLength);
|
|
|
|
|
//if (MaxStreamSize != tlen)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
//{ }//no hit
|
|
|
|
|
|
|
|
|
|
//if (Unknown_4h != 1)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_8h != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_Ch != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_10h != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_14h != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_18h != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_1Ch != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (NameLength != (Name?.Value?.Length ?? 0))
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (NameCapacity != (NameLength + 1))
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_6Ch != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_70h != 1)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//switch (Unknown_74h)
|
|
|
|
|
//{
|
|
|
|
|
// default:
|
|
|
|
|
// break;
|
|
|
|
|
//}
|
|
|
|
|
//switch (Unknown_7Ch)
|
|
|
|
|
//{
|
|
|
|
|
// case 3:
|
|
|
|
|
// case 2:
|
|
|
|
|
// break;
|
|
|
|
|
// default:
|
|
|
|
|
// break;//no hit
|
|
|
|
|
//}
|
|
|
|
|
//if (Unknown_80h != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_84h != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_88h != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
//if (Unknown_8Ch != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
|
|
|
|
{
|
|
|
|
|
// update structure data
|
|
|
|
|
this.NamePointer = (ulong)(this.Name != null ? this.Name.FilePosition : 0);
|
|
|
|
|
|
|
|
|
|
// write structure data
|
|
|
|
|
writer.Write(this.VFT);
|
|
|
|
|
writer.Write(this.Unknown_4h);
|
|
|
|
|
writer.Write(this.Unknown_8h);
|
|
|
|
|
writer.Write(this.Unknown_Ch);
|
|
|
|
|
writer.Write(this.Unknown_10h);
|
|
|
|
|
writer.Write(this.Unknown_14h);
|
|
|
|
|
writer.Write(this.Unknown_18h);
|
|
|
|
|
writer.Write(this.Unknown_1Ch);
|
2022-01-31 16:39:42 +08:00
|
|
|
|
writer.WriteBlock(this.Streams);
|
2020-03-06 00:02:40 +08:00
|
|
|
|
writer.WriteBlock(this.BoneTracks);
|
2022-01-31 16:39:42 +08:00
|
|
|
|
writer.WriteBlock(this.JiggleData);
|
|
|
|
|
writer.WriteBlock(this.ItemHashes);
|
2019-11-21 21:34:27 +08:00
|
|
|
|
writer.Write(this.NamePointer);
|
2020-03-02 04:48:30 +08:00
|
|
|
|
writer.Write(this.NameLength);
|
|
|
|
|
writer.Write(this.NameCapacity);
|
2019-11-21 21:34:27 +08:00
|
|
|
|
writer.Write(this.Unknown_6Ch);
|
|
|
|
|
writer.Write(this.Unknown_70h);
|
|
|
|
|
writer.Write(this.Unknown_74h);
|
2022-01-31 16:39:42 +08:00
|
|
|
|
writer.Write(this.MaxStreamSize);
|
2019-11-21 21:34:27 +08:00
|
|
|
|
writer.Write(this.Unknown_7Ch);
|
|
|
|
|
writer.Write(this.Unknown_80h);
|
|
|
|
|
writer.Write(this.Unknown_84h);
|
|
|
|
|
writer.Write(this.Unknown_88h);
|
|
|
|
|
writer.Write(this.Unknown_8Ch);
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.StringTag(sb, indent, "Name", Name?.Value ?? "");
|
|
|
|
|
YedXml.StringTag(sb, indent, "Unk74", YedXml.HashString(Unknown_74h));
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk7C", Unknown_7Ch.ToString());
|
|
|
|
|
|
|
|
|
|
if ((BoneTracks?.data_items?.Length ?? 0) > 0)
|
|
|
|
|
{
|
|
|
|
|
YedXml.WriteItemArray(sb, BoneTracks.data_items, indent, "BoneTracks");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((Streams?.data_items?.Length ?? 0) > 0)
|
|
|
|
|
{
|
|
|
|
|
YedXml.WriteItemArray(sb, Streams.data_items, indent, "Streams");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
Name = new string_r();
|
|
|
|
|
Name.Value = Xml.GetChildInnerText(node, "Name");
|
|
|
|
|
NameLength = (ushort)Name.Value.Length;
|
|
|
|
|
NameCapacity = (ushort)(NameLength + 1);
|
|
|
|
|
NameHash = JenkHash.GenHash(GetShortName());
|
|
|
|
|
Unknown_74h = XmlMeta.GetHash(Xml.GetChildInnerText(node, "Unk74"));
|
|
|
|
|
Unknown_7Ch = Xml.GetChildUIntAttribute(node, "Unk7C", "value");
|
|
|
|
|
|
|
|
|
|
BoneTracks = new ResourceSimpleList64_s<ExpressionBoneTrack>();
|
|
|
|
|
BoneTracks.data_items = XmlMeta.ReadItemArray<ExpressionBoneTrack>(node, "BoneTracks");
|
|
|
|
|
|
|
|
|
|
Streams = new ResourcePointerList64<ExpressionStream>();
|
|
|
|
|
Streams.data_items = XmlMeta.ReadItemArray<ExpressionStream>(node, "Streams");
|
|
|
|
|
|
|
|
|
|
BuildBoneTracksDict();
|
|
|
|
|
BuildJiggleData();
|
|
|
|
|
UpdateItemHashes();
|
|
|
|
|
UpdateStreamBuffers();
|
|
|
|
|
}
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
|
|
|
|
public override IResourceBlock[] GetReferences()
|
|
|
|
|
{
|
|
|
|
|
var list = new List<IResourceBlock>();
|
|
|
|
|
if (Name != null) list.Add(Name);
|
|
|
|
|
return list.ToArray();
|
|
|
|
|
}
|
|
|
|
|
public override Tuple<long, IResourceBlock>[] GetParts()
|
|
|
|
|
{
|
|
|
|
|
return new Tuple<long, IResourceBlock>[] {
|
2022-01-31 16:39:42 +08:00
|
|
|
|
new Tuple<long, IResourceBlock>(0x20, Streams),
|
2020-03-06 00:02:40 +08:00
|
|
|
|
new Tuple<long, IResourceBlock>(0x30, BoneTracks),
|
2022-01-31 16:39:42 +08:00
|
|
|
|
new Tuple<long, IResourceBlock>(0x40, JiggleData),
|
|
|
|
|
new Tuple<long, IResourceBlock>(0x50, ItemHashes)
|
2019-11-21 21:34:27 +08:00
|
|
|
|
};
|
|
|
|
|
}
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
|
|
|
|
|
2020-03-06 00:02:40 +08:00
|
|
|
|
public void BuildBoneTracksDict()
|
|
|
|
|
{
|
|
|
|
|
BoneTracksDict = new Dictionary<ExpressionBoneTrack, ExpressionBoneTrack>();
|
|
|
|
|
|
|
|
|
|
if (BoneTracks?.data_items == null) return;
|
|
|
|
|
|
|
|
|
|
var mapto = new ExpressionBoneTrack();
|
|
|
|
|
for(int i=0; i< BoneTracks.data_items.Length;i++)
|
|
|
|
|
{
|
|
|
|
|
var bt = BoneTracks.data_items[i];
|
|
|
|
|
if ((bt.Flags & 128) == 0)
|
|
|
|
|
{
|
|
|
|
|
mapto = bt;
|
|
|
|
|
}
|
|
|
|
|
else if (bt.BoneTag != 0)
|
|
|
|
|
{
|
|
|
|
|
bt.Flags &= 0x7F;
|
|
|
|
|
BoneTracksDict[bt] = mapto;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void BuildJiggleData()
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var jiggles = new List<ExpressionJiggleBlock>();
|
|
|
|
|
if (Streams?.data_items != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var stream in Streams.data_items)
|
|
|
|
|
{
|
|
|
|
|
foreach (var node in stream.Items)
|
|
|
|
|
{
|
|
|
|
|
if (node is ExpressionNodeJiggle jnode)
|
|
|
|
|
{
|
|
|
|
|
var jiggle = new ExpressionJiggleBlock();
|
|
|
|
|
jiggle.JiggleData = jnode.JiggleData.Clone();
|
|
|
|
|
jiggles.Add(jiggle);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
JiggleData = new ResourceSimpleList64<ExpressionJiggleBlock>();
|
|
|
|
|
JiggleData.data_items = jiggles.ToArray();
|
2020-03-05 07:40:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void UpdateItemHashes()
|
2020-03-05 07:40:54 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var dict = new Dictionary<MetaHash, int>();
|
|
|
|
|
if (Streams?.data_items != null)
|
2020-03-05 07:40:54 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
foreach (var stream in Streams.data_items)
|
2020-03-05 07:40:54 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
foreach (var item in stream.Items)
|
|
|
|
|
{
|
|
|
|
|
if (item is ExpressionNodeS3 s3)
|
|
|
|
|
{
|
|
|
|
|
dict[s3.Hash] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var list = dict.Keys.ToList();
|
|
|
|
|
list.Sort((a, b) => a.Hash.CompareTo(b.Hash));
|
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
dict[list[i]] = i;
|
|
|
|
|
}
|
|
|
|
|
if (Streams?.data_items != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var stream in Streams.data_items)
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in stream.Items)
|
|
|
|
|
{
|
|
|
|
|
if (item is ExpressionNodeS3 s3)
|
|
|
|
|
{
|
|
|
|
|
var index = dict[s3.Hash];
|
|
|
|
|
s3.HashIndex = (byte)index;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-05 07:40:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
ItemHashes = new ResourceSimpleList64_s<MetaHash>();
|
|
|
|
|
ItemHashes.data_items = list.ToArray();
|
2020-03-05 07:40:54 +08:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void UpdateStreamBuffers()
|
2020-03-05 07:40:54 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
MaxStreamSize = 0;
|
|
|
|
|
if (Streams?.data_items != null)
|
2020-03-05 07:40:54 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
foreach (var item in Streams.data_items)
|
2020-03-05 07:40:54 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
//item.FlattenHierarchy();
|
|
|
|
|
item.WriteItems(); //makes sure the data buffers are updated to the correct length!
|
|
|
|
|
MaxStreamSize = Math.Max(MaxStreamSize, (uint)item.BlockLength);
|
2020-03-05 07:40:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
}
|
2020-03-05 07:40:54 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public string GetShortName()
|
|
|
|
|
{
|
|
|
|
|
return Path.GetFileNameWithoutExtension(Name?.Value ?? "").ToLowerInvariant();
|
2020-03-05 07:40:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return (Name?.ToString() ?? base.ToString()) + " " + Unknown_74h.ToString();
|
|
|
|
|
}
|
2020-03-05 07:40:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TC(typeof(EXP))] public class ExpressionStream : ResourceSystemBlock, IMetaXmlItem
|
2019-11-21 21:34:27 +08:00
|
|
|
|
{
|
|
|
|
|
public override long BlockLength
|
|
|
|
|
{
|
|
|
|
|
get { return 16 + Data1.Length + Data2.Length + Data3.Length; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// structure data
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public MetaHash NameHash { get; set; }//presumably name hash
|
2020-03-05 07:40:54 +08:00
|
|
|
|
public uint Data1Length { get; set; }
|
|
|
|
|
public uint Data2Length { get; set; }
|
|
|
|
|
public ushort Data3Length { get; set; }
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public ushort Unk0E { get; set; }//what is this? possibly max hierarchy depth
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public byte[] Data1 { get; set; }
|
|
|
|
|
public byte[] Data2 { get; set; }
|
|
|
|
|
public byte[] Data3 { get; set; }
|
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public ExpressionNodeBase[] Items { get; set; }
|
|
|
|
|
public ExpressionNodeBase[] Roots { get; set; }
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
|
|
|
|
{
|
|
|
|
|
// read structure data
|
2022-01-31 16:39:42 +08:00
|
|
|
|
this.NameHash = reader.ReadUInt32();
|
2020-03-05 07:40:54 +08:00
|
|
|
|
this.Data1Length = reader.ReadUInt32();
|
|
|
|
|
this.Data2Length = reader.ReadUInt32();
|
|
|
|
|
this.Data3Length = reader.ReadUInt16();
|
2022-01-31 16:39:42 +08:00
|
|
|
|
this.Unk0E = reader.ReadUInt16();
|
2020-03-05 07:40:54 +08:00
|
|
|
|
this.Data1 = reader.ReadBytes((int)Data1Length);
|
|
|
|
|
this.Data2 = reader.ReadBytes((int)Data2Length);
|
|
|
|
|
this.Data3 = reader.ReadBytes((int)Data3Length);
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
ReadItems();
|
|
|
|
|
BuildHierarchy();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-03-05 07:40:54 +08:00
|
|
|
|
|
|
|
|
|
#region testing
|
2022-01-31 16:39:42 +08:00
|
|
|
|
//FlattenHierarchy();
|
|
|
|
|
//WriteItems();
|
|
|
|
|
//switch (Unk1)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
//{
|
|
|
|
|
// case 2:
|
|
|
|
|
// case 8:
|
|
|
|
|
// case 4:
|
|
|
|
|
// case 6:
|
|
|
|
|
// case 59:
|
|
|
|
|
// case 5:
|
|
|
|
|
// case 12:
|
|
|
|
|
// case 58:
|
|
|
|
|
// case 20:
|
|
|
|
|
// case 10:
|
|
|
|
|
// case 9:
|
|
|
|
|
// case 1:
|
|
|
|
|
// case 50:
|
|
|
|
|
// case 14:
|
|
|
|
|
// case 19:
|
|
|
|
|
// case 7:
|
|
|
|
|
// case 25:
|
|
|
|
|
// case 15:
|
|
|
|
|
// case 13:
|
|
|
|
|
// case 28:
|
|
|
|
|
// case 17:
|
|
|
|
|
// case 22:
|
|
|
|
|
// case 26:
|
|
|
|
|
// case 18:
|
|
|
|
|
// case 21:
|
|
|
|
|
// case 23:
|
|
|
|
|
// case 11:
|
|
|
|
|
// case 24:
|
|
|
|
|
// case 27:
|
|
|
|
|
// case 30:
|
|
|
|
|
// case 16:
|
|
|
|
|
// case 377:
|
|
|
|
|
// case 31:
|
|
|
|
|
// case 125:
|
|
|
|
|
// case 32:
|
|
|
|
|
// case 34:
|
|
|
|
|
// case 52:
|
|
|
|
|
// case 51:
|
|
|
|
|
// case 345:
|
|
|
|
|
// case 399:
|
|
|
|
|
// break;
|
|
|
|
|
// default:
|
|
|
|
|
// break;//no hit
|
|
|
|
|
//}
|
2020-03-05 07:40:54 +08:00
|
|
|
|
#endregion
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2019-11-21 21:34:27 +08:00
|
|
|
|
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
|
|
|
|
//FlattenHierarchy();
|
|
|
|
|
//WriteItems();//should already be done by Expression.UpdateStreamBuffers
|
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
// write structure data
|
2022-01-31 16:39:42 +08:00
|
|
|
|
writer.Write(this.NameHash);
|
2020-03-05 07:40:54 +08:00
|
|
|
|
writer.Write(this.Data1Length);
|
|
|
|
|
writer.Write(this.Data2Length);
|
|
|
|
|
writer.Write(this.Data3Length);
|
2022-01-31 16:39:42 +08:00
|
|
|
|
writer.Write(this.Unk0E);
|
2019-11-21 21:34:27 +08:00
|
|
|
|
writer.Write(this.Data1);
|
|
|
|
|
writer.Write(this.Data2);
|
|
|
|
|
writer.Write(this.Data3);
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.StringTag(sb, indent, "Name", YedXml.HashString(NameHash));
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk0E", Unk0E.ToString());
|
|
|
|
|
|
|
|
|
|
//TODO: use hierarchy!
|
|
|
|
|
YedXml.OpenTag(sb, indent, "Instructions");
|
|
|
|
|
var cind = indent + 1;
|
|
|
|
|
var cind2 = cind + 1;
|
|
|
|
|
foreach (var item in Items)
|
|
|
|
|
{
|
|
|
|
|
if (item is ExpressionNodeEmpty)
|
|
|
|
|
{
|
|
|
|
|
YedXml.SelfClosingTag(sb, cind, "Item type=\"" + item.Type.ToString() + "\"");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
YedXml.OpenTag(sb, cind, "Item type=\"" + item.Type.ToString() + "\"");
|
|
|
|
|
item.WriteXml(sb, cind2);
|
|
|
|
|
YedXml.CloseTag(sb, cind, "Item");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
YedXml.CloseTag(sb, indent, "Instructions");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
NameHash = XmlMeta.GetHash(Xml.GetChildInnerText(node, "Name"));
|
|
|
|
|
Unk0E = (ushort)Xml.GetChildUIntAttribute(node, "Unk0E", "value");
|
|
|
|
|
|
|
|
|
|
var items = new List<ExpressionNodeBase>();
|
|
|
|
|
var instnode = node.SelectSingleNode("Instructions");
|
|
|
|
|
if (instnode != null)
|
|
|
|
|
{
|
|
|
|
|
var inodes = instnode.SelectNodes("Item");
|
|
|
|
|
if (inodes?.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (XmlNode inode in inodes)
|
|
|
|
|
{
|
2022-01-31 22:59:29 +08:00
|
|
|
|
if (Enum.TryParse<ExpressionNodeType>(Xml.GetStringAttribute(inode, "type"), out var type))
|
2022-01-31 16:39:42 +08:00
|
|
|
|
{
|
|
|
|
|
var item = CreateItem(type);
|
|
|
|
|
item.Type = type;
|
|
|
|
|
item.ReadXml(inode);
|
|
|
|
|
items.Add(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Items = items.ToArray();
|
|
|
|
|
BuildHierarchy();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void ReadItems()
|
|
|
|
|
{
|
|
|
|
|
var s1 = new MemoryStream(Data1);
|
|
|
|
|
var s2 = new MemoryStream(Data2);
|
|
|
|
|
var s3 = new MemoryStream(Data3);
|
|
|
|
|
var r1 = new DataReader(s1);
|
|
|
|
|
var r2 = new DataReader(s2);
|
|
|
|
|
var r3 = new DataReader(s3);
|
|
|
|
|
|
|
|
|
|
var items = new List<ExpressionNodeBase>();
|
|
|
|
|
while (s3.Position < s3.Length)
|
|
|
|
|
{
|
|
|
|
|
var type = (ExpressionNodeType)r3.ReadByte();
|
|
|
|
|
if (type == ExpressionNodeType.None)
|
|
|
|
|
{
|
|
|
|
|
if (s3.Position != s3.Length)
|
|
|
|
|
{ }//no hit
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
var item = CreateItem(type);
|
|
|
|
|
item.Type = type;
|
|
|
|
|
item.Read(r1, r2);
|
|
|
|
|
items.Add(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((r1.Length - r1.Position) != 0)
|
|
|
|
|
{ }//no hit
|
|
|
|
|
if ((r2.Length - r2.Position) != 0)
|
|
|
|
|
{ }//no hit
|
|
|
|
|
if ((r3.Length - r3.Position) != 0)
|
|
|
|
|
{ }//no hit
|
|
|
|
|
|
|
|
|
|
Items = items.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void BuildHierarchy()
|
|
|
|
|
{
|
|
|
|
|
if (Items == null) return;
|
|
|
|
|
|
|
|
|
|
var stack = new Stack<ExpressionNodeBase>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < Items.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var item = Items[i];
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (item.Type)
|
|
|
|
|
{
|
|
|
|
|
case ExpressionNodeType.Unk01: break;
|
|
|
|
|
case ExpressionNodeType.Unk03: break;
|
|
|
|
|
case ExpressionNodeType.Unk04: break;
|
|
|
|
|
case ExpressionNodeType.Unk05: break;
|
|
|
|
|
case ExpressionNodeType.Unk06: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk07: break;
|
|
|
|
|
case ExpressionNodeType.Unk09: break;
|
|
|
|
|
case ExpressionNodeType.Unk0A: break;
|
|
|
|
|
case ExpressionNodeType.Unk0B: break;
|
|
|
|
|
case ExpressionNodeType.Jiggle: break;
|
|
|
|
|
case ExpressionNodeType.Unk10: item.Children = new[] { stack.Pop() }; break; //####### maybe not
|
|
|
|
|
case ExpressionNodeType.Unk11: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk1B: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk1D: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk1E: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk1F: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk20: break;//first in list
|
|
|
|
|
case ExpressionNodeType.Unk21: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk22: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk23: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk26: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk27: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk28: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk2A: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk2B: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk2C: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk2D: item.Children = new[] { stack.Pop(), stack.Pop() }; break;//4 maybe?
|
|
|
|
|
case ExpressionNodeType.Unk2E: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk2F: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk30: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk31: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk32: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk33: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk35: item.Children = new[] { stack.Pop(), stack.Pop() }; break;//can't be more than 2
|
|
|
|
|
case ExpressionNodeType.Unk36: item.Children = new[] { stack.Pop(), stack.Pop() }; break; //can't be more than 2
|
|
|
|
|
case ExpressionNodeType.Unk37: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk38: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk39: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk3A: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk3B: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break; //####### maybe not
|
|
|
|
|
case ExpressionNodeType.Unk3C: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk3D: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk3E: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk3F: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk40: item.Children = new[] { stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk42: break;//first in list
|
|
|
|
|
case ExpressionNodeType.Unk43: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk44: break;
|
|
|
|
|
case ExpressionNodeType.Unk45: break;
|
|
|
|
|
case ExpressionNodeType.Unk46: item.Children = new[] { stack.Pop() }; break;
|
|
|
|
|
case ExpressionNodeType.Unk49: item.Children = new[] { stack.Pop(), stack.Pop(), stack.Pop() }; break;
|
|
|
|
|
default: break;//no hit
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stack.Push(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Roots = stack.Reverse().ToArray();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
foreach (var item in Items) //probably using the stack caused child arrays to be reversed, so reverse them back again
|
|
|
|
|
{
|
|
|
|
|
if ((item.Children?.Length ?? 0) > 1)
|
|
|
|
|
{
|
|
|
|
|
Array.Reverse(item.Children);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void FlattenHierarchy(ExpressionNodeBase node = null, List<ExpressionNodeBase> list = null)
|
|
|
|
|
{
|
|
|
|
|
if (node == null)
|
|
|
|
|
{
|
|
|
|
|
if (Roots == null) return;
|
|
|
|
|
|
|
|
|
|
list = new List<ExpressionNodeBase>();
|
|
|
|
|
|
|
|
|
|
foreach (var root in Roots)
|
|
|
|
|
{
|
|
|
|
|
FlattenHierarchy(root, list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Items = list.ToArray();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (node.Children != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var child in node.Children)
|
|
|
|
|
{
|
|
|
|
|
FlattenHierarchy(child, list);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
list.Add(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WriteItems()
|
|
|
|
|
{
|
|
|
|
|
var s1 = new MemoryStream();
|
|
|
|
|
var s2 = new MemoryStream();
|
|
|
|
|
var s3 = new MemoryStream();
|
|
|
|
|
var w1 = new DataWriter(s1);
|
|
|
|
|
var w2 = new DataWriter(s2);
|
|
|
|
|
var w3 = new DataWriter(s3);
|
|
|
|
|
|
|
|
|
|
foreach (var item in Items)
|
|
|
|
|
{
|
|
|
|
|
w3.Write((byte)item.Type);
|
|
|
|
|
item.Write(w1, w2);
|
|
|
|
|
}
|
|
|
|
|
w3.Write((byte)0);
|
|
|
|
|
|
|
|
|
|
var b1 = new byte[s1.Length];
|
|
|
|
|
var b2 = new byte[s2.Length];
|
|
|
|
|
var b3 = new byte[s3.Length];
|
|
|
|
|
s1.Position = 0;
|
|
|
|
|
s2.Position = 0;
|
|
|
|
|
s3.Position = 0;
|
|
|
|
|
s1.Read(b1, 0, b1.Length);
|
|
|
|
|
s2.Read(b2, 0, b2.Length);
|
|
|
|
|
s3.Read(b3, 0, b3.Length);
|
|
|
|
|
|
|
|
|
|
Data1 = b1;
|
|
|
|
|
Data2 = b2;
|
|
|
|
|
Data3 = b3;
|
|
|
|
|
Data1Length = (uint)Data1.Length;
|
|
|
|
|
Data2Length = (uint)Data2.Length;
|
|
|
|
|
Data3Length = (ushort)Data3.Length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static ExpressionNodeBase CreateItem(ExpressionNodeType type)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
|
|
|
|
switch (type)
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
case ExpressionNodeType.Unk01:
|
|
|
|
|
case ExpressionNodeType.Unk03:
|
|
|
|
|
case ExpressionNodeType.Unk04:
|
|
|
|
|
case ExpressionNodeType.Unk10:
|
|
|
|
|
case ExpressionNodeType.Unk11:
|
|
|
|
|
case ExpressionNodeType.Unk1B:
|
|
|
|
|
case ExpressionNodeType.Unk1D:
|
|
|
|
|
case ExpressionNodeType.Unk1E:
|
|
|
|
|
case ExpressionNodeType.Unk1F:
|
|
|
|
|
case ExpressionNodeType.Unk21:
|
|
|
|
|
case ExpressionNodeType.Unk22:
|
|
|
|
|
case ExpressionNodeType.Unk2E:
|
|
|
|
|
case ExpressionNodeType.Unk2F:
|
|
|
|
|
case ExpressionNodeType.Unk30:
|
|
|
|
|
case ExpressionNodeType.Unk31:
|
|
|
|
|
case ExpressionNodeType.Unk32:
|
|
|
|
|
case ExpressionNodeType.Unk33:
|
|
|
|
|
case ExpressionNodeType.Unk35:
|
|
|
|
|
case ExpressionNodeType.Unk36:
|
|
|
|
|
case ExpressionNodeType.Unk37:
|
|
|
|
|
case ExpressionNodeType.Unk38:
|
|
|
|
|
case ExpressionNodeType.Unk39:
|
|
|
|
|
case ExpressionNodeType.Unk3A:
|
|
|
|
|
case ExpressionNodeType.Unk3B:
|
|
|
|
|
case ExpressionNodeType.Unk3C:
|
|
|
|
|
case ExpressionNodeType.Unk3D:
|
|
|
|
|
case ExpressionNodeType.Unk3F:
|
|
|
|
|
case ExpressionNodeType.Unk40:
|
|
|
|
|
case ExpressionNodeType.Unk46:
|
|
|
|
|
case ExpressionNodeType.Unk49:
|
|
|
|
|
return new ExpressionNodeEmpty();
|
|
|
|
|
|
|
|
|
|
case ExpressionNodeType.Unk44:
|
|
|
|
|
case ExpressionNodeType.Unk45:
|
|
|
|
|
return new ExpressionNodeS1();
|
|
|
|
|
|
|
|
|
|
case ExpressionNodeType.Unk06:
|
|
|
|
|
case ExpressionNodeType.Unk07:
|
|
|
|
|
case ExpressionNodeType.Unk09:
|
|
|
|
|
case ExpressionNodeType.Unk0A:
|
|
|
|
|
case ExpressionNodeType.Unk20:
|
|
|
|
|
case ExpressionNodeType.Unk23:
|
|
|
|
|
case ExpressionNodeType.Unk26:
|
|
|
|
|
case ExpressionNodeType.Unk27:
|
|
|
|
|
case ExpressionNodeType.Unk28:
|
|
|
|
|
case ExpressionNodeType.Unk2A:
|
|
|
|
|
return new ExpressionNodeS2();
|
|
|
|
|
|
|
|
|
|
case ExpressionNodeType.Unk42:
|
|
|
|
|
case ExpressionNodeType.Unk43:
|
|
|
|
|
return new ExpressionNodeS3();
|
|
|
|
|
|
|
|
|
|
case ExpressionNodeType.Unk2B:
|
|
|
|
|
case ExpressionNodeType.Unk2C:
|
|
|
|
|
case ExpressionNodeType.Unk2D:
|
|
|
|
|
return new ExpressionNode2B();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case ExpressionNodeType.Unk05: return new ExpressionNode05();
|
|
|
|
|
case ExpressionNodeType.Unk0B: return new ExpressionNode0B();
|
|
|
|
|
case ExpressionNodeType.Jiggle: return new ExpressionNodeJiggle();
|
|
|
|
|
case ExpressionNodeType.Unk3E: return new ExpressionNode3E();
|
2020-03-03 04:50:25 +08:00
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
return new ExpressionNodeBase();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
return NameHash.ToString() + " (" + (Items?.Length??0).ToString() + " items, " + (Roots?.Length??0).ToString() + " roots)";
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
|
|
|
|
public enum ExpressionNodeType : byte
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
None = 0,
|
|
|
|
|
Unk01 = 0x01,
|
|
|
|
|
Unk03 = 0x03,
|
|
|
|
|
Unk04 = 0x04,
|
|
|
|
|
Unk05 = 0x05,
|
|
|
|
|
Unk06 = 0x06,
|
|
|
|
|
Unk07 = 0x07,
|
|
|
|
|
Unk09 = 0x09,
|
|
|
|
|
Unk0A = 0x0A,
|
|
|
|
|
Unk0B = 0x0B,
|
|
|
|
|
Jiggle = 0x0E,
|
|
|
|
|
Unk10 = 0x10,
|
|
|
|
|
Unk11 = 0x11,
|
|
|
|
|
Unk1B = 0x1B,
|
|
|
|
|
Unk1D = 0x1D,
|
|
|
|
|
Unk1E = 0x1E,
|
|
|
|
|
Unk1F = 0x1F,
|
|
|
|
|
Unk20 = 0x20,
|
|
|
|
|
Unk21 = 0x21,
|
|
|
|
|
Unk22 = 0x22,
|
|
|
|
|
Unk23 = 0x23,
|
|
|
|
|
Unk26 = 0x26,
|
|
|
|
|
Unk27 = 0x27,
|
|
|
|
|
Unk28 = 0x28,
|
|
|
|
|
Unk2A = 0x2A,
|
|
|
|
|
Unk2B = 0x2B,
|
|
|
|
|
Unk2C = 0x2C,
|
|
|
|
|
Unk2D = 0x2D,
|
|
|
|
|
Unk2E = 0x2E,
|
|
|
|
|
Unk2F = 0x2F,
|
|
|
|
|
Unk30 = 0x30,
|
|
|
|
|
Unk31 = 0x31,
|
|
|
|
|
Unk32 = 0x32,
|
|
|
|
|
Unk33 = 0x33,
|
|
|
|
|
Unk35 = 0x35,
|
|
|
|
|
Unk36 = 0x36,
|
|
|
|
|
Unk37 = 0x37,
|
|
|
|
|
Unk38 = 0x38,
|
|
|
|
|
Unk39 = 0x39,
|
|
|
|
|
Unk3A = 0x3A,
|
|
|
|
|
Unk3B = 0x3B,
|
|
|
|
|
Unk3C = 0x3C,
|
|
|
|
|
Unk3D = 0x3D,
|
|
|
|
|
Unk3E = 0x3E,
|
|
|
|
|
Unk3F = 0x3F,
|
|
|
|
|
Unk40 = 0x40,
|
|
|
|
|
Unk42 = 0x42,
|
|
|
|
|
Unk43 = 0x43,
|
|
|
|
|
Unk44 = 0x44,
|
|
|
|
|
Unk45 = 0x45,
|
|
|
|
|
Unk46 = 0x46,
|
|
|
|
|
Unk49 = 0x49,
|
|
|
|
|
}
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2020-03-05 07:40:54 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNodeBase
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
possible type names:
|
|
|
|
|
crExprInstrBone
|
|
|
|
|
crExprInstrRBFs
|
|
|
|
|
crExprInstrSpring
|
|
|
|
|
crExprInstrConstraint
|
|
|
|
|
crExprInstrLinear
|
|
|
|
|
crExprInstrSpringChain
|
|
|
|
|
crExprInstrCurve
|
|
|
|
|
crExprInstrFrame
|
|
|
|
|
crExprInstrLookAt
|
|
|
|
|
crExprInstrVariable
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ExpressionNodeType Type { get; set; }
|
|
|
|
|
|
|
|
|
|
public ExpressionNodeBase[] Children { get; set; }
|
|
|
|
|
|
|
|
|
|
public virtual void Read(DataReader r1, DataReader r2)
|
2020-03-03 18:27:49 +08:00
|
|
|
|
{ }
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public virtual void Write(DataWriter w1, DataWriter w2)
|
|
|
|
|
{ }
|
|
|
|
|
public virtual void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{ }
|
|
|
|
|
public virtual void ReadXml(XmlNode node)
|
|
|
|
|
{ }
|
|
|
|
|
|
2020-03-03 18:27:49 +08:00
|
|
|
|
public override string ToString()
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
return Type.ToString();
|
2020-03-03 18:27:49 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNodeEmpty : ExpressionNodeBase
|
|
|
|
|
{ }
|
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNodeS1 : ExpressionNodeBase
|
2020-03-03 18:27:49 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ItemStruct : IMetaXmlItem
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public ushort BoneTrack { get; set; }
|
2020-03-04 01:44:28 +08:00
|
|
|
|
public ushort Unk2 { get; set; }
|
|
|
|
|
public float[] Values { get; set; }
|
|
|
|
|
|
|
|
|
|
public void Read(DataReader r)
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
BoneTrack = r.ReadUInt16();
|
2020-03-04 01:44:28 +08:00
|
|
|
|
Unk2 = r.ReadUInt16();
|
|
|
|
|
|
|
|
|
|
switch (Unk2)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
case 4:
|
|
|
|
|
case 8:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void Write(DataWriter w)
|
|
|
|
|
{
|
|
|
|
|
w.Write(BoneTrack);
|
|
|
|
|
w.Write(Unk2);
|
|
|
|
|
}
|
|
|
|
|
public void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.ValueTag(sb, indent, "BoneTrack", BoneTrack.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk2", Unk2.ToString());
|
|
|
|
|
YedXml.WriteRawArray(sb, Values, indent, "Values", "", FloatUtil.ToString, Values.Length);
|
|
|
|
|
}
|
|
|
|
|
public void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
BoneTrack = (ushort)Xml.GetChildUIntAttribute(node, "BoneTrack", "value");
|
|
|
|
|
Unk2 = (ushort)Xml.GetChildUIntAttribute(node, "Unk2", "value");
|
|
|
|
|
Values = Xml.GetChildRawFloatArray(node, "Values");
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 01:44:28 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var str = BoneTrack.ToString() + ", " + Unk2.ToString();
|
2020-03-04 01:44:28 +08:00
|
|
|
|
if (Values != null)
|
|
|
|
|
{
|
|
|
|
|
str += " - ";
|
|
|
|
|
for (int i = 0; i < Values.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (i != 0) str += ", ";
|
|
|
|
|
str += Values[i].ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public uint Length { get; set; }//updated automatically
|
|
|
|
|
public uint ItemCount { get; set; }//updated automatically
|
|
|
|
|
public uint ItemType { get; set; }
|
|
|
|
|
public uint Unk1 { get; set; } // 0x00000000
|
|
|
|
|
public ItemStruct[] Items { get; set; }
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
2020-03-03 18:27:49 +08:00
|
|
|
|
{
|
|
|
|
|
Length = r1.ReadUInt32();
|
|
|
|
|
ItemCount = r1.ReadUInt32();
|
|
|
|
|
ItemType = r1.ReadUInt32();
|
|
|
|
|
Unk1 = r1.ReadUInt32();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var valcnt = (ItemType - 1) * 9 + 6;
|
|
|
|
|
var hlen = ItemCount * 4 + 16;
|
|
|
|
|
var dlen = Length - hlen;
|
|
|
|
|
var tlen = ItemCount * valcnt * 4;
|
2020-03-04 01:44:28 +08:00
|
|
|
|
if (tlen != dlen)
|
|
|
|
|
{ }//no hitting
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
Items = new ItemStruct[ItemCount];
|
2020-03-04 01:44:28 +08:00
|
|
|
|
for (int i = 0; i < ItemCount; i++)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var item1 = new ItemStruct();
|
2020-03-04 01:44:28 +08:00
|
|
|
|
item1.Read(r1);
|
|
|
|
|
Items[i] = item1;
|
|
|
|
|
Items[i].Values = new float[valcnt];
|
|
|
|
|
}
|
|
|
|
|
for (int n = 0; n < valcnt; n++)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < ItemCount; i++)
|
|
|
|
|
{
|
|
|
|
|
Items[i].Values[n] = r1.ReadSingle();
|
|
|
|
|
}
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-03-03 18:27:49 +08:00
|
|
|
|
switch (ItemCount)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2020-03-03 18:27:49 +08:00
|
|
|
|
case 0:
|
|
|
|
|
case 4:
|
|
|
|
|
case 8:
|
|
|
|
|
case 12:
|
|
|
|
|
case 20:
|
|
|
|
|
case 24:
|
|
|
|
|
case 48:
|
|
|
|
|
case 52:
|
|
|
|
|
case 76:
|
|
|
|
|
case 32:
|
|
|
|
|
case 16:
|
|
|
|
|
case 40:
|
|
|
|
|
case 44:
|
|
|
|
|
case 60:
|
|
|
|
|
case 72:
|
|
|
|
|
case 56:
|
|
|
|
|
case 28:
|
|
|
|
|
case 68:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2020-03-03 18:27:49 +08:00
|
|
|
|
switch (ItemType)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2020-03-04 01:44:28 +08:00
|
|
|
|
case 1: break;
|
|
|
|
|
case 2: break;
|
|
|
|
|
case 3: break;
|
|
|
|
|
case 4: break;
|
2020-03-03 18:27:49 +08:00
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2020-03-03 18:27:49 +08:00
|
|
|
|
if (Unk1 != 0)
|
|
|
|
|
{ }//no hit
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
|
|
|
|
{
|
|
|
|
|
ItemCount = (uint)(Items?.Length ?? 0);
|
|
|
|
|
ItemType = Math.Max(ItemType, 1);
|
|
|
|
|
var valcnt = (ItemType - 1) * 9 + 6;
|
|
|
|
|
var hlen = ItemCount * 4 + 16;
|
|
|
|
|
var tlen = ItemCount * valcnt * 4;
|
|
|
|
|
Length = hlen + tlen;
|
|
|
|
|
|
|
|
|
|
w1.Write(Length);
|
|
|
|
|
w1.Write(ItemCount);
|
|
|
|
|
w1.Write(ItemType);
|
|
|
|
|
w1.Write(Unk1);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ItemCount; i++)
|
|
|
|
|
{
|
|
|
|
|
Items[i].Write(w1);
|
|
|
|
|
}
|
|
|
|
|
for (int n = 0; n < valcnt; n++)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < ItemCount; i++)
|
|
|
|
|
{
|
|
|
|
|
var vals = Items[i].Values;
|
|
|
|
|
w1.Write((n < (vals?.Length ?? 0)) ? vals[n] : 0.0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.ValueTag(sb, indent, "ItemType", ItemType.ToString());
|
|
|
|
|
YedXml.WriteItemArray(sb, Items, indent, "Items");
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
ItemType = Xml.GetChildUIntAttribute(node, "ItemType", "value");
|
|
|
|
|
Items = XmlMeta.ReadItemArray<ItemStruct>(node, "Items");
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var str = base.ToString() + " - " + Length.ToString() + ", " + ItemCount.ToString() + ", " + ItemType.ToString();
|
2020-03-04 01:44:28 +08:00
|
|
|
|
if (Items != null)
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
str += " (S1) - " + Items.Length.ToString() + " items";
|
2020-03-04 01:44:28 +08:00
|
|
|
|
}
|
|
|
|
|
return str;
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNodeS2 : ExpressionNodeBase
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public ushort BoneTrack { get; set; } //index of the BoneTag in the Expression.BoneTracks array
|
|
|
|
|
public ushort BoneTag { get; set; }
|
|
|
|
|
public byte Unk01 { get; set; }
|
|
|
|
|
public byte Unk02 { get; set; }
|
|
|
|
|
public byte Unk03 { get; set; }
|
2020-03-03 18:27:49 +08:00
|
|
|
|
public byte Unk04 { get; set; }
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
|
|
|
|
{
|
|
|
|
|
BoneTrack = r2.ReadUInt16();
|
|
|
|
|
BoneTag = r2.ReadUInt16();
|
|
|
|
|
Unk01 = r2.ReadByte();
|
|
|
|
|
Unk02 = r2.ReadByte();
|
|
|
|
|
Unk03 = r2.ReadByte();
|
|
|
|
|
Unk04 = r2.ReadByte();
|
|
|
|
|
}
|
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
|
|
|
|
{
|
|
|
|
|
w2.Write(BoneTrack);
|
|
|
|
|
w2.Write(BoneTag);
|
|
|
|
|
w2.Write(Unk01);
|
|
|
|
|
w2.Write(Unk02);
|
|
|
|
|
w2.Write(Unk03);
|
|
|
|
|
w2.Write(Unk04);
|
|
|
|
|
}
|
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.ValueTag(sb, indent, "BoneTrack", BoneTrack.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "BoneTag", BoneTag.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk01", Unk01.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk02", Unk02.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk03", Unk03.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk04", Unk04.ToString());
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
BoneTrack = (ushort)Xml.GetChildUIntAttribute(node, "BoneTrack", "value");
|
|
|
|
|
BoneTag = (ushort)Xml.GetChildUIntAttribute(node, "BoneTag", "value");
|
|
|
|
|
Unk01 = (byte)Xml.GetChildUIntAttribute(node, "Unk01", "value");
|
|
|
|
|
Unk02 = (byte)Xml.GetChildUIntAttribute(node, "Unk02", "value");
|
|
|
|
|
Unk03 = (byte)Xml.GetChildUIntAttribute(node, "Unk03", "value");
|
|
|
|
|
Unk04 = (byte)Xml.GetChildUIntAttribute(node, "Unk04", "value");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return base.ToString() + " (S2) - Track:" + BoneTrack.ToString() + ", Tag:" + BoneTag.ToString() + ", " + Unk01.ToString() + ", " + Unk02.ToString() + ", " + Unk03.ToString() + ", " + Unk04.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNodeS3 : ExpressionNodeBase
|
|
|
|
|
{
|
|
|
|
|
public MetaHash Hash { get; set; }
|
|
|
|
|
public byte HashIndex { get; set; } //index of the hash in the Expression.ItemHashes array (autoupdated - don't need in XML)
|
|
|
|
|
public byte Unk03 { get; set; }//0
|
|
|
|
|
public byte Unk04 { get; set; }//0
|
|
|
|
|
public byte Unk05 { get; set; }//0
|
|
|
|
|
|
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
Hash = r2.ReadUInt32();
|
|
|
|
|
HashIndex = r2.ReadByte();
|
|
|
|
|
Unk03 = r2.ReadByte();
|
2020-03-03 18:27:49 +08:00
|
|
|
|
Unk04 = r2.ReadByte();
|
|
|
|
|
Unk05 = r2.ReadByte();
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
|
|
|
|
if (Unk03 != 0)
|
|
|
|
|
{ }
|
|
|
|
|
if (Unk04 != 0)
|
|
|
|
|
{ }
|
|
|
|
|
if (Unk05 != 0)
|
|
|
|
|
{ }
|
|
|
|
|
}
|
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
|
|
|
|
{
|
|
|
|
|
w2.Write(Hash);
|
|
|
|
|
w2.Write(HashIndex);
|
|
|
|
|
w2.Write(Unk03);
|
|
|
|
|
w2.Write(Unk04);
|
|
|
|
|
w2.Write(Unk05);
|
2020-03-03 04:50:25 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.StringTag(sb, indent, "Hash", YedXml.HashString(Hash));
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
Hash = XmlMeta.GetHash(Xml.GetChildInnerText(node, "Hash"));
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-03 04:50:25 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
return base.ToString() + " (S3) - Hash:" + Hash.ToString() + ", " + HashIndex.ToString() + ", " + Unk03.ToString() + ", " + Unk04.ToString() + ", " + Unk05.ToString();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNode2B : ExpressionNodeBase
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public uint Unk01 { get; set; }
|
|
|
|
|
public uint Unk02 { get; set; }
|
|
|
|
|
public uint Unk03 { get; set; }
|
2020-03-03 04:50:25 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
Unk01 = r2.ReadUInt32();
|
|
|
|
|
Unk02 = r2.ReadUInt32();
|
|
|
|
|
Unk03 = r2.ReadUInt32();
|
2020-03-04 01:44:28 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (Unk01)//flags?
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
case 128:
|
|
|
|
|
case 464:
|
|
|
|
|
case 352:
|
|
|
|
|
case 240:
|
|
|
|
|
case 16:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (Unk02)//some index?
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
|
|
|
|
case 24:
|
|
|
|
|
case 12:
|
|
|
|
|
case 0:
|
|
|
|
|
case 8:
|
|
|
|
|
case 60:
|
|
|
|
|
case 48:
|
|
|
|
|
case 20:
|
|
|
|
|
case 44:
|
|
|
|
|
case 16:
|
|
|
|
|
case 52:
|
|
|
|
|
case 28:
|
|
|
|
|
case 4:
|
|
|
|
|
case 88:
|
|
|
|
|
case 64:
|
|
|
|
|
case 128:
|
|
|
|
|
case 104:
|
|
|
|
|
case 68:
|
|
|
|
|
case 80:
|
|
|
|
|
case 92:
|
|
|
|
|
case 84:
|
|
|
|
|
case 56:
|
|
|
|
|
case 108:
|
|
|
|
|
case 116:
|
|
|
|
|
case 72:
|
|
|
|
|
case 32:
|
|
|
|
|
case 40:
|
|
|
|
|
case 512:
|
|
|
|
|
case 36:
|
|
|
|
|
case 100:
|
|
|
|
|
case 140:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (Unk03)//some index?
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
|
|
|
|
case 5:
|
|
|
|
|
case 4:
|
|
|
|
|
case 2:
|
|
|
|
|
case 3:
|
|
|
|
|
case 6:
|
|
|
|
|
case 17:
|
|
|
|
|
case 16:
|
|
|
|
|
case 15:
|
|
|
|
|
case 14:
|
|
|
|
|
case 12:
|
|
|
|
|
case 7:
|
|
|
|
|
case 19:
|
|
|
|
|
case 34:
|
|
|
|
|
case 26:
|
|
|
|
|
case 22:
|
|
|
|
|
case 18:
|
|
|
|
|
case 11:
|
|
|
|
|
case 20:
|
|
|
|
|
case 8:
|
|
|
|
|
case 30:
|
|
|
|
|
case 9:
|
|
|
|
|
case 10:
|
|
|
|
|
case 24:
|
|
|
|
|
case 77:
|
|
|
|
|
case 38:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-03 04:50:25 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
|
|
|
|
{
|
|
|
|
|
w2.Write(Unk01);
|
|
|
|
|
w2.Write(Unk02);
|
|
|
|
|
w2.Write(Unk03);
|
|
|
|
|
}
|
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk01", Unk01.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk02", Unk02.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk03", Unk03.ToString());
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
Unk01 = Xml.GetChildUIntAttribute(node, "Unk01", "value");
|
|
|
|
|
Unk02 = Xml.GetChildUIntAttribute(node, "Unk02", "value");
|
|
|
|
|
Unk03 = Xml.GetChildUIntAttribute(node, "Unk03", "value");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return base.ToString() + " (S2B) - " + Unk01.ToString() + ", " + Unk02.ToString() + ", " + Unk03.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNode05 : ExpressionNodeBase
|
|
|
|
|
{
|
|
|
|
|
public float Unk01 { get; set; }
|
|
|
|
|
|
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
|
|
|
|
{
|
|
|
|
|
Unk01 = r2.ReadSingle();
|
|
|
|
|
}
|
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
|
|
|
|
{
|
|
|
|
|
w2.Write(Unk01);
|
|
|
|
|
}
|
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk01", FloatUtil.ToString(Unk01));
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
Unk01 = Xml.GetChildFloatAttribute(node, "Unk01", "value");
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-03 04:50:25 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
return base.ToString() + " (S05) - " + Unk01.ToString();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNode0B : ExpressionNodeBase
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public Vector4 Unk01 { get; set; }
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
|
|
|
|
{
|
|
|
|
|
Unk01 = r1.ReadVector4();
|
|
|
|
|
}
|
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
w1.Write(Unk01);
|
|
|
|
|
}
|
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Unk01 " + FloatUtil.GetVector4XmlString(Unk01));
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
Unk01 = Xml.GetChildVector4Attributes(node, "Unk01");
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
var str = base.ToString() + " (S0B) - " + Unk01.ToString();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
return str;
|
|
|
|
|
}
|
2019-11-21 21:34:27 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNodeJiggle : ExpressionNodeBase
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public ExpressionJiggleData JiggleData { get; set; }
|
|
|
|
|
public uint BoneTrackRot { get; set; }
|
|
|
|
|
public uint BoneTrackPos { get; set; }
|
|
|
|
|
public uint UnkUint13 { get; set; }//0
|
|
|
|
|
public uint UnkUint14 { get; set; }//0
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
|
|
|
|
{
|
|
|
|
|
JiggleData = new ExpressionJiggleData();
|
|
|
|
|
JiggleData.Read(r1);
|
|
|
|
|
BoneTrackRot = r1.ReadUInt32();
|
|
|
|
|
BoneTrackPos = r1.ReadUInt32();
|
|
|
|
|
UnkUint13 = r1.ReadUInt32();
|
|
|
|
|
UnkUint14 = r1.ReadUInt32();
|
|
|
|
|
}
|
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
|
|
|
|
{
|
|
|
|
|
if (JiggleData == null) JiggleData = new ExpressionJiggleData();
|
|
|
|
|
JiggleData.Write(w1);
|
|
|
|
|
w1.Write(BoneTrackRot);
|
|
|
|
|
w1.Write(BoneTrackPos);
|
|
|
|
|
w1.Write(UnkUint13);
|
|
|
|
|
w1.Write(UnkUint14);
|
|
|
|
|
}
|
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
if (JiggleData == null) JiggleData = new ExpressionJiggleData();
|
|
|
|
|
JiggleData.WriteXml(sb, indent);
|
|
|
|
|
YedXml.ValueTag(sb, indent, "BoneTrackRot", BoneTrackRot.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "BoneTrackPos", BoneTrackPos.ToString());
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
JiggleData = new ExpressionJiggleData();
|
|
|
|
|
JiggleData.ReadXml(node);
|
|
|
|
|
BoneTrackRot = Xml.GetChildUIntAttribute(node, "BoneTrackRot", "value");
|
|
|
|
|
BoneTrackPos = Xml.GetChildUIntAttribute(node, "BoneTrackPos", "value");
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
return base.ToString() + " - " + BoneTrackRot.ToString() + ", " + BoneTrackPos.ToString();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionNode3E : ExpressionNodeBase
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public Vector4 Unk01 { get; set; }
|
|
|
|
|
public uint Unk02 { get; set; } // 0, 1, 2
|
|
|
|
|
public uint Unk03 { get; set; } // 0, 2
|
|
|
|
|
public uint Unk04 { get; set; } // 0, 2
|
|
|
|
|
public uint Unk05 { get; set; } // 0x00000000
|
2020-03-03 04:50:25 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Read(DataReader r1, DataReader r2)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
Unk01 = r1.ReadVector4();
|
|
|
|
|
Unk02 = r1.ReadUInt32();
|
|
|
|
|
Unk03 = r1.ReadUInt32();
|
|
|
|
|
Unk04 = r1.ReadUInt32();
|
|
|
|
|
Unk05 = r1.ReadUInt32();
|
2020-03-04 01:44:28 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (Unk02)
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
case 2:
|
|
|
|
|
case 1:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (Unk03)
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
|
|
|
|
case 2:
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (Unk04)
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
|
|
|
|
case 2:
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
switch (Unk05)
|
2020-03-04 01:44:28 +08:00
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;//no hit
|
|
|
|
|
}
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void Write(DataWriter w1, DataWriter w2)
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
w1.Write(Unk01);
|
|
|
|
|
w1.Write(Unk02);
|
|
|
|
|
w1.Write(Unk03);
|
|
|
|
|
w1.Write(Unk04);
|
|
|
|
|
w1.Write(Unk05);
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public override void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Unk01 " + FloatUtil.GetVector4XmlString(Unk01));
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk02", Unk02.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk03", Unk03.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Unk04", Unk04.ToString());
|
|
|
|
|
}
|
|
|
|
|
public override void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
Unk01 = Xml.GetChildVector4Attributes(node, "Unk01");
|
|
|
|
|
Unk02 = Xml.GetChildUIntAttribute(node, "Unk02", "value");
|
|
|
|
|
Unk03 = Xml.GetChildUIntAttribute(node, "Unk03", "value");
|
|
|
|
|
Unk04 = Xml.GetChildUIntAttribute(node, "Unk04", "value");
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
return base.ToString() + " (S3E) - " + Unk01.ToString() + " - " + Unk02.ToString() + ", " + Unk03.ToString() + ", " + Unk04.ToString() + ", " + Unk05.ToString();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TC(typeof(EXP))] public class ExpressionJiggleBlock : ResourceSystemBlock
|
2019-11-21 21:34:27 +08:00
|
|
|
|
{
|
|
|
|
|
public override long BlockLength => 0xA0;
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public ExpressionJiggleData JiggleData { get; set; }
|
2019-11-21 21:34:27 +08:00
|
|
|
|
|
|
|
|
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
JiggleData = new ExpressionJiggleData();
|
|
|
|
|
JiggleData.Read(reader);
|
2019-11-21 21:34:27 +08:00
|
|
|
|
}
|
|
|
|
|
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
|
|
|
|
{
|
2022-01-31 16:39:42 +08:00
|
|
|
|
if (JiggleData == null) JiggleData = new ExpressionJiggleData();
|
|
|
|
|
JiggleData.Write(writer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return JiggleData?.ToString() ?? base.ToString();
|
2019-11-21 21:34:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public class ExpressionJiggleData
|
|
|
|
|
{
|
|
|
|
|
public Vector3 Vector01 { get; set; }
|
|
|
|
|
public ushort Ushort01a { get; set; }
|
|
|
|
|
public ushort Ushort01b { get; set; }
|
|
|
|
|
public Vector3 Vector02 { get; set; }
|
|
|
|
|
public ushort Ushort02a { get; set; }
|
|
|
|
|
public ushort Ushort02b { get; set; }
|
|
|
|
|
public Vector3 Vector03 { get; set; }
|
|
|
|
|
public ushort Ushort03a { get; set; }
|
|
|
|
|
public ushort Ushort03b { get; set; }
|
|
|
|
|
public Vector3 Vector04 { get; set; }
|
|
|
|
|
public ushort Ushort04a { get; set; }
|
|
|
|
|
public ushort Ushort04b { get; set; }
|
|
|
|
|
public Vector3 Vector05 { get; set; }
|
|
|
|
|
public ushort Ushort05a { get; set; }
|
|
|
|
|
public ushort Ushort05b { get; set; }
|
|
|
|
|
public Vector3 Vector06 { get; set; }
|
|
|
|
|
public ushort Ushort06a { get; set; }
|
|
|
|
|
public ushort Ushort06b { get; set; }
|
|
|
|
|
public Vector3 Vector07 { get; set; }
|
|
|
|
|
public ushort Ushort07a { get; set; }
|
|
|
|
|
public ushort Ushort07b { get; set; }
|
|
|
|
|
public Vector3 Vector08 { get; set; }
|
|
|
|
|
public ushort Ushort08a { get; set; }
|
|
|
|
|
public ushort Ushort08b { get; set; }
|
|
|
|
|
public Vector3 Vector09 { get; set; }
|
|
|
|
|
public ushort Ushort09a { get; set; }
|
|
|
|
|
public ushort Ushort09b { get; set; }
|
|
|
|
|
public Vector3 Gravity { get; set; }
|
|
|
|
|
public ushort BoneTag { get; set; }
|
|
|
|
|
public ushort Ushort10b { get; set; }//0
|
|
|
|
|
|
|
|
|
|
public void Read(DataReader r)
|
|
|
|
|
{
|
|
|
|
|
Vector01 = r.ReadVector3();
|
|
|
|
|
Ushort01a = r.ReadUInt16();
|
|
|
|
|
Ushort01b = r.ReadUInt16();
|
|
|
|
|
Vector02 = r.ReadVector3();
|
|
|
|
|
Ushort02a = r.ReadUInt16();
|
|
|
|
|
Ushort02b = r.ReadUInt16();
|
|
|
|
|
Vector03 = r.ReadVector3();
|
|
|
|
|
Ushort03a = r.ReadUInt16();
|
|
|
|
|
Ushort03b = r.ReadUInt16();
|
|
|
|
|
Vector04 = r.ReadVector3();
|
|
|
|
|
Ushort04a = r.ReadUInt16();
|
|
|
|
|
Ushort04b = r.ReadUInt16();
|
|
|
|
|
Vector05 = r.ReadVector3();
|
|
|
|
|
Ushort05a = r.ReadUInt16();
|
|
|
|
|
Ushort05b = r.ReadUInt16();
|
|
|
|
|
Vector06 = r.ReadVector3();
|
|
|
|
|
Ushort06a = r.ReadUInt16();
|
|
|
|
|
Ushort06b = r.ReadUInt16();
|
|
|
|
|
Vector07 = r.ReadVector3();
|
|
|
|
|
Ushort07a = r.ReadUInt16();
|
|
|
|
|
Ushort07b = r.ReadUInt16();
|
|
|
|
|
Vector08 = r.ReadVector3();
|
|
|
|
|
Ushort08a = r.ReadUInt16();
|
|
|
|
|
Ushort08b = r.ReadUInt16();
|
|
|
|
|
Vector09 = r.ReadVector3();
|
|
|
|
|
Ushort09a = r.ReadUInt16();
|
|
|
|
|
Ushort09b = r.ReadUInt16();
|
|
|
|
|
Gravity = r.ReadVector3();
|
|
|
|
|
BoneTag = r.ReadUInt16();
|
|
|
|
|
Ushort10b = r.ReadUInt16();
|
|
|
|
|
|
|
|
|
|
//if (Ushort10b != 0)
|
|
|
|
|
//{ }//no hit
|
|
|
|
|
}
|
|
|
|
|
public void Write(DataWriter w)
|
|
|
|
|
{
|
|
|
|
|
w.Write(Vector01);
|
|
|
|
|
w.Write(Ushort01a);
|
|
|
|
|
w.Write(Ushort01b);
|
|
|
|
|
w.Write(Vector02);
|
|
|
|
|
w.Write(Ushort02a);
|
|
|
|
|
w.Write(Ushort02b);
|
|
|
|
|
w.Write(Vector03);
|
|
|
|
|
w.Write(Ushort03a);
|
|
|
|
|
w.Write(Ushort03b);
|
|
|
|
|
w.Write(Vector04);
|
|
|
|
|
w.Write(Ushort04a);
|
|
|
|
|
w.Write(Ushort04b);
|
|
|
|
|
w.Write(Vector05);
|
|
|
|
|
w.Write(Ushort05a);
|
|
|
|
|
w.Write(Ushort05b);
|
|
|
|
|
w.Write(Vector06);
|
|
|
|
|
w.Write(Ushort06a);
|
|
|
|
|
w.Write(Ushort06b);
|
|
|
|
|
w.Write(Vector07);
|
|
|
|
|
w.Write(Ushort07a);
|
|
|
|
|
w.Write(Ushort07b);
|
|
|
|
|
w.Write(Vector08);
|
|
|
|
|
w.Write(Ushort08a);
|
|
|
|
|
w.Write(Ushort08b);
|
|
|
|
|
w.Write(Vector09);
|
|
|
|
|
w.Write(Ushort09a);
|
|
|
|
|
w.Write(Ushort09b);
|
|
|
|
|
w.Write(Gravity);
|
|
|
|
|
w.Write(BoneTag);
|
|
|
|
|
w.Write(Ushort10b);
|
|
|
|
|
}
|
|
|
|
|
public void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector01 " + FloatUtil.GetVector3XmlString(Vector01));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector02 " + FloatUtil.GetVector3XmlString(Vector02));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector03 " + FloatUtil.GetVector3XmlString(Vector03));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector04 " + FloatUtil.GetVector3XmlString(Vector04));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector05 " + FloatUtil.GetVector3XmlString(Vector05));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector06 " + FloatUtil.GetVector3XmlString(Vector06));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector07 " + FloatUtil.GetVector3XmlString(Vector07));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector08 " + FloatUtil.GetVector3XmlString(Vector08));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Vector09 " + FloatUtil.GetVector3XmlString(Vector09));
|
|
|
|
|
YedXml.SelfClosingTag(sb, indent, "Gravity " + FloatUtil.GetVector3XmlString(Gravity));
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort01a", Ushort01a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort01b", Ushort01b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort02a", Ushort02a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort02b", Ushort02b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort03a", Ushort03a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort03b", Ushort03b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort04a", Ushort04a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort04b", Ushort04b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort05a", Ushort05a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort05b", Ushort05b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort06a", Ushort06a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort06b", Ushort06b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort07a", Ushort07a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort07b", Ushort07b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort08a", Ushort08a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort08b", Ushort08b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort09a", Ushort09a.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Ushort09b", Ushort09b.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "BoneTag", BoneTag.ToString());
|
|
|
|
|
}
|
|
|
|
|
public void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
Vector01 = Xml.GetChildVector3Attributes(node, "Vector01");
|
|
|
|
|
Vector02 = Xml.GetChildVector3Attributes(node, "Vector02");
|
|
|
|
|
Vector03 = Xml.GetChildVector3Attributes(node, "Vector03");
|
|
|
|
|
Vector04 = Xml.GetChildVector3Attributes(node, "Vector04");
|
|
|
|
|
Vector05 = Xml.GetChildVector3Attributes(node, "Vector05");
|
|
|
|
|
Vector06 = Xml.GetChildVector3Attributes(node, "Vector06");
|
|
|
|
|
Vector07 = Xml.GetChildVector3Attributes(node, "Vector07");
|
|
|
|
|
Vector08 = Xml.GetChildVector3Attributes(node, "Vector08");
|
|
|
|
|
Vector09 = Xml.GetChildVector3Attributes(node, "Vector09");
|
|
|
|
|
Gravity = Xml.GetChildVector3Attributes(node, "Gravity");
|
|
|
|
|
Ushort01a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort01a", "value");
|
|
|
|
|
Ushort01b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort01b", "value");
|
|
|
|
|
Ushort02a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort02a", "value");
|
|
|
|
|
Ushort02b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort02b", "value");
|
|
|
|
|
Ushort03a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort03a", "value");
|
|
|
|
|
Ushort03b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort03b", "value");
|
|
|
|
|
Ushort04a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort04a", "value");
|
|
|
|
|
Ushort04b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort04b", "value");
|
|
|
|
|
Ushort05a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort05a", "value");
|
|
|
|
|
Ushort05b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort05b", "value");
|
|
|
|
|
Ushort06a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort06a", "value");
|
|
|
|
|
Ushort06b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort06b", "value");
|
|
|
|
|
Ushort07a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort07a", "value");
|
|
|
|
|
Ushort07b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort07b", "value");
|
|
|
|
|
Ushort08a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort08a", "value");
|
|
|
|
|
Ushort08b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort08b", "value");
|
|
|
|
|
Ushort09a = (ushort)Xml.GetChildUIntAttribute(node, "Ushort09a", "value");
|
|
|
|
|
Ushort09b = (ushort)Xml.GetChildUIntAttribute(node, "Ushort09b", "value");
|
|
|
|
|
BoneTag = (ushort)Xml.GetChildUIntAttribute(node, "BoneTag", "value");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Compare(ExpressionJiggleData o)
|
|
|
|
|
{
|
|
|
|
|
if (o.Vector01 != Vector01) return false;
|
|
|
|
|
if (o.Ushort01a != Ushort01a) return false;
|
|
|
|
|
if (o.Ushort01b != Ushort01b) return false;
|
|
|
|
|
if (o.Vector02 != Vector02) return false;
|
|
|
|
|
if (o.Ushort02a != Ushort02a) return false;
|
|
|
|
|
if (o.Ushort02b != Ushort02b) return false;
|
|
|
|
|
if (o.Vector03 != Vector03) return false;
|
|
|
|
|
if (o.Ushort03a != Ushort03a) return false;
|
|
|
|
|
if (o.Ushort03b != Ushort03b) return false;
|
|
|
|
|
if (o.Vector04 != Vector04) return false;
|
|
|
|
|
if (o.Ushort04a != Ushort04a) return false;
|
|
|
|
|
if (o.Ushort04b != Ushort04b) return false;
|
|
|
|
|
if (o.Vector05 != Vector05) return false;
|
|
|
|
|
if (o.Ushort05a != Ushort05a) return false;
|
|
|
|
|
if (o.Ushort05b != Ushort05b) return false;
|
|
|
|
|
if (o.Vector06 != Vector06) return false;
|
|
|
|
|
if (o.Ushort06a != Ushort06a) return false;
|
|
|
|
|
if (o.Ushort06b != Ushort06b) return false;
|
|
|
|
|
if (o.Vector07 != Vector07) return false;
|
|
|
|
|
if (o.Ushort07a != Ushort07a) return false;
|
|
|
|
|
if (o.Ushort07b != Ushort07b) return false;
|
|
|
|
|
if (o.Vector08 != Vector08) return false;
|
|
|
|
|
if (o.Ushort08a != Ushort08a) return false;
|
|
|
|
|
if (o.Ushort08b != Ushort08b) return false;
|
|
|
|
|
if (o.Vector09 != Vector09) return false;
|
|
|
|
|
if (o.Ushort09a != Ushort09a) return false;
|
|
|
|
|
if (o.Ushort09b != Ushort09b) return false;
|
|
|
|
|
if (o.Gravity != Gravity) return false;
|
|
|
|
|
if (o.BoneTag != BoneTag) return false;
|
|
|
|
|
if (o.Ushort10b != Ushort10b) return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
public ExpressionJiggleData Clone()
|
|
|
|
|
{
|
|
|
|
|
var n = new ExpressionJiggleData();
|
|
|
|
|
n.Vector01 = Vector01;
|
|
|
|
|
n.Ushort01a = Ushort01a;
|
|
|
|
|
n.Ushort01b = Ushort01b;
|
|
|
|
|
n.Vector02 = Vector02;
|
|
|
|
|
n.Ushort02a = Ushort02a;
|
|
|
|
|
n.Ushort02b = Ushort02b;
|
|
|
|
|
n.Vector03 = Vector03;
|
|
|
|
|
n.Ushort03a = Ushort03a;
|
|
|
|
|
n.Ushort03b = Ushort03b;
|
|
|
|
|
n.Vector04 = Vector04;
|
|
|
|
|
n.Ushort04a = Ushort04a;
|
|
|
|
|
n.Ushort04b = Ushort04b;
|
|
|
|
|
n.Vector05 = Vector05;
|
|
|
|
|
n.Ushort05a = Ushort05a;
|
|
|
|
|
n.Ushort05b = Ushort05b;
|
|
|
|
|
n.Vector06 = Vector06;
|
|
|
|
|
n.Ushort06a = Ushort06a;
|
|
|
|
|
n.Ushort06b = Ushort06b;
|
|
|
|
|
n.Vector07 = Vector07;
|
|
|
|
|
n.Ushort07a = Ushort07a;
|
|
|
|
|
n.Ushort07b = Ushort07b;
|
|
|
|
|
n.Vector08 = Vector08;
|
|
|
|
|
n.Ushort08a = Ushort08a;
|
|
|
|
|
n.Ushort08b = Ushort08b;
|
|
|
|
|
n.Vector09 = Vector09;
|
|
|
|
|
n.Ushort09a = Ushort09a;
|
|
|
|
|
n.Ushort09b = Ushort09b;
|
|
|
|
|
n.Gravity = Gravity;
|
|
|
|
|
n.BoneTag = BoneTag;
|
|
|
|
|
n.Ushort10b = Ushort10b;
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return BoneTag.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
[TC(typeof(EXP))] public struct ExpressionBoneTrack : IMetaXmlItem
|
2020-03-02 04:48:30 +08:00
|
|
|
|
{
|
2020-03-06 00:02:40 +08:00
|
|
|
|
public ushort BoneTag { get; set; }
|
|
|
|
|
public byte Track { get; set; }
|
|
|
|
|
public byte Flags { get; set; }
|
2020-03-02 04:48:30 +08:00
|
|
|
|
|
2022-01-31 16:39:42 +08:00
|
|
|
|
public void WriteXml(StringBuilder sb, int indent)
|
|
|
|
|
{
|
|
|
|
|
YedXml.ValueTag(sb, indent, "BoneTag", BoneTag.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Track", Track.ToString());
|
|
|
|
|
YedXml.ValueTag(sb, indent, "Flags", Flags.ToString());
|
|
|
|
|
}
|
|
|
|
|
public void ReadXml(XmlNode node)
|
|
|
|
|
{
|
|
|
|
|
BoneTag = (ushort)Xml.GetChildUIntAttribute(node, "BoneTag", "value");
|
|
|
|
|
Track = (byte)Xml.GetChildUIntAttribute(node, "Track", "value");
|
|
|
|
|
Flags = (byte)Xml.GetChildUIntAttribute(node, "Flags", "value");
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 04:48:30 +08:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
2020-03-06 00:02:40 +08:00
|
|
|
|
return BoneTag.ToString() + ", " + Track.ToString() + ", " + Flags.ToString();
|
2020-03-02 04:48:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-11-21 21:34:27 +08:00
|
|
|
|
}
|