Merge branch 'master' into ImportUnknownModelsetScenarios

This commit is contained in:
PNWParksFan 2019-09-08 22:48:19 -07:00
commit 3030e66aae
218 changed files with 83423 additions and 25223 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="CodeWalker.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
@ -92,7 +92,7 @@
<value>True</value>
</setting>
<setting name="WaitForChildren" serializeAs="String">
<value>False</value>
<value>True</value>
</setting>
<setting name="CacheSize" serializeAs="String">
<value>2147483648</value>
@ -204,4 +204,12 @@
</setting>
</CodeWalker.Properties.Settings>
</userSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WeifenLuo.WinFormsUI.Docking" publicKeyToken="5cded1a1a0a7b481" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.6.0" newVersion="3.0.6.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

1
CodeWalker Vehicles.cmd Normal file
View File

@ -0,0 +1 @@
start codewalker vehicles

View File

@ -48,7 +48,12 @@
</ItemGroup>
<ItemGroup>
<Compile Include="GameFiles\FileTypes\AwcFile.cs" />
<Compile Include="GameFiles\FileTypes\Builders\YndBuilder.cs" />
<Compile Include="GameFiles\FileTypes\Builders\YnvBuilder.cs" />
<Compile Include="GameFiles\FileTypes\CacheDatFile.cs" />
<Compile Include="GameFiles\FileTypes\CarColsFile.cs" />
<Compile Include="GameFiles\FileTypes\CarModColsFile.cs" />
<Compile Include="GameFiles\FileTypes\CarVariationsFile.cs" />
<Compile Include="GameFiles\FileTypes\CutFile.cs" />
<Compile Include="GameFiles\FileTypes\DlcContentFile.cs" />
<Compile Include="GameFiles\FileTypes\DlcSetupFile.cs" />
@ -58,6 +63,8 @@
<Compile Include="GameFiles\FileTypes\JPsoFile.cs" />
<Compile Include="GameFiles\FileTypes\RelFile.cs" />
<Compile Include="GameFiles\FileTypes\Stats.cs" />
<Compile Include="GameFiles\FileTypes\VehicleLayoutsFile.cs" />
<Compile Include="GameFiles\FileTypes\VehiclesFile.cs" />
<Compile Include="GameFiles\FileTypes\YbnFile.cs" />
<Compile Include="GameFiles\FileTypes\YcdFile.cs" />
<Compile Include="GameFiles\FileTypes\YddFile.cs" />
@ -82,9 +89,11 @@
<Compile Include="GameFiles\MetaTypes\MetaTypes.cs" />
<Compile Include="GameFiles\MetaTypes\MetaXml.cs" />
<Compile Include="GameFiles\MetaTypes\Pso.cs" />
<Compile Include="GameFiles\MetaTypes\PsoBuilder.cs" />
<Compile Include="GameFiles\MetaTypes\PsoTypes.cs" />
<Compile Include="GameFiles\MetaTypes\Rbf.cs" />
<Compile Include="GameFiles\MetaTypes\XmlMeta.cs" />
<Compile Include="GameFiles\MetaTypes\XmlPso.cs" />
<Compile Include="GameFiles\Resources\Bounds.cs" />
<Compile Include="GameFiles\Resources\Clip.cs" />
<Compile Include="GameFiles\Resources\Drawable.cs" />
@ -112,7 +121,10 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Utils\BoundingBoxes.cs" />
<Compile Include="Utils\Cache.cs" />
<Compile Include="Utils\Fbx.cs" />
<Compile Include="Utils\FbxConverter.cs" />
<Compile Include="Utils\Matrices.cs" />
<Compile Include="Utils\Quaternions.cs" />
<Compile Include="Utils\Utils.cs" />

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.Core.GameFiles.FileTypes.Builders
{
public class YndBuilder
{
}
}

View File

@ -0,0 +1,473 @@
using CodeWalker.GameFiles;
using CodeWalker.World;
using SharpDX;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.Core.GameFiles.FileTypes.Builders
{
public class YnvBuilder
{
/*
*
* YnvBuilder by dexyfex
*
* This class allows for conversion of navmesh data in a generic format into .ynv files.
* The usage is to call AddPoly() with an array of vertex positions for each polygon.
* Polygons should be wound in an anticlockwise direction.
* The returned YnvPoly object needs to have its Edges array set by the importer.
* YnvPoly.Edges is an array of YnvEdge, with one edge for each vertex in the poly.
* The first edge should join the first and second vertices, and the last edge should
* join the last and first vertices.
* The YnvEdge Poly1 and Poly2 both need to be set to the same value, which is the
* corresponding YnvPoly object that was returned by AddPoly.
* Flags values on the polygons and edges also need to be set by the importer.
*
* Once the polygons and edges have all been added, the Build() method should be called,
* which will return a list of YnvFile objects. Call the Save() method on each of those
* to get the byte array for the .ynv file. The correct filename is given by the
* YnvFile.Name property.
* Note that the .ynv building process will split polygons that cross .ynv area borders,
* and assign all the new polygons into the correct .ynv's.
*
*/
private List<YnvPoly> PolyList = new List<YnvPoly>();
private SpaceNavGrid NavGrid = null;
private List<YnvFile> YnvFiles = null;
public YnvPoly AddPoly(Vector3[] verts)
{
if ((verts == null) || (verts.Length < 3))
{ return null; }
YnvPoly poly = new YnvPoly();
poly.AreaID = 0x3FFF;
poly.Index = PolyList.Count;
poly.Vertices = verts;
PolyList.Add(poly);
return poly;
}
public List<YnvFile> Build(bool forVehicle)
{
NavGrid = new SpaceNavGrid();
YnvFiles = new List<YnvFile>();
if (forVehicle) //for vehicle YNV, only need a single ynv, no splitting
{
//TODO!
}
else //for static world ynv, need to split polys and generate a set of ynv's.
{
//1: split polys going over nav grid borders, first by X then by Y
var splitpolysX = SplitPolys(PolyList, true);
var splitpolysY = SplitPolys(splitpolysX, false);
//2: assign polys into their new ynv's
AddPolysIntoGrid(splitpolysY);
//3: fix up generated ynv's
FinalizeYnvs(YnvFiles);
}
return YnvFiles;
}
private List<YnvPoly> SplitPolys(List<YnvPoly> polys, bool xaxis)
{
var newpolys = new List<YnvPoly>();
var verts1 = new List<Vector3>();
var verts2 = new List<Vector3>();
var edges1 = new List<YnvEdge>();
var edges2 = new List<YnvEdge>();
var polysplits = new Dictionary<YnvPoly, YnvPolySplit>();
foreach (var poly in polys) //split along borders
{
var verts = poly.Vertices;
if (verts == null)
{ continue; }//ignore empty polys..
if (verts.Length < 3)
{ continue; }//not enough verts for a triangle!
Vector2I gprev = NavGrid.GetCellPos(verts[0]);
int split1 = 0;
int split2 = 0;
for (int i = 1; i < verts.Length; i++)
{
Vector2I g = NavGrid.GetCellPos(verts[i]);
int g1 = xaxis ? g.X : g.Y;
int g2 = xaxis ? gprev.X : gprev.Y;
if (g1 != g2) //this poly is crossing a border
{
if (split1 == 0) { split1 = i; }
else { split2 = i; break; }
}
gprev = g;
}
if (split1 > 0)
{
var split2beg = (split2 > 0) ? split2 - 1 : verts.Length - 1;
var split2end = split2beg + 1;
var sv11 = verts[split1 - 1];
var sv12 = verts[split1];
var sv21 = verts[split2beg];
var sv22 = verts[split2];
var sp1 = GetSplitPos(sv11, sv12, xaxis);
var sp2 = GetSplitPos(sv21, sv22, xaxis);
//if ((sp1 == sp2) || (sp1 == sv11) || (sp1 == sv12) || (sp2 == sv21) || (sp2 == sv22))
if (!IsValidSplit(sp1, sp2, sv11, sv12, sv21, sv22))
{
//split did nothing, just leave this poly alone
newpolys.Add(poly);
}
else
{
//split it!
var poly1 = new YnvPoly();
var poly2 = new YnvPoly();
poly1.RawData = poly.RawData;
poly2.RawData = poly.RawData;
verts1.Clear();
verts2.Clear();
for (int i = 0; i < split1; i++) verts1.Add(verts[i]);
verts1.Add(sp1);
verts1.Add(sp2);
for (int i = split2end; i < verts.Length; i++) verts1.Add(verts[i]);
verts2.Add(sp1);
for (int i = split1; i < split2end; i++) verts2.Add(verts[i]);
verts2.Add(sp2);
poly1.Vertices = verts1.ToArray();
poly2.Vertices = verts2.ToArray();
//save this information for the edge splitting pass
var polysplit = new YnvPolySplit();
polysplit.Orig = poly;
polysplit.New1 = poly1;
polysplit.New2 = poly2;
polysplit.Split1 = split1;
polysplit.Split2 = split2end;
polysplits[poly] = polysplit;
newpolys.Add(poly1);
newpolys.Add(poly2);
}
}
else
{
//no need to split
newpolys.Add(poly);
}
}
foreach (var polysplit in polysplits.Values) //build new edges for split polys
{
//the two edges that were split each need to be turned into two new edges (1 for each poly).
//also, the split itself needs to be added as a new edge to the original poly.
var poly = polysplit.Orig;
var poly1 = polysplit.New1;
var poly2 = polysplit.New2;
var edges = poly.Edges;
var verts = poly.Vertices;
var ec = edges?.Length ?? 0;
if (ec <= 0)
{ continue; }//shouldn't happen - no edges?
if (ec != poly.Vertices?.Length)
{ continue; }//shouldn't happen
var split1beg = polysplit.Split1 - 1;
var split1end = polysplit.Split1;
var split2beg = polysplit.Split2 - 1;
var split2end = polysplit.Split2;
edges1.Clear();
edges2.Clear();
var se1 = edges[split1beg]; //the two original edges that got split
var se2 = edges[split2beg];
var sp1 = TryGetSplit(polysplits, se1.Poly1);//could use Poly2, but they should be the same..
var sp2 = TryGetSplit(polysplits, se2.Poly1);
var sv1a = verts[split1beg];
var sv2a = verts[split2beg];
var sp1a = sp1?.GetNearest(sv1a);
var sp1b = sp1?.GetOther(sp1a);
var sp2b = sp2?.GetNearest(sv2a);
var sp2a = sp2?.GetOther(sp2b);
var edge1a = new YnvEdge(se1, sp1a);
var edge1b = new YnvEdge(se1, sp1b);
var edge2a = new YnvEdge(se2, sp2a);
var edge2b = new YnvEdge(se2, sp2b);
var splita = new YnvEdge(se1, poly2);
var splitb = new YnvEdge(se1, poly1);
for (int i = 0; i < split1beg; i++) edges1.Add(edges[i]);//untouched edges
edges1.Add(edge1a);
edges1.Add(splita);
edges1.Add(edge2a);
for (int i = split2end; i < ec; i++) edges1.Add(edges[i]);//untouched edges
edges2.Add(edge1b);
for (int i = split1end; i < split2beg; i++) edges2.Add(edges[i]);//untouched edges
edges2.Add(edge2b);
edges2.Add(splitb);
poly1.Edges = edges1.ToArray();
poly2.Edges = edges2.ToArray();
if (poly1.Edges.Length != poly1.Vertices.Length)
{ }//debug
if (poly2.Edges.Length != poly2.Vertices.Length)
{ }//debug
}
foreach (var poly in newpolys) //fix any untouched edges that joined to split polys
{
if (poly.Edges?.Length != poly.Vertices?.Length)
{ continue; }//shouldn't happen (no edges?)
for (int i = 0; i < poly.Edges.Length; i++)
{
var edge = poly.Edges[i];
var vert = poly.Vertices[i];
if (edge == null)
{ continue; }//shouldn't happen
if (edge.Poly1 != edge.Poly2)
{ continue; }//shouldn't happen?
if (edge.Poly1 == null)
{ continue; }//probably this edge joins to nothing
YnvPolySplit polysplit;
if (polysplits.TryGetValue(edge.Poly1, out polysplit))
{
var newpoly = polysplit.GetNearest(vert);
if (newpoly == null)
{ }//debug
edge.Poly1 = newpoly;
edge.Poly2 = newpoly;
}
}
}
return newpolys;
}
private Vector3 GetSplitPos(Vector3 a, Vector3 b, bool xaxis)
{
Vector3 ca = NavGrid.GetCellRel(a);
Vector3 cb = NavGrid.GetCellRel(b);
float fa = xaxis ? ca.X : ca.Y;
float fb = xaxis ? cb.X : cb.Y;
float f = 0;
if (fb > fa)
{
float ib = (float)Math.Floor(fb);
f = (ib - fa) / (fb - fa);
}
else
{
float ia = (float)Math.Floor(fa);
f = (fa - ia) / (fa - fb);
}
if (f < 0.0f)
{ }//debug
if (f > 1.0f)
{ }//debug
return a + (b - a) * Math.Min(Math.Max(f, 0.0f), 1.0f);
}
private bool IsValidSplit(Vector3 s1, Vector3 s2, Vector3 v1a, Vector3 v1b, Vector3 v2a, Vector3 v2b)
{
if (XYEqual(s1, s2)) return false;
if (XYEqual(s1, v1a)) return false;
if (XYEqual(s1, v1b)) return false;
if (XYEqual(s2, v2a)) return false;
if (XYEqual(s2, v2b)) return false;
return true;
}
private bool XYEqual(Vector3 v1, Vector3 v2)
{
return ((v1.X == v2.X) && (v1.Y == v2.Y));
}
private class YnvPolySplit
{
public YnvPoly Orig;
public YnvPoly New1;
public YnvPoly New2;
public int Split1;
public int Split2;
public YnvPoly GetNearest(Vector3 v)
{
if (New1?.Vertices == null) return New2;
if (New2?.Vertices == null) return New1;
float len1 = float.MaxValue;
float len2 = float.MaxValue;
for (int i = 0; i < New1.Vertices.Length; i++)
{
len1 = Math.Min(len1, (v - New1.Vertices[i]).LengthSquared());
}
if (len1 == 0.0f) return New1;
for (int i = 0; i < New2.Vertices.Length; i++)
{
len2 = Math.Min(len2, (v - New2.Vertices[i]).LengthSquared());
}
if (len2 == 0.0f) return New2;
return (len1 <= len2) ? New1 : New2;
}
public YnvPoly GetOther(YnvPoly p)
{
if (p == New1) return New2;
return New1;
}
}
private YnvPolySplit TryGetSplit(Dictionary<YnvPoly, YnvPolySplit> polysplits, YnvPoly poly)
{
if (poly == null) return null;
YnvPolySplit r = null;
polysplits.TryGetValue(poly, out r);
return r;
}
private void AddPolysIntoGrid(List<YnvPoly> polys)
{
foreach (var poly in polys)
{
poly.CalculatePosition();
var pos = poly.Position;
var cell = NavGrid.GetCell(pos);
var ynv = cell.Ynv;
if (ynv == null)
{
ynv = new YnvFile();
ynv.Name = "navmesh[" + cell.FileX.ToString() + "][" + cell.FileY.ToString() + "]";
ynv.Nav = new NavMesh();
ynv.Nav.SetDefaults(false);
ynv.Nav.AABBSize = new Vector3(NavGrid.CellSize, NavGrid.CellSize, 0.0f);
ynv.Nav.SectorTree = new NavMeshSector();
ynv.Nav.SectorTree.AABBMin = new Vector4(NavGrid.GetCellMin(cell), 0.0f);
ynv.Nav.SectorTree.AABBMax = new Vector4(NavGrid.GetCellMax(cell), 0.0f);
ynv.AreaID = cell.X + cell.Y * 100;
ynv.Polys = new List<YnvPoly>();
ynv.HasChanged = true;//mark it for the project window
ynv.RpfFileEntry = new RpfResourceFileEntry();
ynv.RpfFileEntry.Name = ynv.Name + ".ynv";
ynv.RpfFileEntry.Path = string.Empty;
cell.Ynv = ynv;
YnvFiles.Add(ynv);
}
poly.AreaID = (ushort)ynv.AreaID;
poly.Index = ynv.Polys.Count;
poly.Ynv = ynv;
ynv.Polys.Add(poly);
}
}
private void FinalizeYnvs(List<YnvFile> ynvs)
{
foreach (var ynv in ynvs)
{
//find zmin and zmax and update AABBSize and SectorTree root
float zmin = float.MaxValue;
float zmax = float.MinValue;
foreach (var poly in ynv.Polys)
{
foreach (var vert in poly.Vertices)
{
zmin = Math.Min(zmin, vert.Z);
zmax = Math.Max(zmax, vert.Z);
}
}
var yn = ynv.Nav;
var ys = yn.SectorTree;
yn.AABBSize = new Vector3(yn.AABBSize.X, yn.AABBSize.Y, zmax - zmin);
ys.AABBMin = new Vector4(ys.AABBMin.X, ys.AABBMin.Y, zmin, 0.0f);
ys.AABBMax = new Vector4(ys.AABBMax.X, ys.AABBMax.Y, zmax, 0.0f);
ynv.UpdateContentFlags(false);
//fix up flags on edges that cross ynv borders
foreach (var poly in ynv.Polys)
{
bool border = false;
if (poly.Edges == null)
{ continue; }
foreach (var edge in poly.Edges)
{
if (edge.Poly1 != null)
{
if (edge.Poly1.AreaID != poly.AreaID)
{
edge._RawData._Poly1.Unk2 = 0;//crash without this
edge._RawData._Poly2.Unk2 = 0;//crash without this
edge._RawData._Poly2.Unk3 = 4;////// edge._RawData._Poly2.Unk3 | 4;
border = true;
////DEBUG don't join edges
//edge.Poly1 = null;
//edge.Poly2 = null;
//edge.AreaID1 = 0x3FFF;
//edge.AreaID2 = 0x3FFF;
//edge._RawData._Poly1.PolyID = 0x3FFF;
//edge._RawData._Poly2.PolyID = 0x3FFF;
//edge._RawData._Poly1.Unk2 = 1;
//edge._RawData._Poly2.Unk2 = 1;
//edge._RawData._Poly1.Unk3 = 0;
//edge._RawData._Poly2.Unk3 = 0;
}
}
}
poly.B19_IsCellEdge = border;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using TC = System.ComponentModel.TypeConverterAttribute;
using EXP = System.ComponentModel.ExpandableObjectConverter;
namespace CodeWalker.GameFiles
{
[TC(typeof(EXP))] public class CarModColsFile : GameFile, PackedFile
{
public PsoFile Pso { get; set; }
public string Xml { get; set; }
public CVehicleModColours VehicleModColours { get; set; }
public CarModColsFile() : base(null, GameFileType.CarModCols)
{ }
public CarModColsFile(RpfFileEntry entry) : base(entry, GameFileType.CarModCols)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
RpfFileEntry = entry;
Name = entry.Name;
FilePath = Name;
//always PSO .ymt
MemoryStream ms = new MemoryStream(data);
if (PsoFile.IsPSO(ms))
{
Pso = new PsoFile();
Pso.Load(data);
Xml = PsoXml.GetXml(Pso); //yep let's just convert that to XML :P
}
XmlDocument xdoc = new XmlDocument();
if (!string.IsNullOrEmpty(Xml))
{
try
{
xdoc.LoadXml(Xml);
}
catch (Exception ex)
{
var msg = ex.Message;
}
}
else
{ }
if (xdoc.DocumentElement != null)
{
VehicleModColours = new CVehicleModColours(xdoc.DocumentElement);
}
Loaded = true;
}
}
[TC(typeof(EXP))] public class CVehicleModColours
{
public CVehicleModColor[] metallic { get; set; }
public CVehicleModColor[] classic { get; set; }
public CVehicleModColor[] matte { get; set; }
public CVehicleModColor[] metals { get; set; }
public CVehicleModColor[] chrome { get; set; }
public CVehicleModPearlescentColors pearlescent { get; set; }
public CVehicleModColours(XmlNode node)
{
XmlNode cnode;
cnode = node.SelectSingleNode("metallic");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
metallic = new CVehicleModColor[items.Count];
for (int i = 0; i < items.Count; i++)
{
metallic[i] = new CVehicleModColor(items[i]);
}
}
}
cnode = node.SelectSingleNode("classic");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
classic = new CVehicleModColor[items.Count];
for (int i = 0; i < items.Count; i++)
{
classic[i] = new CVehicleModColor(items[i]);
}
}
}
cnode = node.SelectSingleNode("matte");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
matte = new CVehicleModColor[items.Count];
for (int i = 0; i < items.Count; i++)
{
matte[i] = new CVehicleModColor(items[i]);
}
}
}
cnode = node.SelectSingleNode("metals");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
metals = new CVehicleModColor[items.Count];
for (int i = 0; i < items.Count; i++)
{
metals[i] = new CVehicleModColor(items[i]);
}
}
}
cnode = node.SelectSingleNode("chrome");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
chrome = new CVehicleModColor[items.Count];
for (int i = 0; i < items.Count; i++)
{
chrome[i] = new CVehicleModColor(items[i]);
}
}
}
cnode = node.SelectSingleNode("pearlescent");
if (cnode != null)
{
pearlescent = new CVehicleModPearlescentColors(cnode);
}
}
}
[TC(typeof(EXP))] public class CVehicleModColor
{
public string name { get; set; }
public byte col { get; set; }
public byte spec { get; set; }
public CVehicleModColor(XmlNode node)
{
name = Xml.GetChildInnerText(node, "name");
col = (byte)Xml.GetChildIntAttribute(node, "col", "value");
spec = (byte)Xml.GetChildIntAttribute(node, "spec", "value");
}
public override string ToString()
{
return name;
}
}
[TC(typeof(EXP))] public class CVehicleModPearlescentColors
{
public CVehicleModColor[] baseCols { get; set; }
public CVehicleModColor[] specCols { get; set; }
public CVehicleModPearlescentColors(XmlNode node)
{
XmlNode cnode;
cnode = node.SelectSingleNode("baseCols");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
baseCols = new CVehicleModColor[items.Count];
for (int i = 0; i < items.Count; i++)
{
baseCols[i] = new CVehicleModColor(items[i]);
}
}
}
cnode = node.SelectSingleNode("specCols");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
specCols = new CVehicleModColor[items.Count];
for (int i = 0; i < items.Count; i++)
{
specCols[i] = new CVehicleModColor(items[i]);
}
}
}
}
}
}

View File

@ -0,0 +1,261 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;
using System.IO;
using System.Xml;
using TC = System.ComponentModel.TypeConverterAttribute;
using EXP = System.ComponentModel.ExpandableObjectConverter;
namespace CodeWalker.GameFiles
{
[TC(typeof(EXP))] public class CarVariationsFile : GameFile, PackedFile
{
public PsoFile Pso { get; set; }
public string Xml { get; set; }
public CVehicleModelInfoVariation VehicleModelInfo { get; set; }
public CarVariationsFile() : base(null, GameFileType.CarVariations)
{ }
public CarVariationsFile(RpfFileEntry entry) : base(entry, GameFileType.CarVariations)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
RpfFileEntry = entry;
Name = entry.Name;
FilePath = Name;
//can be PSO .ymt or XML .meta
MemoryStream ms = new MemoryStream(data);
if (PsoFile.IsPSO(ms))
{
Pso = new PsoFile();
Pso.Load(data);
Xml = PsoXml.GetXml(Pso); //yep let's just convert that to XML :P
}
else
{
Xml = Encoding.UTF8.GetString(data);
}
XmlDocument xdoc = new XmlDocument();
if (!string.IsNullOrEmpty(Xml))
{
try
{
xdoc.LoadXml(Xml);
}
catch (Exception ex)
{
var msg = ex.Message;
}
}
else
{ }
if (xdoc.DocumentElement != null)
{
VehicleModelInfo = new CVehicleModelInfoVariation(xdoc.DocumentElement);
}
Loaded = true;
}
}
[TC(typeof(EXP))] public class CVehicleModelInfoVariation
{
public CVehicleModelInfoVariation_418053801[] variationData { get; set; }
public CVehicleModelInfoVariation(XmlNode node)
{
XmlNode cnode;
cnode = node.SelectSingleNode("variationData");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
variationData = new CVehicleModelInfoVariation_418053801[items.Count];
for (int i = 0; i < items.Count; i++)
{
variationData[i] = new CVehicleModelInfoVariation_418053801(items[i]);
}
}
}
}
}
[TC(typeof(EXP))] public class CVehicleModelInfoVariation_418053801
{
public string modelName { get; set; }
public CVehicleModelInfoVariation_2575850962[] colors { get; set; }
public MetaHash[] kits { get; set; }
public MetaHash[] windowsWithExposedEdges { get; set; }
public PlateProbabilities plateProbabilities { get; set; }
public byte lightSettings { get; set; }
public byte sirenSettings { get; set; }
public CVehicleModelInfoVariation_418053801(XmlNode node)
{
modelName = Xml.GetChildInnerText(node, "modelName");
XmlNode cnode;
cnode = node.SelectSingleNode("colors");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
colors = new CVehicleModelInfoVariation_2575850962[items.Count];
for (int i = 0; i < items.Count; i++)
{
colors[i] = new CVehicleModelInfoVariation_2575850962(items[i]);
}
}
}
cnode = node.SelectSingleNode("kits");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
kits = new MetaHash[items.Count];
for (int i = 0; i < items.Count; i++)
{
kits[i] = XmlMeta.GetHash(items[i].InnerText);
}
}
}
cnode = node.SelectSingleNode("windowsWithExposedEdges");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
windowsWithExposedEdges = new MetaHash[items.Count];
for (int i = 0; i < items.Count; i++)
{
windowsWithExposedEdges[i] = XmlMeta.GetHash(items[i].InnerText);
}
}
}
cnode = node.SelectSingleNode("plateProbabilities");
if (cnode != null)
{
plateProbabilities = new PlateProbabilities(cnode);
}
lightSettings = (byte)Xml.GetChildIntAttribute(node, "lightSettings", "value");
sirenSettings = (byte)Xml.GetChildIntAttribute(node, "sirenSettings", "value");
}
public override string ToString()
{
return modelName;
}
}
[TC(typeof(EXP))] public class CVehicleModelInfoVariation_2575850962
{
public byte[] indices { get; set; }
public bool[] liveries { get; set; }
public CVehicleModelInfoVariation_2575850962(XmlNode node)
{
XmlNode cnode;
cnode = node.SelectSingleNode("indices");
if (cnode != null)
{
var astr = cnode.InnerText;
var arrr = astr.Split(new[] { '\n', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
var alist = new List<byte>();
foreach (var item in arrr)
{
var titem = item.Trim();
byte v;
if (byte.TryParse(titem, out v))
{
alist.Add(v);
}
}
indices = alist.ToArray();
}
cnode = node.SelectSingleNode("liveries");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
liveries = new bool[items.Count];
for (int i = 0; i < items.Count; i++)
{
liveries[i] = Xml.GetBoolAttribute(items[i], "value");
}
}
else
{
var astr = cnode.InnerText;
var arrr = astr.Split(new[] { '\n', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
var alist = new List<bool>();
foreach (var item in arrr)
{
var titem = item.Trim();
byte v;
if (byte.TryParse(titem, out v))
{
alist.Add(v > 0);
}
}
liveries = alist.ToArray();
}
}
}
}
[TC(typeof(EXP))] public class PlateProbabilities
{
public PlateProbabilities_938618322[] Probabilities { get; set; }
public PlateProbabilities(XmlNode node)
{
XmlNode cnode;
cnode = node.SelectSingleNode("Probabilities");
if (cnode != null)
{
var items = cnode.SelectNodes("Item");
if (items.Count > 0)
{
Probabilities = new PlateProbabilities_938618322[items.Count];
for (int i = 0; i < items.Count; i++)
{
Probabilities[i] = new PlateProbabilities_938618322(items[i]);
}
}
}
}
}
[TC(typeof(EXP))] public class PlateProbabilities_938618322
{
public MetaHash Name { get; set; }
public uint Value { get; set; }
public PlateProbabilities_938618322(XmlNode node)
{
Name = XmlMeta.GetHash(Xml.GetChildInnerText(node, "Name"));
Value = Xml.GetChildUIntAttribute(node, "Value", "value");
}
public override string ToString()
{
return Name.ToString() + ": " + Value.ToString();
}
}
}

View File

@ -21,6 +21,7 @@ namespace CodeWalker.GameFiles
public bool isLevelPack { get; set; }
public RpfFile DlcFile { get; set; } //used by GameFileCache
public List<RpfFile> DlcSubpacks { get; set; } //used by GameFileCache
public DlcContentFile ContentFile { get; set; }
public void Load(XmlDocument doc)

View File

@ -15,7 +15,7 @@ namespace CodeWalker.GameFiles
public RbfFile Rbf { get; set; }
public Dictionary<string, string> CMapParentTxds { get; set; }
public Dictionary<string, string> TxdRelationships { get; set; }
@ -46,7 +46,7 @@ namespace CodeWalker.GameFiles
if (rbfstruct.Name == "CMapParentTxds")
{
LoadMapParentTxds(rbfstruct);
LoadTxdRelationships(rbfstruct);
}
Loaded = true;
@ -68,7 +68,7 @@ namespace CodeWalker.GameFiles
xml = xml.Remove(0, bom.Length);
}
LoadMapParentTxds(xml);
LoadTxdRelationships(xml);
Loaded = true;
}
@ -76,10 +76,10 @@ namespace CodeWalker.GameFiles
}
private void LoadMapParentTxds(RbfStructure rbfstruct)
private void LoadTxdRelationships(RbfStructure rbfstruct)
{
CMapParentTxds = new Dictionary<string, string>();
TxdRelationships = new Dictionary<string, string>();
//StringBuilder sblist = new StringBuilder();
foreach (var child in rbfstruct.Children)
{
@ -118,9 +118,9 @@ namespace CodeWalker.GameFiles
}
if ((!string.IsNullOrEmpty(parentstr)) && (!string.IsNullOrEmpty(childstr)))
{
if (!CMapParentTxds.ContainsKey(childstr))
if (!TxdRelationships.ContainsKey(childstr))
{
CMapParentTxds.Add(childstr, parentstr);
TxdRelationships.Add(childstr, parentstr);
}
else
{
@ -140,13 +140,13 @@ namespace CodeWalker.GameFiles
private void LoadMapParentTxds(string xml)
private void LoadTxdRelationships(string xml)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(xml); //maybe better load xml.ToLower() and use "cmapparenttxds/txdrelationships/item" as xpath?
XmlNodeList items = xmldoc.SelectNodes("CMapParentTxds/txdRelationships/Item | CMapParentTxds/txdRelationships/item");
CMapParentTxds = new Dictionary<string, string>();
TxdRelationships = new Dictionary<string, string>();
for (int i = 0; i < items.Count; i++)
{
string parentstr = Xml.GetChildInnerText(items[i], "parent");
@ -154,9 +154,9 @@ namespace CodeWalker.GameFiles
if ((!string.IsNullOrEmpty(parentstr)) && (!string.IsNullOrEmpty(childstr)))
{
if (!CMapParentTxds.ContainsKey(childstr))
if (!TxdRelationships.ContainsKey(childstr))
{
CMapParentTxds.Add(childstr, parentstr);
TxdRelationships.Add(childstr, parentstr);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
[TypeConverter(typeof(ExpandableObjectConverter))]
public class VehicleLayoutsFile : GameFile, PackedFile
{
public string Xml { get; set; }
public VehicleLayoutsFile() : base(null, GameFileType.VehicleLayouts)
{ }
public VehicleLayoutsFile(RpfFileEntry entry) : base(entry, GameFileType.VehicleLayouts)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
RpfFileEntry = entry;
Name = entry.Name;
FilePath = Name;
//always XML .meta
Xml = Encoding.UTF8.GetString(data);
//TODO: parse CVehicleMetadataMgr XML
Loaded = true;
}
}
}

View File

@ -0,0 +1,408 @@
using SharpDX;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace CodeWalker.GameFiles
{
public class VehiclesFile : GameFile, PackedFile
{
public string ResidentTxd { get; set; }
public List<VehicleInitData> InitDatas { get; set; }
public Dictionary<string, string> TxdRelationships { get; set; }
public VehiclesFile() : base(null, GameFileType.Vehicles)
{
}
public VehiclesFile(RpfFileEntry entry) : base(entry, GameFileType.Vehicles)
{
}
public void Load(byte[] data, RpfFileEntry entry)
{
RpfFileEntry = entry;
Name = entry.Name;
FilePath = Name;
if (entry.NameLower.EndsWith(".meta"))
{
//required for update\x64\dlcpacks\mpheist\dlc.rpf\common\data\gtxd.meta and update\x64\dlcpacks\mpluxe\dlc.rpf\common\data\gtxd.meta
string bom = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
string xml = Encoding.UTF8.GetString(data);
if (xml.StartsWith(bom, StringComparison.Ordinal))
{
xml = xml.Remove(0, bom.Length);
}
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(xml);
ResidentTxd = Xml.GetChildInnerText(xmldoc.SelectSingleNode("CVehicleModelInfo__InitDataList"), "residentTxd");
LoadInitDatas(xmldoc);
LoadTxdRelationships(xmldoc);
Loaded = true;
}
}
private void LoadInitDatas(XmlDocument xmldoc)
{
XmlNodeList items = xmldoc.SelectNodes("CVehicleModelInfo__InitDataList/InitDatas/Item | CVehicleModelInfo__InitDataList/InitDatas/item");
InitDatas = new List<VehicleInitData>();
for (int i = 0; i < items.Count; i++)
{
var node = items[i];
VehicleInitData d = new VehicleInitData();
d.Load(node);
InitDatas.Add(d);
}
}
private void LoadTxdRelationships(XmlDocument xmldoc)
{
XmlNodeList items = xmldoc.SelectNodes("CVehicleModelInfo__InitDataList/txdRelationships/Item | CVehicleModelInfo__InitDataList/txdRelationships/item");
TxdRelationships = new Dictionary<string, string>();
for (int i = 0; i < items.Count; i++)
{
string parentstr = Xml.GetChildInnerText(items[i], "parent");
string childstr = Xml.GetChildInnerText(items[i], "child");
if ((!string.IsNullOrEmpty(parentstr)) && (!string.IsNullOrEmpty(childstr)))
{
if (!TxdRelationships.ContainsKey(childstr))
{
TxdRelationships.Add(childstr, parentstr);
}
else
{ }
}
}
}
}
public class VehicleInitData
{
public string modelName { get; set; } //<modelName>impaler3</modelName>
public string txdName { get; set; } //<txdName>impaler3</txdName>
public string handlingId { get; set; } //<handlingId>IMPALER3</handlingId>
public string gameName { get; set; } //<gameName>IMPALER3</gameName>
public string vehicleMakeName { get; set; } //<vehicleMakeName>DECLASSE</vehicleMakeName>
public string expressionDictName { get; set; } //<expressionDictName>null</expressionDictName>
public string expressionName { get; set; } //<expressionName>null</expressionName>
public string animConvRoofDictName { get; set; } //<animConvRoofDictName>null</animConvRoofDictName>
public string animConvRoofName { get; set; } //<animConvRoofName>null</animConvRoofName>
public string animConvRoofWindowsAffected { get; set; } //<animConvRoofWindowsAffected />
public string ptfxAssetName { get; set; } //<ptfxAssetName>weap_xs_vehicle_weapons</ptfxAssetName>
public string audioNameHash { get; set; } //<audioNameHash />
public string layout { get; set; } //<layout>LAYOUT_STD_ARENA_1HONLY</layout>
public string coverBoundOffsets { get; set; } //<coverBoundOffsets>IMPALER_COVER_OFFSET_INFO</coverBoundOffsets>
public string explosionInfo { get; set; } //<explosionInfo>EXPLOSION_INFO_DEFAULT</explosionInfo>
public string scenarioLayout { get; set; } //<scenarioLayout />
public string cameraName { get; set; } //<cameraName>FOLLOW_CHEETAH_CAMERA</cameraName>
public string aimCameraName { get; set; } //<aimCameraName>DEFAULT_THIRD_PERSON_VEHICLE_AIM_CAMERA</aimCameraName>
public string bonnetCameraName { get; set; } //<bonnetCameraName>VEHICLE_BONNET_CAMERA_STANDARD_LONG_DEVIANT</bonnetCameraName>
public string povCameraName { get; set; } //<povCameraName>REDUCED_NEAR_CLIP_POV_CAMERA</povCameraName>
public Vector3 FirstPersonDriveByIKOffset { get; set; } //<FirstPersonDriveByIKOffset x="0.020000" y="-0.065000" z="-0.050000" />
public Vector3 FirstPersonDriveByUnarmedIKOffset { get; set; } //<FirstPersonDriveByUnarmedIKOffset x="0.000000" y="-0.100000" z="0.000000" />
public Vector3 FirstPersonProjectileDriveByIKOffset { get; set; } //<FirstPersonProjectileDriveByIKOffset x="0.000000" y="-0.130000" z="-0.050000" />
public Vector3 FirstPersonProjectileDriveByPassengerIKOffset { get; set; } //<FirstPersonProjectileDriveByPassengerIKOffset x="0.000000" y="-0.100000" z="0.000000" />
public Vector3 FirstPersonDriveByRightPassengerIKOffset { get; set; } //<FirstPersonDriveByRightPassengerIKOffset x="-0.020000" y="-0.065000" z="-0.050000" />
public Vector3 FirstPersonDriveByRightPassengerUnarmedIKOffset { get; set; }//<FirstPersonDriveByRightPassengerUnarmedIKOffset x="0.000000" y="-0.100000" z="0.000000" />
public Vector3 FirstPersonMobilePhoneOffset { get; set; } //<FirstPersonMobilePhoneOffset x="0.146000" y="0.220000" z="0.510000" />
public Vector3 FirstPersonPassengerMobilePhoneOffset { get; set; } //<FirstPersonPassengerMobilePhoneOffset x="0.234000" y="0.169000" z="0.395000" />
public Vector3 PovCameraOffset { get; set; } //<PovCameraOffset x="0.000000" y="-0.195000" z="0.640000" />
public Vector3 PovCameraVerticalAdjustmentForRollCage { get; set; } //<PovCameraVerticalAdjustmentForRollCage value="0.000000" />
public Vector3 PovPassengerCameraOffset { get; set; } //<PovPassengerCameraOffset x="0.000000" y="0.000000" z="0.000000" />
public Vector3 PovRearPassengerCameraOffset { get; set; } //<PovRearPassengerCameraOffset x="0.000000" y="0.000000" z="0.000000" />
public string vfxInfoName { get; set; } //<vfxInfoName>VFXVEHICLEINFO_CAR_GENERIC</vfxInfoName>
public bool shouldUseCinematicViewMode { get; set; } //<shouldUseCinematicViewMode value="true" />
public bool shouldCameraTransitionOnClimbUpDown { get; set; } //<shouldCameraTransitionOnClimbUpDown value="false" />
public bool shouldCameraIgnoreExiting { get; set; } //<shouldCameraIgnoreExiting value="false" />
public bool AllowPretendOccupants { get; set; } //<AllowPretendOccupants value="true" />
public bool AllowJoyriding { get; set; } //<AllowJoyriding value="true" />
public bool AllowSundayDriving { get; set; } //<AllowSundayDriving value="true" />
public bool AllowBodyColorMapping { get; set; } //<AllowBodyColorMapping value="true" />
public float wheelScale { get; set; } //<wheelScale value="0.202300" />
public float wheelScaleRear { get; set; } //<wheelScaleRear value="0.0.201800" />
public float dirtLevelMin { get; set; } //<dirtLevelMin value="0.000000" />
public float dirtLevelMax { get; set; } //<dirtLevelMax value="0.450000" />
public float envEffScaleMin { get; set; } //<envEffScaleMin value="0.000000" />
public float envEffScaleMax { get; set; } //<envEffScaleMax value="1.000000" />
public float envEffScaleMin2 { get; set; } //<envEffScaleMin2 value="0.000000" />
public float envEffScaleMax2 { get; set; } //<envEffScaleMax2 value="1.000000" />
public float damageMapScale { get; set; } //<damageMapScale value="0.000000" />
public float damageOffsetScale { get; set; } //<damageOffsetScale value="0.100000" />
public Color4 diffuseTint { get; set; } //<diffuseTint value="0x00FFFFFF" />
public float steerWheelMult { get; set; } //<steerWheelMult value="0.700000" />
public float HDTextureDist { get; set; } //<HDTextureDist value="5.000000" />
public float[] lodDistances { get; set; } //<lodDistances content="float_array">// 10.000000// 25.000000// 60.000000// 120.000000// 500.000000// 500.000000//</lodDistances>
public float minSeatHeight { get; set; } //<minSeatHeight value="0.844" />
public float identicalModelSpawnDistance { get; set; } //<identicalModelSpawnDistance value="20" />
public int maxNumOfSameColor { get; set; } //<maxNumOfSameColor value="1" />
public float defaultBodyHealth { get; set; } //<defaultBodyHealth value="1000.000000" />
public float pretendOccupantsScale { get; set; } //<pretendOccupantsScale value="1.000000" />
public float visibleSpawnDistScale { get; set; } //<visibleSpawnDistScale value="1.000000" />
public float trackerPathWidth { get; set; } //<trackerPathWidth value="2.000000" />
public float weaponForceMult { get; set; } //<weaponForceMult value="1.000000" />
public float frequency { get; set; } //<frequency value="30" />
public string swankness { get; set; } //<swankness>SWANKNESS_4</swankness>
public int maxNum { get; set; } //<maxNum value="10" />
public string[] flags { get; set; } //<flags>FLAG_RECESSED_HEADLIGHT_CORONAS FLAG_EXTRAS_STRONG FLAG_AVERAGE_CAR FLAG_HAS_INTERIOR_EXTRAS FLAG_CAN_HAVE_NEONS FLAG_HAS_JUMP_MOD FLAG_HAS_NITROUS_MOD FLAG_HAS_RAMMING_SCOOP_MOD FLAG_USE_AIRCRAFT_STYLE_WEAPON_TARGETING FLAG_HAS_SIDE_SHUNT FLAG_HAS_WEAPON_SPIKE_MODS FLAG_HAS_SUPERCHARGER FLAG_INCREASE_CAMBER_WITH_SUSPENSION_MOD FLAG_DISABLE_DEFORMATION</flags>
public string type { get; set; } //<type>VEHICLE_TYPE_CAR</type>
public string plateType { get; set; } //<plateType>VPT_FRONT_AND_BACK_PLATES</plateType>
public string dashboardType { get; set; } //<dashboardType>VDT_DUKES</dashboardType>
public string vehicleClass { get; set; } //<vehicleClass>VC_MUSCLE</vehicleClass>
public string wheelType { get; set; } //<wheelType>VWT_MUSCLE</wheelType>
public string[] trailers { get; set; } //<trailers />
public string[] additionalTrailers { get; set; } //<additionalTrailers />
public VehicleDriver[] drivers { get; set; } //<drivers />
public string[] extraIncludes { get; set; } //<extraIncludes />
public string[] doorsWithCollisionWhenClosed { get; set; } //<doorsWithCollisionWhenClosed />
public string[] driveableDoors { get; set; } //<driveableDoors />
public bool bumpersNeedToCollideWithMap { get; set; } //<bumpersNeedToCollideWithMap value="false" />
public bool needsRopeTexture { get; set; } //<needsRopeTexture value="false" />
public string[] requiredExtras { get; set; } //<requiredExtras>EXTRA_1 EXTRA_2 EXTRA_3</requiredExtras>
public string[] rewards { get; set; } //<rewards />
public string[] cinematicPartCamera { get; set; } //<cinematicPartCamera>// <Item>WHEEL_FRONT_RIGHT_CAMERA</Item>// <Item>WHEEL_FRONT_LEFT_CAMERA</Item>// <Item>WHEEL_REAR_RIGHT_CAMERA</Item>// <Item>WHEEL_REAR_LEFT_CAMERA</Item>//</cinematicPartCamera>
public string NmBraceOverrideSet { get; set; } //<NmBraceOverrideSet />
public Vector3 buoyancySphereOffset { get; set; } //<buoyancySphereOffset x="0.000000" y="0.000000" z="0.000000" />
public float buoyancySphereSizeScale { get; set; } //<buoyancySphereSizeScale value="1.000000" />
public VehicleOverrideRagdollThreshold pOverrideRagdollThreshold { get; set; } //<pOverrideRagdollThreshold type="NULL" />
public string[] firstPersonDrivebyData { get; set; } //<firstPersonDrivebyData>// <Item>STD_IMPALER2_FRONT_LEFT</Item>// <Item>STD_IMPALER2_FRONT_RIGHT</Item>//</firstPersonDrivebyData>
public void Load(XmlNode node)
{
modelName = Xml.GetChildInnerText(node, "modelName");
txdName = Xml.GetChildInnerText(node, "txdName");
handlingId = Xml.GetChildInnerText(node, "handlingId");
gameName = Xml.GetChildInnerText(node, "gameName");
vehicleMakeName = Xml.GetChildInnerText(node, "vehicleMakeName");
expressionDictName = Xml.GetChildInnerText(node, "expressionDictName");
expressionName = Xml.GetChildInnerText(node, "expressionName");
animConvRoofDictName = Xml.GetChildInnerText(node, "animConvRoofDictName");
animConvRoofName = Xml.GetChildInnerText(node, "animConvRoofName");
animConvRoofWindowsAffected = Xml.GetChildInnerText(node, "animConvRoofWindowsAffected");//?
ptfxAssetName = Xml.GetChildInnerText(node, "ptfxAssetName");
audioNameHash = Xml.GetChildInnerText(node, "audioNameHash");
layout = Xml.GetChildInnerText(node, "layout");
coverBoundOffsets = Xml.GetChildInnerText(node, "coverBoundOffsets");
explosionInfo = Xml.GetChildInnerText(node, "explosionInfo");
scenarioLayout = Xml.GetChildInnerText(node, "scenarioLayout");
cameraName = Xml.GetChildInnerText(node, "cameraName");
aimCameraName = Xml.GetChildInnerText(node, "aimCameraName");
bonnetCameraName = Xml.GetChildInnerText(node, "bonnetCameraName");
povCameraName = Xml.GetChildInnerText(node, "povCameraName");
FirstPersonDriveByIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByIKOffset", "x", "y", "z");
FirstPersonDriveByUnarmedIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByUnarmedIKOffset", "x", "y", "z");
FirstPersonProjectileDriveByIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonProjectileDriveByIKOffset", "x", "y", "z");
FirstPersonProjectileDriveByPassengerIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonProjectileDriveByPassengerIKOffset", "x", "y", "z");
FirstPersonDriveByRightPassengerIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByRightPassengerIKOffset", "x", "y", "z");
FirstPersonDriveByRightPassengerUnarmedIKOffset = Xml.GetChildVector3Attributes(node, "FirstPersonDriveByRightPassengerUnarmedIKOffset", "x", "y", "z");
FirstPersonMobilePhoneOffset = Xml.GetChildVector3Attributes(node, "FirstPersonMobilePhoneOffset", "x", "y", "z");
FirstPersonPassengerMobilePhoneOffset = Xml.GetChildVector3Attributes(node, "FirstPersonPassengerMobilePhoneOffset", "x", "y", "z");
PovCameraOffset = Xml.GetChildVector3Attributes(node, "PovCameraOffset", "x", "y", "z");
PovCameraVerticalAdjustmentForRollCage = Xml.GetChildVector3Attributes(node, "PovCameraVerticalAdjustmentForRollCage", "x", "y", "z");
PovPassengerCameraOffset = Xml.GetChildVector3Attributes(node, "PovPassengerCameraOffset", "x", "y", "z");
PovRearPassengerCameraOffset = Xml.GetChildVector3Attributes(node, "PovRearPassengerCameraOffset", "x", "y", "z");
vfxInfoName = Xml.GetChildInnerText(node, "vfxInfoName");
shouldUseCinematicViewMode = Xml.GetChildBoolAttribute(node, "shouldUseCinematicViewMode", "value");
shouldCameraTransitionOnClimbUpDown = Xml.GetChildBoolAttribute(node, "shouldCameraTransitionOnClimbUpDown", "value");
shouldCameraIgnoreExiting = Xml.GetChildBoolAttribute(node, "shouldCameraIgnoreExiting", "value");
AllowPretendOccupants = Xml.GetChildBoolAttribute(node, "AllowPretendOccupants", "value");
AllowJoyriding = Xml.GetChildBoolAttribute(node, "AllowJoyriding", "value");
AllowSundayDriving = Xml.GetChildBoolAttribute(node, "AllowSundayDriving", "value");
AllowBodyColorMapping = Xml.GetChildBoolAttribute(node, "AllowBodyColorMapping", "value");
wheelScale = Xml.GetChildFloatAttribute(node, "wheelScale", "value");
wheelScaleRear = Xml.GetChildFloatAttribute(node, "wheelScaleRear", "value");
dirtLevelMin = Xml.GetChildFloatAttribute(node, "dirtLevelMin", "value");
dirtLevelMax = Xml.GetChildFloatAttribute(node, "dirtLevelMax", "value");
envEffScaleMin = Xml.GetChildFloatAttribute(node, "envEffScaleMin", "value");
envEffScaleMax = Xml.GetChildFloatAttribute(node, "envEffScaleMax", "value");
envEffScaleMin2 = Xml.GetChildFloatAttribute(node, "envEffScaleMin2", "value");
envEffScaleMax2 = Xml.GetChildFloatAttribute(node, "envEffScaleMax2", "value");
damageMapScale = Xml.GetChildFloatAttribute(node, "damageMapScale", "value");
damageOffsetScale = Xml.GetChildFloatAttribute(node, "damageOffsetScale", "value");
diffuseTint = new Color4(Convert.ToUInt32(Xml.GetChildStringAttribute(node, "diffuseTint", "value").Replace("0x", ""), 16));
steerWheelMult = Xml.GetChildFloatAttribute(node, "steerWheelMult", "value");
HDTextureDist = Xml.GetChildFloatAttribute(node, "HDTextureDist", "value");
lodDistances = GetFloatArray(node, "lodDistances", '\n');
minSeatHeight = Xml.GetChildFloatAttribute(node, "minSeatHeight", "value");
identicalModelSpawnDistance = Xml.GetChildFloatAttribute(node, "identicalModelSpawnDistance", "value");
maxNumOfSameColor = Xml.GetChildIntAttribute(node, "maxNumOfSameColor", "value");
defaultBodyHealth = Xml.GetChildFloatAttribute(node, "defaultBodyHealth", "value");
pretendOccupantsScale = Xml.GetChildFloatAttribute(node, "pretendOccupantsScale", "value");
visibleSpawnDistScale = Xml.GetChildFloatAttribute(node, "visibleSpawnDistScale", "value");
trackerPathWidth = Xml.GetChildFloatAttribute(node, "trackerPathWidth", "value");
weaponForceMult = Xml.GetChildFloatAttribute(node, "weaponForceMult", "value");
frequency = Xml.GetChildFloatAttribute(node, "frequency", "value");
swankness = Xml.GetChildInnerText(node, "swankness");
maxNum = Xml.GetChildIntAttribute(node, "maxNum", "value");
flags = GetStringArray(node, "flags", ' ');
type = Xml.GetChildInnerText(node, "type");
plateType = Xml.GetChildInnerText(node, "plateType");
dashboardType = Xml.GetChildInnerText(node, "dashboardType");
vehicleClass = Xml.GetChildInnerText(node, "vehicleClass");
wheelType = Xml.GetChildInnerText(node, "wheelType");
trailers = GetStringItemArray(node, "trailers");
additionalTrailers = GetStringItemArray(node, "additionalTrailers");
var dnode = node.SelectSingleNode("drivers");
if (dnode != null)
{
var items = dnode.SelectNodes("Item");
if (items.Count > 0)
{
drivers = new VehicleDriver[items.Count];
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
var driver = new VehicleDriver();
driver.driverName = Xml.GetChildInnerText(item, "driverName");
driver.npcName = Xml.GetChildInnerText(item, "npcName");
drivers[i] = driver;
}
}
}
extraIncludes = GetStringItemArray(node, "extraIncludes");
doorsWithCollisionWhenClosed = GetStringItemArray(node, "doorsWithCollisionWhenClosed");
driveableDoors = GetStringItemArray(node, "driveableDoors");
bumpersNeedToCollideWithMap = Xml.GetChildBoolAttribute(node, "bumpersNeedToCollideWithMap", "value");
needsRopeTexture = Xml.GetChildBoolAttribute(node, "needsRopeTexture", "value");
requiredExtras = GetStringArray(node, "requiredExtras", ' ');
rewards = GetStringItemArray(node, "rewards");
cinematicPartCamera = GetStringItemArray(node, "cinematicPartCamera");
NmBraceOverrideSet = Xml.GetChildInnerText(node, "NmBraceOverrideSet");
buoyancySphereOffset = Xml.GetChildVector3Attributes(node, "buoyancySphereOffset", "x", "y", "z");
buoyancySphereSizeScale = Xml.GetChildFloatAttribute(node, "buoyancySphereSizeScale", "value");
var tnode = node.SelectSingleNode("pOverrideRagdollThreshold");
if (tnode != null)
{
var ttype = tnode.Attributes["type"]?.Value;
switch (ttype)
{
case "NULL": break;
case "CVehicleModelInfo__CVehicleOverrideRagdollThreshold":
pOverrideRagdollThreshold = new VehicleOverrideRagdollThreshold();
pOverrideRagdollThreshold.MinComponent = Xml.GetChildIntAttribute(tnode, "MinComponent", "value");
pOverrideRagdollThreshold.MaxComponent = Xml.GetChildIntAttribute(tnode, "MaxComponent", "value");
pOverrideRagdollThreshold.ThresholdMult = Xml.GetChildFloatAttribute(tnode, "ThresholdMult", "value");
break;
default:
break;
}
}
firstPersonDrivebyData = GetStringItemArray(node, "firstPersonDrivebyData");
}
private string[] GetStringItemArray(XmlNode node, string childName)
{
var cnode = node.SelectSingleNode(childName);
if (cnode == null) return null;
var items = cnode.SelectNodes("Item");
if (items == null) return null;
getStringArrayList.Clear();
foreach (XmlNode inode in items)
{
var istr = inode.InnerText;
if (!string.IsNullOrEmpty(istr))
{
getStringArrayList.Add(istr);
}
}
if (getStringArrayList.Count == 0) return null;
return getStringArrayList.ToArray();
}
private string[] GetStringArray(XmlNode node, string childName, char delimiter)
{
var ldastr = Xml.GetChildInnerText(node, childName);
var ldarr = ldastr?.Split(delimiter);
if (ldarr == null) return null;
getStringArrayList.Clear();
foreach (var ldstr in ldarr)
{
var ldt = ldstr?.Trim();
if (!string.IsNullOrEmpty(ldt))
{
getStringArrayList.Add(ldt);
}
}
if (getStringArrayList.Count == 0) return null;
return getStringArrayList.ToArray();
}
private float[] GetFloatArray(XmlNode node, string childName, char delimiter)
{
var ldastr = Xml.GetChildInnerText(node, childName);
var ldarr = ldastr?.Split(delimiter);
if (ldarr == null) return null;
getFloatArrayList.Clear();
foreach (var ldstr in ldarr)
{
var ldt = ldstr?.Trim();
if (!string.IsNullOrEmpty(ldt))
{
float f;
if (FloatUtil.TryParse(ldt, out f))
{
getFloatArrayList.Add(f);
}
}
}
if (getFloatArrayList.Count == 0) return null;
return getFloatArrayList.ToArray();
}
private static List<string> getStringArrayList = new List<string>(); //kinda hacky..
private static List<float> getFloatArrayList = new List<float>(); //kinda hacky..
public override string ToString()
{
return modelName;
}
}
public class VehicleOverrideRagdollThreshold
{
public int MinComponent { get; set; }
public int MaxComponent { get; set; }
public float ThresholdMult { get; set; }
public override string ToString()
{
return MinComponent.ToString() + ", " + MaxComponent.ToString() + ", " + ThresholdMult.ToString();
}
}
public class VehicleDriver
{
public string driverName { get; set; }
public string npcName { get; set; }
public override string ToString()
{
return driverName + ", " + npcName;
}
}
}

View File

@ -40,5 +40,13 @@ namespace CodeWalker.GameFiles
Loaded = true;
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(Bounds, 43); //ybn is type/version 43...
return data;
}
}
}

View File

@ -85,5 +85,12 @@ namespace CodeWalker.GameFiles
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(DrawableDict, 165); //ydd is type/version 165...
return data;
}
}
}

View File

@ -49,6 +49,13 @@ namespace CodeWalker.GameFiles
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(Drawable, 165); //ydr is type/version 165...
return data;
}
}

View File

@ -37,14 +37,21 @@ namespace CodeWalker.GameFiles
{
Fragment.Drawable.Owner = this;
}
if (Fragment.Unknown_F8h_Data != null)
if (Fragment.Drawable2 != null)
{
Fragment.Unknown_F8h_Data.Owner = this;
Fragment.Drawable2.Owner = this;
}
Loaded = true;
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(Fragment, 162); //yft is type/version 162...
return data;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -60,6 +60,8 @@ namespace CodeWalker.GameFiles
}
return;
}
else
{ }//doesn't get here
@ -96,7 +98,7 @@ namespace CodeWalker.GameFiles
HDTxdAssetBindings = PsoTypes.GetItemArray<CHDTxdAssetBinding>(Pso, d.HDTxdBindingArray);
Interiors = PsoTypes.GetObjectArray<YmfInterior, Unk_741495440>(Pso, d.Interiors);
Interiors = PsoTypes.GetObjectArray<YmfInterior, CInteriorBoundsFiles>(Pso, d.Interiors);
}
@ -167,9 +169,9 @@ namespace CodeWalker.GameFiles
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YmfInterior : PsoClass<Unk_741495440>
[TypeConverter(typeof(ExpandableObjectConverter))] public class YmfInterior : PsoClass<CInteriorBoundsFiles>
{
public Unk_741495440 Interior { get; set; }
public CInteriorBoundsFiles Interior { get; set; }
public MetaHash[] Bounds { get; set; }//ybn hashes?
public override string ToString()
@ -177,7 +179,7 @@ namespace CodeWalker.GameFiles
return Interior.ToString();
}
public override void Init(PsoFile pso, ref Unk_741495440 v)
public override void Init(PsoFile pso, ref CInteriorBoundsFiles v)
{
Interior = v;
Bounds = PsoTypes.GetHashArray(pso, v.Bounds);

View File

@ -14,7 +14,7 @@ namespace CodeWalker.GameFiles
public List<Vector3> Vertices { get; set; }
public List<ushort> Indices { get; set; }
public List<NavMeshAdjPoly> AdjPolys { get; set; }
public List<YnvEdge> Edges { get; set; }
public List<YnvPoly> Polys { get; set; }
public List<YnvPortal> Portals { get; set; }
public List<YnvPoint> Points { get; set; }
@ -48,6 +48,16 @@ namespace CodeWalker.GameFiles
//getters for property grids viewing of the lists
public Vector3[] AllVertices { get { return Vertices?.ToArray(); } }
public ushort[] AllIndices { get { return Indices?.ToArray(); } }
public YnvEdge[] AllEdges { get { return Edges?.ToArray(); } }
public YnvPoly[] AllPolys { get { return Polys?.ToArray(); } }
public YnvPortal[] AllPortals { get { return Portals?.ToArray(); } }
public YnvPoint[] AllPoints { get { return Points?.ToArray(); } }
public YnvFile() : base(null, GameFileType.Ynv)
{
@ -101,9 +111,16 @@ namespace CodeWalker.GameFiles
{
Indices = Nav.Indices.GetFullList();
}
if (Nav.AdjPolys != null)
if (Nav.Edges != null)
{
AdjPolys = Nav.AdjPolys.GetFullList();
var edges = Nav.Edges.GetFullList();
Edges = new List<YnvEdge>(edges.Count);
for (int i = 0; i < edges.Count; i++)
{
YnvEdge edge = new YnvEdge();
edge.Init(this, edges[i]);
Edges.Add(edge);
}
}
if (Nav.Polys != null)
{
@ -114,16 +131,7 @@ namespace CodeWalker.GameFiles
YnvPoly poly = new YnvPoly();
poly.Init(this, polys[i]);
poly.Index = i;
poly.CalculatePosition(); //calc poly center for display purposes..
Polys.Add(poly);
if (poly.PortalType > 0)
{
if (poly.PortalType != 2) //seems to be what portal links need to understand..
{ }
}
}
}
if (Nav.Portals != null)
@ -209,23 +217,97 @@ namespace CodeWalker.GameFiles
Vector3 aabbsizeinv = 1.0f / aabbsize;
var vertlist = new List<NavMeshVertex>();
if (Vertices != null)
{
for (int i = 0; i < Vertices.Count; i++)
{
vertlist.Add(NavMeshVertex.Create((Vertices[i] - posoffset) * aabbsizeinv));
}
}
var indslist = new List<ushort>();
var edgelist = new List<NavMeshEdge>();
var polylist = new List<NavMeshPoly>();
if (Polys != null)
var portallist = new List<NavMeshPortal>();
var portallinks = new List<ushort>();
var vertdict = new Dictionary<Vector3, ushort>();
var areadict = new Dictionary<uint, uint>();
var arealist = new List<uint>();
var areaid = Nav.AreaID;
EnsureEdgeAreaID(areaid, areadict, arealist);
EnsureEdgeAreaID(0x3FFF, areadict, arealist);
EnsureEdgeAreaID(areaid - 100, areadict, arealist);
EnsureEdgeAreaID(areaid - 1, areadict, arealist);
EnsureEdgeAreaID(areaid + 1, areadict, arealist);
EnsureEdgeAreaID(areaid + 100, areadict, arealist);
if (Polys != null) //rebuild vertices, indices, edges and polys lists from poly data.
{
for (int i = 0; i < Polys.Count; i++)
{
Polys[i].Index = i;
polylist.Add(Polys[i].RawData);
var poly = Polys[i];
var vc = poly.Vertices?.Length ?? 0;
//poly.AreaID = (ushort)Nav.AreaID;
poly._RawData.IndexID = (ushort)indslist.Count;
for (int n = 0; n < vc; n++)
{
Vector3 v = poly.Vertices[n];
YnvEdge e = ((poly.Edges != null) && (n < poly.Edges.Length)) ? poly.Edges[n] : null;
ushort ind;
if (!vertdict.TryGetValue(v, out ind))
{
ind = (ushort)vertlist.Count;
vertdict[v] = ind;
vertlist.Add(NavMeshVertex.Create(Vector3.Clamp((v - posoffset) * aabbsizeinv, Vector3.Zero, Vector3.One)));
}
if ((poly.Indices != null) && (n < poly.Indices.Length))
{
poly.Indices[n] = ind;
}
indslist.Add(ind);
NavMeshEdge edge;
if (e != null)
{
if (e.Poly1 != null)
{
e.PolyID1 = (uint)e.Poly1.Index;
e.AreaID1 = e.Poly1.AreaID;
if (e.AreaID1 == 0x3FFF)
{ }//debug
}
if (e.Poly2 != null)
{
e.PolyID2 = (uint)e.Poly2.Index;
e.AreaID2 = e.Poly2.AreaID;
if (e.AreaID2 == 0x3FFF)
{ }//debug
}
if ((e.AreaID1 == 0) || (e.AreaID2 == 0))
{ }//debug
e._RawData._Poly1.AreaIDInd = EnsureEdgeAreaID(e.AreaID1, areadict, arealist);
e._RawData._Poly2.AreaIDInd = EnsureEdgeAreaID(e.AreaID2, areadict, arealist);
edge = e.RawData;
}
else
{
var areaind = EnsureEdgeAreaID(0x3FFF, areadict, arealist);
edge = new NavMeshEdge();//create an empty edge
edge._Poly1.PolyID = 0x3FFF;
edge._Poly2.PolyID = 0x3FFF;
edge._Poly1.AreaIDInd = areaind;
edge._Poly2.AreaIDInd = areaind;
}
edgelist.Add(edge);
}
poly._RawData.IndexCount = vc;
poly._RawData.PortalLinkID = (uint)portallinks.Count;//these shouldn't be directly editable!
poly._RawData.PortalLinkCount = (byte)(poly.PortalLinks?.Length ?? 0);
if (poly.PortalLinks != null)
{
portallinks.AddRange(poly.PortalLinks);
}
poly.Index = i;//this should be redundant...
poly.CalculateAABB();//make sure this is up to date!
polylist.Add(poly.RawData);
}
}
var portallist = new List<NavMeshPortal>();
if (Portals != null)
{
for (int i = 0; i < Portals.Count; i++)
@ -238,7 +320,7 @@ namespace CodeWalker.GameFiles
}
}
if (Points != null)
if (Points != null) //points will be built into the sector tree
{
for (int i = 0; i < Points.Count; i++)
{
@ -259,10 +341,10 @@ namespace CodeWalker.GameFiles
Nav.Indices = new NavMeshList<ushort>();
Nav.Indices.VFT = 1080158424;
}
if (Nav.AdjPolys == null)
if (Nav.Edges == null)
{
Nav.AdjPolys = new NavMeshList<NavMeshAdjPoly>();
Nav.AdjPolys.VFT = 1080158440;
Nav.Edges = new NavMeshList<NavMeshEdge>();
Nav.Edges.VFT = 1080158440;
}
if (Nav.Polys == null)
{
@ -272,16 +354,24 @@ namespace CodeWalker.GameFiles
Nav.Vertices.RebuildList(vertlist);
Nav.VerticesCount = Nav.Vertices.ItemCount;
Nav.Indices.RebuildList(Indices);
Nav.Indices.RebuildList(indslist);
Nav.AdjPolys.RebuildList(AdjPolys);
Nav.Edges.RebuildList(edgelist);
Nav.EdgesIndicesCount = Nav.Indices.ItemCount;
Nav.Polys.RebuildList(polylist);
Nav.PolysCount = Nav.Polys.ItemCount;
Nav.Portals = (portallist.Count > 0) ? portallist.ToArray() : null;
Nav.PortalsCount = (uint)(Nav.Portals?.Length ?? 0);
//TODO: update portal links data.....
Nav.PortalLinks = (portallinks.Count > 0) ? portallinks.ToArray() : null;
Nav.PortalLinksCount = (uint)(Nav.PortalLinks?.Length ?? 0);
var adjAreaIds = new NavMeshUintArray();
adjAreaIds.Set(arealist.ToArray());
Nav.AdjAreaIDs = adjAreaIds;
for (int i = 0; i < Nav.Polys.ListParts.Count; i++) //reassign part id's on all the polys...
@ -315,12 +405,27 @@ namespace CodeWalker.GameFiles
}
private uint EnsureEdgeAreaID(uint areaid, Dictionary<uint, uint> areadict, List<uint> arealist)
{
uint ind;
if (!areadict.TryGetValue(areaid, out ind))
{
ind = (uint)arealist.Count;
areadict[areaid] = ind;
arealist.Add(areaid);
}
return ind;
}
private void BuildSectorTree(NavMeshSector node, int depth, ref uint pointindex)
{
Vector3 min = node.AABBMin.XYZ();
Vector3 max = node.AABBMax.XYZ();
Vector3 cen = (min + max) * 0.5f;
//totbytes += (uint)node.BlockLength;
if (depth <= 0)
{
//go through polys and points and create new lists for this node
@ -329,6 +434,8 @@ namespace CodeWalker.GameFiles
data.PointsStartID = pointindex;
//totbytes += (uint)data.BlockLength;
if (Polys != null)
{
List<ushort> polyids = new List<ushort>();
@ -345,6 +452,7 @@ namespace CodeWalker.GameFiles
{
data.PolyIDs = polyids.ToArray();
}
//totbytes += (uint)(polyids.Count * 2);
}
if (Points != null)
@ -363,6 +471,7 @@ namespace CodeWalker.GameFiles
data.Points = points.ToArray();
pointindex += (uint)points.Count;
}
//totbytes += (uint)(points.Count * 8);
}
}
@ -419,6 +528,18 @@ namespace CodeWalker.GameFiles
public void UpdateContentFlags(bool vehicle)
{
NavMeshFlags f = NavMeshFlags.None;
//if (Nav.VerticesCount > 0) f = f | NavMeshFlags.Vertices;
//if (Nav.PortalsCount > 0) f = f | NavMeshFlags.Portals;
if (Polys?.Count > 0) f = f | NavMeshFlags.Vertices;
if (Portals?.Count > 0) f = f | NavMeshFlags.Portals;
if (vehicle) f = f | NavMeshFlags.Vehicle;
else f = f | NavMeshFlags.Unknown8;
Nav.ContentFlags = f;
}
public void UpdateAllNodePositions()
@ -474,67 +595,39 @@ namespace CodeWalker.GameFiles
//go through the nav mesh polys and generate verts to render...
if ((Vertices == null) || (Vertices.Count == 0)) return;
if ((Indices == null) || (Indices.Count == 0)) return;
if ((Polys == null) || (Polys.Count == 0)) return;
int vc = Vertices.Count;
List<EditorVertex> rverts = new List<EditorVertex>();
EditorVertex p0 = new EditorVertex();
EditorVertex p1 = new EditorVertex();
EditorVertex p2 = new EditorVertex();
foreach (var ypoly in Polys)
{
var poly = ypoly.RawData;
if ((ypoly.Vertices == null) || (ypoly.Vertices.Length < 3))
{ continue; }
var colour = ypoly.GetColour();
var colourval = (uint)colour.ToRgba();
var ic = poly.IndexCount;
var startid = poly.IndexID;
var endid = startid + ic;
if (startid >= Indices.Count)
{ continue; }
if (endid > Indices.Count)
{ continue; }
if(ic<3)
{ continue; }//not enough verts to make a triangle...
if (ic > 15)
{ }
EditorVertex p0 = new EditorVertex();
EditorVertex p1 = new EditorVertex();
EditorVertex p2 = new EditorVertex();
p0.Colour = colourval;
p1.Colour = colourval;
p2.Colour = colourval;
var startind = Indices[startid];
if (startind >= vc)
{ continue; }
p0.Position = Vertices[startind];
p0.Position = ypoly.Vertices[0];
//build triangles for the poly.
int tricount = ic - 2;
int tricount = ypoly.Vertices.Length - 2;
for (int t = 0; t < tricount; t++)
{
int tid = startid + t;
int ind1 = Indices[tid + 1];
int ind2 = Indices[tid + 2];
if ((ind1 >= vc) || (ind2 >= vc))
{ continue; }
p1.Position = Vertices[ind1];
p2.Position = Vertices[ind2];
p1.Position = ypoly.Vertices[t + 1];
p2.Position = ypoly.Vertices[t + 2];
rverts.Add(p0);
rverts.Add(p1);
rverts.Add(p2);
}
}
TriangleVerts = rverts.ToArray();
@ -572,14 +665,14 @@ namespace CodeWalker.GameFiles
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoly
{
public NavMeshPoly _RawData;
public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } }
public YnvFile Ynv { get; set; }
public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } }
public ushort AreaID { get { return _RawData.AreaID; } set { _RawData.AreaID = value; } }
public ushort PartID { get { return _RawData.PartID; } set { _RawData.PartID = value; } }
public ushort PortalLinkID { get { return _RawData.PortalLinkID; } set { _RawData.PortalLinkID = value; } }
public byte PortalType { get { return _RawData.PortalType; } set { _RawData.PortalType = value; } }
public uint PortalLinkID { get { return _RawData.PortalLinkID; } set { _RawData.PortalLinkID = value; } }
public byte PortalLinkCount { get { return _RawData.PortalLinkCount; } set { _RawData.PortalLinkCount = value; } }
public byte Flags1 { get { return (byte)(_RawData.Unknown_00h & 0xFF); } set { _RawData.Unknown_00h = (ushort)((_RawData.Unknown_00h & 0xFF00) | (value & 0xFF)); } }
public byte Flags2 { get { return (byte)((_RawData.Unknown_24h.Value >> 0) & 0xFF); } set { _RawData.Unknown_24h = ((_RawData.Unknown_24h.Value & 0xFFFFFF00u) | ((value & 0xFFu) << 0)); } }
public byte Flags3 { get { return (byte)((_RawData.Unknown_24h.Value >> 9) & 0xFF); } set { _RawData.Unknown_24h = ((_RawData.Unknown_24h.Value & 0xFFFE01FFu) | ((value & 0xFFu) << 9)); } }
@ -624,14 +717,84 @@ namespace CodeWalker.GameFiles
public Vector3 Position { get; set; }
public int Index { get; set; }
public ushort[] Indices { get; set; }
public Vector3[] Vertices { get; set; }
public YnvEdge[] Edges { get; set; }
public ushort[] PortalLinks { get; set; }
public void Init(YnvFile ynv, NavMeshPoly poly)
{
Ynv = ynv;
RawData = poly;
LoadIndices();
LoadPortalLinks();
CalculatePosition(); //calc poly center for display purposes..
}
public void LoadIndices()
{
//load indices, vertices and edges
var indices = Ynv.Indices;
var vertices = Ynv.Vertices;
var edges = Ynv.Edges;
if ((indices == null) || (vertices == null) || (edges == null))
{ return; }
var vc = vertices.Count;
var ic = _RawData.IndexCount;
var startid = _RawData.IndexID;
var endid = startid + ic;
if (startid >= indices.Count)
{ return; }
if (endid > indices.Count)
{ return; }
if (endid > edges.Count)
{ return; }
Indices = new ushort[ic];
Vertices = new Vector3[ic];
Edges = new YnvEdge[ic];
int i = 0;
for (int id = startid; id < endid; id++)
{
var ind = indices[id];
Indices[i] = ind;
Vertices[i] = (ind < vc) ? vertices[ind] : Vector3.Zero;
Edges[i] = edges[id];
i++;
}
}
public void LoadPortalLinks()
{
if (PortalLinkCount == 0)
{ return; }
var links = Ynv.Nav?.PortalLinks;
if (links == null)
{ return; }
var ll = links.Length;
PortalLinks = new ushort[PortalLinkCount];
int offset = (int)PortalLinkID;
for (int i = 0; i < PortalLinkCount; i++)
{
int idx = offset + i;
PortalLinks[i] = (idx < ll) ? links[idx] : (ushort)0;
}
if (PortalLinkCount != 2)
{ }//debug
}
public void SetPosition(Vector3 pos)
{
Vector3 delta = pos - Position;
@ -687,7 +850,7 @@ namespace CodeWalker.GameFiles
//if ((u5 & 8388608) > 0) colour.Red += 1.0f; //slope facing -X,-Y (southwest)
//if (u5 >= 16777216) { } //other bits unused
var u1 = _RawData.PortalType;
var u1 = _RawData.PortalLinkCount;
//if ((u1 & 1) > 0) colour.Red += 1.0f; //portal - don't interact?
//if ((u1 & 2) > 0) colour.Green += 1.0f; //portal - ladder/fence interaction?
//if ((u1 & 4) > 0) colour.Blue += 1.0f; //portal - fence interaction / go away from?
@ -709,32 +872,36 @@ namespace CodeWalker.GameFiles
public void CalculatePosition()
{
//calc poly center for display purposes.
var indices = Ynv.Indices;
var vertices = Ynv.Vertices;
if ((indices == null) || (vertices == null))
{ return; }
var vc = vertices.Count;
var ic = _RawData.IndexCount;
var startid = _RawData.IndexID;
var endid = startid + ic;
if (startid >= indices.Count)
{ return; }
if (endid > indices.Count)
{ return; }
Vector3 pcenter = Vector3.Zero;
float pcount = 0.0f;
for (int id = startid; id < endid; id++)
if (Vertices != null)
{
var ind = indices[id];
if (ind >= vc)
{ continue; }
pcenter += vertices[ind];
pcount += 1.0f;
for (int i = 0; i < Vertices.Length; i++)
{
pcenter += Vertices[i];
}
}
Position = pcenter * (1.0f / pcount);
float c = ((float)Vertices?.Length);
if (c == 0.0f) c = 1.0f;
Position = pcenter * (1.0f / c);
}
public void CalculateAABB()
{
Vector3 min = Vector3.Zero;
Vector3 max = Vector3.Zero;
if ((Vertices != null) && (Vertices.Length > 0))
{
min = new Vector3(float.MaxValue);
max = new Vector3(float.MinValue);
for (int i = 0; i < Vertices.Length; i++)
{
min = Vector3.Min(min, Vertices[i]);
max = Vector3.Max(max, Vertices[i]);
}
}
_RawData.CellAABB = new NavMeshAABB() { Min = min, Max = max };
}
public override string ToString()
@ -870,4 +1037,57 @@ namespace CodeWalker.GameFiles
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvEdge
{
public NavMeshEdge _RawData;
public NavMeshEdge RawData { get { return _RawData; } set { _RawData = value; } }
public YnvFile Ynv { get; set; }
public uint AreaID1 { get; set; }
public uint AreaID2 { get; set; }
public uint PolyID1 { get { return _RawData._Poly1.PolyID; } set { _RawData._Poly1.PolyID = value; } }
public uint PolyID2 { get { return _RawData._Poly2.PolyID; } set { _RawData._Poly2.PolyID = value; } }
public YnvPoly Poly1 { get; set; }
public YnvPoly Poly2 { get; set; }
public YnvEdge() { }
public YnvEdge(YnvEdge copy, YnvPoly poly)
{
_RawData = copy._RawData;
_RawData._Poly1.PolyID = 0x3FFF;
_RawData._Poly2.PolyID = 0x3FFF;
Poly1 = poly;
Poly2 = poly;
AreaID1 = 0x3FFF;
AreaID2 = 0x3FFF;
}
public void Init(YnvFile ynv, NavMeshEdge edge)
{
Ynv = ynv;
RawData = edge;
if (ynv.Nav == null) return;
var n = ynv.Nav;
var ai1 = edge.Poly1.AreaIDInd;
var ai2 = edge.Poly2.AreaIDInd;
AreaID1 = (ai1 < n.AdjAreaIDs.Count) ? n.AdjAreaIDs.Get(ai1) : 16383;
AreaID2 = (ai2 < n.AdjAreaIDs.Count) ? n.AdjAreaIDs.Get(ai2) : 16383;
}
public override string ToString()
{
return AreaID1.ToString() + ", " + AreaID2.ToString() + ", " + PolyID1.ToString() + ", " + PolyID2.ToString() + ", " +
_RawData._Poly1.Unk2.ToString() + ", " + _RawData._Poly2.Unk2.ToString() + ", " +
_RawData._Poly1.Unk3.ToString() + ", " + _RawData._Poly2.Unk3.ToString();
}
}
}

View File

@ -97,6 +97,13 @@ namespace CodeWalker.GameFiles
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(PtfxList, 68); //ypt is type/version 68...
return data;
}
}

View File

@ -45,5 +45,13 @@ namespace CodeWalker.GameFiles
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(TextureDict, 13); //ytd is type/version 13...
return data;
}
}
}

View File

@ -21,8 +21,8 @@ namespace CodeWalker.GameFiles
public uint NameHash { get; set; }
public string[] Strings { get; set; }
public CMapTypes CMapTypes { get; set; }
public CMapTypes _CMapTypes;
public CMapTypes CMapTypes { get { return _CMapTypes; } set { _CMapTypes = value; } }
public Archetype[] AllArchetypes { get; set; }
@ -50,6 +50,125 @@ namespace CodeWalker.GameFiles
return (RpfFileEntry != null) ? RpfFileEntry.Name : string.Empty;
}
public byte[] Save()
{
MetaBuilder mb = new MetaBuilder();
var mdb = mb.EnsureBlock(MetaName.CMapTypes);
CMapTypes mapTypes = _CMapTypes;
if (Extensions == null || Extensions.Length <= 0)
mapTypes.extensions = new Array_StructurePointer();
else
mapTypes.extensions = mb.AddWrapperArrayPtr(Extensions);
if ((AllArchetypes != null) && (AllArchetypes.Length > 0))
{
for (int i = 0; i < AllArchetypes.Length; i++)
{
var arch = AllArchetypes[i]; //save the extensions first..
if (arch._BaseArchetypeDef.extensions.Count1 > 0)
{
arch._BaseArchetypeDef.extensions = mb.AddWrapperArrayPtr(arch.Extensions);
}
}
MetaPOINTER[] ptrs = new MetaPOINTER[AllArchetypes.Length];
for (int i = 0; i < AllArchetypes.Length; i++)
{
var arch = AllArchetypes[i];
switch (arch)
{
case TimeArchetype t:
ptrs[i] = mb.AddItemPtr(MetaName.CTimeArchetypeDef, t._TimeArchetypeDef);
break;
case MloArchetype m:
try
{
m._MloArchetypeDef._MloArchetypeDef.entities = mb.AddWrapperArrayPtr(m.entities);
m._MloArchetypeDef._MloArchetypeDef.rooms = mb.AddWrapperArray(m.rooms);
m._MloArchetypeDef._MloArchetypeDef.portals = mb.AddWrapperArray(m.portals);
m._MloArchetypeDef._MloArchetypeDef.entitySets = mb.AddWrapperArray(m.entitySets);
m._MloArchetypeDef._MloArchetypeDef.timeCycleModifiers = mb.AddItemArrayPtr(MetaName.CMloTimeCycleModifier, m.timeCycleModifiers);
}
catch/* (Exception e)*/
{
//todo: log save error.
}
ptrs[i] = mb.AddItemPtr(MetaName.CMloArchetypeDef, m._MloArchetypeDef);
break;
case Archetype a:
ptrs[i] = mb.AddItemPtr(MetaName.CBaseArchetypeDef, a._BaseArchetypeDef);
break;
}
}
mapTypes.archetypes = mb.AddPointerArray(ptrs);
}
else
{
mapTypes.archetypes = new Array_StructurePointer();
}
if (CompositeEntityTypes != null && CompositeEntityTypes.Length > 0)
{
var cptrs = new MetaPOINTER[CompositeEntityTypes.Length];
for (int i = 0; i < cptrs.Length; i++)
{
var cet = CompositeEntityTypes[i];
cptrs[i] = mb.AddItemPtr(MetaName.CCompositeEntityType, cet);
}
mapTypes.compositeEntityTypes = mb.AddItemArrayPtr(MetaName.CCompositeEntityType, cptrs);
}
mapTypes.name = NameHash;
mapTypes.dependencies = new Array_uint(); // is this never used? possibly a todo?
mb.AddStructureInfo(MetaName.CMapTypes);
if ((AllArchetypes != null && AllArchetypes.Length > 0))
{
mb.AddStructureInfo(MetaName.CBaseArchetypeDef);
mb.AddEnumInfo(MetaName.rage__fwArchetypeDef__eAssetType); // ASSET_TYPE_
}
if ((AllArchetypes != null) && (AllArchetypes.Any(x => x is MloArchetype)))
{
mb.AddStructureInfo(MetaName.CMloArchetypeDef);
mb.AddStructureInfo(MetaName.CMloRoomDef);
mb.AddStructureInfo(MetaName.CMloPortalDef);
mb.AddStructureInfo(MetaName.CMloEntitySet);
mb.AddStructureInfo(MetaName.CMloTimeCycleModifier);
}
if ((AllArchetypes != null) && (AllArchetypes.Any(x => x is MloArchetype m && m.entities.Length > 0)))
{
mb.AddStructureInfo(MetaName.CEntityDef);
mb.AddEnumInfo(MetaName.rage__eLodType); //LODTYPES_
mb.AddEnumInfo(MetaName.rage__ePriorityLevel); //PRI_
}
if ((AllArchetypes != null) && (AllArchetypes.Any(x => x is TimeArchetype)))
{
mb.AddStructureInfo(MetaName.CTimeArchetypeDef);
}
if (CompositeEntityTypes?.Length > 0)
{
mb.AddStructureInfo(MetaName.CCompositeEntityType);
}
mb.AddItem(MetaName.CMapTypes, mapTypes);
Meta meta = mb.GetMeta();
byte[] data = ResourceBuilder.Build(meta, 2);
HasChanged = false;
return data;
}
public void Load(byte[] data)
{
@ -94,12 +213,12 @@ namespace CodeWalker.GameFiles
Meta = rd.ReadBlock<Meta>();
CMapTypes = MetaTypes.GetTypedData<CMapTypes>(Meta, MetaName.CMapTypes);
_CMapTypes = MetaTypes.GetTypedData<CMapTypes>(Meta, MetaName.CMapTypes);
List<Archetype> allarchs = new List<Archetype>();
var ptrs = MetaTypes.GetPointerArray(Meta, CMapTypes.archetypes);
var ptrs = MetaTypes.GetPointerArray(Meta, _CMapTypes.archetypes);
if (ptrs != null)
{
for (int i = 0; i < ptrs.Length; i++)
@ -151,7 +270,8 @@ namespace CodeWalker.GameFiles
AllArchetypes = allarchs.ToArray();
Extensions = MetaTypes.GetExtensions(Meta, CMapTypes.extensions);
Extensions = MetaTypes.GetExtensions(Meta, _CMapTypes.extensions);
if (Extensions != null)
{ }
@ -163,11 +283,11 @@ namespace CodeWalker.GameFiles
//CEntityDefs = MetaTypes.GetTypedDataArray<CEntityDef>(Meta, MetaName.CEntityDef);
CompositeEntityTypes = MetaTypes.ConvertDataArray<CCompositeEntityType>(Meta, MetaName.CCompositeEntityType, CMapTypes.compositeEntityTypes);
CompositeEntityTypes = MetaTypes.ConvertDataArray<CCompositeEntityType>(Meta, MetaName.CCompositeEntityType, _CMapTypes.compositeEntityTypes);
if (CompositeEntityTypes != null)
{ }
NameHash = CMapTypes.name;
NameHash = _CMapTypes.name;
if (NameHash == 0)
{
int ind = entry.NameLower.LastIndexOf('.');
@ -242,7 +362,38 @@ namespace CodeWalker.GameFiles
}
public void AddArchetype(Archetype archetype)
{
if (AllArchetypes == null)
AllArchetypes = new Archetype[0];
List<Archetype> archetypes = AllArchetypes.ToList();
archetype.Ytyp = this;
archetypes.Add(archetype);
AllArchetypes = archetypes.ToArray();
}
public Archetype AddArchetype()
{
var a = new Archetype();
a._BaseArchetypeDef.assetType = rage__fwArchetypeDef__eAssetType.ASSET_TYPE_DRAWABLE;
a._BaseArchetypeDef.lodDist = 60;
a._BaseArchetypeDef.hdTextureDist = 15;
a.Ytyp = this;
AddArchetype(a);
return a;
}
public bool RemoveArchetype(Archetype archetype)
{
List<Archetype> archetypes = AllArchetypes.ToList();
if (archetypes.Remove(archetype))
{
AllArchetypes = archetypes.ToArray();
return true;
}
return false;
}
}

View File

@ -49,6 +49,13 @@ namespace CodeWalker.GameFiles
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(Records, 1); //yvr is type/version 1...
return data;
}
}
}

View File

@ -49,6 +49,13 @@ namespace CodeWalker.GameFiles
}
public byte[] Save()
{
byte[] data = ResourceBuilder.Build(Waypoints, 1); //ywr is type/version 1...
return data;
}
}
}

View File

@ -70,6 +70,11 @@ namespace CodeWalker.GameFiles
Ywr = 14,
Yvr = 15,
Gtxd = 16,
Vehicles = 17,
CarCols = 18,
CarModCols = 19,
CarVariations = 20,
VehicleLayouts = 21,
}

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ namespace CodeWalker.GameFiles
public virtual MetaName Type => MetaName.CBaseArchetypeDef;
public CBaseArchetypeDef _BaseArchetypeDef;
public CBaseArchetypeDef BaseArchetypeDef { get { return _BaseArchetypeDef; } set { _BaseArchetypeDef = value; } }
public CBaseArchetypeDef BaseArchetypeDef => _BaseArchetypeDef; // for browsing.
public MetaHash Hash { get; set; }
public YtypFile Ytyp { get; set; }
@ -31,16 +31,16 @@ namespace CodeWalker.GameFiles
public string Name
public string Name
{
get
get
{
return _BaseArchetypeDef.name.ToString();
}
}
public string AssetName
public string AssetName
{
get
get
{
return _BaseArchetypeDef.assetName.ToString();
}
@ -49,7 +49,7 @@ namespace CodeWalker.GameFiles
protected void InitVars(ref CBaseArchetypeDef arch)
{
BaseArchetypeDef = arch;
_BaseArchetypeDef = arch;
Hash = arch.assetName;
if (Hash.Hash == 0) Hash = arch.name;
DrawableDict = arch.drawableDictionary;
@ -83,36 +83,24 @@ namespace CodeWalker.GameFiles
public class TimeArchetype : Archetype
{
public override MetaName Type => MetaName.CTimeArchetypeDef;
public CTimeArchetypeDefData _TimeArchetypeDef;
public CTimeArchetypeDefData TimeArchetypeDef { get { return _TimeArchetypeDef; } set { _TimeArchetypeDef = value; } }
public CTimeArchetypeDef _TimeArchetypeDef;
public CTimeArchetypeDef TimeArchetypeDef => _TimeArchetypeDef; // for browsing.
public uint TimeFlags { get; set; }
public bool[] ActiveHours { get; set; }
public string[] ActiveHoursText { get; set; }
public bool ExtraFlag { get; set; }
public bool ExtraFlag { get { return ((TimeFlags >> 24) & 1) == 1; } }
public void Init(YtypFile ytyp, ref CTimeArchetypeDef arch)
{
Ytyp = ytyp;
InitVars(ref arch._BaseArchetypeDef);
TimeArchetypeDef = arch.TimeArchetypeDef;
_TimeArchetypeDef = arch;
TimeFlags = _TimeArchetypeDef.timeFlags;
ActiveHours = new bool[24];
ActiveHoursText = new string[24];
for (int i = 0; i < 24; i++)
{
bool v = ((TimeFlags >> i) & 1) == 1;
ActiveHours[i] = v;
TimeFlags = arch.TimeArchetypeDef.timeFlags;
int nxth = (i < 23) ? (i + 1) : 0;
string hrs = string.Format("{0:00}:00 - {1:00}:00", i, nxth);
ActiveHoursText[i] = (hrs + (v ? " - On" : " - Off"));
}
ExtraFlag = ((TimeFlags >> 24) & 1) == 1;
UpdateActiveHours();
}
public override bool IsActive(float hour)
@ -122,14 +110,45 @@ namespace CodeWalker.GameFiles
if ((h < 0) || (h > 23)) return true;
return ActiveHours[h];
}
public void UpdateActiveHours()
{
if (ActiveHours == null)
{
ActiveHours = new bool[24];
ActiveHoursText = new string[24];
}
for (int i = 0; i < 24; i++)
{
bool v = ((TimeFlags >> i) & 1) == 1;
ActiveHours[i] = v;
int nxth = (i < 23) ? (i + 1) : 0;
string hrs = string.Format("{0:00}:00 - {1:00}:00", i, nxth);
ActiveHoursText[i] = (hrs + (v ? " - On" : " - Off"));
}
}
public void SetTimeFlags(uint flags)
{
TimeFlags = flags;
_TimeArchetypeDef._TimeArchetypeDef.timeFlags = flags;
UpdateActiveHours();
}
}
public class MloArchetype : Archetype
{
public override MetaName Type => MetaName.CMloArchetypeDef;
public CMloArchetypeDefData _MloArchetypeDef;
public CMloArchetypeDefData MloArchetypeDef { get { return _MloArchetypeDef; } set { _MloArchetypeDef = value; } }
public CMloArchetypeDef MloArchetypeDef => _MloArchetypeDef; // for browsing.
public CMloArchetypeDef _MloArchetypeDef;
public CMloArchetypeDefData _MloArchetypeDefData;
public MCEntityDef[] entities { get; set; }
public MCMloRoomDef[] rooms { get; set; }
@ -137,36 +156,147 @@ namespace CodeWalker.GameFiles
public MCMloEntitySet[] entitySets { get; set; }
public CMloTimeCycleModifier[] timeCycleModifiers { get; set; }
public void Init(YtypFile ytyp, ref CMloArchetypeDef arch)
{
Ytyp = ytyp;
InitVars(ref arch._BaseArchetypeDef);
MloArchetypeDef = arch.MloArchetypeDef;
_MloArchetypeDef = arch;
_MloArchetypeDefData = arch.MloArchetypeDef;
}
public bool AddEntity(YmapEntityDef ent, int roomIndex)
{
if (ent == null) return false;
// entity already exists in our array. so we'll just add
// it to the instanced entities list and continue.
MloInstanceData mloInstance = ent.MloParent?.MloInstance;
MCEntityDef ymcent = mloInstance?.TryGetArchetypeEntity(ent);
if (ymcent != null)
{
return true;
}
if (roomIndex > rooms.Length)
{
throw new ArgumentOutOfRangeException($"Room index {roomIndex} exceeds the amount of rooms in {Name}.");
}
var mcEntityDef = new MCEntityDef(ref ent._CEntityDef, this);
// Add the new entity def to the entities list.
AddEntity(ent, mcEntityDef);
// Update the attached objects in the room index specified.
AttachEntityToRoom(ent, roomIndex);
return true;
}
// attaches the specified ymap entity index to the room at roomIndex.
private void AttachEntityToRoom(YmapEntityDef ent, int roomIndex)
{
if (roomIndex > rooms.Length)
{
return; // the room index is bigger than the rooms we have...
}
var attachedObjs = rooms[roomIndex].AttachedObjects?.ToList() ?? new List<uint>();
attachedObjs.Add((uint)ent.Index);
rooms[roomIndex].AttachedObjects = attachedObjs.ToArray();
}
// Adds an entity to the entities array and then set's the index of the
// ymap entity to the index of the new MCEntityDef.
private void AddEntity(YmapEntityDef ent, MCEntityDef mcEntityDef)
{
if (ent == null || mcEntityDef == null) return; // no entity?...
// initialize the array.
if (entities == null) entities = new MCEntityDef[0];
List<MCEntityDef> entList = entities.ToList();
entList.Add(mcEntityDef);
ent.Index = entList.IndexOf(mcEntityDef);
entities = entList.ToArray();
}
public bool RemoveEntity(YmapEntityDef ent)
{
if (ent.Index >= entities.Length) return false;
MCEntityDef delent = entities[ent.Index];
MloInstanceData inst = ent.MloParent?.MloInstance;
if (inst == null) return false;
if (delent != null)
{
MCEntityDef[] newentities = new MCEntityDef[entities.Length - 1];
bool didDel = false;
int index = 0;
int delIndex = 0;
for (int i = 0; i < entities.Length; i++)
{
if (entities[i] == delent)
{
delIndex = i;
didDel = true;
continue;
}
newentities[index] = entities[i];
YmapEntityDef ymapEntityDef = inst.TryGetYmapEntity(newentities[index]);
if (ymapEntityDef != null) ymapEntityDef.Index = index;
index++;
}
entities = newentities;
if (didDel) FixRoomIndexes(delIndex);
return didDel;
}
return false;
}
private void FixRoomIndexes(int deletedIndex)
{
foreach (var room in rooms)
{
List<uint> newAttachedObjects = new List<uint>();
if (room.AttachedObjects == null)
continue;
foreach (var objIndex in room.AttachedObjects)
{
if (objIndex == deletedIndex) continue;
if (objIndex > deletedIndex)
newAttachedObjects.Add(objIndex - 1); // move the index back so it matches the index in the entitiy array.
else newAttachedObjects.Add(objIndex); // else just add the index to the attached objects.
}
room.AttachedObjects = newAttachedObjects.ToArray();
}
}
public void LoadChildren(Meta meta)
{
var centities = MetaTypes.ConvertDataArray<CEntityDef>(meta, MetaName.CEntityDef, _MloArchetypeDef.entities);
var centities = MetaTypes.ConvertDataArray<CEntityDef>(meta, MetaName.CEntityDef, _MloArchetypeDefData.entities);
if (centities != null)
{
entities = new MCEntityDef[centities.Length];
for (int i = 0; i < centities.Length; i++)
{
entities[i] = new MCEntityDef(meta, centities[i]);
entities[i] = new MCEntityDef(meta, ref centities[i]) { Archetype = this };
}
}
var crooms = MetaTypes.ConvertDataArray<CMloRoomDef>(meta, MetaName.CMloRoomDef, _MloArchetypeDef.rooms);
var crooms = MetaTypes.ConvertDataArray<CMloRoomDef>(meta, MetaName.CMloRoomDef, _MloArchetypeDefData.rooms);
if (crooms != null)
{
rooms = new MCMloRoomDef[crooms.Length];
for (int i = 0; i < crooms.Length; i++)
{
rooms[i] = new MCMloRoomDef(meta, crooms[i]);
rooms[i] = new MCMloRoomDef(meta, crooms[i]) { Archetype = this, Index = i };
}
}
var cportals = MetaTypes.ConvertDataArray<CMloPortalDef>(meta, MetaName.CMloPortalDef, _MloArchetypeDef.portals);
var cportals = MetaTypes.ConvertDataArray<CMloPortalDef>(meta, MetaName.CMloPortalDef, _MloArchetypeDefData.portals);
if (cportals != null)
{
portals = new MCMloPortalDef[cportals.Length];
@ -176,7 +306,7 @@ namespace CodeWalker.GameFiles
}
}
var centitySets = MetaTypes.ConvertDataArray<CMloEntitySet>(meta, MetaName.CMloEntitySet, _MloArchetypeDef.entitySets);
var centitySets = MetaTypes.ConvertDataArray<CMloEntitySet>(meta, MetaName.CMloEntitySet, _MloArchetypeDefData.entitySets);
if (centitySets != null)
{
entitySets = new MCMloEntitySet[centitySets.Length];
@ -187,14 +317,44 @@ namespace CodeWalker.GameFiles
}
timeCycleModifiers = MetaTypes.ConvertDataArray<CMloTimeCycleModifier>(meta, MetaName.CMloTimeCycleModifier, _MloArchetypeDef.timeCycleModifiers);
timeCycleModifiers = MetaTypes.ConvertDataArray<CMloTimeCycleModifier>(meta, MetaName.CMloTimeCycleModifier, _MloArchetypeDefData.timeCycleModifiers);
}
public MCMloRoomDef GetEntityRoom(MCEntityDef ent)
{
int objectIndex = -1;
for (int i = 0; i < entities.Length; i++)
{
MCEntityDef e = entities[i];
if (e == ent)
{
objectIndex = i;
break;
}
}
if (objectIndex == -1) return null;
MCMloRoomDef room = null;
for (int i = 0; i < rooms.Length; i++)
{
MCMloRoomDef r = rooms[i];
for (int j = 0; j < r.AttachedObjects.Length; j++)
{
uint ind = r.AttachedObjects[j];
if (ind == objectIndex)
{
room = r;
break;
}
}
if (room != null) break;
}
return room;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MloInstanceData
{
@ -204,7 +364,12 @@ namespace CodeWalker.GameFiles
public uint[] defaultEntitySets { get; set; }
public YmapEntityDef[] Entities { get; set; }
public Dictionary<MetaHash, MloInstanceEntitySet> EntitySets { get; set; }
public MloInstanceData()
{
EntitySets = new Dictionary<MetaHash, MloInstanceEntitySet>();
}
public void CreateYmapEntities(YmapEntityDef owner, MloArchetype mloa)
{
@ -230,27 +395,182 @@ namespace CodeWalker.GameFiles
var entitySet = entitySets[i];
if (entitySet.Entities != null)
{
EntitySets[entitySet._Data.name] = new MloInstanceEntitySet(entitySet, this);
MloInstanceEntitySet instset = EntitySets[entitySet._Data.name];
for (int j = 0; j < entitySet.Entities.Length; j++)
{
YmapEntityDef e = CreateYmapEntity(owner, entitySet.Entities[j], lasti);
e.MloEntitySet = entitySet;
entlist.Add(e);
EntitySets[entitySet._Data.name].Entities.Add(e);
e.MloEntitySet = instset;
lasti++;
}
}
}
}
if (defaultEntitySets != null)
if ((defaultEntitySets != null) && (entitySets != null))
{
for (var i = 0; i < defaultEntitySets.Length; i++)
{
uint index = defaultEntitySets[i];
if (index >= entitySets.Length) continue;
MCMloEntitySet set = entitySets[index];
MloInstanceEntitySet instset = EntitySets[set._Data.name];
instset.Visible = true;
}
}
Entities = entlist.ToArray();
}
private YmapEntityDef CreateYmapEntity(YmapEntityDef owner, MCEntityDef ment, int i)
public void InitYmapEntityArchetypes(GameFileCache gfc)
{
YmapEntityDef e = new YmapEntityDef(null, i, ref ment._Data);
if (Owner == null) return;
var arch = Owner.Archetype;
if (Entities != null)
{
for (int j = 0; j < Entities.Length; j++)
{
var ient = Entities[j];
var iarch = gfc.GetArchetype(ient._CEntityDef.archetypeName);
ient.SetArchetype(iarch);
if (iarch == null)
{ } //can't find archetype - des stuff eg {des_prologue_door}
}
UpdateBBs(arch);
}
if (EntitySets != null)
{
foreach (var entitySet in EntitySets)
{
var entities = entitySet.Value.Entities;
if (entities == null) continue;
for (int i = 0; i < entities.Count; i++)
{
var ient = entities[i];
var iarch = gfc.GetArchetype(ient._CEntityDef.archetypeName);
ient.SetArchetype(iarch);
if (iarch == null)
{ } //can't find archetype - des stuff eg {des_prologue_door}
}
}
}
}
public void UpdateBBs(Archetype arch)
{
//update archetype room AABB's.. bad to have this here? where else to put it?
var mloa = arch as MloArchetype;
if (mloa != null)
{
Vector3 mlobbmin = Vector3.Zero;
Vector3 mlobbmax = Vector3.Zero;
Vector3[] c = new Vector3[8];
var rooms = mloa.rooms;
if (rooms != null)
{
for (int j = 0; j < rooms.Length; j++)
{
var room = rooms[j];
if ((room.AttachedObjects == null) || (room.AttachedObjects.Length == 0)) continue;
Vector3 min = new Vector3(float.MaxValue);
Vector3 max = new Vector3(float.MinValue);
for (int k = 0; k < room.AttachedObjects.Length; k++)
{
var objid = room.AttachedObjects[k];
if (objid < Entities.Length)
{
var rooment = Entities[objid];
if ((rooment != null) && (rooment.Archetype != null))
{
var earch = rooment.Archetype;
var pos = rooment._CEntityDef.position;
var ori = rooment.Orientation;
Vector3 abmin = earch.BBMin * rooment.Scale; //entity box
Vector3 abmax = earch.BBMax * rooment.Scale;
c[0] = abmin;
c[1] = new Vector3(abmin.X, abmin.Y, abmax.Z);
c[2] = new Vector3(abmin.X, abmax.Y, abmin.Z);
c[3] = new Vector3(abmin.X, abmax.Y, abmax.Z);
c[4] = new Vector3(abmax.X, abmin.Y, abmin.Z);
c[5] = new Vector3(abmax.X, abmin.Y, abmax.Z);
c[6] = new Vector3(abmax.X, abmax.Y, abmin.Z);
c[7] = abmax;
for (int n = 0; n < 8; n++)
{
Vector3 corn = ori.Multiply(c[n]) + pos;
min = Vector3.Min(min, corn);
max = Vector3.Max(max, corn);
}
}
}
}
room.BBMin_CW = min;
room.BBMax_CW = max;
mlobbmin = Vector3.Min(mlobbmin, min);
mlobbmax = Vector3.Max(mlobbmax, max);
}
}
mloa.BBMin = mlobbmin;
mloa.BBMax = mlobbmax;
}
}
public bool DeleteEntity(YmapEntityDef ent)
{
if (Entities == null)
{
throw new NullReferenceException("The Entities list returned null in our MloInstanceData. This could be an issue with initialization. The MloInstance probably doesn't exist.");
}
if (ent.Index >= Entities.Length)
{
throw new ArgumentOutOfRangeException("The index of the entity was greater than the amount of entities that exist in this MloInstance. Likely an issue with initializion.");
}
int index = 0;
YmapEntityDef[] newentities = new YmapEntityDef[Entities.Length - 1];
YmapEntityDef delentity = Entities[ent.Index];
bool del = false;
for (int i = 0; i < Entities.Length; i++)
{
if (Entities[i] == delentity)
{
del = true;
continue;
}
newentities[index] = Entities[i];
newentities[index].Index = index;
index++;
}
if (!del)
throw new ArgumentException("The entity specified was not found in this MloInstance. It cannot be deleted.");
if (Owner.Archetype is MloArchetype arch)
{
if (arch.RemoveEntity(ent))
{
if (ent.MloEntitySet != null)
if (!ent.MloEntitySet.Entities.Remove(ent))
return false;
// Delete was successful...
Entities = newentities;
return true;
}
}
throw new InvalidCastException("The owner of this archetype's archetype definition is not an MloArchetype.");
}
public YmapEntityDef CreateYmapEntity(YmapEntityDef owner, MCEntityDef ment, int index)
{
YmapEntityDef e = new YmapEntityDef(null, index, ref ment._Data);
e.Extensions = ment.Extensions;
e.MloRefPosition = e.Position;
e.MloRefOrientation = e.Orientation;
@ -259,9 +579,31 @@ namespace CodeWalker.GameFiles
e.Orientation = Quaternion.Multiply(owner.Orientation, e.MloRefOrientation);
e.UpdateWidgetPosition();
e.UpdateWidgetOrientation();
return e;
}
public MCEntityDef TryGetArchetypeEntity(YmapEntityDef ymapEntity)
{
if (ymapEntity == null) return null;
if (Owner?.Archetype == null) return null;
if (!(Owner.Archetype is MloArchetype mloa)) return null;
if (ymapEntity.Index >= mloa.entities.Length) return null;
var entity = mloa.entities[ymapEntity.Index];
return entity;
}
public YmapEntityDef TryGetYmapEntity(MCEntityDef mcEntity)
{
if (mcEntity == null) return null;
if (Owner?.Archetype == null) return null;
if (!(Owner.Archetype is MloArchetype mloa)) return null;
var index = Array.FindIndex(mloa.entities, x => x == mcEntity);
if (index == -1 || index >= Entities.Length) return null;
return Entities[index];
}
public void SetPosition(Vector3 pos)
{
@ -285,16 +627,75 @@ namespace CodeWalker.GameFiles
for (int i = 0; i < Entities.Length; i++)
{
YmapEntityDef e = Entities[i];
e.Position = Owner.Position + Owner.Orientation.Multiply(e.MloRefPosition);
e.Orientation = Quaternion.Multiply(Owner.Orientation, e.MloRefOrientation);
e.UpdateWidgetPosition();
e.UpdateWidgetOrientation();
UpdateEntity(e);
}
}
public void UpdateEntity(YmapEntityDef e)
{
e.Position = Owner.Position + Owner.Orientation.Multiply(e.MloRefPosition);
e.Orientation = Quaternion.Multiply(Owner.Orientation, e.MloRefOrientation);
e.UpdateWidgetPosition();
e.UpdateWidgetOrientation();
}
public void AddEntity(YmapEntityDef e)
{
if (e == null) return;
if (Entities == null) Entities = new YmapEntityDef[0];
var entities = Entities.ToList();
entities.Add(e);
Entities = entities.ToArray();
}
public void UpdateDefaultEntitySets()
{
var list = new List<uint>();
var mloarch = Owner?.Archetype as MloArchetype;
if (mloarch?.entitySets != null)
{
for (uint i = 0; i < mloarch.entitySets.Length; i++)
{
var entset = mloarch.entitySets[i];
MloInstanceEntitySet instset = null;
EntitySets.TryGetValue(entset._Data.name, out instset);
if (instset != null)
{
if (instset.Visible)
{
list.Add(i);
}
}
}
}
defaultEntitySets = list.ToArray();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MloInstanceEntitySet
{
public MloInstanceEntitySet(MCMloEntitySet entSet, MloInstanceData instance)
{
EntitySet = entSet;
Entities = new List<YmapEntityDef>();
Instance = instance;
}
public MCMloEntitySet EntitySet { get; set; }
public List<YmapEntityDef> Entities { get; set; }
public MloInstanceData Instance { get; set; }
public uint[] Locations
{
get { return EntitySet?.Locations; }
set { if (EntitySet != null) EntitySet.Locations = value; }
}
public bool Visible { get; set; }
}

View File

@ -54,6 +54,8 @@ namespace CodeWalker.GameFiles
public string Name { get; private set; }
//public string[] Strings { get; set; }
private string_r NameBlock = null;
/// <summary>
/// Reads the data-block from a stream.
@ -107,6 +109,9 @@ namespace CodeWalker.GameFiles
(ulong)this.NamePointer // offset
);
if (!string.IsNullOrEmpty(Name))
{ }
//Strings = MetaTypes.GetStrings(this);
}
@ -121,7 +126,7 @@ namespace CodeWalker.GameFiles
this.StructureInfosPointer = this.StructureInfos?.FilePosition ?? 0;
this.EnumInfosPointer = this.EnumInfos?.FilePosition ?? 0;
this.DataBlocksPointer = this.DataBlocks?.FilePosition ?? 0;
//this.NamePointer = this.Name?.Position ?? 0; //TODO: fix
this.NamePointer = this.NameBlock?.FilePosition ?? 0;
this.UselessPointer = 0;
this.StructureInfosCount = (short)(this.StructureInfos?.Count ?? 0);
this.EnumInfosCount = (short)(this.EnumInfos?.Count ?? 0);
@ -162,7 +167,11 @@ namespace CodeWalker.GameFiles
if ((StructureInfos != null) && (StructureInfos.Count > 0)) list.Add(StructureInfos);
if ((EnumInfos != null) && (EnumInfos.Count > 0)) list.Add(EnumInfos);
if ((DataBlocks != null) && (DataBlocks.Count > 0)) list.Add(DataBlocks);
//if (Name != null) list.Add(Name); //TODO: fix
if (!string.IsNullOrEmpty(Name))
{
NameBlock = (string_r)Name;
list.Add(NameBlock);
}
return list.ToArray();
}
@ -621,9 +630,9 @@ namespace CodeWalker.GameFiles
public ushort Count2 { get; set; }
public uint Unk1 { get; set; }
public uint PointerDataId { get { return (Pointer & 0xFFF); } }
public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } }
public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } }
public uint PointerDataId { get { return (Pointer & 0xFFF); } set { Pointer = (Pointer & 0xFFFFF000) + (value & 0xFFF); } }
public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } set { PointerDataId = value + 1; } }
public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } set { Pointer = (Pointer & 0xFFF) + ((value << 12) & 0xFFFFF000); } }
@ -920,6 +929,13 @@ namespace CodeWalker.GameFiles
public uint PointerDataIndex { get { return (Ptr0 & 0xFFF) - 1; } }
public uint PointerDataOffset { get { return ((Ptr0 >> 12) & 0xFFFFF); } }
public DataBlockPointer(int blockId, int offset)
{
Ptr0 = ((uint)blockId & 0xFFF) | (((uint)offset & 0xFFFFF) << 12);
Ptr1 = 0;
}
public override string ToString()
{
return "DataBlockPointer: " + Ptr0.ToString() + ", " + Ptr1.ToString();
@ -935,6 +951,10 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public struct ArrayOfUshorts3 //array of 3 ushorts
{
public ushort u0, u1, u2;
public Vector3 XYZ()
{
return new Vector3(u0, u1, u2);
}
public override string ToString()
{
return u0.ToString() + ", " + u1.ToString() + ", " + u2.ToString();
@ -1005,6 +1025,13 @@ namespace CodeWalker.GameFiles
return x.ToString() + ", " + y.ToString() + ", " + z.ToString();
}
public MetaVECTOR3(Vector3 v)
{
x = v.X;
y = v.Y;
z = v.Z;
}
public Vector3 ToVector3()
{
return new Vector3(x, y, z);
@ -1053,12 +1080,40 @@ namespace CodeWalker.GameFiles
}
}
public float Float
{
get
{
return MetaTypes.ConvertData<float>(MetaTypes.ConvertToBytes(Hash));
}
}
public short Short1
{
get
{
return (short)(Hash & 0xFFFF);
}
}
public short Short2
{
get
{
return (short)((Hash >> 16) & 0xFFFF);
}
}
public MetaHash(uint h) { Hash = h; }
public override string ToString()
{
var str = JenkIndex.TryGetString(Hash);
if (!string.IsNullOrEmpty(str)) return str;
if (Enum.IsDefined(typeof(MetaName), Hash))
{
return ((MetaName)Hash).ToString();
}
return GlobalText.GetString(Hash);
}

View File

@ -27,6 +27,10 @@ namespace CodeWalker.GameFiles
}
}
}
return AddBlock(type);
}
public MetaBuilderBlock AddBlock(MetaName type)
{
MetaBuilderBlock b = new MetaBuilderBlock();
b.StructureNameHash = type;
b.Index = Blocks.Count;
@ -91,12 +95,7 @@ namespace CodeWalker.GameFiles
MetaBuilderBlock block = EnsureBlock(MetaName.STRING);
byte[] data = Encoding.ASCII.GetBytes(str);
int datalen = data.Length;
int newlen = datalen;
int lenrem = newlen % 16;
if (lenrem != 0) //need to pad the data length up to multiple of 16.
{
newlen += (16 - lenrem);
}
int newlen = datalen + 1; //include null terminator
byte[] newdata = new byte[newlen];
Buffer.BlockCopy(data, 0, newdata, 0, datalen);
int offs = block.TotalSize;
@ -104,7 +103,7 @@ namespace CodeWalker.GameFiles
MetaBuilderPointer r = new MetaBuilderPointer();
r.BlockID = block.Index + 1;
r.Offset = offs;// (idx * data.Length);
r.Length = datalen; //actual length of string.
r.Length = datalen; //actual length of string. (not incl null terminator)
return r;
}
@ -193,6 +192,14 @@ namespace CodeWalker.GameFiles
var ptr = AddString(str);
return new CharPointer(ptr);
}
public DataBlockPointer AddDataBlockPtr(byte[] data, MetaName type)
{
var block = AddBlock(type);
int offs = block.TotalSize;//should always be 0...
int idx = block.AddItem(data);
var ptr = new DataBlockPointer(block.Index + 1, offs);
return ptr;
}
public Array_StructurePointer AddPointerArray(MetaPOINTER[] arr)
@ -351,19 +358,35 @@ namespace CodeWalker.GameFiles
m.RootBlockIndex = 1; //assume first block is root. todo: make adjustable?
m.StructureInfos = new ResourceSimpleArray<MetaStructureInfo>();
foreach (var si in StructureInfos.Values)
if (StructureInfos.Count > 0)
{
m.StructureInfos.Add(si);
m.StructureInfos = new ResourceSimpleArray<MetaStructureInfo>();
foreach (var si in StructureInfos.Values)
{
m.StructureInfos.Add(si);
}
m.StructureInfosCount = (short)m.StructureInfos.Count;
}
else
{
m.StructureInfos = null;
m.StructureInfosCount = 0;
}
m.StructureInfosCount = (short)m.StructureInfos.Count;
m.EnumInfos = new ResourceSimpleArray<MetaEnumInfo>();
foreach (var ei in EnumInfos.Values)
if (EnumInfos.Count > 0)
{
m.EnumInfos.Add(ei);
m.EnumInfos = new ResourceSimpleArray<MetaEnumInfo>();
foreach (var ei in EnumInfos.Values)
{
m.EnumInfos.Add(ei);
}
m.EnumInfosCount = (short)m.EnumInfos.Count;
}
else
{
m.EnumInfos = null;
m.EnumInfosCount = 0;
}
m.EnumInfosCount = (short)m.EnumInfos.Count;
m.DataBlocks = new ResourceSimpleArray<MetaDataBlock>();
foreach (var bb in Blocks)

File diff suppressed because it is too large Load Diff

View File

@ -317,12 +317,12 @@ namespace CodeWalker.GameFiles
);
case MetaName.rage__spdGrid2D:
return new MetaStructureInfo(MetaName.rage__spdGrid2D, 894636096, 768, 64,
new MetaStructureEntryInfo_s((MetaName)860552138, 12, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)3824598937, 16, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)496029782, 20, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)3374647798, 24, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)2690909759, 44, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)3691675019, 48, MetaStructureEntryDataType.Float, 0, 0, 0)
new MetaStructureEntryInfo_s(MetaName.MinCellX, 12, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.MaxCellX, 16, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.MinCellY, 20, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.MaxCellY, 24, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.CellDimX, 44, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.CellDimY, 48, MetaStructureEntryDataType.Float, 0, 0, 0)
);
case MetaName.CScenarioPointLookUps:
return new MetaStructureInfo(MetaName.CScenarioPointLookUps, 2669361587, 768, 96,
@ -366,7 +366,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.iRadius, 29, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.iTimeTillPedLeaves, 30, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.iScenarioGroup, 32, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.Flags, 36, MetaStructureEntryDataType.IntFlags2, 0, 32, (MetaName)700327466),
new MetaStructureEntryInfo_s(MetaName.Flags, 36, MetaStructureEntryDataType.IntFlags2, 0, 32, MetaName.CScenarioPointFlags__Flags),
new MetaStructureEntryInfo_s(MetaName.vPositionAndDirection, 48, MetaStructureEntryDataType.Float_XYZW, 0, 0, 0)
);
case MetaName.CScenarioEntityOverride:
@ -394,7 +394,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.radius, 80, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.start, 84, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.end, 85, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.flags, 88, MetaStructureEntryDataType.IntFlags2, 0, 32, (MetaName)700327466),
new MetaStructureEntryInfo_s(MetaName.flags, 88, MetaStructureEntryDataType.IntFlags2, 0, 32, MetaName.CScenarioPointFlags__Flags),
new MetaStructureEntryInfo_s(MetaName.highPri, 92, MetaStructureEntryDataType.Boolean, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.extendedRange, 93, MetaStructureEntryDataType.Boolean, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.shortRange, 94, MetaStructureEntryDataType.Boolean, 0, 0, 0)
@ -498,7 +498,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.clipDictionary, 96, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.drawableDictionary, 100, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.physicsDictionary, 104, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.assetType, 108, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)1991964615),
new MetaStructureEntryInfo_s(MetaName.assetType, 108, MetaStructureEntryDataType.IntEnum, 0, 0, MetaName.rage__fwArchetypeDef__eAssetType),
new MetaStructureEntryInfo_s(MetaName.assetName, 112, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.extensions, 120, MetaStructureEntryDataType.Array, 0, 15, 0)
@ -627,11 +627,11 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.entitiesExtentsMax, 80, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.entities, 96, MetaStructureEntryDataType.Array, 0, 8, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)372253349),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.rage__fwContainerLodDef),
new MetaStructureEntryInfo_s(MetaName.containerLods, 112, MetaStructureEntryDataType.Array, 0, 10, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)975711773),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.BoxOccluder),
new MetaStructureEntryInfo_s(MetaName.boxOccluders, 128, MetaStructureEntryDataType.Array, 4, 12, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)2741784237),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.OccludeModel),
new MetaStructureEntryInfo_s(MetaName.occludeModels, 144, MetaStructureEntryDataType.Array, 4, 14, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.physicsDictionaries, 160, MetaStructureEntryDataType.Array, 0, 16, 0),
@ -656,9 +656,9 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.parentIndex, 72, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.lodDist, 76, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.childLodDist, 80, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.lodLevel, 84, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)1264241711),
new MetaStructureEntryInfo_s(MetaName.lodLevel, 84, MetaStructureEntryDataType.IntEnum, 0, 0, MetaName.rage__eLodType),
new MetaStructureEntryInfo_s(MetaName.numChildren, 88, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.priorityLevel, 92, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)648413703),
new MetaStructureEntryInfo_s(MetaName.priorityLevel, 92, MetaStructureEntryDataType.IntEnum, 0, 0, MetaName.rage__ePriorityLevel),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.extensions, 96, MetaStructureEntryDataType.Array, 0, 13, 0),
new MetaStructureEntryInfo_s(MetaName.ambientOcclusionMultiplier, 112, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
@ -690,7 +690,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.clipDictionary, 96, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.drawableDictionary, 100, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.physicsDictionary, 104, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.assetType, 108, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)1991964615),
new MetaStructureEntryInfo_s(MetaName.assetType, 108, MetaStructureEntryDataType.IntEnum, 0, 0, MetaName.rage__fwArchetypeDef__eAssetType),
new MetaStructureEntryInfo_s(MetaName.assetName, 112, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.extensions, 120, MetaStructureEntryDataType.Array, 0, 15, 0),
@ -761,9 +761,9 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.parentIndex, 72, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.lodDist, 76, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.childLodDist, 80, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.lodLevel, 84, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)1264241711),
new MetaStructureEntryInfo_s(MetaName.lodLevel, 84, MetaStructureEntryDataType.IntEnum, 0, 0, MetaName.rage__eLodType),
new MetaStructureEntryInfo_s(MetaName.numChildren, 88, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.priorityLevel, 92, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)648413703),
new MetaStructureEntryInfo_s(MetaName.priorityLevel, 92, MetaStructureEntryDataType.IntEnum, 0, 0, MetaName.rage__ePriorityLevel),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.extensions, 96, MetaStructureEntryDataType.Array, 0, 13, 0),
new MetaStructureEntryInfo_s(MetaName.ambientOcclusionMultiplier, 112, MetaStructureEntryDataType.SignedInt, 0, 0, 0),
@ -776,8 +776,8 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.numExitPortals, 152, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.MLOInstflags, 156, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0)
);
case (MetaName)975711773:
return new MetaStructureInfo((MetaName)975711773, 1831736438, 256, 16,
case MetaName.BoxOccluder:
return new MetaStructureInfo(MetaName.BoxOccluder, 1831736438, 256, 16,
new MetaStructureEntryInfo_s(MetaName.iCenterX, 0, MetaStructureEntryDataType.SignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.iCenterY, 2, MetaStructureEntryDataType.SignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.iCenterZ, 4, MetaStructureEntryDataType.SignedShort, 0, 0, 0),
@ -787,15 +787,15 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.iHeight, 12, MetaStructureEntryDataType.SignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.iSinZ, 14, MetaStructureEntryDataType.SignedShort, 0, 0, 0)
);
case (MetaName)2741784237:
return new MetaStructureInfo((MetaName)2741784237, 1172796107, 1024, 64,
case MetaName.OccludeModel:
return new MetaStructureInfo(MetaName.OccludeModel, 1172796107, 1024, 64,
new MetaStructureEntryInfo_s(MetaName.bmin, 0, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.bmax, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.dataSize, 32, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.verts, 40, MetaStructureEntryDataType.DataBlockPointer, 4, 3, (MetaName)2),
new MetaStructureEntryInfo_s((MetaName)853977995, 48, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)2337695078, 50, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.numVertsInBytes, 48, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.numTris, 50, MetaStructureEntryDataType.UnsignedShort, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.flags, 52, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0)
);
case MetaName.CMloArchetypeDef:
@ -813,7 +813,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.clipDictionary, 96, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.drawableDictionary, 100, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.physicsDictionary, 104, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.assetType, 108, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)1991964615),
new MetaStructureEntryInfo_s(MetaName.assetType, 108, MetaStructureEntryDataType.IntEnum, 0, 0, MetaName.rage__fwArchetypeDef__eAssetType),
new MetaStructureEntryInfo_s(MetaName.assetName, 112, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.StructurePointer, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.extensions, 120, MetaStructureEntryDataType.Array, 0, 15, 0),
@ -894,21 +894,21 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.StartImapFile, 264, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.EndImapFile, 268, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.PtFxAssetName, 272, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)1980345114),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CCompEntityAnims),
new MetaStructureEntryInfo_s(MetaName.Animations, 280, MetaStructureEntryDataType.Array, 0, 13, 0)
);
case (MetaName)1980345114:
return new MetaStructureInfo((MetaName)1980345114, 4110496011, 768, 216,
case MetaName.CCompEntityAnims:
return new MetaStructureInfo(MetaName.CCompEntityAnims, 4110496011, 768, 216,
new MetaStructureEntryInfo_s(MetaName.AnimDict, 0, MetaStructureEntryDataType.ArrayOfChars, 0, 0, (MetaName)64),
new MetaStructureEntryInfo_s(MetaName.AnimName, 64, MetaStructureEntryDataType.ArrayOfChars, 0, 0, (MetaName)64),
new MetaStructureEntryInfo_s(MetaName.AnimatedModel, 128, MetaStructureEntryDataType.ArrayOfChars, 0, 0, (MetaName)64),
new MetaStructureEntryInfo_s(MetaName.punchInPhase, 192, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.punchOutPhase, 196, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)3430328684),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CCompEntityEffectsData),
new MetaStructureEntryInfo_s(MetaName.effectsData, 200, MetaStructureEntryDataType.Array, 0, 5, 0)
);
case (MetaName)3430328684:
return new MetaStructureInfo((MetaName)3430328684, 1724963966, 1024, 160,
case MetaName.CCompEntityEffectsData:
return new MetaStructureInfo(MetaName.CCompEntityEffectsData, 1724963966, 1024, 160,
new MetaStructureEntryInfo_s(MetaName.fxType, 0, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fxOffsetPos, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fxOffsetRot, 32, MetaStructureEntryDataType.Float_XYZW, 0, 0, 0),
@ -970,10 +970,10 @@ namespace CodeWalker.GameFiles
return new MetaStructureInfo(MetaName.CExtensionDefExpression, 24441706, 1024, 48,
new MetaStructureEntryInfo_s(MetaName.name, 8, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.offsetPosition, 16, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)1095612811, 32, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.expressionDictionaryName, 32, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.expressionName, 36, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)2766477159, 40, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)1562817888, 44, MetaStructureEntryDataType.Boolean, 0, 0, 0)
new MetaStructureEntryInfo_s(MetaName.creatureMetadataName, 40, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.initialiseOnCollision, 44, MetaStructureEntryDataType.Boolean, 0, 0, 0)
);
case MetaName.CExtensionDefLightShaft:
return new MetaStructureInfo(MetaName.CExtensionDefLightShaft, 2526429398, 1024, 176,
@ -986,12 +986,12 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.direction, 96, MetaStructureEntryDataType.Float_XYZ, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.directionAmount, 112, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.length, 116, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)1616789093, 120, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)120454521, 124, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)1297365553, 128, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)75548206, 132, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)40301253, 136, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)475013030, 140, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fadeInTimeStart, 120, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fadeInTimeEnd, 124, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fadeOutTimeStart, 128, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fadeOutTimeEnd, 132, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fadeDistanceStart, 136, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.fadeDistanceEnd, 140, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.color, 144, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.intensity, 148, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.flashiness, 152, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
@ -999,7 +999,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.densityType, 160, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)1931949281),
new MetaStructureEntryInfo_s(MetaName.volumeType, 164, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)2266515059),
new MetaStructureEntryInfo_s(MetaName.softness, 168, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)59101696, 172, MetaStructureEntryDataType.Boolean, 0, 0, 0)
new MetaStructureEntryInfo_s(MetaName.scaleBySunIntensity, 172, MetaStructureEntryDataType.Boolean, 0, 0, 0)
);
case MetaName.VECTOR3:
return new MetaStructureInfo(MetaName.VECTOR3, 2751397072, 512, 12,
@ -1007,16 +1007,16 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.y, 4, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.z, 8, MetaStructureEntryDataType.Float, 0, 0, 0)
);
case (MetaName)2858946626:
return new MetaStructureInfo((MetaName)2858946626, 1792487819, 768, 40,
case MetaName.CPedPropInfo:
return new MetaStructureInfo(MetaName.CPedPropInfo, 1792487819, 768, 40,
new MetaStructureEntryInfo_s((MetaName)2598445407, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)94549140),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CPedPropMetaData),
new MetaStructureEntryInfo_s((MetaName)3902803273, 8, MetaStructureEntryDataType.Array, 0, 1, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CAnchorProps),
new MetaStructureEntryInfo_s(MetaName.aAnchors, 24, MetaStructureEntryDataType.Array, 0, 3, 0)
);
case (MetaName)376833625:
return new MetaStructureInfo((MetaName)376833625, 4030871161, 768, 112,
case MetaName.CPedVariationInfo:
return new MetaStructureInfo(MetaName.CPedVariationInfo, 4030871161, 768, 112,
new MetaStructureEntryInfo_s((MetaName)1235281004, 0, MetaStructureEntryDataType.Boolean, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)4086467184, 1, MetaStructureEntryDataType.Boolean, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)911147899, 2, MetaStructureEntryDataType.Boolean, 0, 0, 0),
@ -1025,11 +1025,11 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s((MetaName)2996560424, 4, MetaStructureEntryDataType.ArrayOfBytes, 0, 4, MetaName.PsoPOINTER),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)3538495220),
new MetaStructureEntryInfo_s((MetaName)3796409423, 16, MetaStructureEntryDataType.Array, 0, 6, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)253191135),
new MetaStructureEntryInfo_s((MetaName)2131007641, 32, MetaStructureEntryDataType.Array, 0, 8, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CPedSelectionSet),
new MetaStructureEntryInfo_s(MetaName.aSelectionSets, 32, MetaStructureEntryDataType.Array, 0, 8, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CComponentInfo),
new MetaStructureEntryInfo_s(MetaName.compInfos, 48, MetaStructureEntryDataType.Array, 0, 10, 0),
new MetaStructureEntryInfo_s(MetaName.propInfo, 64, MetaStructureEntryDataType.Structure, 0, 0, (MetaName)2858946626),
new MetaStructureEntryInfo_s(MetaName.propInfo, 64, MetaStructureEntryDataType.Structure, 0, 0, MetaName.CPedPropInfo),
new MetaStructureEntryInfo_s(MetaName.dlcName, 104, MetaStructureEntryDataType.Hash, 0, 0, 0)
);
case (MetaName)3538495220:
@ -1069,8 +1069,8 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s((MetaName)3509540765, 44, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)4196345791, 45, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0)
);
case (MetaName)94549140:
return new MetaStructureInfo((MetaName)94549140, 2029738350, 768, 56,
case MetaName.CPedPropMetaData:
return new MetaStructureInfo(MetaName.CPedPropMetaData, 2029738350, 768, 56,
new MetaStructureEntryInfo_s(MetaName.audioId, 0, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.expressionMods, 4, MetaStructureEntryDataType.ArrayOfBytes, 0, 1, (MetaName)5),
@ -1098,8 +1098,8 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.props, 0, MetaStructureEntryDataType.Array, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.anchor, 16, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)2834549053)
);
case (MetaName)253191135:
return new MetaStructureInfo((MetaName)253191135, 3120284999, 512, 48,
case MetaName.CPedSelectionSet:
return new MetaStructureInfo(MetaName.CPedSelectionSet, 3120284999, 512, 48,
new MetaStructureEntryInfo_s(MetaName.name, 0, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ARRAYINFO, 0, MetaStructureEntryDataType.UnsignedByte, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)173599222, 4, MetaStructureEntryDataType.ArrayOfBytes, 0, 1, MetaName.PsoPOINTER),
@ -1141,7 +1141,7 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.Group, 40, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.ModelSet, 44, MetaStructureEntryDataType.Hash, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.AvailabilityInMpSp, 48, MetaStructureEntryDataType.IntEnum, 0, 0, (MetaName)3573596290),
new MetaStructureEntryInfo_s(MetaName.Flags, 52, MetaStructureEntryDataType.IntFlags2, 0, 32, (MetaName)700327466),
new MetaStructureEntryInfo_s(MetaName.Flags, 52, MetaStructureEntryDataType.IntFlags2, 0, 32, MetaName.CScenarioPointFlags__Flags),
new MetaStructureEntryInfo_s(MetaName.Radius, 56, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.TimeTillPedLeaves, 60, MetaStructureEntryDataType.Float, 0, 0, 0)
);
@ -1210,10 +1210,10 @@ namespace CodeWalker.GameFiles
new MetaStructureEntryInfo_s(MetaName.spacing, 40, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.minScale, 44, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.maxScale, 48, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)3913056845, 52, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)147400493, 56, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)2591582364, 60, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s((MetaName)3889902555, 64, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.minScaleZ, 52, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.maxScaleZ, 56, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.minZOffset, 60, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.maxZOffset, 64, MetaStructureEntryDataType.Float, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.objectHash, 68, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0),
new MetaStructureEntryInfo_s(MetaName.flags, 72, MetaStructureEntryDataType.UnsignedInt, 0, 0, 0)
);
@ -1245,8 +1245,8 @@ namespace CodeWalker.GameFiles
//to generate enuminfos
switch (name)
{
case (MetaName)700327466:
return new MetaEnumInfo((MetaName)700327466, 2814596095,
case MetaName.CScenarioPointFlags__Flags:
return new MetaEnumInfo(MetaName.CScenarioPointFlags__Flags, 2814596095,
new MetaEnumEntryInfo_s(MetaName.IgnoreMaxInRange, 0),
new MetaEnumEntryInfo_s(MetaName.NoSpawn, 1),
new MetaEnumEntryInfo_s(MetaName.StationaryReactions, 2),
@ -1316,16 +1316,16 @@ namespace CodeWalker.GameFiles
new MetaEnumEntryInfo_s((MetaName)3717649022, 14),
new MetaEnumEntryInfo_s((MetaName)3356026130, 15)
);
case (MetaName)1991964615:
return new MetaEnumInfo((MetaName)1991964615, 1866031916,
case MetaName.rage__fwArchetypeDef__eAssetType:
return new MetaEnumInfo(MetaName.rage__fwArchetypeDef__eAssetType, 1866031916,
new MetaEnumEntryInfo_s(MetaName.ASSET_TYPE_UNINITIALIZED, 0),
new MetaEnumEntryInfo_s(MetaName.ASSET_TYPE_FRAGMENT, 1),
new MetaEnumEntryInfo_s(MetaName.ASSET_TYPE_DRAWABLE, 2),
new MetaEnumEntryInfo_s(MetaName.ASSET_TYPE_DRAWABLEDICTIONARY, 3),
new MetaEnumEntryInfo_s(MetaName.ASSET_TYPE_ASSETLESS, 4)
);
case (MetaName)1264241711:
return new MetaEnumInfo((MetaName)1264241711, 1856311430,
case MetaName.rage__eLodType:
return new MetaEnumInfo(MetaName.rage__eLodType, 1856311430,
new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_HD, 0),
new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_LOD, 1),
new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_SLOD1, 2),
@ -1334,8 +1334,8 @@ namespace CodeWalker.GameFiles
new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_ORPHANHD, 5),
new MetaEnumEntryInfo_s(MetaName.LODTYPES_DEPTH_SLOD4, 6)
);
case (MetaName)648413703:
return new MetaEnumInfo((MetaName)648413703, 2200357711,
case MetaName.rage__ePriorityLevel:
return new MetaEnumInfo(MetaName.rage__ePriorityLevel, 2200357711,
new MetaEnumEntryInfo_s(MetaName.PRI_REQUIRED, 0),
new MetaEnumEntryInfo_s(MetaName.PRI_OPTIONAL_HIGH, 1),
new MetaEnumEntryInfo_s(MetaName.PRI_OPTIONAL_MEDIUM, 2),
@ -1728,6 +1728,21 @@ namespace CodeWalker.GameFiles
Buffer.BlockCopy(ptrblock.Data, (int)ptroffset, data, 0, count);
return data;
}
public static byte[] GetByteArray(Meta meta, DataBlockPointer ptr, uint count)
{
//var pointer = array.Pointer;
uint ptrindex = ptr.PointerDataIndex;// (pointer & 0xFFF) - 1;
uint ptroffset = ptr.PointerDataOffset;// ((pointer >> 12) & 0xFFFFF);
var ptrblock = (ptrindex < meta.DataBlocks.Count) ? meta.DataBlocks[(int)ptrindex] : null;
if ((ptrblock == null) || (ptrblock.Data == null))// || (ptrblock.StructureNameHash != name))
{ return null; } //no block or wrong block? shouldn't happen!
//var count = array.Count1;
if ((ptroffset + count) > ptrblock.Data.Length)
{ return null; }
byte[] data = new byte[count];
Buffer.BlockCopy(ptrblock.Data, (int)ptroffset, data, 0, (int)count);
return data;
}
public static T[] GetTypedDataArray<T>(Meta meta, MetaName name) where T : struct
@ -1992,6 +2007,10 @@ namespace CodeWalker.GameFiles
{
return (ushort)(((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8));
}
public static short SwapBytes(short x)
{
return (short)SwapBytes((ushort)x);
}
public static uint SwapBytes(uint x)
{
// swap adjacent 16-bit blocks
@ -2056,7 +2075,7 @@ namespace CodeWalker.GameFiles
//generated enums
[Flags] public enum Unk_700327466 //SCENARIO point flags / extension spawn point flags
[Flags] public enum CScenarioPointFlags__Flags //SCENARIO point flags / extension spawn point flags
: int //Key:2814596095
{
IgnoreMaxInRange = 1,//0,
@ -2137,7 +2156,7 @@ namespace CodeWalker.GameFiles
Unk_15_3356026130 = 15,
}
public enum Unk_1991964615 //archetype assetType
public enum rage__fwArchetypeDef__eAssetType //archetype assetType
: int //Key:1866031916
{
ASSET_TYPE_UNINITIALIZED = 0, //189734893
@ -2147,7 +2166,7 @@ namespace CodeWalker.GameFiles
ASSET_TYPE_ASSETLESS = 4, //4161085041
}
public enum Unk_1264241711 //entity lodLevel
public enum rage__eLodType //entity lodLevel
: int //Key:1856311430
{
LODTYPES_DEPTH_HD = 0,
@ -2159,7 +2178,7 @@ namespace CodeWalker.GameFiles
LODTYPES_DEPTH_SLOD4 = 6,
}
public enum Unk_648413703 //entity priorityLevel
public enum rage__ePriorityLevel //entity priorityLevel
: int //Key:2200357711
{
PRI_REQUIRED = 0, //1943361227
@ -2215,7 +2234,7 @@ namespace CodeWalker.GameFiles
PV_COMP_MAX = 2048,//12,
}
public enum Unk_4212977111 //component peds Unk_94549140 renderFlags
public enum Unk_4212977111 //component peds CPedPropMetaData renderFlags
: int //Key:1551913633
{
Unk_3757767268 = 0,
@ -2295,7 +2314,7 @@ namespace CodeWalker.GameFiles
public MetaHash clipDictionary { get; set; } //96 96: Hash: 0: clipDictionary//424089489
public MetaHash drawableDictionary { get; set; } //100 100: Hash: 0: drawableDictionary
public MetaHash physicsDictionary { get; set; } //104 104: Hash: 0: physicsDictionary//3553040380
public Unk_1991964615 assetType { get; set; } //108 108: IntEnum: 1991964615: assetType
public rage__fwArchetypeDef__eAssetType assetType { get; set; } //108 108: IntEnum: 1991964615: assetType
public MetaHash assetName { get; set; } //112 112: Hash: 0: assetName
public uint Unused08 { get; set; }//116
public Array_StructurePointer extensions { get; set; } //120 120: Array: 0: extensions {0: StructurePointer: 0: 256}
@ -2428,7 +2447,9 @@ namespace CodeWalker.GameFiles
public Vector3 BBMax { get { return (_Data.bbMax); } }
public Vector3 BBMin_CW { get; set; }
public Vector3 BBMax_CW { get; set; }
public MloArchetype Archetype { get; set; }
public int Index { get; set; }
public MCMloRoomDef() { }
public MCMloRoomDef(Meta meta, CMloRoomDef data)
@ -2610,7 +2631,7 @@ namespace CodeWalker.GameFiles
Entities = new MCEntityDef[ents.Length];
for (int i = 0; i < ents.Length; i++)
{
Entities[i] = new MCEntityDef(meta, ents[i]);
Entities[i] = new MCEntityDef(meta, ref ents[i]);
}
}
}
@ -2732,9 +2753,9 @@ namespace CodeWalker.GameFiles
public int parentIndex { get; set; } //72 72: SignedInt: 0: parentIndex
public float lodDist { get; set; } //76 76: Float: 0: lodDist
public float childLodDist { get; set; } //80 80: Float: 0: childLodDist//3398912973
public Unk_1264241711 lodLevel { get; set; } //84 84: IntEnum: 1264241711: lodLevel //LODTYPES_DEPTH_
public rage__eLodType lodLevel { get; set; } //84 84: IntEnum: 1264241711: lodLevel //LODTYPES_DEPTH_
public uint numChildren { get; set; } //88 88: UnsignedInt: 0: numChildren//2793909385
public Unk_648413703 priorityLevel { get; set; } //92 92: IntEnum: 648413703: priorityLevel//647098393
public rage__ePriorityLevel priorityLevel { get; set; } //92 92: IntEnum: 648413703: priorityLevel//647098393
public Array_StructurePointer extensions { get; set; } //96 96: Array: 0: extensions {0: StructurePointer: 0: 256}
public int ambientOcclusionMultiplier { get; set; } //112 112: SignedInt: 0: ambientOcclusionMultiplier//415356295
public int artificialAmbientOcclusion { get; set; } //116 116: SignedInt: 0: artificialAmbientOcclusion//599844163
@ -2750,23 +2771,26 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public class MCEntityDef : MetaWrapper
{
public CEntityDef _Data;
public CEntityDef Data { get { return _Data; } }
public CEntityDef Data { get { return _Data; } set { _Data = value; } }
public MetaWrapper[] Extensions { get; set; }
public MCEntityDef() { }
public MloArchetype Archetype { get; set; } // for browsing/reference purposes
public MCEntityDef(MCEntityDef copy)
{
if (copy != null)
{
_Data = copy.Data;
}
if (copy != null) _Data = copy.Data;
}
public MCEntityDef(Meta meta, CEntityDef d)
public MCEntityDef(Meta meta, ref CEntityDef d)
{
_Data = d;
Extensions = MetaTypes.GetExtensions(meta, _Data.extensions);
}
public MCEntityDef(ref CEntityDef d, MloArchetype arch)
{
_Data = d;
Archetype = arch;
}
public override void Load(Meta meta, MetaPOINTER ptr)
{
@ -2803,7 +2827,7 @@ namespace CodeWalker.GameFiles
}
}
[TC(typeof(EXP))] public struct Unk_975711773 //16 bytes, Key:1831736438 //boxOccluders
[TC(typeof(EXP))] public struct BoxOccluder //16 bytes, Key:1831736438 //boxOccluders
{
public short iCenterX { get; set; } //0 0: SignedShort: 0: 48026296
public short iCenterY { get; set; } //2 2: SignedShort: 0: 896907229
@ -2815,7 +2839,7 @@ namespace CodeWalker.GameFiles
public short iSinZ { get; set; } //14 14: SignedShort: 0: iSinZ
}
[TC(typeof(EXP))] public struct Unk_2741784237 //64 bytes, Key:1172796107 //occludeModels
[TC(typeof(EXP))] public struct OccludeModel //64 bytes, Key:1172796107 //occludeModels
{
public Vector3 bmin { get; set; } //0 0: Float_XYZ: 0: bmin
public float Unused0 { get; set; }//12
@ -2824,8 +2848,8 @@ namespace CodeWalker.GameFiles
public uint dataSize { get; set; } //32 32: UnsignedInt: 0: dataSize//2442753371
public uint Unused2 { get; set; }//36
public DataBlockPointer verts { get; set; } //40 40: DataBlockPointer: 2: verts
public ushort Unk_853977995 { get; set; } //48 48: UnsignedShort: 0: 853977995
public ushort Unk_2337695078 { get; set; } //50 50: UnsignedShort: 0: 2337695078
public ushort numVertsInBytes { get; set; } //48 48: UnsignedShort: 0: numVertsInBytes
public ushort numTris { get; set; } //50 50: UnsignedShort: 0: numTris
public uint flags { get; set; } //52 52: UnsignedInt: 0: flags
public uint Unused3 { get; set; }//56
public uint Unused4 { get; set; }//60
@ -3405,10 +3429,10 @@ namespace CodeWalker.GameFiles
public uint Unused2 { get; set; }//12
public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition
public float Unused3 { get; set; }//28
public MetaHash Unk_1095612811 { get; set; } //32 32: Hash: 0: 1095612811
public MetaHash expressionDictionaryName { get; set; } //32 32: Hash: 0: expressionDictionaryName
public MetaHash expressionName { get; set; } //36 36: Hash: 0: expressionName
public MetaHash Unk_2766477159 { get; set; } //40 40: Hash: 0: 2766477159
public byte Unk_1562817888 { get; set; } //44 44: Boolean: 0: 1562817888
public MetaHash creatureMetadataName { get; set; } //40 40: Hash: 0: creatureMetadataName
public byte initialiseOnCollision { get; set; } //44 44: Boolean: 0: initialiseOnCollision
public byte Unused4 { get; set; }//45
public ushort Unused5 { get; set; }//46
@ -3467,12 +3491,12 @@ namespace CodeWalker.GameFiles
public float Unused08 { get; set; }//108
public float directionAmount { get; set; } //112 112: Float: 0: 1441249296
public float length { get; set; } //116 116: Float: 0: length
public float Unk_1616789093 { get; set; } //120 120: Float: 0: 1616789093
public float Unk_120454521 { get; set; } //124 124: Float: 0: 120454521
public float Unk_1297365553 { get; set; } //128 128: Float: 0: 1297365553
public float Unk_75548206 { get; set; } //132 132: Float: 0: 75548206
public float Unk_40301253 { get; set; } //136 136: Float: 0: 40301253
public float Unk_475013030 { get; set; } //140 140: Float: 0: 475013030
public float fadeInTimeStart { get; set; } //120 120: Float: 0: fadeInTimeStart
public float fadeInTimeEnd { get; set; } //124 124: Float: 0: fadeInTimeEnd
public float fadeOutTimeStart { get; set; } //128 128: Float: 0: fadeOutTimeStart
public float fadeOutTimeEnd { get; set; } //132 132: Float: 0: fadeOutTimeEnd
public float fadeDistanceStart { get; set; } //136 136: Float: 0: fadeDistanceStart
public float fadeDistanceEnd { get; set; } //140 140: Float: 0: fadeDistanceEnd
public uint color { get; set; } //144 144: UnsignedInt: 0: color
public float intensity { get; set; } //148 148: Float: 0: intensity
public byte flashiness { get; set; } //152 152: UnsignedByte: 0: 3829693202
@ -3482,7 +3506,7 @@ namespace CodeWalker.GameFiles
public Unk_1931949281 densityType { get; set; } //160 160: IntEnum: 1931949281: densityType//235100599
public Unk_2266515059 volumeType { get; set; } //164 164: IntEnum: 2266515059: volumeType//4021175589
public float softness { get; set; } //168 168: Float: 0: softness//187712958
public byte Unk_59101696 { get; set; } //172 172: Boolean: 0: 59101696
public byte scaleBySunIntensity { get; set; } //172 172: Boolean: 0: scaleBySunIntensity
public byte Unused11 { get; set; }//173
public ushort Unused12 { get; set; }//174
@ -3595,7 +3619,7 @@ namespace CodeWalker.GameFiles
public byte start { get; set; } //84 84: UnsignedByte: 0: start
public byte end { get; set; } //85 85: UnsignedByte: 0: end
public ushort Unused4 { get; set; }//86
public Unk_700327466 flags { get; set; } //88 88: IntFlags2: 700327466: flags
public CScenarioPointFlags__Flags flags { get; set; } //88 88: IntFlags2: 700327466: flags
public byte highPri { get; set; } //92 92: Boolean: 0: highPri
public byte extendedRange { get; set; } //93 93: Boolean: 0: extendedRange
public byte shortRange { get; set; } //94 94: Boolean: 0: shortRange
@ -3629,7 +3653,7 @@ namespace CodeWalker.GameFiles
public float Radius { get { return _Data.radius; } set { _Data.radius = value; } }
public byte StartTime { get { return _Data.start; } set { _Data.start = value; } }
public byte EndTime { get { return _Data.end; } set { _Data.end = value; } }
public Unk_700327466 Flags { get { return _Data.flags; } set { _Data.flags = value; } }
public CScenarioPointFlags__Flags Flags { get { return _Data.flags; } set { _Data.flags = value; } }
public bool HighPri { get { return _Data.highPri == 1; } set { _Data.highPri = (byte)(value ? 1 : 0); } }
public bool ExtendedRange { get { return _Data.extendedRange == 1; } set { _Data.extendedRange = (byte)(value ? 1 : 0); } }
public bool ShortRange { get { return _Data.shortRange == 1; } set { _Data.shortRange = (byte)(value ? 1 : 0); } }
@ -3663,7 +3687,7 @@ namespace CodeWalker.GameFiles
public override MetaPOINTER Save(MetaBuilder mb)
{
mb.AddEnumInfo((MetaName)3573596290);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint);
return mb.AddItemPtr(MetaName.CExtensionDefSpawnPoint, _Data);
}
@ -3697,7 +3721,7 @@ namespace CodeWalker.GameFiles
public MetaHash Group { get; set; } //40 40: Hash: 0: Group
public MetaHash ModelSet { get; set; } //44 44: Hash: 0: ModelSet
public Unk_3573596290 AvailabilityInMpSp { get; set; } //48 48: IntEnum: 3573596290: AvailabilityInMpSp//2932681318
public Unk_700327466 Flags { get; set; } //52 52: IntFlags2: 700327466: Flags
public CScenarioPointFlags__Flags Flags { get; set; } //52 52: IntFlags2: 700327466: Flags
public float Radius { get; set; } //56 56: Float: 0: Radius
public float TimeTillPedLeaves { get; set; } //60 60: Float: 0: TimeTillPedLeaves//4073598194
@ -3719,7 +3743,7 @@ namespace CodeWalker.GameFiles
public override MetaPOINTER Save(MetaBuilder mb)
{
mb.AddEnumInfo((MetaName)3573596290);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
mb.AddStructureInfo(MetaName.CExtensionDefSpawnPointOverride);
return mb.AddItemPtr(MetaName.CExtensionDefSpawnPointOverride, _Data);
}
@ -3800,16 +3824,16 @@ namespace CodeWalker.GameFiles
public uint Unused2 { get; set; }//12
public Vector3 offsetPosition { get; set; } //16 16: Float_XYZ: 0: offsetPosition
public float Unused3 { get; set; }//28
public float radiusInner { get; set; } //32 32: Float: 0: radiusInner//406390660
public float radiusOuter { get; set; } //36 36: Float: 0: radiusOuter//1814053978
public float radiusInner { get; set; } //32 32: Float: 0: radiusInner
public float radiusOuter { get; set; } //36 36: Float: 0: radiusOuter
public float spacing { get; set; } //40 40: Float: 0: spacing
public float minScale { get; set; } //44 44: Float: 0: minScale//3662913353
public float maxScale { get; set; } //48 48: Float: 0: maxScale//803384552
public float Unk_3913056845 { get; set; } //52 52: Float: 0: 3913056845
public float Unk_147400493 { get; set; } //56 56: Float: 0: 147400493
public float Unk_2591582364 { get; set; } //60 60: Float: 0: 2591582364
public float Unk_3889902555 { get; set; } //64 64: Float: 0: 3889902555
public uint objectHash { get; set; } //68 68: UnsignedInt: 0: objectHash//1951307499
public float minScale { get; set; } //44 44: Float: 0: minScale
public float maxScale { get; set; } //48 48: Float: 0: maxScale
public float minScaleZ { get; set; } //52 52: Float: 0: minScaleZ
public float maxScaleZ { get; set; } //56 56: Float: 0: maxScaleZ
public float minZOffset { get; set; } //60 60: Float: 0: minZOffset
public float maxZOffset { get; set; } //64 64: Float: 0: maxZOffset
public uint objectHash { get; set; } //68 68: UnsignedInt: 0: objectHash
public uint flags { get; set; } //72 72: UnsignedInt: 0: flags
public uint Unused4 { get; set; }//76
@ -3963,16 +3987,16 @@ namespace CodeWalker.GameFiles
public uint Unused0 { get; set; }//0
public uint Unused1 { get; set; }//4
public uint Unused2 { get; set; }//8
public int Unk_MinX_860552138 { get; set; } //12 12: SignedInt: 0: 860552138 //MIN X
public int Unk_MaxX_3824598937 { get; set; } //16 16: SignedInt: 0: 3824598937 //MAX X
public int Unk_MinY_496029782 { get; set; } //20 20: SignedInt: 0: 496029782 //MIN Y
public int Unk_MaxY_3374647798 { get; set; } //24 24: SignedInt: 0: 3374647798 //MAX Y
public int MinCellX { get; set; } //12 12: SignedInt: 0: MinCellX //MIN X
public int MaxCellX { get; set; } //16 16: SignedInt: 0: MaxCellX //MAX X
public int MinCellY { get; set; } //20 20: SignedInt: 0: MinCellY //MIN Y
public int MaxCellY { get; set; } //24 24: SignedInt: 0: MaxCellY //MAX Y
public uint Unused3 { get; set; }//28
public uint Unused4 { get; set; }//32
public uint Unused5 { get; set; }//36
public uint Unused6 { get; set; }//40
public float Unk_X_2690909759 { get; set; } //44 44: Float: 0: 2690909759 //grid scale X (cell size)
public float Unk_Y_3691675019 { get; set; } //48 48: Float: 0: 3691675019 //grid scale Y (cell size)
public float CellDimX { get; set; } //44 44: Float: 0: CellDimX //grid scale X (cell size)
public float CellDimY { get; set; } //48 48: Float: 0: CellDimY //grid scale Y (cell size)
public uint Unused7 { get; set; }//52
public uint Unused8 { get; set; }//56
public uint Unused9 { get; set; }//60
@ -3982,50 +4006,50 @@ namespace CodeWalker.GameFiles
{
get
{
return new Vector2I((Unk_MaxX_3824598937 - Unk_MinX_860552138)+1, (Unk_MaxY_3374647798 - Unk_MinY_496029782)+1);
return new Vector2I((MaxCellX - MinCellX)+1, (MaxCellY - MinCellY)+1);
}
}
public Vector2 Scale
{
get
{
return new Vector2(Unk_X_2690909759, Unk_Y_3691675019);
return new Vector2(CellDimX, CellDimY);
}
set
{
Unk_X_2690909759 = value.X;
Unk_Y_3691675019 = value.Y;
CellDimX = value.X;
CellDimY = value.Y;
}
}
public Vector2 Min
{
get
{
return new Vector2(Unk_MinX_860552138, Unk_MinY_496029782) * Scale;
return new Vector2(MinCellX, MinCellY) * Scale;
}
set
{
var gv = value / Scale;
Unk_MinX_860552138 = (int)Math.Floor(gv.X);
Unk_MinY_496029782 = (int)Math.Floor(gv.Y);
MinCellX = (int)Math.Floor(gv.X);
MinCellY = (int)Math.Floor(gv.Y);
}
}
public Vector2 Max
{
get
{
return new Vector2(Unk_MaxX_3824598937, Unk_MaxY_3374647798) * Scale;
return new Vector2(MaxCellX, MaxCellY) * Scale;
}
set
{
var gv = value / Scale;
Unk_MaxX_3824598937 = (int)Math.Floor(gv.X);
Unk_MaxY_3374647798 = (int)Math.Floor(gv.Y);
MaxCellX = (int)Math.Floor(gv.X);
MaxCellY = (int)Math.Floor(gv.Y);
}
}
}
[TC(typeof(EXP))] public struct rage__spdAABB //32 bytes, Key:1158138379 //WAS: Unk_4084721864
[TC(typeof(EXP))] public struct rage__spdAABB //32 bytes, Key:1158138379
{
public Vector4 min { get; set; } //0 0: Float_XYZW: 0: min
public Vector4 max { get; set; } //16 16: Float_XYZW: 0: max
@ -4138,10 +4162,10 @@ namespace CodeWalker.GameFiles
//if (Unk_3844724227 != null)
//{
// var grid = _Data.AccelGrid;
// var minx = grid.Unk_MinX_860552138;
// var maxx = grid.Unk_MaxX_3824598937;
// var miny = grid.Unk_MinY_496029782;
// var maxy = grid.Unk_MaxY_3374647798;
// var minx = grid.MinCellX;
// var maxx = grid.MaxCellX;
// var miny = grid.MinCellY;
// var maxy = grid.MaxCellY;
// var len = Unk_3844724227.Length;
// var calclen = ((maxx - minx) + 1) * ((maxy - miny) + 1);
// if (len != calclen)
@ -4191,14 +4215,14 @@ namespace CodeWalker.GameFiles
{
mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint);
mb.AddEnumInfo((MetaName)3573596290);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
scp.LoadSavePoints = mb.AddItemArrayPtr(MetaName.CExtensionDefSpawnPoint, loadSavePoints);
}
var myPoints = Points.GetCMyPoints();
if (myPoints != null)
{
mb.AddStructureInfo(MetaName.CScenarioPoint);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
scp.MyPoints = mb.AddItemArrayPtr(MetaName.CScenarioPoint, myPoints);
}
@ -4226,7 +4250,7 @@ namespace CodeWalker.GameFiles
{
mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint);
mb.AddEnumInfo((MetaName)3573596290);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
cent.ScenarioPoints = mb.AddItemArrayPtr(MetaName.CExtensionDefSpawnPoint, scps);
}
cents[i] = cent;
@ -4657,7 +4681,7 @@ namespace CodeWalker.GameFiles
public byte Unused6 { get; set; }//31
public ushort iScenarioGroup { get; set; } //32 32: UnsignedShort: 0: iScenarioGroup//2180252673
public ushort Unused7 { get; set; }//34
public Unk_700327466 Flags { get; set; } //36 36: IntFlags2: 700327466: Flags
public CScenarioPointFlags__Flags Flags { get; set; } //36 36: IntFlags2: 700327466: Flags
public uint Unused8 { get; set; }//40
public uint Unused9 { get; set; }//44
public Vector4 vPositionAndDirection { get; set; } //48 48: Float_XYZW: 0: vPositionAndDirection//4685037
@ -4711,7 +4735,7 @@ namespace CodeWalker.GameFiles
public byte AvailableMpSp { get { return _Data.uAvailableInMpSp; } set { _Data.uAvailableInMpSp = value; } }
public byte Radius { get { return _Data.iRadius; } set { _Data.iRadius = value; } }
public byte WaitTime { get { return _Data.iTimeTillPedLeaves; } set { _Data.iTimeTillPedLeaves = value; } }
public Unk_700327466 Flags { get { return _Data.Flags; } set { _Data.Flags = value; } }
public CScenarioPointFlags__Flags Flags { get { return _Data.Flags; } set { _Data.Flags = value; } }
public int PointIndex { get; set; }
@ -4862,7 +4886,7 @@ namespace CodeWalker.GameFiles
{
mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint);
mb.AddEnumInfo((MetaName)3573596290);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
_Data.ScenarioPoints = mb.AddWrapperArray(ScenarioPoints);
}
@ -5621,14 +5645,14 @@ namespace CodeWalker.GameFiles
{
mb.AddStructureInfo(MetaName.CExtensionDefSpawnPoint);
mb.AddEnumInfo((MetaName)3573596290);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
scp.LoadSavePoints = mb.AddItemArrayPtr(MetaName.CExtensionDefSpawnPoint, loadSavePoints);
}
var myPoints = Points.GetCMyPoints();
if (myPoints != null)
{
mb.AddStructureInfo(MetaName.CScenarioPoint);
mb.AddEnumInfo((MetaName)700327466);
mb.AddEnumInfo(MetaName.CScenarioPointFlags__Flags);
scp.MyPoints = mb.AddItemArrayPtr(MetaName.CScenarioPoint, myPoints);
}
@ -5784,7 +5808,7 @@ namespace CodeWalker.GameFiles
}
}
[TC(typeof(EXP))] public struct Unk_1980345114 //216 bytes, Key:4110496011 //destruction animations?
[TC(typeof(EXP))] public struct CCompEntityAnims //216 bytes, Key:4110496011 //destruction animations?
{
public ArrayOfChars64 AnimDict { get; set; } //0 0: ArrayOfChars: 64: AnimDict
public ArrayOfChars64 AnimName { get; set; } //64 64: ArrayOfChars: 64: AnimName
@ -5794,7 +5818,7 @@ namespace CodeWalker.GameFiles
public Array_Structure effectsData { get; set; } //200 200: Array: 0: effectsData {0: Structure: 3430328684: 256}
}
[TC(typeof(EXP))] public struct Unk_3430328684 //160 bytes, Key:1724963966 //destruction animation effects data
[TC(typeof(EXP))] public struct CCompEntityEffectsData //160 bytes, Key:1724963966 //destruction animation effects data
{
public uint fxType { get; set; } //0 0: UnsignedInt: 0: fxType
public uint Unused0 { get; set; }//4
@ -5944,7 +5968,7 @@ namespace CodeWalker.GameFiles
public struct Unk_376833625 //112 bytes, Key:4030871161 //COMPONENT PEDS YMT ROOT - in componentpeds .rpf's
public struct CPedVariationInfo //112 bytes, Key:4030871161 //COMPONENT PEDS YMT ROOT - in componentpeds .rpf's
{
public byte Unk_1235281004 { get; set; } //0 0: Boolean: 0: 1235281004
public byte Unk_4086467184 { get; set; } //1 1: Boolean: 0: 4086467184
@ -5952,9 +5976,9 @@ namespace CodeWalker.GameFiles
public byte Unk_315291935 { get; set; } //3 3: Boolean: 0: 315291935
public ArrayOfBytes12 Unk_2996560424 { get; set; } //4 4: ArrayOfBytes: 12: 2996560424
public Array_Structure Unk_3796409423 { get; set; } //16 16: Array: 0: 3796409423 {0: Structure: 3538495220: 256}
public Array_Structure Unk_2131007641 { get; set; } //32 32: Array: 0: 2131007641 {0: Structure: 253191135: 256}
public Array_Structure aSelectionSets { get; set; } //32 32: Array: 0: aSelectionSets {0: Structure: 253191135: 256}
public Array_Structure compInfos { get; set; } //48 48: Array: 0: compInfos//592652859 {0: Structure: CComponentInfo//1866571721: 256}
public Unk_2858946626 propInfo { get; set; } //64 64: Structure: 2858946626: propInfo//2240851416
public CPedPropInfo propInfo { get; set; } //64 64: Structure: 2858946626: propInfo//2240851416
public MetaHash dlcName { get; set; } //104 104: Hash: 0: dlcName
public uint Unused0 { get; set; }//108
}
@ -5997,7 +6021,7 @@ namespace CodeWalker.GameFiles
public uint Unused6 { get; set; }//20
}
public struct Unk_253191135 //48 bytes, Key:3120284999 //COMPONENT PEDS unknown
public struct CPedSelectionSet //48 bytes, Key:3120284999 //COMPONENT PEDS unknown
{
public MetaHash name { get; set; } //0 0: Hash: 0: name
public ArrayOfBytes12 Unk_173599222 { get; set; } //4 4: ArrayOfBytes: 12: 173599222
@ -6028,7 +6052,7 @@ namespace CodeWalker.GameFiles
public ushort Unused5 { get; set; }//46
}
public struct Unk_2858946626 //40 bytes, Key:1792487819 //COMPONENT PEDS unknown
public struct CPedPropInfo //40 bytes, Key:1792487819 //COMPONENT PEDS unknown
{
public byte Unk_2598445407 { get; set; } //0 0: UnsignedByte: 0: 2598445407
public byte Unused0 { get; set; }//1
@ -6038,7 +6062,7 @@ namespace CodeWalker.GameFiles
public Array_Structure aAnchors { get; set; } //24 24: Array: 0: aAnchors//162345210 {0: Structure: CAnchorProps//2170383875: 256}
}
public struct Unk_94549140 //56 bytes, Key:2029738350 //COMPONENT PEDS unknown
public struct CPedPropMetaData //56 bytes, Key:2029738350 //COMPONENT PEDS unknown
{
public MetaHash audioId { get; set; } //0 0: Hash: 0: audioId
public ArrayOfBytes5 expressionMods { get; set; } //4 4: ArrayOfBytes: 5: expressionMods//942761829

View File

@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace CodeWalker.GameFiles
{
@ -45,6 +46,11 @@ namespace CodeWalker.GameFiles
CutFile cut = RpfFile.GetFile<CutFile>(e, data);
return GetXml(cut, out filename);
}
else if (fnl.EndsWith(".rel"))
{
RelFile rel = RpfFile.GetFile<RelFile>(e, data);
return GetXml(rel, out filename);
}
filename = fn;
return string.Empty;
}
@ -98,6 +104,12 @@ namespace CodeWalker.GameFiles
filename = string.Empty;
return string.Empty;
}
public static string GetXml(RelFile rel, out string filename)
{
var fn = (rel?.RpfFileEntry?.Name) ?? "";
filename = fn + ".xml";
return RelXml.GetXml(rel);
}
@ -222,10 +234,10 @@ namespace CodeWalker.GameFiles
OneLineTag(sb, cind, ename, charStr);
break;
case MetaStructureEntryDataType.DataBlockPointer:
OpenTag(sb, cind, ename);
var dataPtr = MetaTypes.ConvertData<DataBlockPointer>(data, eoffset);
ErrorXml(sb, cind + 1, "DataBlockPointer not currently supported here!"); //TODO! ymap occludeModels vertices data is this type!
CloseTag(sb, cind, ename);
//need to just get all the data from that block, since this pointer is referring to the whole block! it should be of type BYTE!
var dblock = cont.Meta.GetBlock((int)dataPtr.PointerDataId);
WriteRawArray(sb, dblock.Data, cind, ename, "ByteArray", FormatHexByte, 32);
break;
case MetaStructureEntryDataType.Float:
var floatVal = BitConverter.ToSingle(data, eoffset);
@ -565,14 +577,14 @@ namespace CodeWalker.GameFiles
{
Meta = meta;
if (meta.StructureInfos != null)
if (meta.StructureInfos?.Data != null)
{
foreach (var si in meta.StructureInfos)
{
structInfos[si.StructureNameHash] = si;
}
}
if (meta.EnumInfos != null)
if (meta.EnumInfos?.Data != null)
{
foreach (var ei in meta.EnumInfos)
{
@ -640,6 +652,10 @@ namespace CodeWalker.GameFiles
var structInfo = cont.GetStructureInfo(structName);
if (structInfo == null)
{
structInfo = PsoTypes.GetStructureInfo(structName);//fallback to builtin...
}
if (structInfo == null)
{
ErrorXml(sb, indent, "Couldn't find structure info " + name + "!");
return;
@ -708,7 +724,10 @@ namespace CodeWalker.GameFiles
case 0: //int enum
var intEVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
var intE = enumInfo.FindEntry(intEVal);
StringTag(sb, cind, ename, HashString(intE?.EntryNameHash ?? 0));
var intH = HashString(intE?.EntryNameHash ?? 0);
if (string.IsNullOrEmpty(intH))
{ }
StringTag(sb, cind, ename, intH);
break;
case 2: //byte enum
var byteEVal = data[eoffset];
@ -718,9 +737,9 @@ namespace CodeWalker.GameFiles
}
break;
case PsoDataType.Flags:
uint fCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
uint fEntry = (entry.ReferenceKey & 0xFFFF);
var fEnt = structInfo.GetEntry((int)fEntry);
//uint fCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
uint fEntry = (entry.ReferenceKey & 0xFFF);
var fEnt = (fEntry != 0xFFF) ? structInfo.GetEntry((int)fEntry) : null;
PsoEnumInfo flagsInfo = null;
if ((fEnt != null) && (fEnt.EntryNameHash == MetaName.ARRAYINFO))
{
@ -728,7 +747,9 @@ namespace CodeWalker.GameFiles
}
if (flagsInfo == null)
{
flagsInfo = cont.GetEnumInfo(entry.EntryNameHash);
if (fEntry != 0xFFF)
{ }
//flagsInfo = cont.GetEnumInfo(entry.EntryNameHash);
}
uint? flagsVal = null;
switch (entry.Unk_5h)
@ -805,12 +826,13 @@ namespace CodeWalker.GameFiles
default:
ErrorXml(sb, cind, ename + ": Unexpected Integer subtype: " + entry.Unk_5h.ToString());
break;
case 0: //signed int
case 0: //signed int (? flags?)
var int6aVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
ValueTag(sb, cind, ename, int6aVal.ToString());
break;
case 1: //unsigned int
var int6bVal = MetaTypes.SwapBytes(BitConverter.ToUInt32(data, eoffset));
//ValueTag(sb, cind, ename, int6bVal.ToString());
ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0'));
break;
}
@ -833,16 +855,16 @@ namespace CodeWalker.GameFiles
ValueTag(sb, cind, ename, short4Val.ToString());
break;
case PsoDataType.HFloat://half float?
var short1EVal = MetaTypes.SwapBytes(BitConverter.ToUInt16(data, eoffset));
var short1EVal = MetaTypes.SwapBytes(BitConverter.ToInt16(data, eoffset));
ValueTag(sb, cind, ename, short1EVal.ToString());
break;
case PsoDataType.String:
var str0 = GetStringValue(cont.Pso, entry, data, eoffset);
if (str0 == null)
{
ErrorXml(sb, cind, ename + ": Unexpected String subtype: " + entry.Unk_5h.ToString());
}
else
var str0 = XmlEscape(GetStringValue(cont.Pso, entry, data, eoffset));
//if (str0 == null)
//{
// ErrorXml(sb, cind, ename + ": Unexpected String subtype: " + entry.Unk_5h.ToString());
//}
//else
{
StringTag(sb, cind, ename, str0);
}
@ -874,7 +896,10 @@ namespace CodeWalker.GameFiles
}
if (pbok)
{
var typename = HashString(cont.Pso.GetBlock(pbid).NameHash);
OpenTag(sb, cind, ename + " type=\"" + typename + "\"");
WriteNode(sb, cind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey);
CloseTag(sb, cind, ename);
}
else
{
@ -909,8 +934,13 @@ namespace CodeWalker.GameFiles
var boffset = offset + block.Offset;
var eoffset = boffset + entry.DataOffset;
var aOffset = offset + entry.DataOffset;
var abOffset = aOffset + block.Offset;
var aBlockId = blockId;
uint aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
Array_Structure arrStruc = new Array_Structure();
arrStruc.PointerDataId = (uint)aBlockId;
arrStruc.PointerDataOffset = (uint)aOffset;
arrStruc.Count1 = arrStruc.Count2 = (ushort)aCount;
var aind = indent + 1;
string arrTag = ename;
PsoStructureEntryInfo arrEntry = estruct.GetEntry((int)(entry.ReferenceKey & 0xFFFF));
@ -922,17 +952,24 @@ namespace CodeWalker.GameFiles
var data = cont.Pso.DataSection.Data;
bool embedded = true;
switch (entry.Unk_5h)
{
default:
ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString());
break;
case 0: //Array_Structure
var arrStruc = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
arrStruc = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
arrStruc.SwapEnd();
aBlockId = (int)arrStruc.PointerDataId;
aOffset = (int)arrStruc.PointerDataOffset;
aCount = arrStruc.Count1;
var aBlock = cont.Pso.GetBlock(aBlockId);
if (aBlock != null)
{
abOffset = aOffset + aBlock.Offset;
}
embedded = false;
break;
case 1: //Raw in-line array
break;
@ -941,11 +978,20 @@ namespace CodeWalker.GameFiles
case 4: //pointer array? default array?
if (arrEntry.Unk_5h == 3) //pointers...
{
var arrStruc4 = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
arrStruc4.SwapEnd();
aBlockId = (int)arrStruc4.PointerDataId;
aOffset = (int)arrStruc4.PointerDataOffset;
aCount = arrStruc4.Count1;
arrStruc = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
arrStruc.SwapEnd();
aBlockId = (int)arrStruc.PointerDataId;
aOffset = (int)arrStruc.PointerDataOffset;
aCount = arrStruc.Count1;
var aBlock2 = cont.Pso.GetBlock(aBlockId);
if (aBlock2 != null)
{
abOffset = aOffset + aBlock2.Offset;
}
embedded = false;
}
else
{
}
break;
case 129: //also raw inline array? in junctions.pso
@ -959,10 +1005,11 @@ namespace CodeWalker.GameFiles
break;
case PsoDataType.Array:
var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF;
//var rk1 = entry.ReferenceKey & 0x0000FFFF;
//var rk3 = (arrEntry.ReferenceKey >> 16) & 0x0000FFFF;
//var rk4 = arrEntry.ReferenceKey & 0x0000FFFF;
if (rk0 > 0)
{
//var arrStruc5 = MetaTypes.ConvertDataArray<Array_StructurePointer>(data, eoffset, (int)rk0);
//for (int n = 0; n < rk0; n++) arrStruc5[n].SwapEnd();
aOffset = offset + entry.DataOffset;
OpenTag(sb, indent, arrTag);
@ -997,7 +1044,14 @@ namespace CodeWalker.GameFiles
for (int n = 0; n < aCount; n++)
{
var ptrVal = ptrArr[n];
WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType);
if (ptrVal.Pointer == 0)
{
SelfClosingTag(sb, aind, "Item"); //"null" entry...
}
else
{
WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType);
}
}
CloseTag(sb, indent, ename);
}
@ -1050,6 +1104,8 @@ namespace CodeWalker.GameFiles
ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString());
break;
case 0: //hash array...
if (embedded)
{ }
var arrHash = MetaTypes.ConvertData<Array_uint>(data, eoffset);
arrHash.SwapEnd();
var hashArr = PsoTypes.GetHashArray(cont.Pso, arrHash);
@ -1064,54 +1120,70 @@ namespace CodeWalker.GameFiles
WriteRawArray(sb, v2Arr, indent, ename, "Vector2", FormatVector2Swap, 1);
break;
case PsoDataType.Float3:
aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
if (!embedded)
{ }
arrTag += " itemType=\"Vector3\""; //this is actually aligned as vector4, the W values are crazy in places
var v4Arr = MetaTypes.ConvertDataArray<Vector4>(data, eoffset, (int)aCount);
WriteRawArray(sb, v4Arr, indent, ename, "Vector3", FormatVector4SwapXYZOnly, 1);
break;
case PsoDataType.UByte:
if (embedded)
{ }
else
{ } //block type 2
var barr = new byte[aCount];
if (aCount > 0)
{
var bblock = cont.Pso.GetBlock(aBlockId);
var boffs = bblock.Offset + aOffset;
Buffer.BlockCopy(data, boffs, barr, 0, (int)aCount);
//var bblock = cont.Pso.GetBlock(aBlockId);
//var boffs = bblock.Offset + aOffset;
Buffer.BlockCopy(data, abOffset /*boffs*/, barr, 0, (int)aCount);
}
WriteRawArray(sb, barr, indent, ename, "byte");
break;
case PsoDataType.Bool:
if (embedded)
{ }
else
{ }
var barr2 = new byte[aCount];
if (aCount > 0)
{
var bblock = cont.Pso.GetBlock(aBlockId);
var boffs = bblock.Offset + aOffset;
Buffer.BlockCopy(data, boffs, barr2, 0, (int)aCount);
//var bblock = cont.Pso.GetBlock(aBlockId);
//var boffs = bblock.Offset + aOffset;
Buffer.BlockCopy(data, abOffset /*boffs*/, barr2, 0, (int)aCount);
}
WriteRawArray(sb, barr2, indent, ename, "boolean"); //todo: true/false output
break;
case PsoDataType.Float:
var arrFloat = MetaTypes.ConvertData<Array_float>(data, eoffset);
arrFloat.SwapEnd();
if (embedded)
{ }
var arrFloat = new Array_float(arrStruc.Pointer, arrStruc.Count1); //block type 7
var floatArr = PsoTypes.GetFloatArray(cont.Pso, arrFloat);
WriteRawArray(sb, floatArr, indent, ename, "float");
break;
case PsoDataType.UShort:
var arrShort = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
arrShort.SwapEnd();
var shortArr = PsoTypes.GetUShortArray(cont.Pso, arrShort);
if (embedded)
{ }
var shortArr = PsoTypes.GetUShortArray(cont.Pso, arrStruc); //block type 4
WriteRawArray(sb, shortArr, indent, ename, "ushort");
break;
case PsoDataType.UInt:
var intArr = MetaTypes.ConvertDataArray<int>(data, eoffset, (int)aCount);
if (embedded)
{ }
var arrUint = new Array_uint(arrStruc.Pointer, arrStruc.Count1); //block type 6
var intArr = PsoTypes.GetUintArray(cont.Pso, arrUint);
WriteRawArray(sb, intArr, indent, ename, "int");
break;
case PsoDataType.SInt:
var arrUint2 = MetaTypes.ConvertData<Array_uint>(data, eoffset);
arrUint2.SwapEnd();
if (embedded)
{ }
var arrUint2 = new Array_uint(arrStruc.Pointer, arrStruc.Count1); //block type 5
var intArr2 = PsoTypes.GetUintArray(cont.Pso, arrUint2);
WriteRawArray(sb, intArr2, indent, ename, "int");
break;
case PsoDataType.Enum:
if (embedded)
{ }
var arrEnum = MetaTypes.ConvertData<Array_uint>(data, eoffset);
arrEnum.SwapEnd();
var enumArr = PsoTypes.GetUintArray(cont.Pso, arrEnum);
@ -1139,41 +1211,23 @@ namespace CodeWalker.GameFiles
var mapidx2 = (entry.ReferenceKey >> 16) & 0x0000FFFF;
var mapreftype1 = structInfo.Entries[mapidx2];
var mapreftype2 = structInfo.Entries[mapidx1];
var x1 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));//same as ref key?
var x2 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 4));//0?
var x3 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 8));//pointer?
var x4 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 12));//
var x5 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 16));//count/capacity?
var x6 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 20));//
var x1 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
var x2 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 4));
var sptr = MetaTypes.ConvertData<Array_Structure>(data, eoffset + 8);
sptr.SwapEnd();
//File.WriteAllText("C:\\CodeWalker.Projects\\testxml.xml", sb.ToString());
if (x1 != 0x1000000)
{ }
if (x2 != 0)
{ }
if (x4 != 0)
{ }
if (x6 != 0)
if (mapreftype2.ReferenceKey != 0)
{ }
var xBlockId = x3 & 0xFFF;
var xOffset = (x3 >> 12) & 0xFFFFF;
var xCount1 = x5 & 0xFFFF;
var xCount2 = (x5 >> 16) & 0xFFFF;
//var x1a = x1 & 0xFFF; //block id? for another pointer?
//var x1b = (x1 >> 12) & 0xFFFFF; //offset?
//var x4u = (uint)x4;
//var x4a = x4 & 0xFFF; //block id?
//var x4b = (x4 >> 12) & 0xFFFFF; //offset?
//var x2h = (MetaHash)(uint)x2;
//var x6h = (MetaHash)(uint)x6;
//if (x1a > 0)
//{ }
var xBlockId = (int)sptr.PointerDataId;// x3 & 0xFFF;
var xOffset = sptr.PointerDataOffset;// (x3 >> 12) & 0xFFFFF;
var xCount1 = sptr.Count1;// x5 & 0xFFFF;
var xCount2 = sptr.Count2;// (x5 >> 16) & 0xFFFF;
var xBlock = cont.Pso.GetBlock(xBlockId);
if ((xBlock == null) && (xCount1 > 0))
@ -1183,8 +1237,7 @@ namespace CodeWalker.GameFiles
else
{
if (xCount1 != xCount2)
{
}
{ }
if (xCount1 > 0)
{
var xStruct = cont.GetStructureInfo(xBlock.NameHash);
@ -1218,10 +1271,10 @@ namespace CodeWalker.GameFiles
{
ErrorXml(sb, aind, ename + ": Map Item was not a structure!");
}
else if (iEntry.Unk_5h != 3)
{
ErrorXml(sb, aind, ename + ": Map Item was not a structure pointer - TODO!");
}
//else if (iEntry.Unk_5h != 3)
//{
// ErrorXml(sb, aind, ename + ": Map Item was not a structure pointer - TODO!");
//}
else
{
OpenTag(sb, xind, ename);
@ -1236,30 +1289,39 @@ namespace CodeWalker.GameFiles
var kOffset = sOffset + kEntry.DataOffset;
var iOffset = sOffset + iEntry.DataOffset;
var kStr = GetStringValue(cont.Pso, kEntry, data, kOffset);
var iPtr = MetaTypes.ConvertData<PsoPOINTER>(data, iOffset);
iPtr.SwapEnd();
var iBlock = cont.Pso.GetBlock(iPtr.BlockID);
if (iBlock == null)
if (iEntry.ReferenceKey != 0)//(xBlock.NameHash != MetaName.ARRAYINFO)//257,258,259
{
OpenTag(sb, aind, "Item type=\"" + HashString((MetaName)entry.ReferenceKey) + "\" key=\"" + kStr + "\"");
WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey);
//embedded map values
var vOffset = xOffset2 + iEntry.DataOffset;
OpenTag(sb, aind, "Item type=\"" + HashString((MetaName)iEntry.ReferenceKey) + "\" key=\"" + kStr + "\"");
WriteNode(sb, aind, cont, xBlockId, vOffset, XmlTagMode.None, (MetaName)iEntry.ReferenceKey);
CloseTag(sb, aind, "Item");
}
else
{
var iStr = "Item type=\"" + HashString(iBlock.NameHash) + "\" key=\"" + kStr + "\"";
var iStruc = cont.GetStructureInfo(iBlock.NameHash);
if (iStruc?.EntriesCount == 0)
var iPtr = MetaTypes.ConvertData<PsoPOINTER>(data, iOffset);
iPtr.SwapEnd();
var iBlock = cont.Pso.GetBlock(iPtr.BlockID);
if (iBlock == null)
{
//SelfClosingTag(sb, aind, iStr);
OpenTag(sb, aind, iStr);
CloseTag(sb, aind, "Item");
ErrorXml(sb, aind, ename + ": Could not find iBlock for Map entry!");
}
else
{
OpenTag(sb, aind, iStr);
WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None);//, (MetaName)entry.ReferenceKey);
CloseTag(sb, aind, "Item");
var iStr = "Item type=\"" + HashString(iBlock.NameHash) + "\" key=\"" + kStr + "\"";
var iStruc = cont.GetStructureInfo(iBlock.NameHash);
if (iStruc?.EntriesCount == 0)
{
//SelfClosingTag(sb, aind, iStr);
OpenTag(sb, aind, iStr);
CloseTag(sb, aind, "Item");
}
else
{
OpenTag(sb, aind, iStr);
WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None);//, (MetaName)entry.ReferenceKey);
CloseTag(sb, aind, "Item");
}
}
}
xOffset2 += xStruct.StructureLength;
@ -1311,7 +1373,17 @@ namespace CodeWalker.GameFiles
}
public static string XmlEscape(string unescaped)
{
if (unescaped == null) return null;
XmlDocument doc = new XmlDocument();
XmlNode node = doc.CreateElement("root");
node.InnerText = unescaped;
var escaped = node.InnerXml;
if (escaped != unescaped)
{ }
return node.InnerXml;
}
public class PsoCont
@ -1620,7 +1692,6 @@ namespace CodeWalker.GameFiles
SelfClosingTag(sb, ind, arrTag);
}
}
public static void WriteItemArray<T>(StringBuilder sb, T[] arr, int ind, string name, string typeName, Func<T, string> formatter) where T : struct
{
var aCount = arr?.Length ?? 0;
@ -1643,10 +1714,55 @@ namespace CodeWalker.GameFiles
SelfClosingTag(sb, ind, arrTag);
}
}
public static void WriteItemArray<T>(StringBuilder sb, T[] arr, int ind, string name) where T : IMetaXmlItem
{
var itemCount = arr?.Length ?? 0;
if (itemCount > 0)
{
OpenTag(sb, ind, name);
var cind = ind + 1;
var cind2 = ind + 2;
for (int i = 0; i < itemCount; i++)
{
OpenTag(sb, cind, "Item");
arr[i].WriteXml(sb, cind2);
CloseTag(sb, cind, "Item");
}
CloseTag(sb, ind, name);
}
else
{
SelfClosingTag(sb, ind, name);
}
}
public static void WriteHashItemArray(StringBuilder sb, MetaHash[] arr, int ind, string name)
{
var itemCount = arr?.Length ?? 0;
if (itemCount > 0)
{
OpenTag(sb, ind, name);
var cind = ind + 1;
for (int i = 0; i < itemCount; i++)
{
var iname = HashString(arr[i]);
StringTag(sb, cind, "Item", iname);
}
CloseTag(sb, ind, name);
}
else
{
SelfClosingTag(sb, ind, name);
}
}
public static string FormatHash(MetaHash h) //for use with WriteItemArray
{
return h.ToString();
var str = JenkIndex.TryGetString(h);
if (!string.IsNullOrEmpty(str)) return str;
str = GlobalText.TryGetString(h);
if (!string.IsNullOrEmpty(str)) return str;
return HashString(h);// "hash_" + h.Hex;
//return h.ToString();
}
public static string FormatVector2(Vector2 v) //for use with WriteItemArray
{
@ -1660,6 +1776,10 @@ namespace CodeWalker.GameFiles
{
return FloatUtil.GetVector4String(v);
}
public static string FormatHexByte(byte b)
{
return Convert.ToString(b, 16).ToUpperInvariant().PadLeft(2, '0'); //hex byte array
}
public static string FormatHashSwap(MetaHash h) //for use with WriteItemArray, swaps endianness
{
@ -1757,5 +1877,22 @@ namespace CodeWalker.GameFiles
}
}
public interface IMetaXmlItem
{
void WriteXml(StringBuilder sb, int indent);
void ReadXml(XmlNode node);
}
public enum MetaFormat
{
XML = 0,
RSC = 1,
PSO = 2,
RBF = 3,
CacheFile = 4,
AudioRel = 5,
}
}

View File

@ -23,6 +23,95 @@
//shamelessly stolen and mangled
/*
Regarding saving PSO files:
[for checksum - use whole file]
Brick - Today
uint32_t joaat_checksum(const void* memory, const size_t length)
{
uint32_t hash = 0x3FAC7125;
for (size_t i = 0; i < length; ++i)
{
hash += static_cast<const int8_t*>(memory)[i];
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
[before doing checksum for file:]
v12->Checksum = 0;
v12->FileSize = 0;
v12->Magic = 'SKHC';
v12->Size = 0x14000000;
v22 = v12;
LOBYTE(v12->Platform) = platformChar[0];
Brick - Today
This is a table i made a while ago for the pso types btw
| Index | Type | Size | Align | Name | Serialization
| 0 | Simple | 1 | 1 | bool |
| 1 | Simple | 1 | 1 | s8 |
| 2 | Simple | 1 | 1 | u8 |
| 3 | Simple | 2 | 2 | s16 |
| 4 | Simple | 2 | 2 | u16 |
| 5 | Simple | 4 | 4 | s32 |
| 6 | Simple | 4 | 4 | u32 |
| 7 | Simple | 4 | 4 | f32 |
| 8 | Vector | 8 | 4 | vec2 |
| 9 | Vector | 16 | 16 | vec3 |
| 10 | Vector | 16 | 16 | vec4 |
| 11 | String | 0 | 0 | string |
| 12 | Struct | 0 | 0 | struct |
| 13 | Array | 0 | 0 | array |
| 14 | Enum | 0 | 0 | enum |
| 15 | Bitset | 0 | 0 | bitset |
| 16 | Map | 0 | 0 | map |
| 17 | Matrix | 64 | 16 | matrix43 | shuffled
| 18 | Matrix | 64 | 16 | matrix44 | shuffled
| 19 | Vector | 16 | 16 | vec4 | x, y, x, x
| 20 | Vector | 16 | 16 | vec4 | x, y, z, x
| 21 | Vector | 16 | 16 | vec4 | x, y, z, w
| 22 | Matrix | 48 | 16 | matrix34 |
| 23 | Matrix | 64 | 16 | matrix43 |
| 24 | Matrix | 64 | 16 | matrix44 |
| 25 | Simple | 16 | 16 | f32_vec4 | fill all with f32
| 26 | Simple | 16 | 16 | bool_int4 | fill all with 0x00000000 or 0xFFFFFFFF depending on bool
| 27 | Vector | 16 | 16 | bool4_int4 | fill each with 0x00000000 or 0xFFFFFFFF depending on bools
| 28 | Simple | 8 | 8 | s32_i64 | sign extended s32
| 29 | Simple | 8 | 8 | s32_u64 | sign extended s32
| 30 | Simple | 2 | 2 | f16 | f64 converted to f16
| 31 | Simple | 8 | 8 | s64 |
| 32 | Simple | 8 | 8 | u64 |
| 33 | Simple | 8 | 8 | f64 |
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -116,6 +205,13 @@ namespace CodeWalker.GameFiles
public PsoSTRESection STRESection { get; set; }
public PsoCHKSSection CHKSSection { get; set; }
public void Load(byte[] data)
{
using (var ms = new MemoryStream(data))
Load(ms);
}
public void Load(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Open))
@ -179,6 +275,19 @@ namespace CodeWalker.GameFiles
}
}
public byte[] Save()
{
var ms = new MemoryStream();
Save(ms);
var buf = new byte[ms.Length];
ms.Position = 0;
ms.Read(buf, 0, buf.Length);
return buf;
}
public void Save(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Create))
@ -191,6 +300,11 @@ namespace CodeWalker.GameFiles
if (DataSection != null) DataSection.Write(writer);
if (DataMapSection != null) DataMapSection.Write(writer);
if (SchemaSection != null) SchemaSection.Write(writer);
if (STRFSection != null) STRFSection.Write(writer);
if (STRSSection != null) STRSSection.Write(writer);
if (STRESection != null) STRESection.Write(writer);
if (PSIGSection != null) PSIGSection.Write(writer);
if (CHKSSection != null) CHKSSection.Write(writer);
}
@ -253,11 +367,13 @@ namespace CodeWalker.GameFiles
public void Write(DataWriter writer)
{
Length = Data.Length;
writer.Write(Data);
writer.Position -= Data.Length;
writer.Write((uint)0x5053494E);
writer.Write((uint)(Data.Length));
writer.Position += Data.Length - 8;
writer.Position -= Length;
writer.Write(Ident);
writer.Write((uint)(Length));
writer.Position += Length - 8;
}
public override string ToString()
@ -324,10 +440,10 @@ namespace CodeWalker.GameFiles
public void Read(DataReader reader)
{
this.NameHash = (MetaName)reader.ReadUInt32();
this.Offset = reader.ReadInt32();
this.Unknown_8h = reader.ReadInt32();
this.Length = reader.ReadInt32();
NameHash = (MetaName)reader.ReadUInt32();
Offset = reader.ReadInt32();
Unknown_8h = reader.ReadInt32();
Length = reader.ReadInt32();
}
public void Write(DataWriter writer)
@ -360,7 +476,7 @@ namespace CodeWalker.GameFiles
Length = reader.ReadInt32();
Count = reader.ReadUInt32();
this.EntriesIdx = new PsoElementIndexInfo[Count];
EntriesIdx = new PsoElementIndexInfo[Count];
for (int i = 0; i < Count; i++)
{
var entry = new PsoElementIndexInfo();
@ -368,7 +484,7 @@ namespace CodeWalker.GameFiles
EntriesIdx[i] = entry;
}
this.Entries = new PsoElementInfo[Count];
Entries = new PsoElementInfo[Count];
for (int i = 0; i < Count; i++)
{
reader.Position = EntriesIdx[i].Offset;
@ -417,7 +533,7 @@ namespace CodeWalker.GameFiles
writer.Write(Ident);
writer.Write((int)(12 + entriesStream.Length + indexStream.Length));
writer.Write((int)(Entries.Length));
writer.Write((uint)(Entries.Length));
// write entries index data
var buf1 = new byte[indexStream.Length];
@ -447,8 +563,8 @@ namespace CodeWalker.GameFiles
public void Read(DataReader reader)
{
this.NameHash = (MetaName)reader.ReadUInt32();
this.Offset = reader.ReadInt32();
NameHash = (MetaName)reader.ReadUInt32();
Offset = reader.ReadInt32();
}
public void Write(DataWriter writer)
@ -481,14 +597,34 @@ namespace CodeWalker.GameFiles
public uint Unk_Ch { get; set; } = 0x00000000;
public PsoStructureEntryInfo[] Entries { get; set; }
public PsoStructureInfo()
{ }
public PsoStructureInfo(MetaName nameHash, byte type, byte unk, int length, params PsoStructureEntryInfo[] entries)
{
IndexInfo = new PsoElementIndexInfo();
IndexInfo.NameHash = nameHash;
IndexInfo.Offset = 0; //todo: fix?
Type = type;
EntriesCount = (short)(entries?.Length ?? 0);
Unk = unk;
StructureLength = length;
Unk_Ch = 0;
Entries = entries;
}
public override void Read(DataReader reader)
{
uint x = reader.ReadUInt32();
this.Type = (byte)((x & 0xFF000000) >> 24);
this.EntriesCount = (short)(x & 0xFFFF);
this.Unk = (byte)((x & 0x00FF0000) >> 16);
this.StructureLength = reader.ReadInt32();
this.Unk_Ch = reader.ReadUInt32();
Type = (byte)((x & 0xFF000000) >> 24);
EntriesCount = (short)(x & 0xFFFF);
Unk = (byte)((x & 0x00FF0000) >> 16);
StructureLength = reader.ReadInt32();
Unk_Ch = reader.ReadUInt32();
if (Unk_Ch != 0)
{ }
Entries = new PsoStructureEntryInfo[EntriesCount];
for (int i = 0; i < EntriesCount; i++)
@ -546,17 +682,29 @@ namespace CodeWalker.GameFiles
{
public MetaName EntryNameHash { get; set; }
public PsoDataType Type { get; set; }
public byte Unk_5h { get; set; }
public byte Unk_5h { get; set; } //0 = default, 3 = pointer array?
public ushort DataOffset { get; set; }
public uint ReferenceKey { get; set; } // when array -> entry index with type
public PsoStructureEntryInfo()
{ }
public PsoStructureEntryInfo(MetaName nameHash, PsoDataType type, ushort offset, byte unk, MetaName refKey)
{
EntryNameHash = nameHash;
Type = type;
Unk_5h = unk;
DataOffset = offset;
ReferenceKey = (uint)refKey;
}
public void Read(DataReader reader)
{
this.EntryNameHash = (MetaName)reader.ReadUInt32();
this.Type = (PsoDataType)reader.ReadByte();
this.Unk_5h = reader.ReadByte();
this.DataOffset = reader.ReadUInt16();
this.ReferenceKey = reader.ReadUInt32();
EntryNameHash = (MetaName)reader.ReadUInt32();
Type = (PsoDataType)reader.ReadByte();
Unk_5h = reader.ReadByte();
DataOffset = reader.ReadUInt16();
ReferenceKey = reader.ReadUInt32();
}
public void Write(DataWriter writer)
@ -584,11 +732,24 @@ namespace CodeWalker.GameFiles
public int EntriesCount { get; private set; }
public PsoEnumEntryInfo[] Entries { get; set; }
public PsoEnumInfo()
{ }
public PsoEnumInfo(MetaName nameHash, byte type, params PsoEnumEntryInfo[] entries)
{
IndexInfo = new PsoElementIndexInfo();
IndexInfo.NameHash = nameHash;
IndexInfo.Offset = 0; //todo: fix?
EntriesCount = entries?.Length ?? 0;
Entries = entries;
}
public override void Read(DataReader reader)
{
uint x = reader.ReadUInt32();
this.Type = (byte)((x & 0xFF000000) >> 24);
this.EntriesCount = (int)(x & 0x00FFFFFF);
Type = (byte)((x & 0xFF000000) >> 24);
EntriesCount = (int)(x & 0x00FFFFFF);
Entries = new PsoEnumEntryInfo[EntriesCount];
for (int i = 0; i < EntriesCount; i++)
@ -628,6 +789,21 @@ namespace CodeWalker.GameFiles
return null;
}
public PsoEnumEntryInfo FindEntryByName(MetaName name)
{
if (Entries == null) return null;
for (int i = 0; i < Entries.Length; i++)
{
var entry = Entries[i];
if (entry.EntryNameHash == name)
{
return entry;
}
}
return null;
}
public override string ToString()
{
@ -640,10 +816,19 @@ namespace CodeWalker.GameFiles
public MetaName EntryNameHash { get; set; }
public int EntryKey { get; set; }
public PsoEnumEntryInfo()
{ }
public PsoEnumEntryInfo(MetaName nameHash, int key)
{
EntryNameHash = nameHash;
EntryKey = key;
}
public void Read(DataReader reader)
{
this.EntryNameHash = (MetaName)reader.ReadUInt32();
this.EntryKey = reader.ReadInt32();
EntryNameHash = (MetaName)reader.ReadUInt32();
EntryKey = reader.ReadInt32();
}
public void Write(DataWriter writer)
@ -684,10 +869,25 @@ namespace CodeWalker.GameFiles
public void Write(DataWriter writer)
{
var strStream = new MemoryStream();
var strWriter = new DataWriter(strStream, Endianess.BigEndian);
foreach (var str in Strings)
{
strWriter.Write(str);
}
Length = (int)strStream.Length + 8;
writer.Write(Ident);
writer.Write(Length);
if (strStream.Length > 0)
{
var buf1 = new byte[strStream.Length];
strStream.Position = 0;
strStream.Read(buf1, 0, buf1.Length);
writer.Write(buf1);
}
}
@ -724,10 +924,25 @@ namespace CodeWalker.GameFiles
public void Write(DataWriter writer)
{
var strStream = new MemoryStream();
var strWriter = new DataWriter(strStream, Endianess.BigEndian);
foreach (var str in Strings)
{
strWriter.Write(str);
}
Length = (int)strStream.Length + 8;
writer.Write(Ident);
writer.Write(Length);
if (strStream.Length > 0)
{
var buf1 = new byte[strStream.Length];
strStream.Position = 0;
strStream.Read(buf1, 0, buf1.Length);
writer.Write(buf1);
}
}
@ -743,7 +958,6 @@ namespace CodeWalker.GameFiles
public int Length { get; set; }
public byte[] Data { get; set; }
//public MetaHash[] Hashes { get; set; }
//public byte[] Decr1 { get; set; }
//public byte[] Decr2 { get; set; }
@ -756,26 +970,25 @@ namespace CodeWalker.GameFiles
{
Data = reader.ReadBytes(Length - 8);
//reader.Position = 8;
//List<MetaHash> hashes = new List<MetaHash>();
//while (reader.Position < reader.Length)
//{
// hashes.Add(reader.ReadUInt32());
//}
//Hashes = hashes.ToArray();
//Decr1 = GTACrypto.DecryptAES(Data);
//Decr2 = GTACrypto.DecryptNG(Data, )
//TODO: someone plz figure out that encryption
}
}
public void Write(DataWriter writer)
{
Length = (Data?.Length??0) + 8;
writer.Write(Ident);
writer.Write(Length);
if (Length > 8)
{
writer.Write(Data);
}
}
@ -804,10 +1017,15 @@ namespace CodeWalker.GameFiles
public void Write(DataWriter writer)
{
Length = (Data?.Length ?? 0) + 8;
writer.Write(Ident);
writer.Write(Length);
if (Length > 8)
{
writer.Write(Data);
}
}
@ -840,11 +1058,13 @@ namespace CodeWalker.GameFiles
public void Write(DataWriter writer)
{
Length = 20;
writer.Write(Ident);
writer.Write(Length);
writer.Write(FileSize);
writer.Write(Checksum);
writer.Write(Unk0);
}
public override string ToString()

View File

@ -0,0 +1,504 @@
using SharpDX;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker.GameFiles
{
public class PsoBuilder
{
public PsoBuilderPointer RootPointer { get; set; }
List<string> STRFStrings = new List<string>();
List<string> STRSStrings = new List<string>();
Dictionary<MetaName, PsoStructureInfo> StructureInfos = new Dictionary<MetaName, PsoStructureInfo>();
Dictionary<MetaName, PsoEnumInfo> EnumInfos = new Dictionary<MetaName, PsoEnumInfo>();
List<PsoBuilderBlock> Blocks = new List<PsoBuilderBlock>();
int MaxBlockLength = 0x100000; //TODO: figure what this should be!
public PsoBuilderBlock EnsureBlock(MetaName type)
{
foreach (var block in Blocks)
{
if (block.StructureNameHash == type)
{
if (block.TotalSize < MaxBlockLength)
{
return block;
}
}
}
PsoBuilderBlock b = new PsoBuilderBlock();
b.StructureNameHash = type;
b.Index = Blocks.Count;
Blocks.Add(b);
return b;
}
public PsoBuilderPointer AddItem<T>(MetaName type, T item) where T : struct
{
byte[] data = MetaTypes.ConvertToBytes(item);
return AddItem(type, data);
}
public PsoBuilderPointer AddItem(MetaName type, byte[] data)
{
PsoBuilderBlock block = EnsureBlock(type);
int brem = data.Length % 16;
//if (brem > 0)
//{
// int newlen = data.Length - brem + 16;
// byte[] newdata = new byte[newlen];
// Buffer.BlockCopy(data, 0, newdata, 0, data.Length);
// data = newdata; //make sure item size is multiple of 16... so pointers don't need sub offsets!
//}
int idx = block.AddItem(data);
PsoBuilderPointer r = new PsoBuilderPointer();
r.BlockID = block.Index + 1;
r.Offset = (idx * data.Length);
r.Length = data.Length;
return r;
}
public PsoBuilderPointer AddItemArray<T>(MetaName type, T[] items) where T : struct
{
byte[] data = MetaTypes.ConvertArrayToBytes(items);
return AddItemArray(type, data, items.Length);
}
public PsoBuilderPointer AddItemArray(MetaName type, byte[] data, int length)
{
PsoBuilderBlock block = EnsureBlock(type);
int datalen = data.Length;
int newlen = datalen;
//int lenrem = newlen % 16;
//if (lenrem != 0)
//{
// newlen += (16 - lenrem);
//}
byte[] newdata = new byte[newlen];
Buffer.BlockCopy(data, 0, newdata, 0, datalen);
int offs = block.TotalSize;
int idx = block.AddItem(newdata);
PsoBuilderPointer r = new PsoBuilderPointer();
r.BlockID = block.Index + 1;
r.Offset = offs; //(idx * data.Length);;
r.Length = length;
return r;
}
public PsoPOINTER AddItemPtr<T>(MetaName type, T item) where T : struct //helper method for AddItem<T>
{
var ptr = AddItem(type, item);
return new PsoPOINTER(ptr.BlockID, ptr.Offset, 0);
}
public PsoPOINTER AddItemPtr(MetaName type, byte[] data)//helper method for AddItem<T>
{
var ptr = AddItem(type, data);
return new PsoPOINTER(ptr.BlockID, ptr.Offset, 0);
}
public Array_Structure AddItemArrayPtr<T>(MetaName type, T[] items) where T : struct //helper method for AddItemArray<T>
{
if ((items == null) || (items.Length == 0)) return new Array_Structure();
var ptr = AddItemArray(type, items);
return new Array_Structure(ptr.Pointer, ptr.Length);
}
public Array_Structure AddItemArrayPtr(MetaName type, byte[][] data) //helper method for AddItemArray<T>
{
if ((data == null) || (data.Length == 0)) return new Array_Structure();
int len = 0;
for (int i = 0; i < data.Length; i++)
{
len += data[i].Length;
}
var newdata = new byte[len];
int offset = 0;
for (int i = 0; i < data.Length; i++)
{
Buffer.BlockCopy(data[i], 0, newdata, offset, data[i].Length);
offset += data[i].Length;
}
var ptr = AddItemArray(type, newdata, data.Length);
return new Array_Structure(ptr.Pointer, ptr.Length);
}
public Array_StructurePointer AddPointerArray(PsoPOINTER[] arr)
{
if ((arr == null) || (arr.Length == 0)) return new Array_StructurePointer();
var ptr = AddItemArray(MetaName.PsoPOINTER, arr);
Array_StructurePointer sp = new Array_StructurePointer();
sp.Count1 = (ushort)arr.Length;
sp.Count2 = sp.Count1;
sp.Pointer = ptr.Pointer;
return sp;
}
public PsoBuilderPointer AddString(string str)
{
PsoBuilderBlock block = EnsureBlock((MetaName)1); //PsoSTRING seems to be 1
byte[] data = Encoding.ASCII.GetBytes(str + (char)0);
int datalen = data.Length;
int newlen = datalen;
//int lenrem = newlen % 16;
//if (lenrem != 0) //pad the data length up to multiple of 16.
//{
// newlen += (16 - lenrem);
//}
byte[] newdata = new byte[newlen];
Buffer.BlockCopy(data, 0, newdata, 0, datalen);
int offs = block.TotalSize;
int idx = block.AddItem(newdata);
PsoBuilderPointer r = new PsoBuilderPointer();
r.BlockID = block.Index + 1;
r.Offset = offs;// (idx * data.Length);
r.Length = datalen; //actual length of string.
return r;
}
public Array_Vector3 AddPaddedVector3ArrayPtr(Vector4[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_Vector3();
var ptr = AddItemArray((MetaName)1, items); //MetaName.VECTOR4 padded to vec4...
return new Array_Vector3(ptr.Pointer, items.Length);
}
public Array_Vector3 AddVector2ArrayPtr(Vector2[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_Vector3();
var ptr = AddItemArray((MetaName)1, items); //MetaName.VECTOR4 padded to vec4...?
return new Array_Vector3(ptr.Pointer, items.Length);
}
public Array_uint AddHashArrayPtr(MetaHash[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_uint();
var ptr = AddItemArray((MetaName)6, items); //MetaName.HASH
return new Array_uint(ptr.Pointer, items.Length);
}
public Array_uint AddUIntArrayPtr(uint[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_uint();
var ptr = AddItemArray((MetaName)6, items);
return new Array_uint(ptr.Pointer, items.Length);
}
public Array_uint AddSIntArrayPtr(int[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_uint();
var ptr = AddItemArray((MetaName)5, items);
return new Array_uint(ptr.Pointer, items.Length);
}
public Array_ushort AddUShortArrayPtr(ushort[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_ushort();
var ptr = AddItemArray((MetaName)4, items);
return new Array_ushort(ptr.Pointer, items.Length);
}
public Array_byte AddByteArrayPtr(byte[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_byte();
var ptr = AddItemArray((MetaName)2, items);
return new Array_byte(ptr.Pointer, items.Length);
}
public Array_float AddFloatArrayPtr(float[] items)
{
if ((items == null) || (items.Length == 0)) return new Array_float();
var ptr = AddItemArray((MetaName)7, items); //MetaName.PsoFLOAT ? comes up as MetaName.POINTER due to RSC meta values
return new Array_float(ptr.Pointer, items.Length);
}
public void AddStringToSTRF(string str)
{
STRFStrings.Add(str);
}
public void AddStringToSTRS(string str)
{
STRSStrings.Add(str);
}
public void AddStructureInfo(MetaName name)
{
if (!StructureInfos.ContainsKey(name))
{
PsoStructureInfo si = PsoTypes.GetStructureInfo(name);
if (si != null)
{
StructureInfos[name] = si;
}
}
}
public void AddEnumInfo(MetaName name)
{
if (!EnumInfos.ContainsKey(name))
{
PsoEnumInfo ei = PsoTypes.GetEnumInfo(name);
if (ei != null)
{
EnumInfos[name] = ei;
}
}
}
public PsoStructureInfo AddMapNodeStructureInfo(MetaName valType)
{
PsoStructureInfo inf = null;
if (valType == 0)
{
inf = PsoTypes.GetStructureInfo(MetaName.ARRAYINFO); //default ARRAYINFO with pointer
if (!StructureInfos.ContainsKey(inf.IndexInfo.NameHash))
{
StructureInfos[inf.IndexInfo.NameHash] = inf;
}
return inf;
}
var structInfo = PsoTypes.GetStructureInfo(valType);
if (structInfo == null)
{ }//error?
MetaName xName = MetaName.ARRAYINFO + 1; //257
bool nameOk = !StructureInfos.ContainsKey(xName);
while (!nameOk)
{
var exInfo = StructureInfos[xName];
var exInfoItem = exInfo.FindEntry(MetaName.Item);
if (((MetaName)(exInfoItem?.ReferenceKey ?? 0) == valType))
{
return exInfo; //this one already exists.. use it!
}
xName++;
nameOk = !StructureInfos.ContainsKey(xName);
}
inf = new PsoStructureInfo(xName, 0, 2, 8 + structInfo.StructureLength,
new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, valType)
);
if (!StructureInfos.ContainsKey(xName))
{
StructureInfos[xName] = inf;
}
return inf;
//switch (valType)
//{
// case MetaName.fwClipDictionaryMetadata: return PsoTypes.GetStructureInfo((MetaName)257);
// case MetaName.fwMemoryGroupMetadata: return PsoTypes.GetStructureInfo((MetaName)258);
// case (MetaName)3219912345: return PsoTypes.GetStructureInfo((MetaName)259);
// case (MetaName)0: return PsoTypes.GetStructureInfo(MetaName.ARRAYINFO);
// default:
// return PsoTypes.GetStructureInfo(MetaName.ARRAYINFO);//error?
//}
//case (MetaName)257:
// return new PsoStructureInfo((MetaName)257, 0, 2, 32,
// new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
// new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, MetaName.fwClipDictionaryMetadata)
// );
//case (MetaName)258:
// return new PsoStructureInfo((MetaName)258, 0, 2, 24,
// new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
// new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, MetaName.fwMemoryGroupMetadata)
// );
//case (MetaName)259:
// return new PsoStructureInfo((MetaName)259, 0, 2, 32,
// new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
// new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, (MetaName)3219912345)
// );
//case (MetaName)3219912345:
// return new PsoStructureInfo((MetaName)3219912345, 0, 0, 24,
// new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2356519750),
// new PsoStructureEntryInfo(MetaName.Adjustments, PsoDataType.Array, 8, 0, 0)
// );
}
public byte[] GetData()
{
int totlen = 16;
for (int i = 0; i < Blocks.Count; i++)
{
totlen += Blocks[i].TotalSize;
}
byte[] data = new byte[totlen];
int offset = 16; //reserved space for headers
for (int i = 0; i < Blocks.Count; i++)
{
var block = Blocks[i];
for (int j = 0; j < block.Items.Count; j++)
{
var bdata = block.Items[j];
Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length);
offset += bdata.Length;
}
}
if (offset != data.Length)
{ }
return data;
}
public PsoFile GetPso()
{
PsoFile pso = new PsoFile();
pso.SchemaSection = new PsoSchemaSection();
var schEntries = new List<PsoElementInfo>();
foreach (var structInfo in StructureInfos.Values)
{
schEntries.Add(structInfo);
}
foreach (var enumInfo in EnumInfos.Values)
{
schEntries.Add(enumInfo);
}
pso.SchemaSection.Entries = schEntries.ToArray();
pso.SchemaSection.EntriesIdx = new PsoElementIndexInfo[schEntries.Count];
for (int i = 0; i < schEntries.Count; i++)
{
pso.SchemaSection.EntriesIdx[i] = new PsoElementIndexInfo();
pso.SchemaSection.EntriesIdx[i].NameHash = schEntries[i].IndexInfo.NameHash;
}
if (STRFStrings.Count > 0)
{
pso.STRFSection = new PsoSTRFSection();
pso.STRFSection.Strings = STRFStrings.ToArray();
}
if (STRSStrings.Count > 0)
{
pso.STRSSection = new PsoSTRSSection();
pso.STRSSection.Strings = STRSStrings.ToArray();
}
pso.DataSection = new PsoDataSection();
pso.DataSection.Data = GetData();
pso.DataMapSection = new PsoDataMapSection();
pso.DataMapSection.Entries = new PsoDataMappingEntry[Blocks.Count];
pso.DataMapSection.RootId = RootPointer.BlockID;
var offset = 16;
for (int i = 0; i < Blocks.Count; i++)
{
var b = Blocks[i];
var e = new PsoDataMappingEntry();
e.NameHash = b.StructureNameHash;
e.Length = b.TotalSize;
e.Offset = offset;
offset += b.TotalSize;
pso.DataMapSection.Entries[i] = e;
}
return pso;
}
}
public class PsoBuilderBlock
{
public MetaName StructureNameHash { get; set; }
public List<byte[]> Items { get; set; } = new List<byte[]>();
public int TotalSize { get; set; } = 0;
public int Index { get; set; } = 0;
public int AddItem(byte[] item)
{
int idx = Items.Count;
Items.Add(item);
TotalSize += item.Length;
return idx;
}
public uint BasePointer
{
get
{
return (((uint)Index + 1) & 0xFFF);
}
}
//public MetaDataBlock GetMetaDataBlock()
//{
// if (TotalSize <= 0) return null;
// byte[] data = new byte[TotalSize];
// int offset = 0;
// for (int j = 0; j < Items.Count; j++)
// {
// var bdata = Items[j];
// Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length);
// offset += bdata.Length;
// }
// MetaDataBlock db = new MetaDataBlock();
// db.StructureNameHash = StructureNameHash;
// db.DataLength = TotalSize;
// db.Data = data;
// return db;
//}
}
public struct PsoBuilderPointer
{
public int BlockID { get; set; } //1-based id
public int Offset { get; set; } //byte offset
public int Length { get; set; } //for temp use...
public uint Pointer
{
get
{
uint bidx = (((uint)BlockID) & 0xFFF);
uint offs = (((uint)Offset) & 0xFFFFF) << 12;
return bidx + offs;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Xml;
using SharpDX;
@ -85,11 +86,11 @@ namespace CodeWalker.GameFiles
case MetaStructureEntryDataType.ArrayOfChars:
{
int offset = entry.DataOffset;
var split = Split(cnode.InnerText, 2);
var split = cnode.InnerText;// Split(cnode.InnerText, 1);
for (int j = 0; j < split.Length; j++)
{
byte val = Convert.ToByte(split[j], 16);
byte val = (byte)split[j];// Convert.ToByte(split[j], 16);
data[offset] = val;
offset += sizeof(byte);
}
@ -127,7 +128,23 @@ namespace CodeWalker.GameFiles
case MetaStructureEntryDataType.DataBlockPointer:
{
// TODO
var ns = NumberStyles.HexNumber;
var ic = CultureInfo.InvariantCulture;
var sa = new[] { ' ', '\n' };
var so = StringSplitOptions.RemoveEmptyEntries;
var split = cnode.InnerText.Trim().Split(sa, so); //split = Split(node.InnerText, 2); to read as unsplitted HEX
var bytes = new List<byte>();
for (int j = 0; j < split.Length; j++)
{
byte val;// = Convert.ToByte(split[j], 10);
if (byte.TryParse(split[j].Trim(), ns, ic, out val))
{
bytes.Add(val);
}
}
var ptr = mb.AddDataBlockPtr(bytes.ToArray(), MetaName.BYTE);
var byt = MetaTypes.ConvertToBytes(ptr);
Buffer.BlockCopy(byt, 0, data, entry.DataOffset, byt.Length);
break;
}
@ -178,22 +195,26 @@ namespace CodeWalker.GameFiles
case MetaStructureEntryDataType.IntFlags1:
case MetaStructureEntryDataType.IntFlags2:
{
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
if (entry.ReferenceKey != 0)
{
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
mb.AddEnumInfo(_infos.EnumNameHash);
}
mb.AddEnumInfo(_infos.EnumNameHash);
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText);
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText, entry.DataType);
Write(val, data, entry.DataOffset);
break;
}
case MetaStructureEntryDataType.ShortFlags:
{
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
if (entry.ReferenceKey != 0)
{
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
mb.AddEnumInfo(_infos.EnumNameHash);
}
mb.AddEnumInfo(_infos.EnumNameHash);
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText);
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText, entry.DataType);
Write((short)val, data, entry.DataOffset);
break;
}
@ -296,11 +317,16 @@ namespace CodeWalker.GameFiles
private static void GetParsedArrayOfBytes(XmlNode node, byte[] data, MetaStructureEntryInfo_s entry, MetaStructureEntryInfo_s arrEntry)
{
int offset = entry.DataOffset;
string[] split;
var ns = NumberStyles.Any;
var ic = CultureInfo.InvariantCulture;
var sa = new[] { ' ' };
var so = StringSplitOptions.RemoveEmptyEntries;
var split = node.InnerText.Trim().Split(sa, so); //split = Split(node.InnerText, 2); to read as unsplitted HEX
switch (arrEntry.DataType)
{
default:
default: //expecting hex string.
split = Split(node.InnerText, 2);
for (int j = 0; j < split.Length; j++)
{
@ -309,67 +335,81 @@ namespace CodeWalker.GameFiles
offset += sizeof(byte);
}
break;
case MetaStructureEntryDataType.SignedByte:
split = node.InnerText.Split(); //split = Split(node.InnerText, 2); to read as unsplitted HEX
case MetaStructureEntryDataType.SignedByte: //expecting space-separated array.
for (int j = 0; j < split.Length; j++)
{
sbyte val = Convert.ToSByte(split[j], 10);
data[offset] = (byte)val;
offset += sizeof(sbyte);
sbyte val;// = Convert.ToSByte(split[j], 10);
if (sbyte.TryParse(split[j].Trim(), ns, ic, out val))
{
data[offset] = (byte)val;
offset += sizeof(sbyte);
}
}
break;
case MetaStructureEntryDataType.UnsignedByte:
split = node.InnerText.Split();
case MetaStructureEntryDataType.UnsignedByte: //expecting space-separated array.
for (int j = 0; j < split.Length; j++)
{
byte val = Convert.ToByte(split[j], 10);
data[offset] = val;
offset += sizeof(byte);
byte val;// = Convert.ToByte(split[j], 10);
if (byte.TryParse(split[j].Trim(), ns, ic, out val))
{
data[offset] = val;
offset += sizeof(byte);
}
}
break;
case MetaStructureEntryDataType.SignedShort:
split = node.InnerText.Split();
case MetaStructureEntryDataType.SignedShort: //expecting space-separated array.
for (int j = 0; j < split.Length; j++)
{
short val = Convert.ToInt16(split[j], 10);
Write(val, data, offset);
offset += sizeof(short);
short val;// = Convert.ToInt16(split[j], 10);
if (short.TryParse(split[j].Trim(), ns, ic, out val))
{
Write(val, data, offset);
offset += sizeof(short);
}
}
break;
case MetaStructureEntryDataType.UnsignedShort:
split = node.InnerText.Split();
case MetaStructureEntryDataType.UnsignedShort: //expecting space-separated array.
for (int j = 0; j < split.Length; j++)
{
ushort val = Convert.ToUInt16(split[j], 10);
Write(val, data, offset);
offset += sizeof(ushort);
ushort val;// = Convert.ToUInt16(split[j], 10);
if (ushort.TryParse(split[j].Trim(), ns, ic, out val))
{
Write(val, data, offset);
offset += sizeof(ushort);
}
}
break;
case MetaStructureEntryDataType.SignedInt:
split = node.InnerText.Split();
case MetaStructureEntryDataType.SignedInt: //expecting space-separated array.
for (int j = 0; j < split.Length; j++)
{
int val = Convert.ToInt32(split[j], 10);
Write(val, data, offset);
offset += sizeof(int);
int val;// = Convert.ToInt32(split[j], 10);
if (int.TryParse(split[j].Trim(), ns, ic, out val))
{
Write(val, data, offset);
offset += sizeof(int);
}
}
break;
case MetaStructureEntryDataType.UnsignedInt:
split = node.InnerText.Split();
case MetaStructureEntryDataType.UnsignedInt: //expecting space-separated array.
for (int j = 0; j < split.Length; j++)
{
uint val = Convert.ToUInt32(split[j], 10);
Write(val, data, offset);
offset += sizeof(uint);
uint val;// = Convert.ToUInt32(split[j], 10);
if (uint.TryParse(split[j].Trim(), ns, ic, out val))
{
Write(val, data, offset);
offset += sizeof(uint);
}
}
break;
case MetaStructureEntryDataType.Float:
split = node.InnerText.Split();
case MetaStructureEntryDataType.Float: //expecting space-separated array.
for (int j = 0; j < split.Length; j++)
{
float val = FloatUtil.Parse(split[j]);
Write(val, data, offset);
offset += sizeof(float);
float val;// = FloatUtil.Parse(split[j]);
if (FloatUtil.TryParse(split[j].Trim(), out val))
{
Write(val, data, offset);
offset += sizeof(float);
}
}
break;
}
@ -565,39 +605,61 @@ namespace CodeWalker.GameFiles
{
var items = new List<Vector4>();
var split = node.InnerText.Split('\n');// Regex.Split(node.InnerText, @"[\s\r\n\t]");
float x = 0f;
float y = 0f;
float z = 0f;
float w = 0f;
for (int i = 0; i < split.Length; i++)
var cnodes = node.SelectNodes("Item");
if (cnodes.Count > 0)
{
var s = split[i]?.Trim();
if (string.IsNullOrEmpty(s)) continue;
var split2 = Regex.Split(s, @"[\s\t]");
int c = 0;
x = 0f; y = 0f; z = 0f;
for (int n = 0; n < split2.Length; n++)
foreach (XmlNode cnode in cnodes)
{
var ts = split2[n]?.Trim();
if (string.IsNullOrEmpty(ts)) continue;
var f = FloatUtil.Parse(ts);
switch (c)
var str = cnode.InnerText;
var strs = str.Split(',');
if (strs.Length >= 3)
{
case 0: x = f; break;
case 1: y = f; break;
case 2: z = f; break;
x = FloatUtil.Parse(strs[0].Trim());
y = FloatUtil.Parse(strs[1].Trim());
z = FloatUtil.Parse(strs[2].Trim());
if (strs.Length >= 4)
{
w = FloatUtil.Parse(strs[3].Trim());
}
var val = new Vector4(x, y, z, w);
items.Add(val);
}
c++;
}
if (c >= 3)
}
else
{
var split = node.InnerText.Split('\n');// Regex.Split(node.InnerText, @"[\s\r\n\t]");
for (int i = 0; i < split.Length; i++)
{
var val = new Vector4(x, y, z, w);
items.Add(val);
var s = split[i]?.Trim();
if (string.IsNullOrEmpty(s)) continue;
var split2 = Regex.Split(s, @"[\s\t]");
int c = 0;
x = 0f; y = 0f; z = 0f;
for (int n = 0; n < split2.Length; n++)
{
var ts = split2[n]?.Trim();
if (string.IsNullOrEmpty(ts)) continue;
var f = FloatUtil.Parse(ts);
switch (c)
{
case 0: x = f; break;
case 1: y = f; break;
case 2: z = f; break;
}
c++;
}
if (c >= 3)
{
var val = new Vector4(x, y, z, w);
items.Add(val);
}
}
}
@ -648,14 +710,16 @@ namespace CodeWalker.GameFiles
Buffer.BlockCopy(bytes, 0, data, offset, sizeof(float));
}
private static MetaHash GetHash(string str)
public static MetaHash GetHash(string str)
{
if (string.IsNullOrEmpty(str)) return 0;
if (str.StartsWith("hash_"))
{
return (MetaHash) Convert.ToUInt32(str.Substring(5), 16);
}
else
{
JenkIndex.Ensure(str);
return JenkHash.GenHash(str);
}
}
@ -685,23 +749,62 @@ namespace CodeWalker.GameFiles
return chunks.ToArray();
}
private static int GetEnumInt(MetaName type, string enumString)
private static int GetEnumInt(MetaName type, string enumString, MetaStructureEntryDataType dataType)
{
var enumName = (MetaName)(uint)GetHash(enumString);
var infos = MetaTypes.GetEnumInfo(type);
var intval = 0;
if (int.TryParse(enumString, out intval))
{
return intval; //it's already an int.... maybe enum not found or has no entries... or original value didn't match anything
}
var infos = MetaTypes.GetEnumInfo(type);
if (infos == null)
{
return 0;
}
for (int j = 0; j < infos.Entries.Length; j++)
{
var entry = infos.Entries[j];
if (entry.EntryNameHash == enumName)
bool isFlags = (dataType == MetaStructureEntryDataType.IntFlags1) ||
(dataType == MetaStructureEntryDataType.IntFlags2);// ||
//(dataType == MetaStructureEntryDataType.ShortFlags);
if (isFlags)
{
//flags enum. (multiple values, comma-separated)
var split = enumString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
int enumVal = 0;
for (int i = 0; i < split.Length; i++)
{
return entry.EntryValue;
var enumName = (MetaName)(uint)GetHash(split[i].Trim());
for (int j = 0; j < infos.Entries.Length; j++)
{
var entry = infos.Entries[j];
if (entry.EntryNameHash == enumName)
{
enumVal += (1 << entry.EntryValue);
break;
}
}
}
return enumVal;
}
else
{
//single value enum.
var enumName = (MetaName)(uint)GetHash(enumString);
for (int j = 0; j < infos.Entries.Length; j++)
{
var entry = infos.Entries[j];
if (entry.EntryNameHash == enumName)
{
return entry.EntryValue;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -291,9 +291,9 @@ namespace CodeWalker.GameFiles
public uint Unknown_38h { get; set; }
public uint Unknown_3Ch { get; set; }
public ResourcePointerList64<Sequence> Sequences { get; set; }
//public ResourceSimpleList64<uint_r> Unknown_50h { get; set; }
public ResourceSimpleList64Ptr BoneIdsPtr { get; set; }
public AnimationBoneId[] BoneIds { get; set; }
public ResourceSimpleList64_s<AnimationBoneId> BoneIds { get; set; }
//public ResourceSimpleList64Ptr BoneIdsPtr { get; set; }
//public AnimationBoneId[] BoneIds { get; set; }
public YcdFile Ycd { get; set; }
@ -323,10 +323,10 @@ namespace CodeWalker.GameFiles
this.Unknown_38h = reader.ReadUInt32(); //314 174 1238 390 sequences length?
this.Unknown_3Ch = reader.ReadUInt32(); //2 2 2 2 material/type?
this.Sequences = reader.ReadBlock<ResourcePointerList64<Sequence>>();
//this.Unknown_50h = reader.ReadBlock<ResourceSimpleList64<uint_r>>();
this.BoneIdsPtr = reader.ReadStruct<ResourceSimpleList64Ptr>();
//this.BoneIds = reader.ReadUintsAt(this.BoneIdsPtr.EntriesPointer, this.BoneIdsPtr.EntriesCount);
this.BoneIds = reader.ReadStructsAt<AnimationBoneId>(this.BoneIdsPtr.EntriesPointer, this.BoneIdsPtr.EntriesCount);
this.BoneIds = reader.ReadBlock<ResourceSimpleList64_s<AnimationBoneId>>();
//this.BoneIdsPtr = reader.ReadStruct<ResourceSimpleList64Ptr>();
////this.BoneIds = reader.ReadUintsAt(this.BoneIdsPtr.EntriesPointer, this.BoneIdsPtr.EntriesCount);
//this.BoneIds = reader.ReadStructsAt<AnimationBoneId>(this.BoneIdsPtr.EntriesPointer, this.BoneIdsPtr.EntriesCount);
}
public override void Write(ResourceDataWriter writer, params object[] parameters)
@ -352,14 +352,14 @@ namespace CodeWalker.GameFiles
writer.Write(this.Unknown_38h);
writer.Write(this.Unknown_3Ch);
writer.WriteBlock(this.Sequences);
//writer.WriteBlock(this.Unknown_50h);//todo: fix!!
writer.WriteBlock(this.BoneIds);
}
public override Tuple<long, IResourceBlock>[] GetParts()
{
return new Tuple<long, IResourceBlock>[] {
new Tuple<long, IResourceBlock>(0x40, Sequences),
//new Tuple<long, IResourceBlock>(0x50, Unknown_50h)//todo: fix!
new Tuple<long, IResourceBlock>(0x50, BoneIds)
};
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -54,8 +54,8 @@ namespace CodeWalker.GameFiles
public uint Unused_078h { get; set; } // 0x00000000
public uint Unused_07Ch { get; set; } // 0x00000000
public ulong IndicesPointer { get; set; }
public ulong AdjPolysPointer { get; set; }
public uint AdjPolysIndicesCount { get; set; }
public ulong EdgesPointer { get; set; }
public uint EdgesIndicesCount { get; set; }
public NavMeshUintArray AdjAreaIDs { get; set; }
public ulong PolysPointer { get; set; }
public ulong SectorTreePointer { get; set; }
@ -79,7 +79,7 @@ namespace CodeWalker.GameFiles
public NavMeshList<NavMeshVertex> Vertices { get; set; }
public NavMeshList<ushort> Indices { get; set; }
public NavMeshList<NavMeshAdjPoly> AdjPolys { get; set; }
public NavMeshList<NavMeshEdge> Edges { get; set; }
public NavMeshList<NavMeshPoly> Polys { get; set; }
public NavMeshSector SectorTree { get; set; }
public NavMeshPortal[] Portals { get; set; }
@ -109,8 +109,8 @@ namespace CodeWalker.GameFiles
Unused_078h = reader.ReadUInt32();
Unused_07Ch = reader.ReadUInt32();
IndicesPointer = reader.ReadUInt64();
AdjPolysPointer = reader.ReadUInt64();
AdjPolysIndicesCount = reader.ReadUInt32();
EdgesPointer = reader.ReadUInt64();
EdgesIndicesCount = reader.ReadUInt32();
AdjAreaIDs = reader.ReadStruct<NavMeshUintArray>();
PolysPointer = reader.ReadUInt64();
SectorTreePointer = reader.ReadUInt64();
@ -135,7 +135,7 @@ namespace CodeWalker.GameFiles
Vertices = reader.ReadBlockAt<NavMeshList<NavMeshVertex>>(VerticesPointer);
Indices = reader.ReadBlockAt<NavMeshList<ushort>>(IndicesPointer);
AdjPolys = reader.ReadBlockAt<NavMeshList<NavMeshAdjPoly>>(AdjPolysPointer);
Edges = reader.ReadBlockAt<NavMeshList<NavMeshEdge>>(EdgesPointer);
Polys = reader.ReadBlockAt<NavMeshList<NavMeshPoly>>(PolysPointer);
SectorTree = reader.ReadBlockAt<NavMeshSector>(SectorTreePointer);
Portals = reader.ReadStructsAt<NavMeshPortal>(PortalsPointer, PortalsCount);
@ -150,7 +150,7 @@ namespace CodeWalker.GameFiles
VerticesPointer = (ulong)(Vertices != null ? Vertices.FilePosition : 0);
IndicesPointer = (ulong)(Indices != null ? Indices.FilePosition : 0);
AdjPolysPointer = (ulong)(AdjPolys != null ? AdjPolys.FilePosition : 0);
EdgesPointer = (ulong)(Edges != null ? Edges.FilePosition : 0);
PolysPointer = (ulong)(Polys != null ? Polys.FilePosition : 0);
SectorTreePointer = (ulong)(SectorTree != null ? SectorTree.FilePosition : 0);
PortalsPointer = (ulong)(PortalsBlock?.FilePosition ?? 0);
@ -158,6 +158,39 @@ namespace CodeWalker.GameFiles
//uint totbytes = 0;
//Stack<NavMeshSector> sectorstack = new Stack<NavMeshSector>();
//if (SectorTree != null) sectorstack.Push(SectorTree);
//while (sectorstack.Count > 0)
//{
// var sector = sectorstack.Pop();
// if (sector.SubTree1 != null) sectorstack.Push(sector.SubTree1);
// if (sector.SubTree2 != null) sectorstack.Push(sector.SubTree2);
// if (sector.SubTree3 != null) sectorstack.Push(sector.SubTree3);
// if (sector.SubTree4 != null) sectorstack.Push(sector.SubTree4);
// if (sector.Data != null)
// {
// var sdata = sector.Data;
// totbytes += (uint)(sdata.PolyIDsBlock?.BlockLength ?? 0);
// totbytes += (uint)(sdata.PointsBlock?.BlockLength ?? 0);
// }
//}
//totbytes += PadSize(VerticesCount * (uint)Vertices.ItemSize);
//totbytes += PadSize(EdgesIndicesCount * (uint)Indices.ItemSize);
//totbytes += PadSize(EdgesIndicesCount * (uint)Edges.ItemSize);
//totbytes += PadSize(PolysCount * (uint)Polys.ItemSize);
////totbytes += (uint)BlockLength;
//totbytes += (uint)Vertices.ListParts.BlockLength;//Vertices.ListPartsCount * 16;
//totbytes += (uint)Indices.ListParts.BlockLength;//Indices.ListPartsCount * 16;
//totbytes += (uint)Edges.ListParts.BlockLength;//Edges.ListPartsCount * 16;
//totbytes += (uint)Polys.ListParts.BlockLength;//Polys.ListPartsCount * 16;
//totbytes += (uint)(PortalsBlock?.BlockLength ?? 0);//PortalsCount * 28;
//totbytes += (uint)(PortalLinksBlock?.BlockLength ?? 0);//PortalLinksCount * 2;
//int remaining = ((int)TotalBytes) - ((int)totbytes);
//if (totbytes != TotalBytes)
//{ }
writer.Write((uint)ContentFlags);
writer.Write(VersionUnk1);
writer.Write(Unused_018h);
@ -169,8 +202,8 @@ namespace CodeWalker.GameFiles
writer.Write(Unused_078h);
writer.Write(Unused_07Ch);
writer.Write(IndicesPointer);
writer.Write(AdjPolysPointer);
writer.Write(AdjPolysIndicesCount);
writer.Write(EdgesPointer);
writer.Write(EdgesIndicesCount);
writer.WriteStruct(AdjAreaIDs);
writer.Write(PolysPointer);
writer.Write(SectorTreePointer);
@ -192,13 +225,19 @@ namespace CodeWalker.GameFiles
writer.Write(Unused_16Ch);
}
private uint PadSize(uint s)
{
const uint align = 16;
if ((s % align) != 0) s += (align - (s % align));
return s;
}
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>(base.GetReferences());
if (Vertices != null) list.Add(Vertices);
if (Indices != null) list.Add(Indices);
if (AdjPolys != null) list.Add(AdjPolys);
if (Edges != null) list.Add(Edges);
if (Polys != null) list.Add(Polys);
if (SectorTree != null) list.Add(SectorTree);
@ -221,6 +260,15 @@ namespace CodeWalker.GameFiles
}
public void SetDefaults(bool vehicle)
{
VersionUnk1 = 0x00010011;
VersionUnk2 = vehicle ? 0 : 0x85CB3561;
Transform = Matrix.Identity;
}
public override string ToString()
{
return "(Size: " + FloatUtil.GetVector3String(AABBSize) + ")";
@ -325,6 +373,50 @@ namespace CodeWalker.GameFiles
}
}
public uint Get(uint i)
{
switch (i)
{
default:
case 0: return v00;
case 1: return v01;
case 2: return v02;
case 3: return v03;
case 4: return v04;
case 5: return v05;
case 6: return v06;
case 7: return v07;
case 8: return v08;
case 9: return v09;
case 10: return v10;
case 11: return v11;
case 12: return v12;
case 13: return v13;
case 14: return v14;
case 15: return v15;
case 16: return v16;
case 17: return v17;
case 18: return v18;
case 19: return v19;
case 20: return v20;
case 21: return v21;
case 22: return v22;
case 23: return v23;
case 24: return v24;
case 25: return v25;
case 26: return v26;
case 27: return v27;
case 28: return v28;
case 29: return v29;
case 30: return v30;
case 31: return v31;
}
}
public void Set(uint[] arr)
{
Values = arr;
}
public override string ToString()
{
@ -459,7 +551,7 @@ namespace CodeWalker.GameFiles
}
ListParts = parts;
ListOffsets = offsets.ToArray();
ItemCount = (uint)items.Count;
}
@ -592,19 +684,21 @@ namespace CodeWalker.GameFiles
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPoly
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshEdge
{
public NavMeshAdjPolyPart Unknown_0h { get; set; }
public NavMeshAdjPolyPart Unknown_4h { get; set; }
public NavMeshEdgePart _Poly1;
public NavMeshEdgePart _Poly2;
public NavMeshEdgePart Poly1 { get { return _Poly1; } set { _Poly1 = value; } }
public NavMeshEdgePart Poly2 { get { return _Poly2; } set { _Poly2 = value; } }
public override string ToString()
{
return //Unknown_0h.Bin + " | " + Unknown_4h.Bin + " | " +
Unknown_0h.ToString() + " | " + Unknown_4h.ToString();
return //Poly1.Bin + " | " + Poly2.Bin + " | " +
_Poly1.ToString() + " | " + _Poly2.ToString();
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPolyPart
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshEdgePart
{
public uint Value { get; set; }
@ -616,14 +710,15 @@ namespace CodeWalker.GameFiles
}
}
public uint AreaIDInd { get { return (Value >> 0) & 0x1F; } }
public uint PolyID { get { return (Value >> 5) & 0x3FFF; } }
public uint Unk2 { get { return (Value >> 19) & 0x3; } }
public uint Unk3 { get { return (Value >> 21) & 0x7FF; } }
public uint AreaIDInd { get { return (Value >> 0) & 0x1F; } set { Value = (Value & 0xFFFFFFE0) | (value & 0x1F); } }
public uint PolyID { get { return (Value >> 5) & 0x3FFF; } set { Value = (Value & 0xFFF8001F) | ((value & 0x3FFF) << 5); } }
public uint Unk2 { get { return (Value >> 19) & 0x3; } set { Value = (Value & 0xFFE7FFFF) | ((value & 0x3) << 19); } }
public uint Unk3 { get { return (Value >> 21) & 0x7FF; } set { Value = (Value & 0x001FFFFF) | ((value & 0x7FF) << 21); } }
public override string ToString()
{
return AreaIDInd.ToString() + ", " + PolyID.ToString() + ", " + Unk2.ToString() + ", " + Unk3.ToString();
string pid = (PolyID == 0x3FFF) ? "-" : PolyID.ToString();
return AreaIDInd.ToString() + ", " + pid + ", " + Unk2.ToString() + ", " + Unk3.ToString();
}
}
@ -642,16 +737,16 @@ namespace CodeWalker.GameFiles
public NavMeshAABB CellAABB { get; set; }
public FlagsUint Unknown_24h { get; set; }
public FlagsUint Unknown_28h { get; set; }
public ushort PartFlags { get; set; }
public ushort PortalLinkID { get; set; }
public uint PartFlags { get; set; }
//public int IndexUnk { get { return (IndexFlags >> 0) & 31; } } //always 0
public int IndexCount { get { return (IndexFlags >> 5); } }
public int IndexCount { get { return (IndexFlags >> 5); } set { IndexFlags = (ushort)((IndexFlags & 31) | ((value & 0x7FF) << 5)); } }
//public int PartUnk1 { get { return (PartFlags >> 0) & 0xF; } } //always 0
public ushort PartID { get { return (ushort)((PartFlags >> 4) & 0xFF); } set { PartFlags = (ushort)((PartFlags & 0xF00F) | ((value & 0xFF) << 4)); } }
public byte PortalType { get { return (byte)((PartFlags >> 12) & 0xF); } set { PartFlags = (ushort)((PartFlags & 0x0FFF) | ((value & 0xF) << 12)); } }
public ushort PartID { get { return (ushort)((PartFlags >> 4) & 0xFF); } set { PartFlags = ((PartFlags & 0xFFFFF00F) | (((uint)value & 0xFF) << 4)); } }
public byte PortalLinkCount { get { return (byte)((PartFlags >> 12) & 0x7); } set { PartFlags = ((PartFlags & 0xFFFF8FFF) | (((uint)value & 0x7) << 12)); } }
public uint PortalLinkID { get { return ((PartFlags >> 15) & 0x1FFFF); } set { PartFlags = ((PartFlags & 0x7FFF) | ((value & 0x1FFFF) << 15)); } }
public ushort Unknown_28h_16 { get { return (ushort)((Unknown_28h.Value & 0xFFFF)); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFF0000) | (value & 0xFFFFu); } }
@ -672,7 +767,7 @@ namespace CodeWalker.GameFiles
Unknown_28h.Hex + ", " +
//PartFlags.ToString() + ", " + //PartUnk1.ToString() + ", " +
PartID.ToString() + ", " +
PortalType.ToString() + ", " +
PortalLinkCount.ToString() + ", " +
PortalLinkID.ToString();
}
}
@ -790,8 +885,8 @@ namespace CodeWalker.GameFiles
public ushort[] PolyIDs { get; set; }
public NavMeshPoint[] Points { get; set; }
private ResourceSystemStructBlock<ushort> PolyIDsBlock = null;
private ResourceSystemStructBlock<NavMeshPoint> PointsBlock = null;
public ResourceSystemStructBlock<ushort> PolyIDsBlock = null;
public ResourceSystemStructBlock<NavMeshPoint> PointsBlock = null;
public override void Read(ResourceDataReader reader, params object[] parameters)
{

View File

@ -116,12 +116,12 @@ namespace CodeWalker.GameFiles
base.Write(writer, parameters);
// update structure data
//this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0);//TODO: fix?!
//this.TextureDictionaryPointer = (ulong)(this.TextureDictionary != null ? this.TextureDictionary.Position : 0);
//this.DrawableDictionaryPointer = (ulong)(this.DrawableDictionary != null ? this.DrawableDictionary.Position : 0);
//this.ParticleRuleDictionaryPointer = (ulong)(this.ParticleRuleDictionary != null ? this.ParticleRuleDictionary.Position : 0);
//this.EmitterRuleDictionaryPointer = (ulong)(this.EffectRuleDictionary != null ? this.EffectRuleDictionary.Position : 0);
//this.EffectRuleDictionaryPointer = (ulong)(this.EmitterRuleDictionary != null ? this.EmitterRuleDictionary.Position : 0);
this.NamePointer = (ulong)(this.Name != null ? this.Name.FilePosition : 0);
this.TextureDictionaryPointer = (ulong)(this.TextureDictionary != null ? this.TextureDictionary.FilePosition : 0);
this.DrawableDictionaryPointer = (ulong)(this.DrawableDictionary != null ? this.DrawableDictionary.FilePosition : 0);
this.ParticleRuleDictionaryPointer = (ulong)(this.ParticleRuleDictionary != null ? this.ParticleRuleDictionary.FilePosition : 0);
this.EmitterRuleDictionaryPointer = (ulong)(this.EffectRuleDictionary != null ? this.EffectRuleDictionary.FilePosition : 0);
this.EffectRuleDictionaryPointer = (ulong)(this.EmitterRuleDictionary != null ? this.EmitterRuleDictionary.FilePosition : 0);
// write structure data
writer.Write(this.NamePointer);
@ -142,13 +142,13 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>(base.GetReferences()); //TODO: fix!!
//if (Name != null) list.Add(Name);
//if (TextureDictionary != null) list.Add(TextureDictionary);
//if (DrawableDictionary != null) list.Add(DrawableDictionary);
//if (ParticleRuleDictionary != null) list.Add(ParticleRuleDictionary);
//if (EffectRuleDictionary != null) list.Add(EffectRuleDictionary);
//if (EmitterRuleDictionary != null) list.Add(EmitterRuleDictionary);
var list = new List<IResourceBlock>(base.GetReferences());
if (Name != null) list.Add(Name);
if (TextureDictionary != null) list.Add(TextureDictionary);
if (DrawableDictionary != null) list.Add(DrawableDictionary);
if (ParticleRuleDictionary != null) list.Add(ParticleRuleDictionary);
if (EffectRuleDictionary != null) list.Add(EffectRuleDictionary);
if (EmitterRuleDictionary != null) list.Add(EmitterRuleDictionary);
return list.ToArray();
}
}
@ -350,10 +350,12 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
//this.HashesPointer = (ulong)(this.Hashes != null ? this.Hashes.Position : 0);
////this.HashesCount1 = (ushort)(this.Hashes != null ? this.Hashes.Count : 0);
//this.EffectRulesPointer = (ulong)(this.EmitterRules != null ? this.EmitterRules.Position : 0);
////this.EffectRulesCount1 = (ushort)(this.EffectRules != null ? this.EffectRules.Count : 0);
this.HashesPointer = (ulong)(this.Hashes != null ? this.Hashes.FilePosition : 0);
this.HashesCount1 = (ushort)(this.Hashes != null ? this.Hashes.Count : 0);
this.HashesCount2 = this.HashesCount1;
this.EffectRulesPointer = (ulong)(this.EmitterRules != null ? this.EmitterRules.FilePosition : 0);
this.EffectRulesCount1 = (ushort)(this.EmitterRules != null ? this.EmitterRules.Count : 0);
this.EffectRulesCount2 = this.EffectRulesCount1;
// write structure data
writer.Write(this.VFT);
@ -548,10 +550,10 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
//// update structure data //TODO: fix!
//this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0);
//this.p9 = (ulong)(this.p9data != null ? this.p9data.Position : 0);
//this.p10 = (ulong)(this.p10data != null ? this.p10data.Position : 0);
// update structure data
this.NamePointer = (ulong)(this.Name != null ? this.Name.FilePosition : 0);
this.p9 = (ulong)(this.p9data != null ? this.p9data.FilePosition : 0);
this.p10 = (ulong)(this.p10data != null ? this.p10data.FilePosition : 0);
// write structure data
writer.Write(this.VFT);
@ -622,9 +624,9 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
//if (Name != null) list.Add(Name);
//if (p9data != null) list.Add(p9data);
//if (p10data != null) list.Add(p10data);
if (Name != null) list.Add(Name);
if (p9data != null) list.Add(p9data);
if (p10data != null) list.Add(p10data);
return list.ToArray();
}
@ -732,9 +734,9 @@ namespace CodeWalker.GameFiles
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix!!
//this.EmitterRulePointer = (ulong)(this.EmitterRule != null ? this.EmitterRule.Position : 0);
//this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0);
// update structure data
this.EmitterRulePointer = (ulong)(this.EmitterRule != null ? this.EmitterRule.FilePosition : 0);
this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0);
// write structure data
writer.Write(this.VFT);
@ -943,13 +945,13 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
//// update structure data
//this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0);
//this.EventEmittersPointer = (ulong)(this.EventEmitters != null ? this.EventEmitters.Position : 0);
////this.c3b = (ushort)(this.p3data != null ? this.p3data.Count : 0);
//this.p4 = (ulong)(this.p4data != null ? this.p4data.Position : 0);
//this.KeyframePropsPointer = (ulong)(this.KeyframeProps != null ? this.KeyframeProps.Position : 0);
////this.refcnt2 = (ushort)(this.refs != null ? this.refs.Count : 0);
// update structure data
this.NamePointer = (ulong)(this.Name != null ? this.Name.FilePosition : 0);
this.EventEmittersPointer = (ulong)(this.EventEmitters != null ? this.EventEmitters.FilePosition : 0);
//this.c3b = (ushort)(this.p3data != null ? this.p3data.Count : 0);
this.p4 = (ulong)(this.p4data != null ? this.p4data.FilePosition : 0);
this.KeyframePropsPointer = (ulong)(this.KeyframeProps != null ? this.KeyframeProps.FilePosition : 0);
//this.refcnt2 = (ushort)(this.refs != null ? this.refs.Count : 0);
// write structure data
writer.Write(this.VFT);
@ -1020,10 +1022,10 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
//if (Name != null) list.Add(Name);
//if (EventEmitters != null) list.Add(EventEmitters);
//if (p4data != null) list.Add(p4data);
//if (KeyframeProps != null) list.Add(KeyframeProps);
if (Name != null) list.Add(Name);
if (EventEmitters != null) list.Add(EventEmitters);
if (p4data != null) list.Add(p4data);
if (KeyframeProps != null) list.Add(KeyframeProps);
return list.ToArray();
}
@ -1302,11 +1304,11 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
//this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0);
//this.p2 = (ulong)(this.p2data != null ? this.p2data.Position : 0);
//this.p3 = (ulong)(this.p3data != null ? this.p3data.Position : 0);
//this.p4 = (ulong)(this.EmitterRule != null ? this.EmitterRule.Position : 0);
//this.p5 = (ulong)(this.ParticleRule != null ? this.ParticleRule.Position : 0);
this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0);
this.p2 = (ulong)(this.p2data != null ? this.p2data.FilePosition : 0);
this.p3 = (ulong)(this.p3data != null ? this.p3data.FilePosition : 0);
this.p4 = (ulong)(this.EmitterRule != null ? this.EmitterRule.FilePosition : 0);
this.p5 = (ulong)(this.ParticleRule != null ? this.ParticleRule.FilePosition : 0);
// write structure data
writer.Write(this.VFT);
@ -1337,11 +1339,11 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
//if (p1data != null) list.Add(p1data);
//if (p2data != null) list.Add(p2data);
//if (p3data != null) list.Add(p3data);
//if (EmitterRule != null) list.Add(EmitterRule);
//if (ParticleRule != null) list.Add(ParticleRule);
if (p1data != null) list.Add(p1data);
if (p2data != null) list.Add(p2data);
if (p3data != null) list.Add(p3data);
if (EmitterRule != null) list.Add(EmitterRule);
if (ParticleRule != null) list.Add(ParticleRule);
return list.ToArray();
}
}
@ -1426,7 +1428,7 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
//this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0);
this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0);
// write structure data
writer.Write(this.p1);
@ -1597,7 +1599,7 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
//this.Unknown_8h_Pointer = (ulong)(this.Unknown_8h_Data != null ? this.Unknown_8h_Data.Position : 0);
this.Unknown_8h_Pointer = (ulong)(this.Unknown_8h_Data != null ? this.Unknown_8h_Data.FilePosition : 0);
// write structure data
writer.Write(this.Unknown_0h);
@ -1741,12 +1743,12 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
//this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0);
//this.p2 = (ulong)(this.p2data != null ? this.p2data.Position : 0);
//this.p3 = (ulong)(this.p3data != null ? this.p3data.Position : 0);
//this.p4 = (ulong)(this.p4data != null ? this.p4data.Position : 0);
//this.KeyframePropsPointer = (ulong)(this.KeyframeProps != null ? this.KeyframeProps.Position : 0);
////this.refcnt2 = (ushort)(this.refs != null ? this.refs.Count : 0);
this.NamePointer = (ulong)(this.Name != null ? this.Name.FilePosition : 0);
this.p2 = (ulong)(this.p2data != null ? this.p2data.FilePosition : 0);
this.p3 = (ulong)(this.p3data != null ? this.p3data.FilePosition : 0);
this.p4 = (ulong)(this.p4data != null ? this.p4data.FilePosition : 0);
this.KeyframePropsPointer = (ulong)(this.KeyframeProps != null ? this.KeyframeProps.FilePosition : 0);
//this.refcnt2 = (ushort)(this.refs != null ? this.refs.Count : 0);
// write structure data
writer.Write(this.VFT);
@ -1796,11 +1798,11 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
//if (Name != null) list.Add(Name);
//if (p2data != null) list.Add(p2data);
//if (p3data != null) list.Add(p3data);
//if (p4data != null) list.Add(p4data);
//if (KeyframeProps != null) list.Add(KeyframeProps);
if (Name != null) list.Add(Name);
if (p2data != null) list.Add(p2data);
if (p3data != null) list.Add(p3data);
if (p4data != null) list.Add(p4data);
if (KeyframeProps != null) list.Add(KeyframeProps);
return list.ToArray();
}
@ -2027,7 +2029,7 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
////this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0);
this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0);
// write structure data
writer.Write(this.p1);
@ -2073,7 +2075,7 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
////this.p1 = (ulong)(this.p1data != null ? this.p1data.Position : 0);
this.p1 = (ulong)(this.p1data != null ? this.p1data.FilePosition : 0);
// write structure data
writer.Write(this.Unknown_0h);
@ -4074,8 +4076,8 @@ namespace CodeWalker.GameFiles
base.Write(writer, parameters);
// update structure data
//this.TexturePointer = (ulong)(this.Texture != null ? this.Texture.Position : 0);
//this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0);
this.TexturePointer = (ulong)(this.Texture != null ? this.Texture.FilePosition : 0);
this.NamePointer = (ulong)(this.Name != null ? this.Name.FilePosition : 0);
// write structure data
writer.Write(this.Unknown_18h);
@ -4091,8 +4093,8 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>(base.GetReferences());
//if (Texture != null) list.Add(Texture);
//if (Name != null) list.Add(Name);
if (Texture != null) list.Add(Texture);
if (Name != null) list.Add(Name);
return list.ToArray();
}
}
@ -4248,9 +4250,9 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
//// update structure data
//this.Unknown_10h_Pointer = (ulong)(this.Unknown_10h_Data != null ? this.Unknown_10h_Data.Position : 0);
//this.DrawablePointer = (ulong)(this.Drawable != null ? this.Drawable.Position : 0);
// update structure data
this.Unknown_10h_Pointer = (ulong)(this.Unknown_10h_Data != null ? this.Unknown_10h_Data.FilePosition : 0);
this.DrawablePointer = (ulong)(this.Drawable != null ? this.Drawable.FilePosition : 0);
// write structure data
writer.Write(this.Unknown_0h);

View File

@ -28,6 +28,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
@ -194,6 +195,10 @@ namespace CodeWalker.GameFiles
{
return new FlagsByte(v);
}
public static implicit operator byte(FlagsByte v)
{
return v.Value; //implicit conversion
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public struct FlagsUshort
@ -234,6 +239,11 @@ namespace CodeWalker.GameFiles
{
return new FlagsUshort(v);
}
public static implicit operator ushort(FlagsUshort v)
{
return v.Value; //implicit conversion
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public struct FlagsUint
@ -274,6 +284,11 @@ namespace CodeWalker.GameFiles
{
return new FlagsUint(v);
}
public static implicit operator uint(FlagsUint v)
{
return v.Value; //implicit conversion
}
}
@ -644,6 +659,9 @@ namespace CodeWalker.GameFiles
//public ResourceSimpleArray<T> Entries;
public T[] data_items { get; private set; }
private ResourceSimpleArray<T> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
@ -679,9 +697,9 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
//this.EntriesPointer = (ulong)(this.Entries != null ? this.Entries.Position : 0);
//this.EntriesCount = (ushort)(this.Entries != null ? this.Entries.Count : 0);
//this.EntriesCapacity = (ushort)(this.Entries != null ? this.Entries.Count : 0);
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.Count : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.Count : 0);
// write structure data
writer.Write(this.EntriesPointer);
@ -696,7 +714,567 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
//if (Entries != null) list.Add(Entries);
if (data_items?.Length > 0)
{
data_block = new ResourceSimpleArray<T>();
data_block.Data = new List<T>();
data_block.Data.AddRange(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
public override string ToString()
{
return "(Count: " + EntriesCount.ToString() + ")";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64_s<T> : ResourceSystemBlock where T : struct
{
public override long BlockLength
{
get { return 16; }
}
// structure data
public ulong EntriesPointer { get; private set; }
public ushort EntriesCount { get; private set; }
public ushort EntriesCapacity { get; private set; }
// reference data
public T[] data_items { get; private set; }
private ResourceSystemStructBlock<T> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
public override void Read(ResourceDataReader reader, params object[] parameters)
{
// read structure data
this.EntriesPointer = reader.ReadUInt64();
this.EntriesCount = reader.ReadUInt16();
this.EntriesCapacity = reader.ReadUInt16();
reader.Position += 4;
// read reference data
//TODO: NEEDS TO BE TESTED!!!
data_items = reader.ReadStructsAt<T>(EntriesPointer, EntriesCount);
}
/// <summary>
/// Writes the data-block to a stream.
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data
writer.Write(this.EntriesPointer);
writer.Write(this.EntriesCount);
writer.Write(this.EntriesCapacity);
writer.Write((uint)0x00000000);
}
/// <summary>
/// Returns a list of data blocks which are referenced by this block.
/// </summary>
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
if (data_items?.Length > 0)
{
data_block = new ResourceSystemStructBlock<T>(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
public override string ToString()
{
return "(Count: " + EntriesCount.ToString() + ")";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64b_s<T> : ResourceSystemBlock where T : struct
{
//this version uses uints for the count/cap!
public override long BlockLength
{
get { return 16; }
}
// structure data
public ulong EntriesPointer { get; private set; }
public uint EntriesCount { get; private set; }
public uint EntriesCapacity { get; private set; }
// reference data
public T[] data_items { get; private set; }
private ResourceSystemStructBlock<T> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
public override void Read(ResourceDataReader reader, params object[] parameters)
{
// read structure data
this.EntriesPointer = reader.ReadUInt64();
this.EntriesCount = reader.ReadUInt32();
this.EntriesCapacity = reader.ReadUInt32();
//reader.Position += 4;
// read reference data
//TODO: NEEDS TO BE TESTED!!!
data_items = reader.ReadStructsAt<T>(EntriesPointer, EntriesCount);
}
/// <summary>
/// Writes the data-block to a stream.
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data
writer.Write(this.EntriesPointer);
writer.Write(this.EntriesCount);
writer.Write(this.EntriesCapacity);
//writer.Write((uint)0x00000000);
}
/// <summary>
/// Returns a list of data blocks which are referenced by this block.
/// </summary>
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
if (data_items?.Length > 0)
{
data_block = new ResourceSystemStructBlock<T>(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
public override string ToString()
{
return "(Count: " + EntriesCount.ToString() + ")";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64_byte : ResourceSystemBlock
{
public override long BlockLength
{
get { return 16; }
}
// structure data
public ulong EntriesPointer { get; private set; }
public ushort EntriesCount { get; private set; }
public ushort EntriesCapacity { get; private set; }
// reference data
public byte[] data_items { get; private set; }
private ResourceSystemStructBlock<byte> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
public override void Read(ResourceDataReader reader, params object[] parameters)
{
// read structure data
this.EntriesPointer = reader.ReadUInt64();
this.EntriesCount = reader.ReadUInt16();
this.EntriesCapacity = reader.ReadUInt16();
reader.Position += 4;
// read reference data
//TODO: NEEDS TO BE TESTED!!!
data_items = reader.ReadBytesAt(EntriesPointer, EntriesCount);
}
/// <summary>
/// Writes the data-block to a stream.
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data
writer.Write(this.EntriesPointer);
writer.Write(this.EntriesCount);
writer.Write(this.EntriesCapacity);
writer.Write((uint)0x00000000);
}
/// <summary>
/// Returns a list of data blocks which are referenced by this block.
/// </summary>
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
if (data_items?.Length > 0)
{
data_block = new ResourceSystemStructBlock<byte>(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
public override string ToString()
{
return "(Count: " + EntriesCount.ToString() + ")";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64_ushort : ResourceSystemBlock
{
public override long BlockLength
{
get { return 16; }
}
// structure data
public ulong EntriesPointer { get; private set; }
public ushort EntriesCount { get; private set; }
public ushort EntriesCapacity { get; private set; }
// reference data
public ushort[] data_items { get; private set; }
private ResourceSystemStructBlock<ushort> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
public override void Read(ResourceDataReader reader, params object[] parameters)
{
// read structure data
this.EntriesPointer = reader.ReadUInt64();
this.EntriesCount = reader.ReadUInt16();
this.EntriesCapacity = reader.ReadUInt16();
reader.Position += 4;
// read reference data
//TODO: NEEDS TO BE TESTED!!!
data_items = reader.ReadUshortsAt(EntriesPointer, EntriesCount);
}
/// <summary>
/// Writes the data-block to a stream.
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data
writer.Write(this.EntriesPointer);
writer.Write(this.EntriesCount);
writer.Write(this.EntriesCapacity);
writer.Write((uint)0x00000000);
}
/// <summary>
/// Returns a list of data blocks which are referenced by this block.
/// </summary>
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
if (data_items?.Length > 0)
{
data_block = new ResourceSystemStructBlock<ushort>(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
public override string ToString()
{
return "(Count: " + EntriesCount.ToString() + ")";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64_uint : ResourceSystemBlock
{
public override long BlockLength
{
get { return 16; }
}
// structure data
public ulong EntriesPointer { get; private set; }
public ushort EntriesCount { get; private set; }
public ushort EntriesCapacity { get; private set; }
// reference data
public uint[] data_items { get; private set; }
private ResourceSystemStructBlock<uint> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
public override void Read(ResourceDataReader reader, params object[] parameters)
{
// read structure data
this.EntriesPointer = reader.ReadUInt64();
this.EntriesCount = reader.ReadUInt16();
this.EntriesCapacity = reader.ReadUInt16();
reader.Position += 4;
// read reference data
//TODO: NEEDS TO BE TESTED!!!
data_items = reader.ReadUintsAt(EntriesPointer, EntriesCount);
}
/// <summary>
/// Writes the data-block to a stream.
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data
writer.Write(this.EntriesPointer);
writer.Write(this.EntriesCount);
writer.Write(this.EntriesCapacity);
writer.Write((uint)0x00000000);
}
/// <summary>
/// Returns a list of data blocks which are referenced by this block.
/// </summary>
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
if (data_items?.Length > 0)
{
data_block = new ResourceSystemStructBlock<uint>(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
public override string ToString()
{
return "(Count: " + EntriesCount.ToString() + ")";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64_ulong : ResourceSystemBlock
{
public override long BlockLength
{
get { return 16; }
}
// structure data
public ulong EntriesPointer { get; private set; }
public ushort EntriesCount { get; private set; }
public ushort EntriesCapacity { get; private set; }
// reference data
public ulong[] data_items { get; private set; }
private ResourceSystemStructBlock<ulong> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
public override void Read(ResourceDataReader reader, params object[] parameters)
{
// read structure data
this.EntriesPointer = reader.ReadUInt64();
this.EntriesCount = reader.ReadUInt16();
this.EntriesCapacity = reader.ReadUInt16();
reader.Position += 4;
// read reference data
//TODO: NEEDS TO BE TESTED!!!
data_items = reader.ReadUlongsAt(EntriesPointer, EntriesCount);
}
/// <summary>
/// Writes the data-block to a stream.
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data
writer.Write(this.EntriesPointer);
writer.Write(this.EntriesCount);
writer.Write(this.EntriesCapacity);
writer.Write((uint)0x00000000);
}
/// <summary>
/// Returns a list of data blocks which are referenced by this block.
/// </summary>
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
if (data_items?.Length > 0)
{
data_block = new ResourceSystemStructBlock<ulong>(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
public override string ToString()
{
return "(Count: " + EntriesCount.ToString() + ")";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourceSimpleList64_float : ResourceSystemBlock
{
public override long BlockLength
{
get { return 16; }
}
// structure data
public ulong EntriesPointer { get; private set; }
public ushort EntriesCount { get; private set; }
public ushort EntriesCapacity { get; private set; }
// reference data
public float[] data_items { get; private set; }
private ResourceSystemStructBlock<float> data_block;//used for saving.
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
public override void Read(ResourceDataReader reader, params object[] parameters)
{
// read structure data
this.EntriesPointer = reader.ReadUInt64();
this.EntriesCount = reader.ReadUInt16();
this.EntriesCapacity = reader.ReadUInt16();
reader.Position += 4;
// read reference data
//TODO: NEEDS TO BE TESTED!!!
data_items = reader.ReadFloatsAt(EntriesPointer, EntriesCount);
}
/// <summary>
/// Writes the data-block to a stream.
/// </summary>
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data //TODO: fix
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.ItemCount : 0);
// write structure data
writer.Write(this.EntriesPointer);
writer.Write(this.EntriesCount);
writer.Write(this.EntriesCapacity);
writer.Write((uint)0x00000000);
}
/// <summary>
/// Returns a list of data blocks which are referenced by this block.
/// </summary>
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
if (data_items?.Length > 0)
{
data_block = new ResourceSystemStructBlock<float>(data_items);
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
@ -738,53 +1316,23 @@ namespace CodeWalker.GameFiles
}
//// structure data
//public List<ulong> data_pointers;
//// reference data
//public List<T> data_items;
public ulong[] data_pointers { get; private set; }
public T[] data_items { get; private set; }
public T[] data_items { get; set; }
public ResourcePointerArray64()
{
//data_items = new List<T>();
}
public override void Read(ResourceDataReader reader, params object[] parameters)
{
int numElements = Convert.ToInt32(parameters[0]);
// read structure data
//data_pointers = new List<ulong>();
//for (int i = 0; i < numElements; i++)
//{
// data_pointers.Add(reader.ReadUInt64());
//}
data_pointers = reader.ReadUlongsAt((ulong)reader.Position, (uint)numElements);
//foreach (var dp in data_pointers)
//{
// if (dp == 0)
// {
// }
//}
// read reference data
//data_items = new List<T>();
//for (int i = 0; i < numElements; i++)
//{
// data_items.Add(
// reader.ReadBlockAt<T>(data_pointers[i])
// );
//}
data_items = new T[numElements];
for (int i = 0; i < numElements; i++)
{
@ -797,13 +1345,13 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update...
//data_pointers = new List<ulong>();
//foreach (var x in data_items)
// if (x != null)
// data_pointers.Add((uint)x.Position);
// else
// data_pointers.Add((uint)0);
//TODO: fix!
var list = new List<ulong>();
foreach (var x in data_items)
if (x != null)
list.Add((uint)x.FilePosition);
else
list.Add((uint)0);
data_pointers = list.ToArray();
// write...
foreach (var x in data_pointers)
@ -914,68 +1462,29 @@ namespace CodeWalker.GameFiles
[TypeConverter(typeof(ExpandableObjectConverter))] public class ResourcePointerArray64_s<T> : ResourceSystemBlock, IList<T> where T : struct
{
//public int GetNonEmptyNumber()
//{
// int i = 0;
// foreach (var q in data_items)
// if (q != null)
// i++;
// return i;
//}
public override long BlockLength
{
get { return (data_items != null) ? 8 * data_items.Length : 0; }
}
//// structure data
//public List<ulong> data_pointers;
//// reference data
//public List<T> data_items;
public ulong[] data_pointers { get; private set; }
public T[] data_items { get; private set; }
private ResourceSystemStructBlock<T>[] data_blocks = null;
public ResourcePointerArray64_s()
{
//data_items = new List<T>();
}
public override void Read(ResourceDataReader reader, params object[] parameters)
{
int numElements = Convert.ToInt32(parameters[0]);
// read structure data
//data_pointers = new List<ulong>();
//for (int i = 0; i < numElements; i++)
//{
// data_pointers.Add(reader.ReadUInt64());
//}
data_pointers = reader.ReadUlongsAt((ulong)reader.Position, (uint)numElements);
//foreach (var dp in data_pointers)
//{
// if (dp == 0)
// {
// }
//}
// read reference data
//data_items = new List<T>();
//for (int i = 0; i < numElements; i++)
//{
// data_items.Add(
// reader.ReadBlockAt<T>(data_pointers[i])
// );
//}
data_items = new T[numElements];
for (int i = 0; i < numElements; i++)
{
@ -987,13 +1496,20 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update...
//data_pointers = new List<ulong>();
var list = new List<ulong>();
if (data_blocks != null)
{
foreach (var x in data_blocks)
{
list.Add((ulong)x.FilePosition);
}
}
//foreach (var x in data_items)
// if (x != null)
// data_pointers.Add((uint)x.Position);
// else
// data_pointers.Add((uint)0);
//TODO: fix!
data_pointers = list.ToArray();
// write...
foreach (var x in data_pointers)
@ -1005,7 +1521,18 @@ namespace CodeWalker.GameFiles
{
var list = new List<IResourceBlock>();
//foreach (var x in data_items) //TODO: fix
var blocks = new List<ResourceSystemStructBlock<T>>();
if (data_items != null)
{
foreach (var x in data_items)
{
var block = new ResourceSystemStructBlock<T>(new[] { x });
blocks.Add(block);
list.Add(block);
}
}
data_blocks = blocks.ToArray();
//foreach (var x in data_items)
// list.Add(x);
return list.ToArray();
@ -1117,8 +1644,9 @@ namespace CodeWalker.GameFiles
//public ResourcePointerArray64<T> Entries;
public ulong[] data_pointers { get; private set; }
public T[] data_items { get; private set; }
public T[] data_items { get; set; }
private ResourcePointerArray64<T> data_block;//used for saving.
public override void Read(ResourceDataReader reader, params object[] parameters)
@ -1145,10 +1673,11 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update... //TODO: fix...
//this.EntriesPointer = (ulong)(this.Entries != null ? this.Entries.Position : 0);
//this.EntriesCount = (ushort)(this.Entries != null ? this.Entries.Count : 0);
//this.EntriesCapacity = (ushort)(this.Entries != null ? this.Entries.Count : 0);
// update...
this.EntriesPointer = (ulong)(this.data_block != null ? this.data_block.FilePosition : 0);
this.EntriesCount = (ushort)(this.data_block != null ? this.data_block.Count : 0);
this.EntriesCapacity = (ushort)(this.data_block != null ? this.data_block.Count : 0);
// write...
writer.Write(EntriesPointer);
@ -1160,7 +1689,18 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
//if (Entries != null) list.Add(Entries); //TODO: fix..
if (data_items?.Length > 0)
{
data_block = new ResourcePointerArray64<T>();
data_block.data_items = data_items;
list.Add(data_block);
}
else
{
data_block = null;
}
return list.ToArray();
}
@ -1262,8 +1802,8 @@ namespace CodeWalker.GameFiles
get
{
long len = 8 * Data.Count;
foreach (var f in Data)
len += f.BlockLength;
//foreach (var f in Data)
// len += f.BlockLength;
return len;
}
}
@ -1344,8 +1884,8 @@ namespace CodeWalker.GameFiles
foreach (var x in ptr_list)
writer.Write(x);
foreach (var x in Data)
x.Write(writer);
//foreach (var x in Data)
// x.Write(writer);
}
@ -1355,7 +1895,7 @@ namespace CodeWalker.GameFiles
{
var children = new List<IResourceBlock>();
//if (Data != null) children.AddRange(Data);
if (Data != null) children.AddRange(Data);
return children.ToArray();
}
@ -1364,15 +1904,15 @@ namespace CodeWalker.GameFiles
{
var children = new List<Tuple<long, IResourceBlock>>();
if (Data != null)
{
long len = 8 * Data.Count;
foreach (var f in Data)
{
children.Add(new Tuple<long, IResourceBlock>(len, f));
len += f.BlockLength;
}
}
//if (Data != null)
//{
// long len = 8 * Data.Count;
// foreach (var f in Data)
// {
// children.Add(new Tuple<long, IResourceBlock>(len, f));
// len += f.BlockLength;
// }
//}
return children.ToArray();
}
@ -1451,4 +1991,78 @@ namespace CodeWalker.GameFiles
public class ResourceSystemDataBlock : ResourceSystemBlock //used for writing resources.
{
public byte[] Data { get; set; }
public int DataLength { get; set; }
public override long BlockLength
{
get
{
return (Data != null) ? Data.Length : DataLength;
}
}
public ResourceSystemDataBlock(byte[] data)
{
Data = data;
DataLength = (Data != null) ? Data.Length : 0;
}
public override void Read(ResourceDataReader reader, params object[] parameters)
{
Data = reader.ReadBytes(DataLength);
}
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
writer.Write(Data);
}
}
public class ResourceSystemStructBlock<T> : ResourceSystemBlock where T : struct //used for writing resources.
{
public T[] Items { get; set; }
public int ItemCount { get; set; }
public int StructureSize { get; set; }
public override long BlockLength
{
get
{
return ((Items != null) ? Items.Length : ItemCount) * StructureSize;
}
}
public ResourceSystemStructBlock(T[] items)
{
Items = items;
ItemCount = (Items != null) ? Items.Length : 0;
StructureSize = Marshal.SizeOf(typeof(T));
}
public override void Read(ResourceDataReader reader, params object[] parameters)
{
int datalength = ItemCount * StructureSize;
byte[] data = reader.ReadBytes(datalength);
Items = MetaTypes.ConvertDataArray<T>(data, 0, ItemCount);
}
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
byte[] data = MetaTypes.ConvertArrayToBytes(Items);
if (data != null)
{
writer.Write(data);
}
}
}
}

View File

@ -127,7 +127,7 @@ namespace CodeWalker.GameFiles
foreach (var block in blocks)
{
if (block.FilePosition != -1)
throw new Exception("A position of -1 is not possible!");
throw new Exception("Block was already assigned a position!");
//if (block.Length == 0)
// throw new Exception("A length of 0 is not allowed!");
@ -226,23 +226,14 @@ namespace CodeWalker.GameFiles
var sysDataSize = 0x2000;
while (sysDataSize < systemStream.Length)
{
sysDataSize *= 2;
}
var sysDataSize = systemPageCount * systemPageSize;
var sysData = new byte[sysDataSize];
systemStream.Flush();
systemStream.Position = 0;
systemStream.Read(sysData, 0, (int)systemStream.Length);
var gfxPageSize = 0x2000;
while (gfxPageSize != graphicsPageSize)
{
gfxPageSize *= 2;
}
var gfxDataSize = graphicsPageCount * gfxPageSize;
var gfxDataSize = graphicsPageCount * graphicsPageSize;
var gfxData = new byte[gfxDataSize];
graphicsStream.Flush();
graphicsStream.Position = 0;

View File

@ -87,6 +87,19 @@ namespace CodeWalker.GameFiles
var systemSize = resentry.SystemSize;
var graphicsSize = resentry.GraphicsSize;
//if (data != null)
//{
// if (systemSize > data.Length)
// {
// systemSize = data.Length;
// graphicsSize = 0;
// }
// else if ((systemSize + graphicsSize) > data.Length)
// {
// graphicsSize = data.Length - systemSize;
// }
//}
this.systemStream = new MemoryStream(data, 0, systemSize);
this.graphicsStream = new MemoryStream(data, systemSize, graphicsSize);
this.blockPool = new Dictionary<long, List<IResourceBlock>>();
@ -500,7 +513,14 @@ namespace CodeWalker.GameFiles
Marshal.FreeHGlobal(ptr);
Write(arr);
}
public void WriteStructs<T>(T[] val) where T : struct
{
if (val == null) return;
foreach (var v in val)
{
WriteStruct(v);
}
}
}
@ -671,76 +691,6 @@ namespace CodeWalker.GameFiles
public class ResourceSystemDataBlock : ResourceSystemBlock //used for writing resources.
{
public byte[] Data { get; set; }
public int DataLength { get; set; }
public override long BlockLength
{
get
{
return (Data != null) ? Data.Length : DataLength;
}
}
public ResourceSystemDataBlock(byte[] data)
{
Data = data;
DataLength = (Data != null) ? Data.Length : 0;
}
public override void Read(ResourceDataReader reader, params object[] parameters)
{
Data = reader.ReadBytes(DataLength);
}
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
writer.Write(Data);
}
}
public class ResourceSystemStructBlock<T> : ResourceSystemBlock where T : struct //used for writing resources.
{
public T[] Items { get; set; }
public int ItemCount { get; set; }
public int StructureSize { get; set; }
public override long BlockLength
{
get
{
return ((Items != null) ? Items.Length : ItemCount) * StructureSize;
}
}
public ResourceSystemStructBlock(T[] items)
{
Items = items;
ItemCount = (Items != null) ? Items.Length : 0;
StructureSize = Marshal.SizeOf(typeof(T));
}
public override void Read(ResourceDataReader reader, params object[] parameters)
{
int datalength = ItemCount * StructureSize;
byte[] data = reader.ReadBytes(datalength);
Items = MetaTypes.ConvertDataArray<T>(data, 0, ItemCount);
}
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
byte[] data = MetaTypes.ConvertArrayToBytes(Items);
writer.Write(data);
}
}
//public interface ResourceDataStruct
//{
// void Read(ResourceDataReader reader);

View File

@ -24,11 +24,12 @@ namespace CodeWalker.GameFiles
public uint Unknown_14h { get; set; } // 0x00000000
public uint Unknown_18h { get; set; } // 0x00000001
public uint Unknown_1Ch { get; set; } // 0x00000000
public ResourceSimpleList64Ptr TextureNameHashesPtr { get; set; }
public uint[] TextureNameHashes { get; set; }
public ResourceSimpleList64_uint TextureNameHashes { get; set; }
public ResourcePointerList64<Texture> Textures { get; set; }
public Dictionary<uint, Texture> Dict { get; set; }
public long MemoryUsage
{
get
@ -50,8 +51,8 @@ namespace CodeWalker.GameFiles
public TextureDictionary()
{
//this.TextureNameHashes = new ResourceSimpleList64<uint_r>();
this.Textures = new ResourcePointerList64<Texture>();
//this.TextureNameHashes = new ResourceSimpleList64_uint();
//this.Textures = new ResourcePointerList64<Texture>();
}
/// <summary>
@ -66,22 +67,20 @@ namespace CodeWalker.GameFiles
this.Unknown_14h = reader.ReadUInt32();
this.Unknown_18h = reader.ReadUInt32();
this.Unknown_1Ch = reader.ReadUInt32();
this.TextureNameHashesPtr = reader.ReadStruct<ResourceSimpleList64Ptr>();
this.TextureNameHashes = reader.ReadUintsAt(this.TextureNameHashesPtr.EntriesPointer, this.TextureNameHashesPtr.EntriesCount);
//this.TextureNameHashes = reader.ReadBlock<ResourceSimpleList64<uint_r>>();
this.TextureNameHashes = reader.ReadBlock<ResourceSimpleList64_uint>();
this.Textures = reader.ReadBlock<ResourcePointerList64<Texture>>();
var dict = new Dictionary<uint, Texture>();
if ((Textures != null) && (Textures.data_items != null) && (TextureNameHashes != null))
if ((Textures?.data_items != null) && (TextureNameHashes?.data_items != null))
{
for (int i = 0; (i < Textures.data_items.Length) && (i < TextureNameHashes.Length); i++)
for (int i = 0; (i < Textures.data_items.Length) && (i < TextureNameHashes.data_items.Length); i++)
{
var tex = Textures.data_items[i];
var hash = TextureNameHashes[i];
var hash = TextureNameHashes.data_items[i];
dict[hash] = tex;
}
}
Dict = new Dictionary<uint, Texture>(dict);
Dict = dict;// new Dictionary<uint, Texture>(dict);
}
/// <summary>
@ -91,38 +90,24 @@ namespace CodeWalker.GameFiles
{
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.TextureNameHashes); //TODO: fix!
//writer.WriteBlock(this.Textures);
writer.WriteBlock(this.TextureNameHashes);
writer.WriteBlock(this.Textures);
}
public override Tuple<long, IResourceBlock>[] GetParts()
{
return new Tuple<long, IResourceBlock>[] {
//new Tuple<long, IResourceBlock>(0x20, TextureNameHashes), //TODO: fix!
new Tuple<long, IResourceBlock>(0x20, TextureNameHashes),
new Tuple<long, IResourceBlock>(0x30, Textures)
};
}
public Dictionary<uint, Texture> GetDictionary()
{
Dictionary<uint, Texture> td = new Dictionary<uint, Texture>();
if ((Textures != null) && (Textures.data_items != null))
{
var texs = Textures.data_items;
var hashes = TextureNameHashes;
for (int i = 0; (i < texs.Length) && (i < hashes.Length); i++)
{
td.Add(hashes[i], texs[i]);
}
}
return td;
}
public Texture Lookup(uint hash)
{
Texture tex = null;
@ -132,6 +117,21 @@ namespace CodeWalker.GameFiles
}
return tex;
}
//public Dictionary<uint, Texture> GetDictionary()
//{
// Dictionary<uint, Texture> td = new Dictionary<uint, Texture>();
// if ((Textures != null) && (Textures.data_items != null))
// {
// var texs = Textures.data_items;
// var hashes = TextureNameHashes;
// for (int i = 0; (i < texs.Length) && (i < hashes.Length); i++)
// {
// td.Add(hashes[i], texs[i]);
// }
// }
// return td;
//}
}
[TypeConverter(typeof(ExpandableObjectConverter))] public class TextureBase : ResourceSystemBlock
@ -162,6 +162,8 @@ namespace CodeWalker.GameFiles
public string Name { get; set; }
public uint NameHash { get; set; }
private string_r NameBlock = null;
/// <summary>
/// Reads the data-block from a stream.
/// </summary>
@ -201,7 +203,7 @@ namespace CodeWalker.GameFiles
public override void Write(ResourceDataWriter writer, params object[] parameters)
{
// update structure data
//this.NamePointer = (ulong)(this.Name != null ? this.Name.Position : 0); //TODO: fix
this.NamePointer = (ulong)(this.NameBlock != null ? this.NameBlock.FilePosition : 0);
// write structure data
writer.Write(this.VFT);
@ -227,7 +229,11 @@ namespace CodeWalker.GameFiles
public override IResourceBlock[] GetReferences()
{
var list = new List<IResourceBlock>();
//if (Name != null) list.Add(Name); //TODO: fix
if (!string.IsNullOrEmpty(Name))
{
NameBlock = (string_r)Name;
list.Add(NameBlock);
}
return list.ToArray();
}

View File

@ -15,8 +15,8 @@ namespace CodeWalker.GameFiles
DefaultEx = 16473, //PNCTX
PNCCT = 121,
PNCCTTTT = 1017,
PCCNCCTTX = 16639,
PCCNCCT = 127,
PBBNCCTTX = 16639,
PBBNCCT = 127,
PNCTTTX = 16857,
PNCTTX = 16601,
PNCTTTX_2 = 19545,
@ -24,9 +24,9 @@ namespace CodeWalker.GameFiles
PNCCTTX = 16633,
PNCCTTX_2 = 17017,
PNCCTTTX = 17145,
PCCNCCTX = 16511,
PCCNCTX = 16479,
PCCNCT = 95,
PBBNCCTX = 16511,
PBBNCTX = 16479,
PBBNCT = 95,
PNCCTT = 249,
PNCCTX = 16505,
PCT = 81,
@ -39,16 +39,16 @@ namespace CodeWalker.GameFiles
PNCH2 = 2147483737, //0x80000059 (89 + 0x80000000) Default Cloth?
PNCTTTTX = 19673, //normal_spec_detail_dpm_vertdecal_tnt
PNCTTTT = 985,
PCCNCCTT = 255,
PBBNCCTT = 255,
PCTT = 209,
PCCCCT = 119,
PCCNC = 31,
PCCNCTT = 223,
PCCNCTTX = 16607,
PCCNCTTT = 479,
PBBCCT = 119,
PBBNC = 31,
PBBNCTT = 223,
PBBNCTTX = 16607,
PBBNCTTT = 479,
PNCTT = 217,
PNCTTT = 473,
PCCNCTTTX = 16863,
PBBNCTTTX = 16863,
}

View File

@ -43,9 +43,9 @@ namespace CodeWalker.GameFiles
{
base.Write(writer, parameters);
//// update structure data
//this.EntriesPointer = (ulong)(this.Entries?.Position ?? 0);
//this.EntriesCount = (uint)(this.Entries?.Count ?? 0);
// update structure data
this.EntriesPointer = (ulong)(this.Entries?.FilePosition ?? 0);
this.EntriesCount = (uint)(this.Entries?.Count ?? 0);
// write structure data
writer.Write(this.Unknown_10h);

View File

@ -626,6 +626,7 @@ namespace CodeWalker.GameFiles
RpfFileEntry entry = CreateResourceFileEntry(ref data, 0);
if ((data != null) && (entry != null))
{
data = ResourceBuilder.Decompress(data);
file = new T();
file.Load(data, entry);
}
@ -2011,6 +2012,10 @@ namespace CodeWalker.GameFiles
}
public string GetShortNameLower()
{
if (NameLower == null)
{
NameLower = Name.ToLowerInvariant();
}
int ind = NameLower.LastIndexOf('.');
if (ind > 0)
{

View File

@ -15,6 +15,7 @@ namespace CodeWalker.GameFiles
public string Folder { get; private set; }
public string[] ExcludePaths { get; set; }
public bool EnableMods { get; set; }
public bool BuildExtendedJenkIndex { get; set; } = true;
public Action<string> UpdateStatus { get; private set; }
public Action<string> ErrorLog { get; private set; }
@ -73,6 +74,11 @@ namespace CodeWalker.GameFiles
rf.ScanStructure(updateStatus, errorLog);
if (rf.LastException != null) //incase of corrupted rpf (or renamed NG encrypted RPF)
{
continue;
}
AddRpfFile(rf, false, false);
}
catch (Exception ex)
@ -124,7 +130,7 @@ namespace CodeWalker.GameFiles
private void AddRpfFile(RpfFile file, bool isdlc, bool ismod)
{
isdlc = isdlc || (file.NameLower == "dlc.rpf") || (file.NameLower == "update.rpf");
isdlc = isdlc || (file.NameLower == "update.rpf") || (file.NameLower.StartsWith("dlc") && file.NameLower.EndsWith(".rpf"));
ismod = ismod || (file.Path.StartsWith("mods\\"));
if (file.AllEntries != null)
@ -381,102 +387,109 @@ namespace CodeWalker.GameFiles
JenkIndex.Ensure(entry.Name);
JenkIndex.Ensure(nlow);
}
if (nlow.EndsWith(".ydr") || nlow.EndsWith(".yft"))
if (BuildExtendedJenkIndex)
{
var sname = nlow.Substring(0, nlow.Length - 4);
JenkIndex.Ensure(sname + "_lod");
JenkIndex.Ensure(sname + "_loda");
JenkIndex.Ensure(sname + "_lodb");
}
if (nlow.EndsWith(".ydd"))
{
if (nlow.EndsWith("_children.ydd"))
if (nlow.EndsWith(".ydr"))// || nlow.EndsWith(".yft")) //do yft's get lods?
{
var strn = nlow.Substring(0, nlow.Length - 13);
JenkIndex.Ensure(strn);
JenkIndex.Ensure(strn + "_lod");
JenkIndex.Ensure(strn + "_loda");
JenkIndex.Ensure(strn + "_lodb");
var sname = nlow.Substring(0, nlow.Length - 4);
JenkIndex.Ensure(sname + "_lod");
JenkIndex.Ensure(sname + "_loda");
JenkIndex.Ensure(sname + "_lodb");
}
var idx = nlow.LastIndexOf('_');
if (idx > 0)
if (nlow.EndsWith(".ydd"))
{
var str1 = nlow.Substring(0, idx);
var idx2 = str1.LastIndexOf('_');
if (idx2 > 0)
if (nlow.EndsWith("_children.ydd"))
{
var str2 = str1.Substring(0, idx2);
JenkIndex.Ensure(str2 + "_lod");
var maxi = 100;
for (int i = 1; i <= maxi; i++)
var strn = nlow.Substring(0, nlow.Length - 13);
JenkIndex.Ensure(strn);
JenkIndex.Ensure(strn + "_lod");
JenkIndex.Ensure(strn + "_loda");
JenkIndex.Ensure(strn + "_lodb");
}
var idx = nlow.LastIndexOf('_');
if (idx > 0)
{
var str1 = nlow.Substring(0, idx);
var idx2 = str1.LastIndexOf('_');
if (idx2 > 0)
{
var str3 = str2 + "_" + i.ToString().PadLeft(2, '0');
//JenkIndex.Ensure(str3);
JenkIndex.Ensure(str3 + "_lod");
var str2 = str1.Substring(0, idx2);
JenkIndex.Ensure(str2 + "_lod");
var maxi = 100;
for (int i = 1; i <= maxi; i++)
{
var str3 = str2 + "_" + i.ToString().PadLeft(2, '0');
//JenkIndex.Ensure(str3);
JenkIndex.Ensure(str3 + "_lod");
}
}
}
}
}
if (nlow.EndsWith(".awc")) //create audio container path hashes...
{
string[] parts = entry.Path.Split('\\');
int pl = parts.Length;
if (pl > 2)
if (nlow.EndsWith(".sps"))
{
string fn = parts[pl - 1];
string fd = parts[pl - 2];
string hpath = fn.Substring(0, fn.Length - 4);
if (fd.EndsWith(".rpf"))
{
fd = fd.Substring(0, fd.Length - 4);
}
hpath = fd + "/" + hpath;
if (parts[pl - 3] != "sfx")
{ }//no hit
JenkIndex.Ensure(hpath);
JenkIndex.Ensure(nlow);//for shader preset filename hashes!
}
}
if (nlow.EndsWith(".nametable"))
{
RpfBinaryFileEntry binfe = entry as RpfBinaryFileEntry;
if (binfe != null)
if (nlow.EndsWith(".awc")) //create audio container path hashes...
{
byte[] data = file.ExtractFile(binfe);
if (data != null)
string[] parts = entry.Path.Split('\\');
int pl = parts.Length;
if (pl > 2)
{
sb.Clear();
for (int i = 0; i < data.Length; i++)
string fn = parts[pl - 1];
string fd = parts[pl - 2];
string hpath = fn.Substring(0, fn.Length - 4);
if (fd.EndsWith(".rpf"))
{
byte c = data[i];
if (c == 0)
fd = fd.Substring(0, fd.Length - 4);
}
hpath = fd + "/" + hpath;
if (parts[pl - 3] != "sfx")
{ }//no hit
JenkIndex.Ensure(hpath);
}
}
if (nlow.EndsWith(".nametable"))
{
RpfBinaryFileEntry binfe = entry as RpfBinaryFileEntry;
if (binfe != null)
{
byte[] data = file.ExtractFile(binfe);
if (data != null)
{
sb.Clear();
for (int i = 0; i < data.Length; i++)
{
string str = sb.ToString();
if (!string.IsNullOrEmpty(str))
byte c = data[i];
if (c == 0)
{
string strl = str.ToLowerInvariant();
//JenkIndex.Ensure(str);
JenkIndex.Ensure(strl);
string str = sb.ToString();
if (!string.IsNullOrEmpty(str))
{
string strl = str.ToLowerInvariant();
//JenkIndex.Ensure(str);
JenkIndex.Ensure(strl);
////DirMod_Sounds_ entries apparently can be used to infer SP audio strings
////no luck here yet though
//if (strl.StartsWith("dirmod_sounds_") && (strl.Length > 14))
//{
// strl = strl.Substring(14);
// JenkIndex.Ensure(strl);
//}
////DirMod_Sounds_ entries apparently can be used to infer SP audio strings
////no luck here yet though
//if (strl.StartsWith("dirmod_sounds_") && (strl.Length > 14))
//{
// strl = strl.Substring(14);
// JenkIndex.Ensure(strl);
//}
}
sb.Clear();
}
else
{
sb.Append((char)c);
}
sb.Clear();
}
else
{
sb.Append((char)c);
}
}
}
else
{ }
}
else
{ }
}
}

View File

@ -0,0 +1,39 @@
using System;
using SharpDX;
namespace CodeWalker.Core.Utils
{
public static class BoundingBoxExtensions
{
public static Vector3 Size(this BoundingBox bounds)
{
return new Vector3(
Math.Abs(bounds.Maximum.X - bounds.Minimum.X),
Math.Abs(bounds.Maximum.Y - bounds.Minimum.Y),
Math.Abs(bounds.Maximum.Z - bounds.Minimum.Z));
}
public static Vector3 Center(this BoundingBox bounds)
{
return (bounds.Minimum + bounds.Maximum) * 0.5F;
}
public static BoundingBox Encapsulate(this BoundingBox box, BoundingBox bounds)
{
box.Minimum = Vector3.Min(box.Minimum, bounds.Minimum);
box.Maximum = Vector3.Max(box.Maximum, bounds.Maximum);
return box;
}
public static float Radius(this BoundingBox box)
{
var extents = (box.Maximum - box.Minimum) * 0.5F;
return extents.Length();
}
public static BoundingBox Expand(this BoundingBox b, float amount)
{
return new BoundingBox(b.Minimum - Vector3.One * amount, b.Maximum + Vector3.One * amount);
}
}
}

View File

@ -16,6 +16,14 @@ namespace CodeWalker
private LinkedList<TVal> loadedList = new LinkedList<TVal>();
private Dictionary<TKey, LinkedListNode<TVal>> loadedListDict = new Dictionary<TKey, LinkedListNode<TVal>>();
public int Count
{
get
{
return loadedList.Count;
}
}
public Cache()
{
}

1877
CodeWalker.Core/Utils/Fbx.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,996 @@
using CodeWalker.GameFiles;
using SharpDX;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeWalker
{
public class FbxConverter
{
public bool InvertTexcoordV { get; set; } = true;
public YdrFile ConvertToYdr(string name, byte[] fbxdata)
{
var fdoc = FbxIO.Read(fbxdata);
if (fdoc == null)
return null;
var dwbl = TryConvertDrawable(fdoc, name);
YdrFile ydr = new YdrFile();
ydr.Drawable = dwbl;
ydr.Name = name;
return ydr;
}
private Drawable TryConvertDrawable(FbxDocument fdoc, string name)
{
var rootnodes = fdoc.GetSceneNodes();
var mlists = new List<List<FbxModel>>();
var mlistall = new List<FbxModel>();
foreach (var node in rootnodes)
{
if (node.Name == "Model")
{
var mlist = TryConvertModels(node); //flatten any models structure with depth >2
if (mlist != null)
{
mlists.Add(mlist);
mlistall.AddRange(mlist);
}
}
}
var mlHigh = new List<DrawableModel>();
var mlMed = new List<DrawableModel>();
var mlLow = new List<DrawableModel>();
var mlVlow = new List<DrawableModel>();
var mlUnks = new List<DrawableModel>();
var mlAll = new List<DrawableModel>();
foreach (var m in mlistall)
{
var mnl = m.Name.ToLowerInvariant();
if (mnl.EndsWith("_vlow"))
{
mlVlow.Add(m.Model);
}
else if (mnl.EndsWith("_low"))
{
mlLow.Add(m.Model);
}
else if (mnl.EndsWith("_med"))
{
mlMed.Add(m.Model);
}
else if (mnl.EndsWith("_high"))
{
mlHigh.Add(m.Model);
}
else
{
mlUnks.Add(m.Model);
}
}
if (mlHigh.Count == 0)//mlUnks could be embedded collisions... ignore for now
{
mlHigh.AddRange(mlUnks);
}
mlAll.AddRange(mlHigh);
mlAll.AddRange(mlMed);
mlAll.AddRange(mlLow);
mlAll.AddRange(mlVlow);
var allVerts = new List<Vector3>();
var bbMin = new Vector3(float.MaxValue);
var bbMax = new Vector3(float.MinValue);
var bsCen = Vector3.Zero;
var bsRad = 0.0f;
foreach (var m in mlistall)
{
if (m?.Model?.Geometries?.data_items == null) continue;
foreach (var g in m.Model.Geometries.data_items)
{
var vb = g.VertexData.VertexBytes;
var vs = g.VertexData.VertexStride;
var vc = g.VertexData.VertexCount;
for (int i = 0; i < vc; i++)
{
var vp = MetaTypes.ConvertData<Vector3>(vb, i * vs);//position offset should always be 0!
allVerts.Add(vp);
bbMin = Vector3.Min(bbMin, vp);
bbMax = Vector3.Max(bbMax, vp);
//bsCen += vp;
}
}
}
if (allVerts.Count > 0)
{
//bsCen = bsCen / allVerts.Count;
bsCen = (bbMin + bbMax) * 0.5f;
foreach (var vp in allVerts)
{
bsRad = Math.Max(bsRad, (vp - bsCen).Length());
}
}
var sgrp = new ShaderGroup();
var slist = new List<ShaderFX>();
var smapp = new List<ushort>();
foreach (var m in mlAll)
{
if (m?.Geometries?.data_items == null) continue;
smapp.Clear();
foreach (var g in m.Geometries.data_items)
{
smapp.Add((ushort)slist.Count);
slist.Add(g.Shader);
}
m.ShaderMapping = smapp.ToArray();//TODO: re-use shaders!!
}
sgrp.Shaders = new ResourcePointerArray64<ShaderFX>();
sgrp.Shaders.data_items = slist.ToArray();
sgrp.ShadersCount1 = (ushort)slist.Count;
sgrp.ShadersCount2 = (ushort)slist.Count;
sgrp.VFT = 1080113376;//is this needed?
sgrp.Unknown_4h = 1;
sgrp.Unknown_30h = (uint)(8 + slist.Count*3);//WTF is this?
var d = new Drawable();
d.Name = name + ".#dr";
d.ShaderGroup = sgrp;
d.BoundingCenter = bsCen;
d.BoundingSphereRadius = bsRad;
d.BoundingBoxMin = new Vector4(bbMin, float.NaN);
d.BoundingBoxMax = new Vector4(bbMax, float.NaN);
d.LodDistHigh = 9998;//lod dist defaults
d.LodDistMed = 9998;
d.LodDistLow = 9998;
d.LodDistVlow = 9998;
d.Unknown_80h = 0;//TODO: figure these out! related to high/med/low/vlow 0xFF00 + ?
d.Unknown_84h = 0;
d.Unknown_88h = 0;
d.Unknown_8Ch = 0;
d.Unknown_9Ah = 33;//WTF is this???
d.FileVFT = 1079446584;
d.FileUnknown = 1;
if (mlHigh.Count > 0)
{
d.DrawableModelsHigh = new ResourcePointerList64<DrawableModel>();
d.DrawableModelsHigh.data_items = mlHigh.ToArray();
d.Unknown_80h = 65281;//WTF is this??? 0xFF00 + ?
}
if (mlMed.Count > 0)
{
d.DrawableModelsMedium = new ResourcePointerList64<DrawableModel>();
d.DrawableModelsMedium.data_items = mlMed.ToArray();
d.LodDistHigh = bsRad * 2.0f; //when med models present, generate a high lod dist..
d.Unknown_84h = 65281;//WTF is this??? 0xFF00 + ?
}
if (mlLow.Count > 0)
{
d.DrawableModelsLow = new ResourcePointerList64<DrawableModel>();
d.DrawableModelsLow.data_items = mlLow.ToArray();
d.LodDistMed = bsRad * 8.0f; //when low models present, generate a med lod dist..
d.Unknown_88h = 65281;//WTF is this??? 0xFF00 + ?
}
if (mlVlow.Count > 0)
{
d.DrawableModelsVeryLow = new ResourcePointerList64<DrawableModel>();
d.DrawableModelsVeryLow.data_items = mlVlow.ToArray();
d.LodDistLow = bsRad * 32.0f; //when vlow models present, generate a low lod dist..
d.Unknown_8Ch = 65281;//WTF is this??? 0xFF00 + ?
}
d.DrawableModelsX = d.DrawableModelsHigh;
d.LightAttributes = new ResourceSimpleList64_s<LightAttributes_s>();
//todo: light attributes?
return d;
}
private List<FbxModel> TryConvertModels(FbxNode mnode)
{
var result = new List<FbxModel>();
var nodemodel = TryConvertModel(mnode);
if (nodemodel != null)
{
result.Add(nodemodel);
}
foreach (var cnode in mnode.Connections)
{
if (cnode.Name == "Model")
{
var mlist = TryConvertModels(cnode);
if (mlist != null)
{
result.AddRange(mlist);
}
}
}
return result;
}
private FbxModel TryConvertModel(FbxNode mnode)
{
FbxNode geonode = null;
var matnodes = new List<FbxNode>();
foreach (var cnode in mnode.Connections)
{
if (cnode == null) continue;
switch (cnode.Name)
{
case "Geometry":
geonode = cnode;
break;
case "Material":
matnodes.Add(cnode);
break;
}
}
if (geonode == null) return null;
if (matnodes.Count == 0)
return null; //need atleast one material...
var fnEdges = geonode["Edges"]?.Value as int[];//do we need this? maybe for collision/navmesh
var fnVerts = geonode["Vertices"]?.Value as double[];
var fnIndices = geonode["PolygonVertexIndex"]?.Value as int[];
if ((fnVerts == null) || (fnIndices == null))
{ return null; } //no mesh data.. abort!
var fnNormals = new List<FbxNode>();
var fnBinormals = new List<FbxNode>();
var fnTangents = new List<FbxNode>();
var fnTexcoords = new List<FbxNode>();
var fnColours = new List<FbxNode>();
var fnMaterials = new List<FbxNode>();
foreach (var cnode in geonode.Nodes)
{
if (cnode == null) continue;
switch (cnode.Name)
{
case "LayerElementNormal": fnNormals.Add(cnode); break;
case "LayerElementBinormal": fnBinormals.Add(cnode); break;
case "LayerElementTangent": fnTangents.Add(cnode); break;
case "LayerElementUV": fnTexcoords.Add(cnode); break;
case "LayerElementColor": fnColours.Add(cnode); break;
case "LayerElementMaterial": fnMaterials.Add(cnode); break;
case "LayerElementSmoothing": break;//ignore currently
case "Layer": break;//ignore- merge all layers data instead
}
}
var nNormals = fnNormals.Count;
var nBinormals = fnBinormals.Count;
var nTangents = fnTangents.Count;
var nTexcoords = fnTexcoords.Count;
var nColours = fnColours.Count;
var nMaterials = fnMaterials.Count;
var fPolys = new List<FbxPolygon>();
var fPolyVerts = new List<FbxVertex>();
var fPolysByMat = new List<FbxPolygon>[matnodes.Count];
foreach (var fnIndex in fnIndices) //build the polygons.
{
var pVert = new FbxVertex();
pVert.Position = GetVector3FromDoubleArray(fnVerts, (fnIndex < 0) ? (-fnIndex-1) : fnIndex);
pVert.Normals = nNormals > 0 ? new Vector3[nNormals] : null;
pVert.Binormals = nBinormals > 0 ? new Vector3[nBinormals] : null;
pVert.Tangents = nTangents > 0 ? new Vector3[nTangents] : null;
pVert.Texcoords = nTexcoords > 0 ? new Vector2[nTexcoords] : null;
pVert.Colours = nColours > 0 ? new Vector4[nColours] : null;
fPolyVerts.Add(pVert);
if (fnIndex < 0) //yeah because negative index means end of polygon...
{
var fPoly = new FbxPolygon();
fPoly.Vertices = fPolyVerts.ToArray();
fPoly.Materials = nMaterials > 0 ? new FbxNode[nMaterials] : null;
fPolyVerts.Clear();
fPolys.Add(fPoly);
if (fPoly.Vertices.Length > 3)
{ } //more than 3 vertices in this poly! will need to split it into triangles!! but do it later since all poly verts are needed for next steps
}
}
for (int i = 0; i < nNormals; i++)
{
var fnNorms = fnNormals[i];
var arNorms = fnNorms["Normals"]?.Value as double[];
var aiNorms = fnNorms["NormalIndex"]?.Value as int[];
if (!IsByPolygonVertexMapType(fnNorms))
{ continue; }
var indexed = IsIndexToDirectRefType(fnNorms);
if (indexed && (aiNorms == null))
{ continue; } //need the index array if it's IndexToDirect!
int j = 0;
foreach (var fPoly in fPolys)
{
foreach (var fVert in fPoly.Vertices)
{
var ai = indexed ? aiNorms[j] : j;
fVert.Normals[i] = GetVector3FromDoubleArray(arNorms, ai);
j++;
}
}
}
for (int i = 0; i < nBinormals; i++)
{
var fnBinorms = fnBinormals[i];
var arBinorms = fnBinorms["Binormals"]?.Value as double[];
var aiBinorms = fnBinorms["BinormalIndex"]?.Value as int[];
if (!IsByPolygonVertexMapType(fnBinorms))
{ continue; }
var indexed = IsIndexToDirectRefType(fnBinorms);
if (indexed && (aiBinorms == null))
{ continue; } //need the index array if it's IndexToDirect!
int j = 0;
foreach (var fPoly in fPolys)
{
foreach (var fVert in fPoly.Vertices)
{
var ai = indexed ? aiBinorms[j] : j;
fVert.Binormals[i] = GetVector3FromDoubleArray(arBinorms, ai);
j++;
}
}
}
for (int i = 0; i < nTangents; i++)
{
var fnTangs = fnTangents[i];
var arTangs = fnTangs["Tangents"]?.Value as double[];
var aiTangs = fnTangs["TangentIndex"]?.Value as int[];
if (!IsByPolygonVertexMapType(fnTangs))
{ continue; }
var indexed = IsIndexToDirectRefType(fnTangs);
if (indexed && (aiTangs == null))
{ continue; } //need the index array if it's IndexToDirect!
int j = 0;
foreach (var fPoly in fPolys)
{
foreach (var fVert in fPoly.Vertices)
{
var ai = indexed ? aiTangs[j] : j;
fVert.Tangents[i] = GetVector3FromDoubleArray(arTangs, ai);
j++;
}
}
}
for (int i = 0; i < nTexcoords; i++)
{
var fnTexcs = fnTexcoords[i];
var arTexcs = fnTexcs["UV"]?.Value as double[];
var aiTexcs = fnTexcs["UVIndex"]?.Value as int[];
if (!IsByPolygonVertexMapType(fnTexcs))
{ continue; }
var indexed = IsIndexToDirectRefType(fnTexcs);
if (indexed && (aiTexcs == null))
{ continue; } //need the index array if it's IndexToDirect!
int j = 0;
foreach (var fPoly in fPolys)
{
foreach (var fVert in fPoly.Vertices)
{
var ai = indexed ? aiTexcs[j] : j;
var tc = GetVector2FromDoubleArray(arTexcs, ai);
fVert.Texcoords[i] = InvertTexcoordV ? new Vector2(tc.X, -tc.Y) : tc;//whyyyy
j++;
}
}
}
for (int i = 0; i < nColours; i++)
{
var fnCols = fnColours[i];
var arCols = fnCols["Colors"]?.Value as double[];
var aiCols = fnCols["ColorIndex"]?.Value as int[];
if (!IsByPolygonVertexMapType(fnCols))
{ continue; }
var indexed = IsIndexToDirectRefType(fnCols);
if (indexed && (aiCols == null))
{ continue; } //need the index array if it's IndexToDirect!
int j = 0;
foreach (var fPoly in fPolys)
{
foreach (var fVert in fPoly.Vertices)
{
var ai = indexed ? aiCols[j] : j;
fVert.Colours[i] = GetVector4FromDoubleArray(arCols, ai);
j++;
}
}
}
for (int i = 0; i < nMaterials; i++)
{
var fnMats = fnMaterials[i];
var arMats = fnMats["Materials"]?.Value as int[];
var mapType = fnMats["MappingInformationType"]?.Value as string;
var refType = fnMats["ReferenceInformationType"]?.Value as string;
var allSame = false;
switch (mapType)
{
case "ByPolygon": break;
case "AllSame": allSame = true; break;
default:
continue;
}
switch (refType)
{
case "IndexToDirect": break;
default:
continue;
}
for (int j = 0; j < fPolys.Count; j++)
{
var fPoly = fPolys[j];
var iMat = allSame ? arMats[0] : arMats[j];
fPoly.Materials[i] = matnodes[iMat];
//group all the polygons by material...
var matPolys = fPolysByMat[iMat];
if (matPolys == null)
{
matPolys = new List<FbxPolygon>();
fPolysByMat[iMat] = matPolys;
}
matPolys.Add(fPoly);
}
}
var dModel = new DrawableModel();
var dGeoms = new List<DrawableGeometry>();
var dGeomAABBs = new List<AABB_s>();
var dModelAABB = new AABB_s();
for (int i = 0; i < fPolysByMat.Length; i++)
{
AABB_s dGeomAABB;
var dGeom = TryConvertGeometry(fPolysByMat[i], matnodes[i], out dGeomAABB);
if (dGeom != null)
{
dGeoms.Add(dGeom);
dGeomAABBs.Add(dGeomAABB);
}
}
if (dGeomAABBs.Count > 1)//need to include whole model AABB first, if more than one geometry..
{
var dGeomAABBs2 = new List<AABB_s>();
dModelAABB.Min = new Vector4(float.MaxValue);
dModelAABB.Max = new Vector4(float.MinValue);
foreach (var aabb in dGeomAABBs)
{
dModelAABB.Min = Vector4.Min(dModelAABB.Min, aabb.Min);
dModelAABB.Max = Vector4.Max(dModelAABB.Max, aabb.Max);
}
dGeomAABBs2.Add(dModelAABB);
dGeomAABBs2.AddRange(dGeomAABBs);
dGeomAABBs = dGeomAABBs2;
}
dModel.VFT = 1080101496;//is this needed?
dModel.Unknown_4h = 1;
dModel.RenderMaskFlags = 0x00FF; //GIMS "Mask"
dModel.Geometries = new ResourcePointerArray64<DrawableGeometry>();
dModel.Geometries.data_items = dGeoms.ToArray();
dModel.GeometriesCount1 = (ushort)dGeoms.Count;
dModel.GeometriesCount2 = (ushort)dGeoms.Count;
dModel.GeometriesCount3 = (ushort)dGeoms.Count;
dModel.BoundsData = dGeomAABBs.ToArray();
//shader mappings array will be added when adding models to drawable.
var fModel = new FbxModel();
fModel.Name = (mnode.Properties.Count > 1) ? (mnode.Properties[1] as string)?.Replace("Model::", "") : null;
fModel.Node = mnode;
fModel.Model = dModel;
return fModel;
}
private DrawableGeometry TryConvertGeometry(List<FbxPolygon> fPolys, FbxNode matNode, out AABB_s aabb)
{
aabb = new AABB_s();
if (matNode == null) return null;
if (fPolys == null) return null;
if (fPolys.Count == 0) return null;
var dShader = TryConvertMaterial(matNode);
var dVertDecl = GetVertexDeclaration(dShader);
var vDict = new Dictionary<FbxVertex, ushort>();
var vList = new List<FbxVertex>();
var iList = new List<ushort>();
foreach (var fPoly in fPolys)
{
if (fPoly.Vertices == null) continue;
if (vList.Count >= 65535)
break;//too many vertices in this geometry!!
ushort i0 = 0;//first generated index
ushort iP = 0;//previous generated index
ushort iN = 0;//current index
for (int v = 0; v < fPoly.Vertices.Length; v++)
{
var vert = fPoly.Vertices[v];
vert.GenVertexBytes(dVertDecl);
if (!vDict.TryGetValue(vert, out iN))
{
iN = (ushort)vList.Count;
vDict[vert] = iN;
vList.Add(vert);
}
else
{ }//found identical vertex, use its index
if (v == 0) i0 = iN;
if (v < 3) //first triangle
{
iList.Add(iN);
}
else //for each extra vertex, make triangle from v0, vN-1, vN - assumes convex polygon!!
{
iList.Add(i0);
iList.Add(iP);
iList.Add(iN);
}
iP = iN;
}
}
var vStride = dVertDecl.Stride;
var vBytes = new byte[vList.Count * vStride];
for (int i = 0; i < vList.Count; i++)
{
var v = vList[i].Bytes;
var o = i * vStride;
for (int j = 0; j < vStride; j++)
{
vBytes[o + j] = v[j];
}
}
if (vList.Count > 0)
{
aabb.Min = new Vector4(float.MaxValue);
aabb.Max = new Vector4(float.MinValue);
foreach (var vert in vList)
{
var v = new Vector4(vert.Position, vert.Position.X);
aabb.Min = Vector4.Min(aabb.Min, v);
aabb.Max = Vector4.Max(aabb.Max, v);
}
}
var vData = new VertexData();
vData.info = dVertDecl;
vData.VertexType = (VertexType)dVertDecl.Flags;
vData.VertexStride = dVertDecl.Stride;
vData.VertexCount = vList.Count;
vData.VertexBytes = vBytes;
var vBuff = new VertexBuffer();
vBuff.Data1 = vData;
vBuff.Data2 = vData;
vBuff.Info = dVertDecl;
vBuff.VertexCount = (uint)vList.Count;
vBuff.VertexStride = vStride;
vBuff.VFT = 1080153064;//is this needed?
vBuff.Unknown_4h = 1;
var iBuff = new IndexBuffer();
iBuff.IndicesCount = (uint)iList.Count;
iBuff.Indices = iList.ToArray();
iBuff.VFT = 1080111576;//is this needed?
iBuff.Unknown_4h = 1;
var dGeom = new DrawableGeometry();
dGeom.Shader = dShader;
dGeom.VertexData = vData;
dGeom.VertexBuffer = vBuff;
dGeom.IndexBuffer = iBuff;
dGeom.VFT = 1080133736;//is this needed?
dGeom.Unknown_4h = 1;
dGeom.IndicesCount = (uint)iList.Count;
dGeom.TrianglesCount = (uint)iList.Count / 3;
dGeom.VerticesCount = (ushort)vList.Count;
dGeom.Unknown_62h = 3; //indices per triangle..?
dGeom.VertexStride = vStride;
dGeom.BoneIdsCount = 0;//todo: bones
return dGeom;
}
private ShaderFX TryConvertMaterial(FbxNode matNode)
{
var shader = new ShaderFX();
var spsName = "default";
var texConns = new List<FbxNode>();
var texNames = new List<string>();
#region 3dsmax/GIMS properties
//var floatValueNames = new List<string>();
//var floatValues = new List<Vector4>();
//var texValueNames = new List<string>();
//var texValues = new List<FbxNode>();
//var matProps = matNode["Properties70"];
//foreach (var matProp in matProps.Nodes)//currently broken due to GIMS not doing things right
//{
// if (matProp == null) continue;
// if (matProp.Name != "P") continue;
// var propStr = GetStringFromObjectList(matProp.Properties, 4);
// var propId = matProp.Value as string;
// if (propId == null) continue;
// if (propId == "3dsMax|params|SPSName") spsName = propStr?.ToLowerInvariant() ?? "default";
// if (propId.StartsWith("3dsMax|params|FloatValueNames|FloatValueNames")) floatValueNames.Add(propStr);
// if (propId.StartsWith("3dsMax|params|FloatValues|FloatValues")) floatValues.Add(GetVector4FromObjectList(matProp.Properties, 4));
// if (propId.StartsWith("3dsMax|params|TexValueNames|TexValueNames")) texValueNames.Add(propStr);
// if (propId.StartsWith("3dsMax|params|TexValues|TexValues")) texValues.Add(matProp);
//}
#endregion
foreach (var conn in matNode.Connections)
{
if (conn.Name == "Texture")
{
texConns.Add(conn);
var texName = GetStringFromObjectList(conn.Properties, 1)?.Replace("Texture::", "");
var ftexName = conn["FileName"]?.Value as string;
if (ftexName != null)
{
try
{
texName = Path.GetFileNameWithoutExtension(ftexName);
}
catch
{ }
}
texNames.Add(texName);
}
}
if (texNames.Count > 1)
{
spsName = "normal";
}
var spsFileName = spsName + ".sps";
shader.Name = JenkHash.GenHash(spsName);
shader.FileName = JenkHash.GenHash(spsFileName);
shader.ParametersList = new ShaderParametersBlock();
var paramsBlock = shader.ParametersList;
var pNames = new List<MetaName>();
var pVals = new List<ShaderParameter>();
shader.Unknown_Ch = 0;
shader.RenderBucket = 0;
shader.Unknown_12h = 32768;//shrugs
shader.Unknown_1Ch = 0;
shader.Unknown_24h = 0;
shader.Unknown_26h = 0;
shader.Unknown_28h = 0;
shader.Unknown_2Ch = 0;
switch (spsName)
{
default:
case "default":
//shader.RenderBucket = 3;
//shader.ParameterSize = 208;
//shader.ParameterDataSize = 272;
AddShaderParam(pNames, pVals, MetaName.DiffuseSampler, GetTextureBaseParam(texNames, 0));//assume first texture is diffuse...
AddShaderParam(pNames, pVals, MetaName.matMaterialColorScale, new Vector4(1, 0, 0, 1));
AddShaderParam(pNames, pVals, MetaName.HardAlphaBlend, new Vector4(0, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.useTessellation, new Vector4(0, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.wetnessMultiplier, new Vector4(1, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.globalAnimUV1, new Vector4(0, 1, 0, 0));
AddShaderParam(pNames, pVals, MetaName.globalAnimUV0, new Vector4(1, 0, 0, 0));
break;
case "normal":
//shader.RenderBucket = 0;
//shader.ParameterSize = 320;
//shader.ParameterDataSize = 400;
AddShaderParam(pNames, pVals, MetaName.DiffuseSampler, GetTextureBaseParam(texNames, 0));//assume first texture is diffuse...
AddShaderParam(pNames, pVals, MetaName.BumpSampler, GetTextureBaseParam(texNames, 1));//assume 2nd texture is normalmap..
AddShaderParam(pNames, pVals, MetaName.HardAlphaBlend, new Vector4(1, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.useTessellation, new Vector4(0, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.wetnessMultiplier, new Vector4(1, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.bumpiness, new Vector4(1, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.specularIntensityMult, new Vector4(0.5f, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.specularFalloffMult, new Vector4(20, 0, 0, 0));//too metallic?
AddShaderParam(pNames, pVals, MetaName.specularFresnel, new Vector4(0.9f, 0, 0, 0));
AddShaderParam(pNames, pVals, MetaName.globalAnimUV1, new Vector4(0, 1, 0, 0));
AddShaderParam(pNames, pVals, MetaName.globalAnimUV0, new Vector4(1, 0, 0, 0));
break;
}
for (int i = 0; i < pVals.Count; i++)
{
var pVal = pVals[i];
if (pVal.DataType == 1)
{
pVal.Unknown_1h = (byte)(160 + ((pVals.Count - 1) - i));//seriously wtf is this and why
}
}
paramsBlock.Hashes = pNames.ToArray();
paramsBlock.Parameters = pVals.ToArray();
paramsBlock.Count = pVals.Count;
shader.ParameterSize = paramsBlock.ParametersSize;
shader.ParameterDataSize = (ushort)(paramsBlock.BlockLength + 36);//but why +36?
shader.ParameterCount = (byte)pVals.Count;
shader.TextureParametersCount = paramsBlock.TextureParamsCount;
shader.RenderBucketMask = (1u << shader.RenderBucket) | 0xFF00;
return shader;
}
private TextureBase GetTextureBaseParam(List<string> texNames, int index)
{
var name = "givemechecker";
if (texNames.Count > index)
{
var nameval = texNames[index];
if (nameval != null)
{
name = texNames[index];
}
}
var texParam = new TextureBase();
texParam.Unknown_4h = 1;
texParam.Unknown_30h = 131073;//wtf is this? 2x shorts, 0x00020001
texParam.Name = name;
texParam.NameHash = JenkHash.GenHash(name.ToLowerInvariant());
return texParam;
}
private void AddShaderParam(List<MetaName> paramNames, List<ShaderParameter> paramValues, MetaName paramName, object paramValue)
{
var p = new ShaderParameter();
p.Data = paramValue;
if (paramValue is TextureBase)
{
p.DataType = 0;
p.Unknown_1h = (byte)((paramNames.Count > 0) ? paramNames.Count + 1 : 0);//seriously wtf is this?
}
else if (paramValue is Vector4)
{
p.DataType = 1;
}
else
{ }
paramNames.Add(paramName);
paramValues.Add(p);
}
private VertexDeclaration GetVertexDeclaration(ShaderFX shader)
{
var d = new VertexDeclaration();
d.Types = 8598872888530528662;
d.Unknown_6h = 0;
switch (shader.Name)
{
default:
case 3839837909: //default
d.Flags = 89;
d.Stride = 36;
d.Count = 4;
break;
case 1330140418: //normal
d.Flags = 16473;
d.Stride = 52;
d.Count = 5;
break;
}
return d;
}
private bool IsByPolygonVertexMapType(FbxNode node)
{
var mapType = node["MappingInformationType"]?.Value as string;
if (mapType != "ByPolygonVertex")
{ return false; } //any other types?
return true;
}
private bool IsIndexToDirectRefType(FbxNode node)
{
var refType = node["ReferenceInformationType"]?.Value as string;
var indexed = false;
switch (refType)
{
case "Direct": break;
case "IndexToDirect": indexed = true; break;
default:
break;//shouldn't be possible
}
return indexed;
}
private Vector2 GetVector2FromDoubleArray(double[] arr, int i)
{
var aIndX = i * 2;
var aIndY = aIndX + 1;
var pX = aIndX < arr.Length ? arr[aIndX] : 0;
var pY = aIndY < arr.Length ? arr[aIndY] : 0;
return new Vector2((float)pX, (float)pY);
}
private Vector3 GetVector3FromDoubleArray(double[] arr, int i)
{
var aIndX = i * 3;
var aIndY = aIndX + 1;
var aIndZ = aIndX + 2;
var pX = aIndX < arr.Length ? arr[aIndX] : 0;
var pY = aIndY < arr.Length ? arr[aIndY] : 0;
var pZ = aIndZ < arr.Length ? arr[aIndZ] : 0;
return new Vector3((float)pX, (float)pY, (float)pZ);
}
private Vector4 GetVector4FromDoubleArray(double[] arr, int i)
{
var aIndX = i * 4;
var aIndY = aIndX + 1;
var aIndZ = aIndX + 2;
var aIndW = aIndX + 3;
var pX = aIndX < arr.Length ? arr[aIndX] : 0;
var pY = aIndY < arr.Length ? arr[aIndY] : 0;
var pZ = aIndZ < arr.Length ? arr[aIndZ] : 0;
var pW = aIndW < arr.Length ? arr[aIndW] : 0;
return new Vector4((float)pX, (float)pY, (float)pZ, (float)pW);
}
private Vector4 GetVector4FromObjectList(List<object> list, int i)
{
var aIndX = i;
var aIndY = aIndX + 1;
var aIndZ = aIndX + 2;
var aIndW = aIndX + 3;
var pX = aIndX < list.Count ? list[aIndX] : 0;
var pY = aIndY < list.Count ? list[aIndY] : 0;
var pZ = aIndZ < list.Count ? list[aIndZ] : 0;
var pW = aIndW < list.Count ? list[aIndW] : 0;
var r = Vector4.Zero;
if (pX is double) r.X = (float)(double)pX;
if (pY is double) r.Y = (float)(double)pY;
if (pZ is double) r.Z = (float)(double)pZ;
if (pW is double) r.W = (float)(double)pW;
return r;
}
private string GetStringFromObjectList(List<object> list, int i)
{
return (list.Count > i) ? list[i] as string : string.Empty;
}
}
public class FbxModel
{
public string Name { get; set; }
public FbxNode Node { get; set; }
public DrawableModel Model { get; set; }
public override string ToString()
{
return Name;
}
}
public class FbxPolygon
{
public FbxVertex[] Vertices { get; set; }
public FbxNode[] Materials { get; set; }
}
public class FbxVertex : IEquatable<FbxVertex>
{
public Vector3 Position { get; set; }
public Vector3[] Normals { get; set; }
public Vector3[] Binormals { get; set; }
public Vector3[] Tangents { get; set; }
public Vector2[] Texcoords { get; set; }
public Vector4[] Colours { get; set; }
public byte[] Bytes { get; set; }
public void GenVertexBytes(VertexDeclaration decl)
{
Bytes = new byte[decl.Stride];
switch ((VertexType)decl.Flags)
{
default:
case VertexType.Default://PNCT
WriteBytes(Position, 0);
WriteBytes((Normals?.Length > 0) ? Normals[0] : Vector3.UnitZ, 12);
WriteBytes(GetColourInt((Colours?.Length > 0) ? Colours[0] : Vector4.One), 24);
WriteBytes((Texcoords?.Length > 0) ? Texcoords[0] : Vector2.Zero, 28);
break;
case VertexType.DefaultEx://PNCTX
WriteBytes(Position, 0);
WriteBytes((Normals?.Length > 0) ? Normals[0] : Vector3.UnitZ, 12);
WriteBytes(GetColourInt((Colours?.Length > 0) ? Colours[0] : Vector4.One), 24);
WriteBytes((Texcoords?.Length > 0) ? Texcoords[0] : Vector2.Zero, 28);
WriteBytes(new Vector4((Tangents?.Length > 0) ? Tangents[0] : Vector3.UnitX, 0), 36);
//WriteBytes(new Vector4((Binormals?.Length > 0) ? Binormals[0] : Vector3.UnitX, 0), 36);
break;
}
}
private void WriteBytes<T>(T val, int offset) where T : struct
{
var data = MetaTypes.ConvertToBytes(val);
for (int i = 0; i < data.Length; i++)
{
Bytes[offset + i] = data[i];
}
}
private int GetColourInt(Vector4 c)
{
Color v = new Color(c);
return v.ToRgba();
}
public override bool Equals(object obj)
{
return Equals(obj as FbxVertex);
}
public bool Equals(FbxVertex other)
{
return (other != null)
&& ((Bytes == null) ? (other.Bytes == null) : Bytes.SequenceEqual(other.Bytes));
}
public override int GetHashCode()
{
var hashCode = -907793594;
if (Bytes != null) hashCode = hashCode * -1521134295 + ((IStructuralEquatable)Bytes).GetHashCode(EqualityComparer<byte>.Default);
return hashCode;
}
}
}

View File

@ -27,6 +27,14 @@ namespace CodeWalker
return new Vector3(x, y, z);
//this quick mul ignores W...
}
public static Vector3 MultiplyRot(this Matrix m, Vector3 v)
{
float x = (((m.M11 * v.X) + (m.M21 * v.Y)) + (m.M31 * v.Z));// + m.M41;
float y = (((m.M12 * v.X) + (m.M22 * v.Y)) + (m.M32 * v.Z));// + m.M42;
float z = (((m.M13 * v.X) + (m.M23 * v.Y)) + (m.M33 * v.Z));// + m.M43;
return new Vector3(x, y, z);
//this quick mul ignores W and translation...
}
public static Vector4 Multiply(this Matrix m, Vector4 v)
{

View File

@ -114,6 +114,11 @@ namespace CodeWalker
var c = CultureInfo.InvariantCulture;
return v.X.ToString(c) + ", " + v.Y.ToString(c);
}
public static string GetVector2XmlString(Vector2 v)
{
var c = CultureInfo.InvariantCulture;
return string.Format("x=\"{0}\" y=\"{1}\"", v.X.ToString(c), v.Y.ToString(c));
}
public static string GetVector3String(Vector3 v)
{
var c = CultureInfo.InvariantCulture;
@ -140,21 +145,37 @@ namespace CodeWalker
return string.Format("x=\"{0}\" y=\"{1}\" z=\"{2}\" w=\"{3}\"", q.X.ToString(c), q.Y.ToString(c), q.Z.ToString(c), q.W.ToString(c));
}
public static Vector2 ParseVector2String(string s)
{
Vector2 p = new Vector2(0.0f);
string[] ss = s.Split(',');
if (ss.Length > 0)
{
TryParse(ss[0].Trim(), out p.X);
}
if (ss.Length > 1)
{
TryParse(ss[1].Trim(), out p.Y);
}
return p;
}
public static Vector3 ParseVector3String(string s)
{
Vector3 p = new Vector3(0.0f);
string[] ss = s.Split(',');
if (ss.Length > 0)
{
FloatUtil.TryParse(ss[0].Trim(), out p.X);
TryParse(ss[0].Trim(), out p.X);
}
if (ss.Length > 1)
{
FloatUtil.TryParse(ss[1].Trim(), out p.Y);
TryParse(ss[1].Trim(), out p.Y);
}
if (ss.Length > 2)
{
FloatUtil.TryParse(ss[2].Trim(), out p.Z);
TryParse(ss[2].Trim(), out p.Z);
}
return p;
}
@ -172,19 +193,19 @@ namespace CodeWalker
string[] ss = s.Split(',');
if (ss.Length > 0)
{
FloatUtil.TryParse(ss[0].Trim(), out p.X);
TryParse(ss[0].Trim(), out p.X);
}
if (ss.Length > 1)
{
FloatUtil.TryParse(ss[1].Trim(), out p.Y);
TryParse(ss[1].Trim(), out p.Y);
}
if (ss.Length > 2)
{
FloatUtil.TryParse(ss[2].Trim(), out p.Z);
TryParse(ss[2].Trim(), out p.Z);
}
if (ss.Length > 3)
{
FloatUtil.TryParse(ss[3].Trim(), out p.W);
TryParse(ss[3].Trim(), out p.W);
}
return p;
}

View File

@ -4,18 +4,17 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CodeWalker.GameFiles;
namespace CodeWalker
{
public static class Vectors
{
public static Vector3 XYZ(this Vector4 v)
{
return new Vector3(v.X, v.Y, v.Z);
}
public static Vector3 Round(this Vector3 v)
{
return new Vector3((float)Math.Round(v.X), (float)Math.Round(v.Y), (float)Math.Round(v.Z));
@ -26,6 +25,15 @@ namespace CodeWalker
return new Vector4((float)Math.Floor(v.X), (float)Math.Floor(v.Y), (float)Math.Floor(v.Z), (float)Math.Floor(v.W));
}
public static Vector4 Abs(this Vector4 v)
{
return new Vector4(Math.Abs(v.X), Math.Abs(v.Y), Math.Abs(v.Z), Math.Abs(v.W));
}
public static Quaternion ToQuaternion(this Vector4 v)
{
return new Quaternion(v);
}
}

View File

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
@ -32,6 +33,14 @@ namespace CodeWalker
int.TryParse(val, out i);
return i;
}
public static uint GetUIntAttribute(XmlNode node, string attribute)
{
if (node == null) return 0;
string val = node.Attributes[attribute]?.InnerText;
uint i;
uint.TryParse(val, out i);
return i;
}
public static float GetFloatAttribute(XmlNode node, string attribute)
{
if (node == null) return 0;
@ -70,6 +79,26 @@ namespace CodeWalker
FloatUtil.TryParse(val, out f);
return f;
}
public static T GetChildEnumInnerText<T>(XmlNode node, string name) where T : struct
{
if (node == null) return new T();
string val = node.SelectSingleNode(name)?.InnerText;
return GetEnumValue<T>(val);
}
public static T GetEnumValue<T>(string val) where T : struct
{
if (val.StartsWith("hash_"))
{
//convert hash_12ABC to Unk_12345
var substr = val.Substring(5);
var uval = Convert.ToUInt32(substr, 16);
val = "Unk_" + uval.ToString();
}
T enumval;
Enum.TryParse(val, out enumval);
return enumval;
}
public static bool GetChildBoolAttribute(XmlNode node, string name, string attribute)
{
@ -87,6 +116,22 @@ namespace CodeWalker
int.TryParse(val, out i);
return i;
}
public static uint GetChildUIntAttribute(XmlNode node, string name, string attribute)
{
if (node == null) return 0;
string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText;
uint i;
if (val?.StartsWith("0x") ?? false)
{
var subs = val.Substring(2);
i = Convert.ToUInt32(subs, 16);
}
else
{
uint.TryParse(val, out i);
}
return i;
}
public static float GetChildFloatAttribute(XmlNode node, string name, string attribute)
{
if (node == null) return 0;
@ -101,6 +146,12 @@ namespace CodeWalker
string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText;
return val;
}
public static Vector2 GetChildVector2Attributes(XmlNode node, string name, string x, string y)
{
float fx = GetChildFloatAttribute(node, name, x);
float fy = GetChildFloatAttribute(node, name, y);
return new Vector2(fx, fy);
}
public static Vector3 GetChildVector3Attributes(XmlNode node, string name, string x, string y, string z)
{
float fx = GetChildFloatAttribute(node, name, x);
@ -108,6 +159,14 @@ namespace CodeWalker
float fz = GetChildFloatAttribute(node, name, z);
return new Vector3(fx, fy, fz);
}
public static Vector4 GetChildVector4Attributes(XmlNode node, string name, string x, string y, string z, string w)
{
float fx = GetChildFloatAttribute(node, name, x);
float fy = GetChildFloatAttribute(node, name, y);
float fz = GetChildFloatAttribute(node, name, z);
float fw = GetChildFloatAttribute(node, name, w);
return new Vector4(fx, fy, fz, fw);
}
public static XmlElement GetChild(XmlElement element, string name)
{
@ -133,5 +192,182 @@ namespace CodeWalker
return child;
}
public static byte[] GetRawByteArray(XmlNode node)
{
if (node == null) return new byte[0];
var data = new List<byte>();
var split = Regex.Split(node.InnerText, @"[\s\r\n\t]");
for (int i = 0; i < split.Length; i++)
{
if (!string.IsNullOrEmpty(split[i]))
{
var str = split[i];
if (string.IsNullOrEmpty(str)) continue;
var val = Convert.ToByte(str, 16);
data.Add(val);
}
}
return data.ToArray();
}
public static byte[] GetChildRawByteArray(XmlNode node, string name)
{
var cnode = node.SelectSingleNode(name);
return GetRawByteArray(cnode);
}
public static float[] GetRawFloatArray(XmlNode node)
{
if (node == null) return new float[0];
var items = new List<float>();
var split = node.InnerText.Split('\n');// Regex.Split(node.InnerText, @"[\s\r\n\t]");
for (int i = 0; i < split.Length; i++)
{
var s = split[i]?.Trim();
if (string.IsNullOrEmpty(s)) continue;
var f = FloatUtil.Parse(s);
items.Add(f);
}
return items.ToArray();
}
public static float[] GetChildRawFloatArray(XmlNode node, string name)
{
var cnode = node.SelectSingleNode(name);
return GetRawFloatArray(cnode);
}
public static Vector2[] GetRawVector2Array(XmlNode node)
{
if (node == null) return new Vector2[0];
float x = 0f;
float y = 0f;
var items = new List<Vector2>();
var split = node.InnerText.Split('\n');// Regex.Split(node.InnerText, @"[\s\r\n\t]");
for (int i = 0; i < split.Length; i++)
{
var s = split[i]?.Trim();
if (string.IsNullOrEmpty(s)) continue;
var split2 = s.Split(',');// Regex.Split(s, @"[\s\t]");
int c = 0;
x = 0f; y = 0f;
for (int n = 0; n < split2.Length; n++)
{
var ts = split2[n]?.Trim();
if (string.IsNullOrEmpty(ts)) continue;
var f = FloatUtil.Parse(ts);
switch (c)
{
case 0: x = f; break;
case 1: y = f; break;
//case 2: z = f; break;
}
c++;
}
if (c >= 2)
{
var val = new Vector2(x, y);
items.Add(val);
}
}
return items.ToArray();
}
public static Vector2[] GetChildRawVector2Array(XmlNode node, string name)
{
var cnode = node.SelectSingleNode(name);
return GetRawVector2Array(cnode);
}
public static Vector3[] GetRawVector3Array(XmlNode node)
{
if (node == null) return new Vector3[0];
float x = 0f;
float y = 0f;
float z = 0f;
var items = new List<Vector3>();
var split = node.InnerText.Split('\n');// Regex.Split(node.InnerText, @"[\s\r\n\t]");
for (int i = 0; i < split.Length; i++)
{
var s = split[i]?.Trim();
if (string.IsNullOrEmpty(s)) continue;
var split2 = s.Split(',');// Regex.Split(s, @"[\s\t]");
int c = 0;
x = 0f; y = 0f;
for (int n = 0; n < split2.Length; n++)
{
var ts = split2[n]?.Trim();
if (string.IsNullOrEmpty(ts)) continue;
var f = FloatUtil.Parse(ts);
switch (c)
{
case 0: x = f; break;
case 1: y = f; break;
case 2: z = f; break;
}
c++;
}
if (c >= 3)
{
var val = new Vector3(x, y, z);
items.Add(val);
}
}
return items.ToArray();
}
public static Vector3[] GetChildRawVector3Array(XmlNode node, string name)
{
var cnode = node.SelectSingleNode(name);
return GetRawVector3Array(cnode);
}
public static Vector4[] GetRawVector4Array(XmlNode node)
{
if (node == null) return new Vector4[0];
float x = 0f;
float y = 0f;
float z = 0f;
float w = 0f;
var items = new List<Vector4>();
var split = node.InnerText.Split('\n');// Regex.Split(node.InnerText, @"[\s\r\n\t]");
for (int i = 0; i < split.Length; i++)
{
var s = split[i]?.Trim();
if (string.IsNullOrEmpty(s)) continue;
var split2 = s.Split(',');// Regex.Split(s, @"[\s\t]");
int c = 0;
x = 0f; y = 0f;
for (int n = 0; n < split2.Length; n++)
{
var ts = split2[n]?.Trim();
if (string.IsNullOrEmpty(ts)) continue;
var f = FloatUtil.Parse(ts);
switch (c)
{
case 0: x = f; break;
case 1: y = f; break;
case 2: z = f; break;
case 3: w = f; break;
}
c++;
}
if (c >= 4)
{
var val = new Vector4(x, y, z, w);
items.Add(val);
}
}
return items.ToArray();
}
public static Vector4[] GetChildRawVector4Array(XmlNode node, string name)
{
var cnode = node.SelectSingleNode(name);
return GetRawVector4Array(cnode);
}
}
}

View File

@ -31,6 +31,8 @@ namespace CodeWalker.World
public List<AudioPlacement> Emitters = new List<AudioPlacement>();
public List<AudioPlacement> AllItems = new List<AudioPlacement>();
public List<RelFile> AllFiles = new List<RelFile>();
public Dictionary<RelFile, AudioPlacement[]> PlacementsDict = new Dictionary<RelFile, AudioPlacement[]>();
public void Init(GameFileCache gameFileCache, Action<string> updateStatus)
@ -67,23 +69,20 @@ namespace CodeWalker.World
}
}
List<AudioPlacement> placements = new List<AudioPlacement>();
foreach (var dat151entry in datrelentries.Values)
{
var relfile = rpfman.GetFile<RelFile>(dat151entry);
if (relfile != null)
{
foreach (var reldata in relfile.RelDatas)
{
if (reldata is Dat151AmbientZone)
{
Zones.Add(new AudioPlacement(relfile, reldata as Dat151AmbientZone));
}
else if (reldata is Dat151AmbientEmitter)
{
Emitters.Add(new AudioPlacement(relfile, reldata as Dat151AmbientEmitter));
}
}
AllFiles.Add(relfile);
placements.Clear();
CreatePlacements(relfile, placements, true);
PlacementsDict[relfile] = placements.ToArray();
}
}
@ -119,6 +118,49 @@ namespace CodeWalker.World
}
}
private void CreatePlacements(RelFile relfile, List<AudioPlacement> placements, bool addtoLists = false)
{
foreach (var reldata in relfile.RelDatas)
{
AudioPlacement placement = null;
if (reldata is Dat151AmbientZone)
{
placement = new AudioPlacement(relfile, reldata as Dat151AmbientZone);
if (addtoLists) Zones.Add(placement);
}
else if (reldata is Dat151AmbientEmitter)
{
placement = new AudioPlacement(relfile, reldata as Dat151AmbientEmitter);
if (addtoLists) Emitters.Add(placement);
}
if (placement != null)
{
placements.Add(placement);
}
}
}
public void GetPlacements(List<RelFile> relfiles, List<AudioPlacement> placements)
{
foreach (var relfile in relfiles)
{
AudioPlacement[] fileplacements = null;
if (!PlacementsDict.TryGetValue(relfile, out fileplacements))
{
List<AudioPlacement> newplacements = new List<AudioPlacement>();
CreatePlacements(relfile, newplacements);
fileplacements = newplacements.ToArray();
PlacementsDict[relfile] = fileplacements;
}
if (fileplacements != null)
{
placements.AddRange(fileplacements);
}
}
}
}
@ -157,11 +199,30 @@ namespace CodeWalker.World
{
RelFile = rel;
AudioZone = zone;
Shape = zone.Shape;
ShortTypeName = "AudioZone";
FullTypeName = "Audio Zone";
UpdateFromZone();
}
public AudioPlacement(RelFile rel, Dat151AmbientEmitter emitter)
{
RelFile = rel;
AudioEmitter = emitter;
ShortTypeName = "AudioEmitter";
FullTypeName = "Audio Emitter";
UpdateFromEmitter();
}
public void UpdateFromZone()
{
if (AudioZone == null) return;
var zone = AudioZone;
Name = zone.Name;
NameHash = zone.NameHash;
Shape = zone.Shape;
float deg2rad = (float)(Math.PI / 180.0);
@ -205,16 +266,17 @@ namespace CodeWalker.World
{
Position = InnerPos;
}
}
public AudioPlacement(RelFile rel, Dat151AmbientEmitter emitter)
public void UpdateFromEmitter()
{
RelFile = rel;
AudioEmitter = emitter;
Shape = Dat151ZoneShape.Sphere;
ShortTypeName = "AudioEmitter";
FullTypeName = "Audio Emitter";
if (AudioEmitter == null) return;
var emitter = AudioEmitter;
Name = emitter.Name;
NameHash = emitter.NameHash;
Shape = Dat151ZoneShape.Sphere;
Orientation = Quaternion.Identity;
OrientationInv = Quaternion.Identity;
@ -230,6 +292,7 @@ namespace CodeWalker.World
}
Position = InnerPos;
HitSphereRad = InnerRad;// useouter ? OuterRad : InnerRad;
}
@ -240,16 +303,39 @@ namespace CodeWalker.World
InnerPos = pos;
OuterPos += delta;
Position = useouter ? OuterPos : InnerPos;
if (AudioZone != null)
{
AudioZone.InnerPos = InnerPos;
AudioZone.OuterPos = OuterPos;
}
if (AudioEmitter != null)
{
AudioEmitter.Position = InnerPos;
}
}
public void SetOrientation(Quaternion ori)
{
Orientation = ori;
OrientationInv = Quaternion.Invert(ori);
Vector3 t = ori.Multiply(Vector3.UnitX);
float angl = (float)Math.Atan2(t.Y, t.X);
while (angl < 0) angl += ((float)Math.PI * 2.0f);
float rad2deg = (float)(180.0 / Math.PI);
float dangl = angl * rad2deg;
uint uangl = (uint)dangl;
if (InnerOri == OuterOri)
{
InnerOri = Orientation;
OuterOri = Orientation;
if (AudioZone != null)
{
AudioZone.InnerAngle = uangl;
AudioZone.OuterAngle = uangl;
}
}
else
{
@ -259,10 +345,18 @@ namespace CodeWalker.World
if (useouter)
{
OuterOri = Orientation;
if (AudioZone != null)
{
AudioZone.OuterAngle = uangl;
}
}
else
{
InnerOri = Orientation;
if (AudioZone != null)
{
AudioZone.InnerAngle = uangl;
}
}
}
}

View File

@ -334,5 +334,36 @@ namespace CodeWalker.World
}
return true;
}
public bool ContainsAABBNoClipNoOpt(ref Vector3 bmin, ref Vector3 bmax)
{
var c = (bmax + bmin) * 0.5f - Position;
var e = (bmax - bmin) * 0.5f;
for (int i = 0; i < 5; i++)
{
var pd = Planes[i].D;
var pn = Planes[i].Normal;
var d = (c.X * pn.X) + (c.Y * pn.Y) + (c.Z * pn.Z);
var r = (e.X * (pn.X > 0 ? pn.X : -pn.X)) + (e.Y * (pn.Y > 0 ? pn.Y : -pn.Y)) + (e.Z * (pn.Z > 0 ? pn.Z : -pn.Z));
if ((d + r) < -pd) return false;
//if ((d - r) < -pd) ; //intersecting
}
return true;
}
public bool ContainsAABBNoFrontClipNoOpt(ref Vector3 bmin, ref Vector3 bmax)
{
var c = (bmax + bmin) * 0.5f - Position;
var e = (bmax - bmin) * 0.5f;
for (int i = 0; i < 4; i++)
{
var pd = Planes[i].D;
var pn = Planes[i].Normal;
var d = (c.X * pn.X) + (c.Y * pn.Y) + (c.Z * pn.Z);
var r = (e.X * (pn.X > 0 ? pn.X : -pn.X)) + (e.Y * (pn.Y > 0 ? pn.Y : -pn.Y)) + (e.Z * (pn.Z > 0 ? pn.Z : -pn.Z));
if ((d + r) < -pd) return false;
//if ((d - r) < -pd) ; //intersecting
}
return true;
}
}
}

View File

@ -491,10 +491,10 @@ namespace CodeWalker.World
//if (r.Unk_3844724227 != null) //visualise AccelGrid...
//{
// var grid = r._Data.AccelGrid;
// var minx = grid.Unk_MinX_860552138;
// var maxx = grid.Unk_MaxX_3824598937;
// var miny = grid.Unk_MinY_496029782;
// var maxy = grid.Unk_MaxY_3374647798;
// var minx = grid.MinCellX;
// var maxx = grid.MaxCellX;
// var miny = grid.MinCellY;
// var maxy = grid.MaxCellY;
// var cntx = (maxx - minx) + 1;
// var cnty = (maxy - miny) + 1;
// var calclen = cntx * cnty; //==r.Unk_3844724227.Length;
@ -994,7 +994,7 @@ namespace CodeWalker.World
newpoints.AddRange(cell);
foreach (var point in cell)
{
if ((point.Flags & Unk_700327466.ExtendedRange) > 0)
if ((point.Flags & CScenarioPointFlags__Flags.ExtendedRange) > 0)
{
flag = true;
}
@ -1016,12 +1016,12 @@ namespace CodeWalker.World
rage__spdGrid2D grid = new rage__spdGrid2D();
grid.Unk_X_2690909759 = cellsize;
grid.Unk_Y_3691675019 = cellsize;
grid.Unk_MinX_860552138 = imin.X;
grid.Unk_MinY_496029782 = imin.Y;
grid.Unk_MaxX_3824598937 = imax.X;
grid.Unk_MaxY_3374647798 = imax.Y;
grid.CellDimX = cellsize;
grid.CellDimY = cellsize;
grid.MinCellX = imin.X;
grid.MinCellY = imin.Y;
grid.MaxCellX = imax.X;
grid.MaxCellY = imax.Y;
Region._Data.AccelGrid = grid;
//store the reordered points.

View File

@ -420,19 +420,23 @@ namespace CodeWalker.World
{
AddRpfYnds(rpffile, yndentries);
}
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load nodes from current dlc rpfs
if (GameFileCache.EnableDlc)
{
foreach (var rpffile in dlcrpf.Children)
var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load nodes from patch area...
if (updrpf != null)
{
AddRpfYnds(rpffile, yndentries);
foreach (var rpffile in updrpf.Children)
{
AddRpfYnds(rpffile, yndentries);
}
}
}
var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load nodes from patch area...
if (updrpf != null)
{
foreach (var rpffile in updrpf.Children)
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load nodes from current dlc rpfs
{
AddRpfYnds(rpffile, yndentries);
if (dlcrpf.Path.StartsWith("x64")) continue; //don't override update.rpf YNDs with x64 ones! *hack
foreach (var rpffile in dlcrpf.Children)
{
AddRpfYnds(rpffile, yndentries);
}
}
}
@ -721,19 +725,22 @@ namespace CodeWalker.World
{
AddRpfYnvs(rpffile, ynventries);
}
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load navmeshes from current dlc rpfs
if (GameFileCache.EnableDlc)
{
foreach (var rpffile in dlcrpf.Children)
var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load navmeshes from patch area...
if (updrpf != null)
{
AddRpfYnvs(rpffile, ynventries);
foreach (var rpffile in updrpf.Children)
{
AddRpfYnvs(rpffile, ynventries);
}
}
}
var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load navmeshes from patch area...
if (updrpf != null)
{
foreach (var rpffile in updrpf.Children)
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load navmeshes from current dlc rpfs
{
AddRpfYnvs(rpffile, ynventries);
foreach (var rpffile in dlcrpf.Children)
{
AddRpfYnvs(rpffile, ynventries);
}
}
}
@ -1057,7 +1064,7 @@ namespace CodeWalker.World
{
if (!IsYmapAvailable(hash, hour, weather)) break;
ymaps[hash] = ymap;
hash = ymap.CMapData.parent;
hash = ymap._CMapData.parent;
if (ymaps.ContainsKey(hash)) break;
ymap = (hash > 0) ? GameFileCache.GetYmap(hash) : null;
}
@ -1199,7 +1206,7 @@ namespace CodeWalker.World
}
public SpaceRayIntersectResult RayIntersect(Ray ray, float maxdist = float.MaxValue)
public SpaceRayIntersectResult RayIntersect(Ray ray, float maxdist = float.MaxValue, bool[] layers = null)
{
var res = new SpaceRayIntersectResult();
if (GameFileCache == null) return res;
@ -1225,6 +1232,7 @@ namespace CodeWalker.World
float polyhittestdist = 0;
bool hit = false;
BoundPolygon hitpoly = null;
BoundMaterial_s hitmat = new BoundMaterial_s();
Vector3 hitnorm = Vector3.Zero;
Vector3 hitpos = Vector3.Zero;
while (cell != null)
@ -1233,6 +1241,12 @@ namespace CodeWalker.World
{
foreach (var bound in cell.BoundsList)
{
uint l = bound.Layer;
if ((layers != null) && (l < 3))
{
if (!layers[l]) continue;
}
box.Minimum = bound.Min;
box.Maximum = bound.Max;
float boxhitdisttest;
@ -1272,7 +1286,7 @@ namespace CodeWalker.World
{ continue; }
if (bgeom.Polygons == null)
{ continue; }
if ((bgeom.BVH == null) || (bgeom.BVH.Trees == null))
if ((bgeom.BVH?.Nodes?.data_items == null) || (bgeom.BVH?.Trees?.data_items == null))
{ continue; }
box.Minimum = bgeom.BoundingBoxMin;
@ -1286,9 +1300,9 @@ namespace CodeWalker.World
var q = bgeom.BVH.Quantum.XYZ();
var c = bgeom.BVH.BoundingBoxCenter.XYZ();
var cg = bgeom.CenterGeom;
for (int t = 0; t < bgeom.BVH.Trees.Length; t++)
for (int t = 0; t < bgeom.BVH.Trees.data_items.Length; t++)
{
var tree = bgeom.BVH.Trees[t];
var tree = bgeom.BVH.Trees.data_items[t];
box.Minimum = new Vector3(tree.MinX, tree.MinY, tree.MinZ) * q + c;
box.Maximum = new Vector3(tree.MaxX, tree.MaxY, tree.MaxZ) * q + c;
if (!ray.Intersects(ref box, out bvhboxhittest))
@ -1302,7 +1316,7 @@ namespace CodeWalker.World
int lastind = tree.NodeIndex2;
while (nodeind < lastind)
{
var node = bgeom.BVH.Nodes[nodeind];
var node = bgeom.BVH.Nodes.data_items[nodeind];
box.Minimum = new Vector3(node.MinX, node.MinY, node.MinZ) * q + c;
box.Maximum = new Vector3(node.MaxX, node.MaxY, node.MaxZ) * q + c;
bool nodehit = ray.Intersects(ref box, out bvhboxhittest);
@ -1395,6 +1409,10 @@ namespace CodeWalker.World
hit = true;
hitnorm = n1;
hitpoly = polygon;
byte matind = ((bgeom.PolygonMaterialIndices != null) && (p < bgeom.PolygonMaterialIndices.Length)) ? bgeom.PolygonMaterialIndices[p] : (byte)0;
BoundMaterial_s mat = ((bgeom.Materials != null) && (matind < bgeom.Materials.Length)) ? bgeom.Materials[matind] : new BoundMaterial_s();
hitmat = mat;
}
polytestcount++;
}
@ -1474,6 +1492,7 @@ namespace CodeWalker.World
res.Hit = hit;
res.HitDist = itemhitdist;
res.HitPolygon = hitpoly;
res.Material = hitmat;
res.Position = hitpos;
res.Normal = hitnorm;
@ -1549,7 +1568,7 @@ namespace CodeWalker.World
{ continue; }
if (bgeom.Polygons == null)
{ continue; }
if ((bgeom.BVH == null) || (bgeom.BVH.Trees == null))
if ((bgeom.BVH?.Nodes?.data_items == null) || (bgeom.BVH?.Trees?.data_items == null))
{ continue; }
box.Minimum = bgeom.BoundingBoxMin;
@ -1560,9 +1579,9 @@ namespace CodeWalker.World
var q = bgeom.BVH.Quantum.XYZ();
var c = bgeom.BVH.BoundingBoxCenter.XYZ();
var cg = bgeom.CenterGeom;
for (int t = 0; t < bgeom.BVH.Trees.Length; t++)
for (int t = 0; t < bgeom.BVH.Trees.data_items.Length; t++)
{
var tree = bgeom.BVH.Trees[t];
var tree = bgeom.BVH.Trees.data_items[t];
box.Minimum = new Vector3(tree.MinX, tree.MinY, tree.MinZ) * q + c;
box.Maximum = new Vector3(tree.MaxX, tree.MaxY, tree.MaxZ) * q + c;
if (!sph.Intersects(ref box))
@ -1572,7 +1591,7 @@ namespace CodeWalker.World
int lastind = tree.NodeIndex2;
while (nodeind < lastind)
{
var node = bgeom.BVH.Nodes[nodeind];
var node = bgeom.BVH.Nodes.data_items[nodeind];
box.Minimum = new Vector3(node.MinX, node.MinY, node.MinZ) * q + c;
box.Maximum = new Vector3(node.MaxX, node.MaxY, node.MaxZ) * q + c;
bool nodehit = sph.Intersects(ref box);
@ -1731,7 +1750,7 @@ namespace CodeWalker.World
public const int CellCount = 500; //cells along a side, total cell count is this squared
public const int LastCell = CellCount - 1; //the last cell index in the array
public const float WorldSize = 10000.0f; //max world grid size +/- 10000 units
public const float CellSize = 2.0f * WorldSize / (float)CellCount;//20.0f; //size of a cell
public const float CellSize = 2.0f * WorldSize / (float)CellCount;//40.0f; //size of a cell
public const float CellSizeInv = 1.0f / CellSize; //inverse of the cell size.
public const float CellSizeHalf = CellSize * 0.5f; //half the cell size
@ -2013,7 +2032,7 @@ namespace CodeWalker.World
public float CellSizeInv; //inverse of the cell size.
public int CellCountX = 100;
public int CellCountY = 100;
public float CornerX = -6000.0f;
public float CornerX = -6000.0f;//max = -6000+(100*150) = 9000
public float CornerY = -6000.0f;
public SpaceNavGrid()
@ -2043,7 +2062,10 @@ namespace CodeWalker.World
}
public Vector3 GetCellRel(Vector3 p)//float value in cell coords
{
return (p - new Vector3(CornerX, CornerY, 0)) * CellSizeInv;
}
public Vector2I GetCellPos(Vector3 p)
{
Vector3 ind = (p - new Vector3(CornerX, CornerY, 0)) * CellSizeInv;
@ -2069,7 +2091,15 @@ namespace CodeWalker.World
}
public Vector3 GetCellMin(SpaceNavGridCell cell)
{
Vector3 c = new Vector3(cell.X, cell.Y, 0);
return new Vector3(CornerX, CornerY, 0) + (c * CellSize);
}
public Vector3 GetCellMax(SpaceNavGridCell cell)
{
return GetCellMin(cell) + new Vector3(CellSize, CellSize, 0.0f);
}
}
public class SpaceNavGridCell
@ -2106,6 +2136,7 @@ namespace CodeWalker.World
public int TestedNodeCount;
public int TestedPolyCount;
public bool TestComplete;
public BoundMaterial_s Material;
}
public struct SpaceSphereIntersectResult
{

View File

@ -69,11 +69,14 @@ namespace CodeWalker.World
get
{
int sc = 0;
foreach (var node in Nodes)
if (Nodes != null)
{
if ((node.NodeType == 1) || (node.NodeType == 2) || (node.NodeType == 5))
foreach (var node in Nodes)
{
sc++;
if ((node.NodeType == 1) || (node.NodeType == 2) || (node.NodeType == 5))
{
sc++;
}
}
}
return sc;

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{47A2C383-99B4-4447-94D9-0685E6D7E2DA}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>CodeWalker.ErrorReport</RootNamespace>
<AssemblyName>CodeWalker.ErrorReport</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>CW.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ReportForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ReportForm.Designer.cs">
<DependentUpon>ReportForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="ReportForm.resx">
<DependentUpon>ReportForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Content Include="CW.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.ErrorReport
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ReportForm());
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CodeWalker.ErrorReport")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CodeWalker.ErrorReport")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("47a2c383-99b4-4447-94d9-0685e6d7e2da")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CodeWalker.ErrorReport.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeWalker.ErrorReport.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CodeWalker.ErrorReport.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,80 @@
namespace CodeWalker.ErrorReport
{
partial class ReportForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ReportForm));
this.label1 = new System.Windows.Forms.Label();
this.ErrorTextBox = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(136, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Last CodeWalker.exe error:";
//
// ErrorTextBox
//
this.ErrorTextBox.AcceptsReturn = true;
this.ErrorTextBox.AcceptsTab = true;
this.ErrorTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ErrorTextBox.Location = new System.Drawing.Point(12, 36);
this.ErrorTextBox.Multiline = true;
this.ErrorTextBox.Name = "ErrorTextBox";
this.ErrorTextBox.Size = new System.Drawing.Size(630, 329);
this.ErrorTextBox.TabIndex = 1;
//
// ReportForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(654, 377);
this.Controls.Add(this.ErrorTextBox);
this.Controls.Add(this.label1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "ReportForm";
this.Text = "CodeWalker Error Report Tool";
this.Load += new System.EventHandler(this.ReportForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox ErrorTextBox;
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.ErrorReport
{
public partial class ReportForm : Form
{
public ReportForm()
{
InitializeComponent();
}
private void ReportForm_Load(object sender, EventArgs e)
{
EventLog myLog = new EventLog();
myLog.Log = "Application";
//myLog.Source = ".NET Runtime";
var lastEntry = myLog.Entries[myLog.Entries.Count - 1];
var last_error_Message = lastEntry.Message;
bool found = false;
for (int index = myLog.Entries.Count - 1; index > 0; index--)
{
var errLastEntry = myLog.Entries[index];
if (errLastEntry.EntryType == EventLogEntryType.Error)
{
if (errLastEntry.Source == ".NET Runtime")
{
var msg = errLastEntry.Message;
var lines = msg.Split('\n');
if ((lines.Length > 0) && (lines[0].Contains("CodeWalker.exe")))
{
ErrorTextBox.Text = msg.Replace("\n", "\r\n");
found = true;
break;
}
}
}
}
if (!found)
{
ErrorTextBox.Text = "Event Log entry not found!";
MessageBox.Show("Unable to find the last CodeWalker.exe error in the Event Log.");
}
}
}
}

View File

@ -40,11 +40,11 @@
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WeifenLuo.WinFormsUI.Docking, Version=3.0.4.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>..\packages\DockPanelSuite.3.0.4\lib\net40\WeifenLuo.WinFormsUI.Docking.dll</HintPath>
<Reference Include="WeifenLuo.WinFormsUI.Docking, Version=3.0.6.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>..\packages\DockPanelSuite.3.0.6\lib\net40\WeifenLuo.WinFormsUI.Docking.dll</HintPath>
</Reference>
<Reference Include="WeifenLuo.WinFormsUI.Docking.ThemeVS2015, Version=3.0.4.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>..\packages\DockPanelSuite.ThemeVS2015.3.0.4\lib\net40\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll</HintPath>
<Reference Include="WeifenLuo.WinFormsUI.Docking.ThemeVS2015, Version=3.0.6.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>..\packages\DockPanelSuite.ThemeVS2015.3.0.6\lib\net40\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@ -109,6 +109,7 @@
<Compile Include="FormUtils.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -1,17 +1,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.WinForms
{
public partial class TextBoxFix : TextBox
{
bool ignoreChange = true;
List<string> storageUndo;
List<string> storageRedo;
public TextBoxFix()
{
InitializeComponent();
@ -22,17 +20,75 @@ namespace CodeWalker.WinForms
base.OnPaint(pe);
}
protected override void OnCreateControl()
{
base.OnCreateControl();
storageRedo = new List<string>();
storageUndo = new List<string> { Text };
ignoreChange = false;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
//Fix for Ctrl-A not working in multiline textboxes.
//Fix for Ctrl-A/Z/Y not working in multiline textboxes.
const int WM_KEYDOWN = 0x100;
var keyCode = (Keys)(msg.WParam.ToInt32() & Convert.ToInt32(Keys.KeyCode));
if ((msg.Msg == WM_KEYDOWN && keyCode == Keys.A) && (ModifierKeys == Keys.Control) && Focused)
if (msg.Msg == WM_KEYDOWN && (ModifierKeys == Keys.Control) && Focused)
{
SelectAll();
return true;
if (keyCode == Keys.A)
{
SelectAll();
return true;
}
if (keyCode == Keys.Z)
{
Undo();
return true;
}
if (keyCode == Keys.Y)
{
Redo();
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
if (!ignoreChange)
{
ClearUndo();
if (storageUndo.Count > 2048) storageUndo.RemoveAt(0);
if (storageRedo.Count > 2048) storageRedo.RemoveAt(0);
storageUndo.Add(Text);
}
}
public void Redo()
{
if (storageRedo.Count > 0)
{
ignoreChange = true;
Text = storageRedo[storageRedo.Count - 1];
storageUndo.Add(Text);
storageRedo.RemoveAt(storageRedo.Count - 1);
ignoreChange = false;
}
}
public new void Undo()
{
if (storageUndo.Count > 1)
{
ignoreChange = true;
Text = storageUndo[storageUndo.Count - 2];
storageRedo.Add(storageUndo[storageUndo.Count - 1]);
storageUndo.RemoveAt(storageUndo.Count - 1);
ignoreChange = false;
}
}
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WeifenLuo.WinFormsUI.Docking" publicKeyToken="5cded1a1a0a7b481" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.6.0" newVersion="3.0.6.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DockPanelSuite" version="3.0.4" targetFramework="net452" />
<package id="DockPanelSuite.ThemeVS2015" version="3.0.4" targetFramework="net452" />
<package id="DockPanelSuite" version="3.0.6" targetFramework="net452" />
<package id="DockPanelSuite.ThemeVS2015" version="3.0.6" targetFramework="net452" />
</packages>

View File

@ -91,9 +91,8 @@
<ApplicationIcon>Resources\CW.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="FastColoredTextBox, Version=2.16.21.0, Culture=neutral, PublicKeyToken=fb8aa12b994ef61b, processorArchitecture=MSIL">
<HintPath>packages\FCTB.2.16.21.0\lib\FastColoredTextBox.dll</HintPath>
<EmbedInteropTypes>False</EmbedInteropTypes>
<Reference Include="FastColoredTextBox, Version=2.16.24.0, Culture=neutral, PublicKeyToken=fb8aa12b994ef61b, processorArchitecture=MSIL">
<HintPath>packages\FCTB.2.16.24\lib\FastColoredTextBox.dll</HintPath>
</Reference>
<Reference Include="SharpDX, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<HintPath>packages\SharpDX.4.0.1\lib\net45\SharpDX.dll</HintPath>
@ -130,11 +129,11 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="WeifenLuo.WinFormsUI.Docking, Version=3.0.4.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>packages\DockPanelSuite.3.0.4\lib\net40\WeifenLuo.WinFormsUI.Docking.dll</HintPath>
<Reference Include="WeifenLuo.WinFormsUI.Docking, Version=3.0.6.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>packages\DockPanelSuite.3.0.6\lib\net40\WeifenLuo.WinFormsUI.Docking.dll</HintPath>
</Reference>
<Reference Include="WeifenLuo.WinFormsUI.Docking.ThemeVS2015, Version=3.0.4.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>packages\DockPanelSuite.ThemeVS2015.3.0.4\lib\net40\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll</HintPath>
<Reference Include="WeifenLuo.WinFormsUI.Docking.ThemeVS2015, Version=3.0.6.0, Culture=neutral, PublicKeyToken=5cded1a1a0a7b481, processorArchitecture=MSIL">
<HintPath>packages\DockPanelSuite.ThemeVS2015.3.0.6\lib\net40\WeifenLuo.WinFormsUI.Docking.ThemeVS2015.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@ -144,10 +143,22 @@
<Compile Include="AboutForm.Designer.cs">
<DependentUpon>AboutForm.cs</DependentUpon>
</Compile>
<Compile Include="BrowseForm.cs">
<Compile Include="Forms\ModelMatForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="BrowseForm.Designer.cs">
<Compile Include="Forms\ModelMatForm.Designer.cs">
<DependentUpon>ModelMatForm.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\GenerateLODLightsPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\GenerateLODLightsPanel.Designer.cs">
<DependentUpon>GenerateLODLightsPanel.cs</DependentUpon>
</Compile>
<Compile Include="Tools\BrowseForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Tools\BrowseForm.Designer.cs">
<DependentUpon>BrowseForm.cs</DependentUpon>
</Compile>
<Compile Include="ExploreForm.cs">
@ -156,34 +167,34 @@
<Compile Include="ExploreForm.Designer.cs">
<DependentUpon>ExploreForm.cs</DependentUpon>
</Compile>
<Compile Include="ExtractKeysForm.cs">
<Compile Include="Tools\ExtractKeysForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExtractKeysForm.Designer.cs">
<Compile Include="Tools\ExtractKeysForm.Designer.cs">
<DependentUpon>ExtractKeysForm.cs</DependentUpon>
</Compile>
<Compile Include="ExtractScriptsForm.cs">
<Compile Include="Tools\ExtractScriptsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExtractScriptsForm.Designer.cs">
<Compile Include="Tools\ExtractScriptsForm.Designer.cs">
<DependentUpon>ExtractScriptsForm.cs</DependentUpon>
</Compile>
<Compile Include="ExtractRawForm.cs">
<Compile Include="Tools\ExtractRawForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExtractRawForm.Designer.cs">
<Compile Include="Tools\ExtractRawForm.Designer.cs">
<DependentUpon>ExtractRawForm.cs</DependentUpon>
</Compile>
<Compile Include="ExtractShadersForm.cs">
<Compile Include="Tools\ExtractShadersForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExtractShadersForm.Designer.cs">
<Compile Include="Tools\ExtractShadersForm.Designer.cs">
<DependentUpon>ExtractShadersForm.cs</DependentUpon>
</Compile>
<Compile Include="ExtractTexForm.cs">
<Compile Include="Tools\ExtractTexForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExtractTexForm.Designer.cs">
<Compile Include="Tools\ExtractTexForm.Designer.cs">
<DependentUpon>ExtractTexForm.cs</DependentUpon>
</Compile>
<Compile Include="Forms\AwcForm.cs">
@ -266,16 +277,22 @@
</Compile>
<Compile Include="GameFiles\FxcParser.cs" />
<Compile Include="GameFiles\GameFileCacheFactory.cs" />
<Compile Include="JenkGenForm.cs">
<Compile Include="Tools\ImportFbxForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="JenkGenForm.Designer.cs">
<Compile Include="Tools\ImportFbxForm.Designer.cs">
<DependentUpon>ImportFbxForm.cs</DependentUpon>
</Compile>
<Compile Include="Tools\JenkGenForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Tools\JenkGenForm.Designer.cs">
<DependentUpon>JenkGenForm.cs</DependentUpon>
</Compile>
<Compile Include="JenkIndForm.cs">
<Compile Include="Tools\JenkIndForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="JenkIndForm.Designer.cs">
<Compile Include="Tools\JenkIndForm.Designer.cs">
<DependentUpon>JenkIndForm.cs</DependentUpon>
</Compile>
<Compile Include="KeyBindForm.cs">
@ -292,6 +309,48 @@
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Project\MenyooXml.cs" />
<Compile Include="Project\Panels\EditAudioEmitterListPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditAudioEmitterListPanel.Designer.cs">
<DependentUpon>EditAudioEmitterListPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditAudioEmitterPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditAudioEmitterPanel.Designer.cs">
<DependentUpon>EditAudioEmitterPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditAudioFilePanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditAudioFilePanel.Designer.cs">
<DependentUpon>EditAudioFilePanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditAudioInteriorPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditAudioInteriorPanel.Designer.cs">
<DependentUpon>EditAudioInteriorPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditAudioInteriorRoomPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditAudioInteriorRoomPanel.Designer.cs">
<DependentUpon>EditAudioInteriorRoomPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditAudioZoneListPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditAudioZoneListPanel.Designer.cs">
<DependentUpon>EditAudioZoneListPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditAudioZonePanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditAudioZonePanel.Designer.cs">
<DependentUpon>EditAudioZonePanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditProjectPanel.cs">
<SubType>Form</SubType>
</Compile>
@ -328,6 +387,12 @@
<Compile Include="Project\Panels\EditYmapCarGenPanel.Designer.cs">
<DependentUpon>EditYmapCarGenPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditYtypArchetypeMloRoomPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditYtypArchetypeMloRoomPanel.Designer.cs">
<DependentUpon>EditYtypArchetypeMloRoomPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditYmapEntityPanel.cs">
<SubType>Form</SubType>
</Compile>
@ -382,12 +447,24 @@
<Compile Include="Project\Panels\EditYnvPortalPanel.Designer.cs">
<DependentUpon>EditYnvPortalPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditYtypArchetypePanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditYtypArchetypePanel.Designer.cs">
<DependentUpon>EditYtypArchetypePanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\EditYtypPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\EditYtypPanel.Designer.cs">
<DependentUpon>EditYtypPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\GenerateNavMeshPanel.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\Panels\GenerateNavMeshPanel.Designer.cs">
<DependentUpon>GenerateNavMeshPanel.cs</DependentUpon>
</Compile>
<Compile Include="Project\Panels\ProjectExplorerPanel.cs">
<SubType>Form</SubType>
</Compile>
@ -457,10 +534,16 @@
<Compile Include="SettingsForm.Designer.cs">
<DependentUpon>SettingsForm.cs</DependentUpon>
</Compile>
<Compile Include="TextInputForm.cs">
<Compile Include="StatisticsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="TextInputForm.Designer.cs">
<Compile Include="StatisticsForm.Designer.cs">
<DependentUpon>StatisticsForm.cs</DependentUpon>
</Compile>
<Compile Include="Utils\TextInputForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Utils\TextInputForm.Designer.cs">
<DependentUpon>TextInputForm.cs</DependentUpon>
</Compile>
<Compile Include="Utils\DDSIO.cs" />
@ -469,11 +552,11 @@
<Compile Include="Utils\MapUtils.cs" />
<Compile Include="GameFiles\TextureFormats.cs" />
<Compile Include="Utils\TextureLoader.cs" />
<Compile Include="Project\ProjectFormOLD.cs">
<Compile Include="Vehicles\VehicleForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\ProjectFormOLD.Designer.cs">
<DependentUpon>ProjectFormOLD.cs</DependentUpon>
<Compile Include="Vehicles\VehicleForm.Designer.cs">
<DependentUpon>VehicleForm.cs</DependentUpon>
</Compile>
<Compile Include="WorldInfoForm.cs">
<SubType>Form</SubType>
@ -490,10 +573,10 @@
<Compile Include="Rendering\DirectX\DXForm.cs" />
<Compile Include="Rendering\DirectX\DXManager.cs" />
<Compile Include="Rendering\Utils\UnitQuad.cs" />
<Compile Include="BinarySearchForm.cs">
<Compile Include="Tools\BinarySearchForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="BinarySearchForm.Designer.cs">
<Compile Include="Tools\BinarySearchForm.Designer.cs">
<DependentUpon>BinarySearchForm.cs</DependentUpon>
</Compile>
<Compile Include="WorldForm.cs">
@ -506,25 +589,31 @@
<EmbeddedResource Include="AboutForm.resx">
<DependentUpon>AboutForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BrowseForm.resx">
<EmbeddedResource Include="Forms\ModelMatForm.resx">
<DependentUpon>ModelMatForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\GenerateLODLightsPanel.resx">
<DependentUpon>GenerateLODLightsPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Tools\BrowseForm.resx">
<DependentUpon>BrowseForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ExploreForm.resx">
<DependentUpon>ExploreForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ExtractKeysForm.resx">
<EmbeddedResource Include="Tools\ExtractKeysForm.resx">
<DependentUpon>ExtractKeysForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ExtractScriptsForm.resx">
<EmbeddedResource Include="Tools\ExtractScriptsForm.resx">
<DependentUpon>ExtractScriptsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ExtractRawForm.resx">
<EmbeddedResource Include="Tools\ExtractRawForm.resx">
<DependentUpon>ExtractRawForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ExtractShadersForm.resx">
<EmbeddedResource Include="Tools\ExtractShadersForm.resx">
<DependentUpon>ExtractShadersForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ExtractTexForm.resx">
<EmbeddedResource Include="Tools\ExtractTexForm.resx">
<DependentUpon>ExtractTexForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\AwcForm.resx">
@ -566,10 +655,13 @@
<EmbeddedResource Include="Forms\YwrForm.resx">
<DependentUpon>YwrForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="JenkGenForm.resx">
<EmbeddedResource Include="Tools\ImportFbxForm.resx">
<DependentUpon>ImportFbxForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Tools\JenkGenForm.resx">
<DependentUpon>JenkGenForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="JenkIndForm.resx">
<EmbeddedResource Include="Tools\JenkIndForm.resx">
<DependentUpon>JenkIndForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="KeyBindForm.resx">
@ -578,6 +670,27 @@
<EmbeddedResource Include="MenuForm.resx">
<DependentUpon>MenuForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditAudioEmitterListPanel.resx">
<DependentUpon>EditAudioEmitterListPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditAudioEmitterPanel.resx">
<DependentUpon>EditAudioEmitterPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditAudioFilePanel.resx">
<DependentUpon>EditAudioFilePanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditAudioInteriorPanel.resx">
<DependentUpon>EditAudioInteriorPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditAudioInteriorRoomPanel.resx">
<DependentUpon>EditAudioInteriorRoomPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditAudioZoneListPanel.resx">
<DependentUpon>EditAudioZoneListPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditAudioZonePanel.resx">
<DependentUpon>EditAudioZonePanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditProjectPanel.resx">
<DependentUpon>EditProjectPanel.cs</DependentUpon>
</EmbeddedResource>
@ -596,6 +709,9 @@
<EmbeddedResource Include="Project\Panels\EditYmapCarGenPanel.resx">
<DependentUpon>EditYmapCarGenPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYtypArchetypeMloRoomPanel.resx">
<DependentUpon>EditYtypArchetypeMloRoomPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYmapEntityPanel.resx">
<DependentUpon>EditYmapEntityPanel.cs</DependentUpon>
</EmbeddedResource>
@ -623,9 +739,15 @@
<EmbeddedResource Include="Project\Panels\EditYnvPortalPanel.resx">
<DependentUpon>EditYnvPortalPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYtypArchetypePanel.resx">
<DependentUpon>EditYtypArchetypePanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYtypPanel.resx">
<DependentUpon>EditYtypPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\GenerateNavMeshPanel.resx">
<DependentUpon>GenerateNavMeshPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\ProjectExplorerPanel.resx">
<DependentUpon>ProjectExplorerPanel.cs</DependentUpon>
</EmbeddedResource>
@ -648,21 +770,24 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="BinarySearchForm.resx">
<EmbeddedResource Include="Tools\BinarySearchForm.resx">
<DependentUpon>BinarySearchForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SelectFolderForm.resx">
<DependentUpon>SelectFolderForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\ProjectFormOLD.resx">
<DependentUpon>ProjectFormOLD.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SettingsForm.resx">
<DependentUpon>SettingsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="TextInputForm.resx">
<EmbeddedResource Include="StatisticsForm.resx">
<DependentUpon>StatisticsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Utils\TextInputForm.resx">
<DependentUpon>TextInputForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Vehicles\VehicleForm.resx">
<DependentUpon>VehicleForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="WorldForm.resx">
<DependentUpon>WorldForm.cs</DependentUpon>
</EmbeddedResource>
@ -691,7 +816,6 @@
<Content Include="icons\icon_glokon_debug_32x32.png" />
<Content Include="icons\icon_glokon_normal_32x32.png" />
<Content Include="icons\icon_google_marker_64x64.png" />
<Content Include="Materials.txt" />
<Content Include="Notice.txt" />
<None Include="README.md" />
<None Include="Resources\CW.ico" />

View File

@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeWalker.WinForms", "Code
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeWalker.Core", "CodeWalker.Core\CodeWalker.Core.csproj", "{DE50D3A6-B49E-47A0-ABE6-101473A00759}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeWalker.ErrorReport", "CodeWalker.ErrorReport\CodeWalker.ErrorReport.csproj", "{47A2C383-99B4-4447-94D9-0685E6D7E2DA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -73,6 +75,18 @@ Global
{DE50D3A6-B49E-47A0-ABE6-101473A00759}.Release|x64.Build.0 = Release|Any CPU
{DE50D3A6-B49E-47A0-ABE6-101473A00759}.Release|x86.ActiveCfg = Release|Any CPU
{DE50D3A6-B49E-47A0-ABE6-101473A00759}.Release|x86.Build.0 = Release|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Debug|x64.ActiveCfg = Debug|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Debug|x64.Build.0 = Debug|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Debug|x86.ActiveCfg = Debug|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Debug|x86.Build.0 = Debug|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Release|Any CPU.Build.0 = Release|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Release|x64.ActiveCfg = Release|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Release|x64.Build.0 = Release|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Release|x86.ActiveCfg = Release|Any CPU
{47A2C383-99B4-4447-94D9-0685E6D7E2DA}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -41,6 +41,7 @@
this.EditExtractRawMenu = new System.Windows.Forms.ToolStripMenuItem();
this.EditExtractAllMenu = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this.EditImportFbxMenu = new System.Windows.Forms.ToolStripMenuItem();
this.EditImportXmlMenu = new System.Windows.Forms.ToolStripMenuItem();
this.EditImportRawMenu = new System.Windows.Forms.ToolStripMenuItem();
this.EditImportMenuSeparator = new System.Windows.Forms.ToolStripSeparator();
@ -115,6 +116,7 @@
this.ListContextNewMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ListContextNewFolderMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ListContextNewRpfArchiveMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ListContextImportFbxMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ListContextImportXmlMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ListContextImportRawMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ListContextImportSeparator = new System.Windows.Forms.ToolStripSeparator();
@ -196,6 +198,7 @@
this.EditExtractRawMenu,
this.EditExtractAllMenu,
this.toolStripSeparator4,
this.EditImportFbxMenu,
this.EditImportXmlMenu,
this.EditImportRawMenu,
this.EditImportMenuSeparator,
@ -267,6 +270,14 @@
this.toolStripSeparator4.Name = "toolStripSeparator4";
this.toolStripSeparator4.Size = new System.Drawing.Size(204, 6);
//
// EditImportFbxMenu
//
this.EditImportFbxMenu.Name = "EditImportFbxMenu";
this.EditImportFbxMenu.Size = new System.Drawing.Size(207, 22);
this.EditImportFbxMenu.Text = "Import FBX...";
this.EditImportFbxMenu.Visible = false;
this.EditImportFbxMenu.Click += new System.EventHandler(this.EditImportFbxMenu_Click);
//
// EditImportXmlMenu
//
this.EditImportXmlMenu.Image = ((System.Drawing.Image)(resources.GetObject("EditImportXmlMenu.Image")));
@ -383,21 +394,21 @@
// ViewLargeIconsMenu
//
this.ViewLargeIconsMenu.Name = "ViewLargeIconsMenu";
this.ViewLargeIconsMenu.Size = new System.Drawing.Size(152, 22);
this.ViewLargeIconsMenu.Size = new System.Drawing.Size(134, 22);
this.ViewLargeIconsMenu.Text = "Large Icons";
this.ViewLargeIconsMenu.Click += new System.EventHandler(this.ViewLargeIconsMenu_Click);
//
// ViewSmallIconsMenu
//
this.ViewSmallIconsMenu.Name = "ViewSmallIconsMenu";
this.ViewSmallIconsMenu.Size = new System.Drawing.Size(152, 22);
this.ViewSmallIconsMenu.Size = new System.Drawing.Size(134, 22);
this.ViewSmallIconsMenu.Text = "Small Icons";
this.ViewSmallIconsMenu.Click += new System.EventHandler(this.ViewSmallIconsMenu_Click);
//
// ViewListMenu
//
this.ViewListMenu.Name = "ViewListMenu";
this.ViewListMenu.Size = new System.Drawing.Size(152, 22);
this.ViewListMenu.Size = new System.Drawing.Size(134, 22);
this.ViewListMenu.Text = "List";
this.ViewListMenu.Click += new System.EventHandler(this.ViewListMenu_Click);
//
@ -406,14 +417,14 @@
this.ViewDetailsMenu.Checked = true;
this.ViewDetailsMenu.CheckState = System.Windows.Forms.CheckState.Checked;
this.ViewDetailsMenu.Name = "ViewDetailsMenu";
this.ViewDetailsMenu.Size = new System.Drawing.Size(152, 22);
this.ViewDetailsMenu.Size = new System.Drawing.Size(134, 22);
this.ViewDetailsMenu.Text = "Details";
this.ViewDetailsMenu.Click += new System.EventHandler(this.ViewDetailsMenu_Click);
//
// toolStripSeparator11
//
this.toolStripSeparator11.Name = "toolStripSeparator11";
this.toolStripSeparator11.Size = new System.Drawing.Size(149, 6);
this.toolStripSeparator11.Size = new System.Drawing.Size(131, 6);
//
// ViewThemeMenu
//
@ -423,7 +434,7 @@
this.ViewThemeLightMenu,
this.ViewThemeDarkMenu});
this.ViewThemeMenu.Name = "ViewThemeMenu";
this.ViewThemeMenu.Size = new System.Drawing.Size(152, 22);
this.ViewThemeMenu.Size = new System.Drawing.Size(134, 22);
this.ViewThemeMenu.Text = "Theme";
//
// ViewThemeWindowsMenu
@ -431,28 +442,28 @@
this.ViewThemeWindowsMenu.Checked = true;
this.ViewThemeWindowsMenu.CheckState = System.Windows.Forms.CheckState.Checked;
this.ViewThemeWindowsMenu.Name = "ViewThemeWindowsMenu";
this.ViewThemeWindowsMenu.Size = new System.Drawing.Size(152, 22);
this.ViewThemeWindowsMenu.Size = new System.Drawing.Size(123, 22);
this.ViewThemeWindowsMenu.Text = "Windows";
this.ViewThemeWindowsMenu.Click += new System.EventHandler(this.ViewThemeWindowsMenu_Click);
//
// ViewThemeBlueMenu
//
this.ViewThemeBlueMenu.Name = "ViewThemeBlueMenu";
this.ViewThemeBlueMenu.Size = new System.Drawing.Size(152, 22);
this.ViewThemeBlueMenu.Size = new System.Drawing.Size(123, 22);
this.ViewThemeBlueMenu.Text = "Blue";
this.ViewThemeBlueMenu.Click += new System.EventHandler(this.ViewThemeBlueMenu_Click);
//
// ViewThemeLightMenu
//
this.ViewThemeLightMenu.Name = "ViewThemeLightMenu";
this.ViewThemeLightMenu.Size = new System.Drawing.Size(152, 22);
this.ViewThemeLightMenu.Size = new System.Drawing.Size(123, 22);
this.ViewThemeLightMenu.Text = "Light";
this.ViewThemeLightMenu.Click += new System.EventHandler(this.ViewThemeLightMenu_Click);
//
// ViewThemeDarkMenu
//
this.ViewThemeDarkMenu.Name = "ViewThemeDarkMenu";
this.ViewThemeDarkMenu.Size = new System.Drawing.Size(152, 22);
this.ViewThemeDarkMenu.Size = new System.Drawing.Size(123, 22);
this.ViewThemeDarkMenu.Text = "Dark";
this.ViewThemeDarkMenu.Click += new System.EventHandler(this.ViewThemeDarkMenu_Click);
//
@ -891,6 +902,7 @@
this.ListContextExtractAllMenu,
this.toolStripSeparator5,
this.ListContextNewMenu,
this.ListContextImportFbxMenu,
this.ListContextImportXmlMenu,
this.ListContextImportRawMenu,
this.ListContextImportSeparator,
@ -908,7 +920,7 @@
this.ListContextDefragmentSeparator,
this.ListContextSelectAllMenu});
this.ListContextMenu.Name = "MainContextMenu";
this.ListContextMenu.Size = new System.Drawing.Size(208, 442);
this.ListContextMenu.Size = new System.Drawing.Size(208, 464);
//
// ListContextViewMenu
//
@ -995,6 +1007,13 @@
this.ListContextNewRpfArchiveMenu.Text = "RPF Archive...";
this.ListContextNewRpfArchiveMenu.Click += new System.EventHandler(this.ListContextNewRpfArchiveMenu_Click);
//
// ListContextImportFbxMenu
//
this.ListContextImportFbxMenu.Name = "ListContextImportFbxMenu";
this.ListContextImportFbxMenu.Size = new System.Drawing.Size(207, 22);
this.ListContextImportFbxMenu.Text = "Import FBX...";
this.ListContextImportFbxMenu.Click += new System.EventHandler(this.ListContextImportFbxMenu_Click);
//
// ListContextImportXmlMenu
//
this.ListContextImportXmlMenu.Image = ((System.Drawing.Image)(resources.GetObject("ListContextImportXmlMenu.Image")));
@ -1326,5 +1345,7 @@
private System.Windows.Forms.ToolStripMenuItem ViewThemeDarkMenu;
private WeifenLuo.WinFormsUI.Docking.VisualStudioToolStripExtender VSExtender;
private System.Windows.Forms.ToolStripMenuItem ViewThemeWindowsMenu;
private System.Windows.Forms.ToolStripMenuItem ListContextImportFbxMenu;
private System.Windows.Forms.ToolStripMenuItem EditImportFbxMenu;
}
}

View File

@ -44,7 +44,7 @@ namespace CodeWalker
private GameFileCache FileCache { get; set; } = GameFileCacheFactory.Create();
private object FileCacheSyncRoot = new object();
private bool EditMode = false;
public bool EditMode { get; private set; } = false;
public ThemeBase Theme { get; private set; }
@ -537,10 +537,11 @@ namespace CodeWalker
var str = ic.ToString() + " item" + ((ic != 1) ? "s" : "") + " shown";
bool isitem = false;
bool isfile = false;
bool issearch = CurrentFolder?.IsSearchResults ?? false;
bool canview = false;
bool canedit = false;
bool canexportxml = false;
bool canimport = false;
bool canimport = EditMode && (CurrentFolder?.RpfFolder != null) && !issearch;
if (sc != 0)
{
long bc = 0;
@ -578,6 +579,7 @@ namespace CodeWalker
EditExtractRawMenu.Enabled = isfile;
EditImportRawMenu.Visible = canimport;
EditImportFbxMenu.Visible = canimport;
EditImportXmlMenu.Visible = canimport;
EditImportMenuSeparator.Visible = canimport;
@ -689,6 +691,11 @@ namespace CodeWalker
rpf.ScanStructure(UpdateStatus, UpdateErrorLog);
if (rpf.LastException != null) //incase of corrupted rpf (or renamed NG encrypted RPF)
{
continue;
}
node = CreateRpfTreeFolder(rpf, relpath, path);
RecurseMainTreeViewRPF(node, allRpfs);
@ -905,7 +912,6 @@ namespace CodeWalker
RecurseAddMainTreeViewNodes(f, CurrentFolder.TreeNode);
CurrentFolder.AddChild(f);
CurrentFolder.ListItems = null;
RefreshMainListView();
}
@ -1053,11 +1059,26 @@ namespace CodeWalker
}
}
public void RefreshMainListViewInvoke()
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => { RefreshMainListView(); }));
}
else
{
RefreshMainListView();
}
}
private void RefreshMainListView()
{
MainListView.VirtualListSize = 0;
if (CurrentFolder != null)
{
if (!CurrentFolder.IsSearchResults)
{
CurrentFolder.ListItems = null; //makes sure to rebuild the current files list
}
CurrentFiles = CurrentFolder.GetListItems();
foreach (var file in CurrentFiles) //cache all the data for use by the list view.
@ -1302,6 +1323,7 @@ namespace CodeWalker
case FileTypeAction.ViewYtyp:
case FileTypeAction.ViewJPso:
case FileTypeAction.ViewCut:
case FileTypeAction.ViewRel:
return true;
}
return false;
@ -1314,6 +1336,13 @@ namespace CodeWalker
try
#endif
{
var exform = FindExistingForm(item?.File);
if (exform != null)
{
exform.Focus();
return;
}
byte[] data = null;
string name = "";
string path = "";
@ -1336,61 +1365,68 @@ namespace CodeWalker
if (data == null) return;
var ft = item.FileType;
var fe = item.File;
if (fe == null)
{
//this should only happen when opening a file from filesystem...
fe = CreateFileEntry(name, path, ref data);
}
switch (ft.DefaultAction)
{
case FileTypeAction.ViewText:
ViewText(name, path, data);
ViewText(name, path, data, fe);
break;
case FileTypeAction.ViewXml:
ViewXml(name, path, data);
ViewXml(name, path, data, fe);
break;
case FileTypeAction.ViewYtd:
ViewYtd(name, path, data, item.File);
ViewYtd(name, path, data, fe);
break;
case FileTypeAction.ViewYmt:
ViewYmt(name, path, data, item.File);
ViewYmt(name, path, data, fe);
break;
case FileTypeAction.ViewYmf:
ViewYmf(name, path, data, item.File);
ViewYmf(name, path, data, fe);
break;
case FileTypeAction.ViewYmap:
ViewYmap(name, path, data, item.File);
ViewYmap(name, path, data, fe);
break;
case FileTypeAction.ViewYtyp:
ViewYtyp(name, path, data, item.File);
ViewYtyp(name, path, data, fe);
break;
case FileTypeAction.ViewJPso:
ViewJPso(name, path, data, item.File);
ViewJPso(name, path, data, fe);
break;
case FileTypeAction.ViewCut:
ViewCut(name, path, data, item.File);
ViewCut(name, path, data, fe);
break;
case FileTypeAction.ViewModel:
ViewModel(name, path, data, item.File);
ViewModel(name, path, data, fe);
break;
case FileTypeAction.ViewAwc:
ViewAwc(name, path, data, item.File);
ViewAwc(name, path, data, fe);
break;
case FileTypeAction.ViewGxt:
ViewGxt(name, path, data, item.File);
ViewGxt(name, path, data, fe);
break;
case FileTypeAction.ViewRel:
ViewRel(name, path, data, item.File);
ViewRel(name, path, data, fe);
break;
case FileTypeAction.ViewFxc:
ViewFxc(name, path, data, item.File);
ViewFxc(name, path, data, fe);
break;
case FileTypeAction.ViewYwr:
ViewYwr(name, path, data, item.File);
ViewYwr(name, path, data, fe);
break;
case FileTypeAction.ViewYvr:
ViewYvr(name, path, data, item.File);
ViewYvr(name, path, data, fe);
break;
case FileTypeAction.ViewYcd:
ViewYcd(name, path, data, item.File);
ViewYcd(name, path, data, fe);
break;
case FileTypeAction.ViewCacheDat:
ViewCacheDat(name, path, data, item.File);
ViewCacheDat(name, path, data, fe);
break;
case FileTypeAction.ViewHex:
default:
@ -1445,19 +1481,19 @@ namespace CodeWalker
f.Show();
f.LoadData(name, path, data);
}
private void ViewXml(string name, string path, byte[] data)
private void ViewXml(string name, string path, byte[] data, RpfFileEntry e)
{
string xml = Encoding.UTF8.GetString(data);
XmlForm f = new XmlForm();
XmlForm f = new XmlForm(this);
f.Show();
f.LoadXml(name, path, xml);
f.LoadXml(name, path, xml, e);
}
private void ViewText(string name, string path, byte[] data)
private void ViewText(string name, string path, byte[] data, RpfFileEntry e)
{
string txt = Encoding.UTF8.GetString(data);
TextForm f = new TextForm();
TextForm f = new TextForm(this);
f.Show();
f.LoadText(name, path, txt);
f.LoadText(name, path, txt, e);
}
private void ViewYtd(string name, string path, byte[] data, RpfFileEntry e)
{
@ -1469,35 +1505,35 @@ namespace CodeWalker
private void ViewYmt(string name, string path, byte[] data, RpfFileEntry e)
{
var ymt = RpfFile.GetFile<YmtFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ymt);
}
private void ViewYmf(string name, string path, byte[] data, RpfFileEntry e)
{
var ymf = RpfFile.GetFile<YmfFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ymf);
}
private void ViewYmap(string name, string path, byte[] data, RpfFileEntry e)
{
var ymap = RpfFile.GetFile<YmapFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ymap);
}
private void ViewYtyp(string name, string path, byte[] data, RpfFileEntry e)
{
var ytyp = RpfFile.GetFile<YtypFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(ytyp);
}
private void ViewJPso(string name, string path, byte[] data, RpfFileEntry e)
{
var pso = RpfFile.GetFile<JPsoFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(pso);
}
@ -1538,7 +1574,7 @@ namespace CodeWalker
private void ViewCut(string name, string path, byte[] data, RpfFileEntry e)
{
var cut = RpfFile.GetFile<CutFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(cut);
}
@ -1559,7 +1595,7 @@ namespace CodeWalker
private void ViewRel(string name, string path, byte[] data, RpfFileEntry e)
{
var rel = RpfFile.GetFile<RelFile>(e, data);
RelForm f = new RelForm();
RelForm f = new RelForm(this);
f.Show();
f.LoadRel(rel);
}
@ -1594,11 +1630,53 @@ namespace CodeWalker
private void ViewCacheDat(string name, string path, byte[] data, RpfFileEntry e)
{
var cachedat = RpfFile.GetFile<CacheDatFile>(e, data);
MetaForm f = new MetaForm();
MetaForm f = new MetaForm(this);
f.Show();
f.LoadMeta(cachedat);
}
private RpfFileEntry CreateFileEntry(string name, string path, ref byte[] data)
{
//this should only really be used when loading a file from the filesystem.
RpfFileEntry e = null;
uint rsc7 = (data?.Length > 4) ? BitConverter.ToUInt32(data, 0) : 0;
if (rsc7 == 0x37435352) //RSC7 header present! create RpfResourceFileEntry and decompress data...
{
e = RpfFile.CreateResourceFileEntry(ref data, 0);//"version" should be loadable from the header in the data..
data = ResourceBuilder.Decompress(data);
}
else
{
var be = new RpfBinaryFileEntry();
be.FileSize = (uint)data?.Length;
be.FileUncompressedSize = be.FileSize;
e = be;
}
e.Name = name;
e.NameLower = name?.ToLowerInvariant();
e.NameHash = JenkHash.GenHash(e.NameLower);
e.ShortNameHash = JenkHash.GenHash(Path.GetFileNameWithoutExtension(e.NameLower));
e.Path = path;
return e;
}
private Form FindExistingForm(RpfFileEntry e)
{
if (e == null) return null;
var allforms = Application.OpenForms;
var path = e.Path.ToLowerInvariant();
foreach (var form in allforms)
{
var metaform = form as MetaForm;
if (metaform?.rpfFileEntry == e) return metaform;
if (metaform?.rpfFileEntry?.Path?.ToLowerInvariant() == path)
return metaform; //need to test the path as well since the file entry may have been replaced by a new version..!
}
return null;
}
private void ShowTreeContextMenu(TreeNode n, Point p)
{
@ -1664,6 +1742,7 @@ namespace CodeWalker
ListContextNewMenu.Visible = cancreate;
ListContextImportRawMenu.Visible = canimport;
ListContextImportFbxMenu.Visible = canimport;
ListContextImportXmlMenu.Visible = canimport;
ListContextImportSeparator.Visible = cancreate;
@ -1708,6 +1787,7 @@ namespace CodeWalker
MainListView.LabelEdit = enable;
EnsureEditModeWarning();
UpdateSelectionUI();
}
private void EnsureEditModeWarning()
@ -1745,7 +1825,7 @@ namespace CodeWalker
private bool EnsureRpfValidEncryption(RpfFile file = null)
public bool EnsureRpfValidEncryption(RpfFile file = null)
{
if ((file == null) && (CurrentFolder.RpfFolder == null)) return false;
@ -2176,6 +2256,98 @@ namespace CodeWalker
AddNewFolderTreeNode(node);
}
}
private void ImportFbx()
{
if (!EditMode) return;
if (CurrentFolder?.IsSearchResults ?? false) return;
RpfDirectoryEntry parentrpffldr = CurrentFolder.RpfFolder;
if (parentrpffldr == null)
{
MessageBox.Show("No parent RPF folder selected! This shouldn't happen. Refresh the view and try again.");
return;
}
if (!EnsureRpfValidEncryption()) return;
OpenFileDialog.Filter = "FBX Files|*.fbx";
if (OpenFileDialog.ShowDialog(this) != DialogResult.OK)
{
return;//canceled
}
var fpaths = OpenFileDialog.FileNames;
var fdict = new Dictionary<string, byte[]>();
foreach (var fpath in fpaths)
{
#if !DEBUG
try
#endif
{
if (!File.Exists(fpath))
{
continue;//this shouldn't happen...
}
var fi = new FileInfo(fpath);
var fname = fi.Name;
var fnamel = fname.ToLowerInvariant();
var trimlength = 4;
if (!fnamel.EndsWith(".fbx"))
{
MessageBox.Show(fname + ": Not an FBX file!", "Cannot import FBX");
continue;
}
fname = fname.Substring(0, fname.Length - trimlength);
var data = File.ReadAllBytes(fpath);
fdict[fname] = data;
}
#if !DEBUG
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Unable to read file " + fpath);
}
#endif
}
var fbxForm = new ImportFbxForm();
fbxForm.SetInputFiles(fdict);
fbxForm.ShowDialog();
if (fbxForm.DialogResult != DialogResult.OK)
{
return; //fbx import canceled
}
var converted = fbxForm.GetOutputFiles();
if (converted == null)
{
return;
}
foreach (var kvp in converted)
{
var fname = kvp.Key;
var data = kvp.Value;
if (data != null)
{
RpfFile.CreateFile(parentrpffldr, fname, data);
}
}
RefreshMainListView();
}
private void ImportXml()
{
@ -2201,7 +2373,9 @@ namespace CodeWalker
var fpaths = OpenFileDialog.FileNames;
foreach (var fpath in fpaths)
{
#if !DEBUG
try
#endif
{
if (!File.Exists(fpath))
{
@ -2211,6 +2385,8 @@ namespace CodeWalker
var fi = new FileInfo(fpath);
var fname = fi.Name;
var fnamel = fname.ToLowerInvariant();
var mformat = MetaFormat.RSC;
var trimlength = 4;
if (!fnamel.EndsWith(".xml"))
{
@ -2219,17 +2395,21 @@ namespace CodeWalker
}
if (fnamel.EndsWith(".pso.xml"))
{
MessageBox.Show(fname + ": PSO XML import not yet supported.", "Cannot import XML");
continue;
mformat = MetaFormat.PSO;
trimlength = 8;
}
if (fnamel.EndsWith(".rbf.xml"))
{
MessageBox.Show(fname + ": RBF XML import not yet supported.", "Cannot import XML");
continue;
}
if (fnamel.EndsWith(".rel.xml"))
{
mformat = MetaFormat.AudioRel;
}
fname = fname.Substring(0, fname.Length - 4);
fnamel = fnamel.Substring(0, fnamel.Length - 4);
fname = fname.Substring(0, fname.Length - trimlength);
fnamel = fnamel.Substring(0, fnamel.Length - trimlength);
var doc = new XmlDocument();
string text = File.ReadAllText(fpath);
@ -2238,29 +2418,67 @@ namespace CodeWalker
doc.LoadXml(text);
}
var meta = XmlMeta.GetMeta(doc);
byte[] data = null;
if ((meta.DataBlocks?.Data == null) || (meta.DataBlocks.Count == 0))
switch (mformat)
{
MessageBox.Show(fname + ": Schema not supported.", "Cannot import XML");
continue;
case MetaFormat.RSC:
{
var meta = XmlMeta.GetMeta(doc);
if ((meta.DataBlocks?.Data == null) || (meta.DataBlocks.Count == 0))
{
MessageBox.Show(fname + ": Schema not supported.", "Cannot import Meta XML");
continue;
}
data = ResourceBuilder.Build(meta, 2); //meta is RSC V:2
break;
}
case MetaFormat.PSO:
{
var pso = XmlPso.GetPso(doc);
if ((pso.DataSection == null) || (pso.DataMapSection == null) || (pso.SchemaSection == null))
{
MessageBox.Show(fname + ": Schema not supported.", "Cannot import PSO XML");
continue;
}
data = pso.Save();
break;
}
case MetaFormat.RBF:
{
//todo!
break;
}
case MetaFormat.AudioRel:
{
var rel = XmlRel.GetRel(doc);
if ((rel.RelDatasSorted == null) || (rel.RelDatas == null))
{
MessageBox.Show(fname + ": Schema not supported.", "Cannot import REL XML");
continue;
}
data = rel.Save();
break;
}
}
byte[] data = ResourceBuilder.Build(meta, 2); //meta is RSC V:2
if (data != null)
{
RpfFile.CreateFile(parentrpffldr, fname, data);
}
RpfFile.CreateFile(parentrpffldr, fname, data);
}
#if !DEBUG
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Unable to import file");
}
#endif
}
CurrentFolder.ListItems = null;
RefreshMainListView();
}
@ -2402,7 +2620,6 @@ namespace CodeWalker
}
}
CurrentFolder.ListItems = null;
RefreshMainListView();
}
private void CopySelected()
@ -2822,6 +3039,17 @@ namespace CodeWalker
protected override void WndProc(ref Message m)
{
//handle back/forward buttons globally for all the form
if (m.Msg == 0x319) //WM_APPCOMMAND
{
var cmd = (m.LParam.ToInt64() >> 16) & 0xFFF;
if (cmd == 1) GoBack(); //APPCOMMAND_BROWSER_BACKWARD
if (cmd == 2) GoForward(); //APPCOMMAND_BROWSER_FORWARD
}
base.WndProc(ref m);
}
private void ExploreForm_Load(object sender, EventArgs e)
@ -3329,6 +3557,11 @@ namespace CodeWalker
NewRpfArchive();
}
private void ListContextImportFbxMenu_Click(object sender, EventArgs e)
{
ImportFbx();
}
private void ListContextImportXmlMenu_Click(object sender, EventArgs e)
{
ImportXml();
@ -3414,6 +3647,11 @@ namespace CodeWalker
ExtractAll();
}
private void EditImportFbxMenu_Click(object sender, EventArgs e)
{
ImportFbx();
}
private void EditImportXmlMenu_Click(object sender, EventArgs e)
{
ImportXml();

View File

@ -313,7 +313,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADo
HwAAAk1TRnQBSQFMAgEBGAEAARgBAQEYAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
HwAAAk1TRnQBSQFMAgEBGAEAATgBAQE4AQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
AwABQAMAAXADAAEBAQABCAYAARwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA

View File

@ -11,6 +11,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
namespace CodeWalker.Forms
{
@ -44,8 +45,15 @@ namespace CodeWalker.Forms
private bool DelayHighlight = false;
public MetaForm()
private ExploreForm exploreForm = null;
public RpfFileEntry rpfFileEntry { get; private set; } = null;
private MetaFormat metaFormat = MetaFormat.XML;
public MetaForm(ExploreForm owner)
{
exploreForm = owner;
InitializeComponent();
}
@ -119,14 +127,18 @@ namespace CodeWalker.Forms
Xml = "";
RawPropertyGrid.SelectedObject = null;
modified = false;
rpfFileEntry = null;
return true;
}
private void NewDocument()
{
if (!CloseDocument()) return; //same thing really..
if (!CloseDocument()) return;
FileName = "New.xml";
rpfFileEntry = null;
//TODO: decide XML/RSC/PSO/RBF format..?
}
private void OpenDocument()
{
@ -144,9 +156,32 @@ namespace CodeWalker.Forms
FilePath = fn;
FileName = new FileInfo(fn).Name;
RawPropertyGrid.SelectedObject = null;
rpfFileEntry = null;
//TODO: open RSC/PSO/RBF..?
}
private void SaveDocument(bool saveAs = false)
{
if ((metaFormat != MetaFormat.XML) && (saveAs == false))
{
var doc = new XmlDocument();
try
{
doc.LoadXml(xml);
}
catch (Exception ex)
{
MessageBox.Show("There's something wrong with your XML document:\r\n" + ex.Message, "Unable to parse XML");
return;
}
if (SaveMeta(doc))
{
return;
}
//if Meta saving failed for whatever reason, fallback to saving the XML in the filesystem.
saveAs = true;
}
if (string.IsNullOrEmpty(FileName)) saveAs = true;
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
@ -171,6 +206,7 @@ namespace CodeWalker.Forms
modified = false;
FilePath = fn;
FileName = new FileInfo(fn).Name;
metaFormat = MetaFormat.XML;
}
@ -181,7 +217,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ymt, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ymt;
rpfFileEntry = ymt?.RpfFileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ymt != null)
{
if (ymt.Meta != null) metaFormat = MetaFormat.RSC;
if (ymt.Pso != null) metaFormat = MetaFormat.PSO;
if (ymt.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(YmfFile ymf)
{
@ -189,7 +233,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ymf, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ymf;
rpfFileEntry = ymf?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ymf != null)
{
if (ymf.Meta != null) metaFormat = MetaFormat.RSC;
if (ymf.Pso != null) metaFormat = MetaFormat.PSO;
if (ymf.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(YmapFile ymap)
{
@ -197,7 +249,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ymap, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ymap;
rpfFileEntry = ymap?.RpfFileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ymap != null)
{
if (ymap.Meta != null) metaFormat = MetaFormat.RSC;
if (ymap.Pso != null) metaFormat = MetaFormat.PSO;
if (ymap.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(YtypFile ytyp)
{
@ -205,7 +265,15 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(ytyp, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = ytyp;
rpfFileEntry = ytyp?.RpfFileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (ytyp != null)
{
if (ytyp.Meta != null) metaFormat = MetaFormat.RSC;
if (ytyp.Pso != null) metaFormat = MetaFormat.PSO;
if (ytyp.Rbf != null) metaFormat = MetaFormat.RBF;
}
}
public void LoadMeta(JPsoFile jpso)
{
@ -213,7 +281,13 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(jpso, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = jpso;
rpfFileEntry = jpso?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (jpso != null)
{
if (jpso.Pso != null) metaFormat = MetaFormat.PSO;
}
}
public void LoadMeta(CutFile cut)
{
@ -221,7 +295,13 @@ namespace CodeWalker.Forms
Xml = MetaXml.GetXml(cut, out fn);
FileName = fn;
RawPropertyGrid.SelectedObject = cut;
rpfFileEntry = cut?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (cut != null)
{
if (cut.Pso != null) metaFormat = MetaFormat.PSO;
}
}
public void LoadMeta(CacheDatFile cachedat)
{
@ -229,11 +309,112 @@ namespace CodeWalker.Forms
Xml = cachedat.GetXml();
FileName = fn;
RawPropertyGrid.SelectedObject = cachedat;
rpfFileEntry = cachedat?.FileEntry;
modified = false;
metaFormat = MetaFormat.XML;
if (cachedat?.FileEntry != null)
{
metaFormat = MetaFormat.CacheFile;
}
}
public bool SaveMeta(XmlDocument doc)
{
//if explorer is in edit mode, and the current RpfFileEntry is valid, convert XML to the
//current meta format and then save the file into the RPF.
//otherwise, save the generated file to disk?
//(currently just return false and revert to XML file save)
if (!(exploreForm?.EditMode ?? false)) return false;
if (rpfFileEntry?.Parent == null) return false;
byte[] data = null;
#if !DEBUG
try
#endif
{
switch (metaFormat)
{
default:
case MetaFormat.XML: return false;//what are we even doing here?
case MetaFormat.RSC:
var meta = XmlMeta.GetMeta(doc);
if ((meta.DataBlocks?.Data == null) || (meta.DataBlocks.Count == 0))
{
MessageBox.Show("Schema not supported.", "Cannot import Meta XML");
return false;
}
data = ResourceBuilder.Build(meta, 2); //meta is RSC "Version":2 (it's actually a type identifier, not a version!)
break;
case MetaFormat.PSO:
var pso = XmlPso.GetPso(doc);
if ((pso.DataSection == null) || (pso.DataMapSection == null) || (pso.SchemaSection == null))
{
MessageBox.Show("Schema not supported.", "Cannot import PSO XML");
return false;
}
data = pso.Save();
break;
case MetaFormat.RBF:
MessageBox.Show("Sorry, RBF import is not supported.", "Cannot import RBF XML");
return false;
case MetaFormat.CacheFile:
MessageBox.Show("Sorry, CacheFile import is not supported.", "Cannot import CacheFile XML");
return false;
}
}
#if !DEBUG
catch (Exception ex)
{
MessageBox.Show("Exception encountered!\r\n" + ex.ToString(), "Cannot convert XML");
return false;
}
#endif
if (data == null)
{
MessageBox.Show("Schema not supported. (Unspecified error - data was null!)", "Cannot convert XML");
return false;
}
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
{
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return false;//that was a close one
}
}
try
{
if (!(exploreForm?.EnsureRpfValidEncryption(rpfFileEntry.File) ?? false)) return false;
var newentry = RpfFile.CreateFile(rpfFileEntry.Parent, rpfFileEntry.Name, data);
if (newentry != rpfFileEntry)
{ }
rpfFileEntry = newentry;
exploreForm?.RefreshMainListViewInvoke(); //update the file details in explorer...
modified = false;
StatusLabel.Text = metaFormat.ToString() + " file saved successfully at " + DateTime.Now.ToString();
return true; //victory!
}
catch (Exception ex)
{
MessageBox.Show("Error saving file to RPF! The RPF archive may be corrupted...\r\n" + ex.ToString(), "Really Bad Error");
}
return false;
}
Style BlueStyle = new TextStyle(Brushes.Blue, null, FontStyle.Regular);
Style RedStyle = new TextStyle(Brushes.Red, null, FontStyle.Regular);
Style MaroonStyle = new TextStyle(Brushes.Maroon, null, FontStyle.Regular);

View File

@ -38,14 +38,22 @@
this.ConsolePanel = new System.Windows.Forms.Panel();
this.ConsoleTextBox = new CodeWalker.WinForms.TextBoxFix();
this.ToolsPanel = new System.Windows.Forms.Panel();
this.MainToolbarPanel = new System.Windows.Forms.Panel();
this.MainToolbar = new System.Windows.Forms.ToolStrip();
this.SaveButton = new System.Windows.Forms.ToolStripSplitButton();
this.SaveMenuButton = new System.Windows.Forms.ToolStripMenuItem();
this.SaveAsMenuButton = new System.Windows.Forms.ToolStripMenuItem();
this.ToolsTabControl = new System.Windows.Forms.TabControl();
this.ToolsModelsTabPage = new System.Windows.Forms.TabPage();
this.ModelsTreeView = new CodeWalker.WinForms.TreeViewFix();
this.ToolsTexturesTabPage = new System.Windows.Forms.TabPage();
this.ToolsMaterialsTabPage = new System.Windows.Forms.TabPage();
this.MaterialEditorButton = new System.Windows.Forms.Button();
this.TextureViewerButton = new System.Windows.Forms.Button();
this.TexturesTreeView = new CodeWalker.WinForms.TreeViewFix();
this.ToolsDetailsTabPage = new System.Windows.Forms.TabPage();
this.DetailsPropertyGrid = new CodeWalker.WinForms.ReadOnlyPropertyGrid();
this.ToolsOptionsTabPage = new System.Windows.Forms.TabPage();
this.HDTexturesCheckBox = new System.Windows.Forms.CheckBox();
this.SkeletonsCheckBox = new System.Windows.Forms.CheckBox();
this.TimeOfDayLabel = new System.Windows.Forms.Label();
this.label19 = new System.Windows.Forms.Label();
@ -73,13 +81,15 @@
this.ToolsPanelHideButton = new System.Windows.Forms.Button();
this.ToolsDragPanel = new System.Windows.Forms.Panel();
this.ToolsPanelShowButton = new System.Windows.Forms.Button();
this.TextureViewerButton = new System.Windows.Forms.Button();
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.StatusStrip.SuspendLayout();
this.ConsolePanel.SuspendLayout();
this.ToolsPanel.SuspendLayout();
this.MainToolbarPanel.SuspendLayout();
this.MainToolbar.SuspendLayout();
this.ToolsTabControl.SuspendLayout();
this.ToolsModelsTabPage.SuspendLayout();
this.ToolsTexturesTabPage.SuspendLayout();
this.ToolsMaterialsTabPage.SuspendLayout();
this.ToolsDetailsTabPage.SuspendLayout();
this.ToolsOptionsTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.TimeOfDayTrackBar)).BeginInit();
@ -156,6 +166,7 @@
this.ToolsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.ToolsPanel.BackColor = System.Drawing.SystemColors.ControlDark;
this.ToolsPanel.Controls.Add(this.MainToolbarPanel);
this.ToolsPanel.Controls.Add(this.ToolsTabControl);
this.ToolsPanel.Controls.Add(this.ToolsPanelHideButton);
this.ToolsPanel.Controls.Add(this.ToolsDragPanel);
@ -165,13 +176,63 @@
this.ToolsPanel.TabIndex = 2;
this.ToolsPanel.Visible = false;
//
// MainToolbarPanel
//
this.MainToolbarPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.MainToolbarPanel.BackColor = System.Drawing.SystemColors.ControlDark;
this.MainToolbarPanel.Controls.Add(this.MainToolbar);
this.MainToolbarPanel.Location = new System.Drawing.Point(181, 2);
this.MainToolbarPanel.Name = "MainToolbarPanel";
this.MainToolbarPanel.Size = new System.Drawing.Size(34, 24);
this.MainToolbarPanel.TabIndex = 4;
//
// MainToolbar
//
this.MainToolbar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
this.MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.SaveButton});
this.MainToolbar.Location = new System.Drawing.Point(0, 0);
this.MainToolbar.Name = "MainToolbar";
this.MainToolbar.Size = new System.Drawing.Size(34, 25);
this.MainToolbar.TabIndex = 7;
this.MainToolbar.Text = "Main Toolbar";
//
// SaveButton
//
this.SaveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.SaveButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.SaveMenuButton,
this.SaveAsMenuButton});
this.SaveButton.Image = ((System.Drawing.Image)(resources.GetObject("SaveButton.Image")));
this.SaveButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this.SaveButton.Name = "SaveButton";
this.SaveButton.Size = new System.Drawing.Size(32, 22);
this.SaveButton.Text = "Save";
this.SaveButton.ButtonClick += new System.EventHandler(this.SaveButton_ButtonClick);
//
// SaveMenuButton
//
this.SaveMenuButton.Image = ((System.Drawing.Image)(resources.GetObject("SaveMenuButton.Image")));
this.SaveMenuButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this.SaveMenuButton.Name = "SaveMenuButton";
this.SaveMenuButton.Size = new System.Drawing.Size(123, 22);
this.SaveMenuButton.Text = "Save";
this.SaveMenuButton.Click += new System.EventHandler(this.SaveMenuButton_Click);
//
// SaveAsMenuButton
//
this.SaveAsMenuButton.Name = "SaveAsMenuButton";
this.SaveAsMenuButton.Size = new System.Drawing.Size(123, 22);
this.SaveAsMenuButton.Text = "Save As...";
this.SaveAsMenuButton.Click += new System.EventHandler(this.SaveAsMenuButton_Click);
//
// ToolsTabControl
//
this.ToolsTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ToolsTabControl.Controls.Add(this.ToolsModelsTabPage);
this.ToolsTabControl.Controls.Add(this.ToolsTexturesTabPage);
this.ToolsTabControl.Controls.Add(this.ToolsMaterialsTabPage);
this.ToolsTabControl.Controls.Add(this.ToolsDetailsTabPage);
this.ToolsTabControl.Controls.Add(this.ToolsOptionsTabPage);
this.ToolsTabControl.Location = new System.Drawing.Point(2, 30);
@ -206,17 +267,38 @@
this.ModelsTreeView.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.ModelsTreeView_NodeMouseDoubleClick);
this.ModelsTreeView.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.ModelsTreeView_KeyPress);
//
// ToolsTexturesTabPage
// ToolsMaterialsTabPage
//
this.ToolsTexturesTabPage.Controls.Add(this.TextureViewerButton);
this.ToolsTexturesTabPage.Controls.Add(this.TexturesTreeView);
this.ToolsTexturesTabPage.Location = new System.Drawing.Point(4, 22);
this.ToolsTexturesTabPage.Name = "ToolsTexturesTabPage";
this.ToolsTexturesTabPage.Padding = new System.Windows.Forms.Padding(3);
this.ToolsTexturesTabPage.Size = new System.Drawing.Size(205, 500);
this.ToolsTexturesTabPage.TabIndex = 1;
this.ToolsTexturesTabPage.Text = "Textures";
this.ToolsTexturesTabPage.UseVisualStyleBackColor = true;
this.ToolsMaterialsTabPage.Controls.Add(this.MaterialEditorButton);
this.ToolsMaterialsTabPage.Controls.Add(this.TextureViewerButton);
this.ToolsMaterialsTabPage.Controls.Add(this.TexturesTreeView);
this.ToolsMaterialsTabPage.Location = new System.Drawing.Point(4, 22);
this.ToolsMaterialsTabPage.Name = "ToolsMaterialsTabPage";
this.ToolsMaterialsTabPage.Padding = new System.Windows.Forms.Padding(3);
this.ToolsMaterialsTabPage.Size = new System.Drawing.Size(205, 500);
this.ToolsMaterialsTabPage.TabIndex = 1;
this.ToolsMaterialsTabPage.Text = "Materials";
this.ToolsMaterialsTabPage.UseVisualStyleBackColor = true;
//
// MaterialEditorButton
//
this.MaterialEditorButton.Location = new System.Drawing.Point(3, 6);
this.MaterialEditorButton.Name = "MaterialEditorButton";
this.MaterialEditorButton.Size = new System.Drawing.Size(91, 23);
this.MaterialEditorButton.TabIndex = 3;
this.MaterialEditorButton.Text = "Material editor";
this.MaterialEditorButton.UseVisualStyleBackColor = true;
this.MaterialEditorButton.Click += new System.EventHandler(this.MaterialEditorButton_Click);
//
// TextureViewerButton
//
this.TextureViewerButton.Location = new System.Drawing.Point(111, 6);
this.TextureViewerButton.Name = "TextureViewerButton";
this.TextureViewerButton.Size = new System.Drawing.Size(91, 23);
this.TextureViewerButton.TabIndex = 2;
this.TextureViewerButton.Text = "Texture viewer";
this.TextureViewerButton.UseVisualStyleBackColor = true;
this.TextureViewerButton.Click += new System.EventHandler(this.TextureViewerButton_Click);
//
// TexturesTreeView
//
@ -255,6 +337,7 @@
//
// ToolsOptionsTabPage
//
this.ToolsOptionsTabPage.Controls.Add(this.HDTexturesCheckBox);
this.ToolsOptionsTabPage.Controls.Add(this.SkeletonsCheckBox);
this.ToolsOptionsTabPage.Controls.Add(this.TimeOfDayLabel);
this.ToolsOptionsTabPage.Controls.Add(this.label19);
@ -286,13 +369,26 @@
this.ToolsOptionsTabPage.Text = "Options";
this.ToolsOptionsTabPage.UseVisualStyleBackColor = true;
//
// HDTexturesCheckBox
//
this.HDTexturesCheckBox.AutoSize = true;
this.HDTexturesCheckBox.Checked = true;
this.HDTexturesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.HDTexturesCheckBox.Location = new System.Drawing.Point(19, 242);
this.HDTexturesCheckBox.Name = "HDTexturesCheckBox";
this.HDTexturesCheckBox.Size = new System.Drawing.Size(82, 17);
this.HDTexturesCheckBox.TabIndex = 10;
this.HDTexturesCheckBox.Text = "HD textures";
this.HDTexturesCheckBox.UseVisualStyleBackColor = true;
this.HDTexturesCheckBox.CheckedChanged += new System.EventHandler(this.HDTexturesCheckBox_CheckedChanged);
//
// SkeletonsCheckBox
//
this.SkeletonsCheckBox.AutoSize = true;
this.SkeletonsCheckBox.Location = new System.Drawing.Point(19, 444);
this.SkeletonsCheckBox.Name = "SkeletonsCheckBox";
this.SkeletonsCheckBox.Size = new System.Drawing.Size(103, 17);
this.SkeletonsCheckBox.TabIndex = 21;
this.SkeletonsCheckBox.TabIndex = 22;
this.SkeletonsCheckBox.Text = "Show Skeletons";
this.SkeletonsCheckBox.UseVisualStyleBackColor = true;
this.SkeletonsCheckBox.CheckedChanged += new System.EventHandler(this.SkeletonsCheckBox_CheckedChanged);
@ -344,7 +440,7 @@
// ShowCollisionMeshesCheckBox
//
this.ShowCollisionMeshesCheckBox.AutoSize = true;
this.ShowCollisionMeshesCheckBox.Location = new System.Drawing.Point(19, 176);
this.ShowCollisionMeshesCheckBox.Location = new System.Drawing.Point(19, 173);
this.ShowCollisionMeshesCheckBox.Name = "ShowCollisionMeshesCheckBox";
this.ShowCollisionMeshesCheckBox.Size = new System.Drawing.Size(132, 17);
this.ShowCollisionMeshesCheckBox.TabIndex = 7;
@ -355,10 +451,10 @@
// GridCheckBox
//
this.GridCheckBox.AutoSize = true;
this.GridCheckBox.Location = new System.Drawing.Point(19, 353);
this.GridCheckBox.Location = new System.Drawing.Point(19, 364);
this.GridCheckBox.Name = "GridCheckBox";
this.GridCheckBox.Size = new System.Drawing.Size(45, 17);
this.GridCheckBox.TabIndex = 16;
this.GridCheckBox.TabIndex = 17;
this.GridCheckBox.Text = "Grid";
this.GridCheckBox.UseVisualStyleBackColor = true;
this.GridCheckBox.CheckedChanged += new System.EventHandler(this.GridCheckBox_CheckedChanged);
@ -372,19 +468,19 @@
"40",
"60",
"100"});
this.GridCountComboBox.Location = new System.Drawing.Point(83, 403);
this.GridCountComboBox.Location = new System.Drawing.Point(83, 411);
this.GridCountComboBox.Name = "GridCountComboBox";
this.GridCountComboBox.Size = new System.Drawing.Size(114, 21);
this.GridCountComboBox.TabIndex = 20;
this.GridCountComboBox.TabIndex = 21;
this.GridCountComboBox.SelectedIndexChanged += new System.EventHandler(this.GridCountComboBox_SelectedIndexChanged);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(7, 406);
this.label2.Location = new System.Drawing.Point(7, 414);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(59, 13);
this.label2.TabIndex = 19;
this.label2.TabIndex = 20;
this.label2.Text = "Grid count:";
//
// GridSizeComboBox
@ -396,19 +492,19 @@
"1.0",
"10",
"100"});
this.GridSizeComboBox.Location = new System.Drawing.Point(83, 376);
this.GridSizeComboBox.Location = new System.Drawing.Point(83, 384);
this.GridSizeComboBox.Name = "GridSizeComboBox";
this.GridSizeComboBox.Size = new System.Drawing.Size(114, 21);
this.GridSizeComboBox.TabIndex = 18;
this.GridSizeComboBox.TabIndex = 19;
this.GridSizeComboBox.SelectedIndexChanged += new System.EventHandler(this.GridSizeComboBox_SelectedIndexChanged);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(7, 379);
this.label1.Location = new System.Drawing.Point(7, 387);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(70, 13);
this.label1.TabIndex = 17;
this.label1.TabIndex = 18;
this.label1.Text = "Grid unit size:";
//
// StatusBarCheckBox
@ -419,7 +515,7 @@
this.StatusBarCheckBox.Location = new System.Drawing.Point(19, 480);
this.StatusBarCheckBox.Name = "StatusBarCheckBox";
this.StatusBarCheckBox.Size = new System.Drawing.Size(74, 17);
this.StatusBarCheckBox.TabIndex = 22;
this.StatusBarCheckBox.TabIndex = 23;
this.StatusBarCheckBox.Text = "Status bar";
this.StatusBarCheckBox.UseVisualStyleBackColor = true;
this.StatusBarCheckBox.CheckedChanged += new System.EventHandler(this.StatusBarCheckBox_CheckedChanged);
@ -430,7 +526,7 @@
this.ErrorConsoleCheckBox.Location = new System.Drawing.Point(105, 480);
this.ErrorConsoleCheckBox.Name = "ErrorConsoleCheckBox";
this.ErrorConsoleCheckBox.Size = new System.Drawing.Size(88, 17);
this.ErrorConsoleCheckBox.TabIndex = 23;
this.ErrorConsoleCheckBox.TabIndex = 24;
this.ErrorConsoleCheckBox.Text = "Error console";
this.ErrorConsoleCheckBox.UseVisualStyleBackColor = true;
this.ErrorConsoleCheckBox.CheckedChanged += new System.EventHandler(this.ErrorConsoleCheckBox_CheckedChanged);
@ -475,7 +571,7 @@
// WireframeCheckBox
//
this.WireframeCheckBox.AutoSize = true;
this.WireframeCheckBox.Location = new System.Drawing.Point(19, 199);
this.WireframeCheckBox.Location = new System.Drawing.Point(19, 196);
this.WireframeCheckBox.Name = "WireframeCheckBox";
this.WireframeCheckBox.Size = new System.Drawing.Size(74, 17);
this.WireframeCheckBox.TabIndex = 8;
@ -497,19 +593,19 @@
"Texture coord 1",
"Texture coord 2",
"Texture coord 3"});
this.RenderModeComboBox.Location = new System.Drawing.Point(83, 255);
this.RenderModeComboBox.Location = new System.Drawing.Point(83, 274);
this.RenderModeComboBox.Name = "RenderModeComboBox";
this.RenderModeComboBox.Size = new System.Drawing.Size(114, 21);
this.RenderModeComboBox.TabIndex = 11;
this.RenderModeComboBox.TabIndex = 12;
this.RenderModeComboBox.SelectedIndexChanged += new System.EventHandler(this.RenderModeComboBox_SelectedIndexChanged);
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(7, 285);
this.label11.Location = new System.Drawing.Point(7, 304);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(67, 13);
this.label11.TabIndex = 12;
this.label11.TabIndex = 13;
this.label11.Text = "Tex sampler:";
//
// TextureSamplerComboBox
@ -517,10 +613,10 @@
this.TextureSamplerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.TextureSamplerComboBox.Enabled = false;
this.TextureSamplerComboBox.FormattingEnabled = true;
this.TextureSamplerComboBox.Location = new System.Drawing.Point(83, 282);
this.TextureSamplerComboBox.Location = new System.Drawing.Point(83, 301);
this.TextureSamplerComboBox.Name = "TextureSamplerComboBox";
this.TextureSamplerComboBox.Size = new System.Drawing.Size(114, 21);
this.TextureSamplerComboBox.TabIndex = 13;
this.TextureSamplerComboBox.TabIndex = 14;
this.TextureSamplerComboBox.SelectedIndexChanged += new System.EventHandler(this.TextureSamplerComboBox_SelectedIndexChanged);
//
// TextureCoordsComboBox
@ -532,19 +628,19 @@
"Texture coord 1",
"Texture coord 2",
"Texture coord 3"});
this.TextureCoordsComboBox.Location = new System.Drawing.Point(83, 309);
this.TextureCoordsComboBox.Location = new System.Drawing.Point(83, 328);
this.TextureCoordsComboBox.Name = "TextureCoordsComboBox";
this.TextureCoordsComboBox.Size = new System.Drawing.Size(114, 21);
this.TextureCoordsComboBox.TabIndex = 15;
this.TextureCoordsComboBox.TabIndex = 16;
this.TextureCoordsComboBox.SelectedIndexChanged += new System.EventHandler(this.TextureCoordsComboBox_SelectedIndexChanged);
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(7, 258);
this.label10.Location = new System.Drawing.Point(7, 277);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(74, 13);
this.label10.TabIndex = 10;
this.label10.TabIndex = 11;
this.label10.Text = "Render mode:";
//
// AnisotropicFilteringCheckBox
@ -552,7 +648,7 @@
this.AnisotropicFilteringCheckBox.AutoSize = true;
this.AnisotropicFilteringCheckBox.Checked = true;
this.AnisotropicFilteringCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.AnisotropicFilteringCheckBox.Location = new System.Drawing.Point(19, 222);
this.AnisotropicFilteringCheckBox.Location = new System.Drawing.Point(19, 219);
this.AnisotropicFilteringCheckBox.Name = "AnisotropicFilteringCheckBox";
this.AnisotropicFilteringCheckBox.Size = new System.Drawing.Size(114, 17);
this.AnisotropicFilteringCheckBox.TabIndex = 9;
@ -563,10 +659,10 @@
// label14
//
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(7, 312);
this.label14.Location = new System.Drawing.Point(7, 331);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(63, 13);
this.label14.TabIndex = 14;
this.label14.TabIndex = 15;
this.label14.Text = "Tex coords:";
//
// ToolsPanelHideButton
@ -602,15 +698,9 @@
this.ToolsPanelShowButton.UseVisualStyleBackColor = true;
this.ToolsPanelShowButton.Click += new System.EventHandler(this.ToolsPanelShowButton_Click);
//
// TextureViewerButton
// SaveFileDialog
//
this.TextureViewerButton.Location = new System.Drawing.Point(6, 6);
this.TextureViewerButton.Name = "TextureViewerButton";
this.TextureViewerButton.Size = new System.Drawing.Size(113, 23);
this.TextureViewerButton.TabIndex = 2;
this.TextureViewerButton.Text = "Open texture viewer";
this.TextureViewerButton.UseVisualStyleBackColor = true;
this.TextureViewerButton.Click += new System.EventHandler(this.TextureViewerButton_Click);
this.SaveFileDialog.Filter = "All files|*.*";
//
// ModelForm
//
@ -638,9 +728,13 @@
this.ConsolePanel.ResumeLayout(false);
this.ConsolePanel.PerformLayout();
this.ToolsPanel.ResumeLayout(false);
this.MainToolbarPanel.ResumeLayout(false);
this.MainToolbarPanel.PerformLayout();
this.MainToolbar.ResumeLayout(false);
this.MainToolbar.PerformLayout();
this.ToolsTabControl.ResumeLayout(false);
this.ToolsModelsTabPage.ResumeLayout(false);
this.ToolsTexturesTabPage.ResumeLayout(false);
this.ToolsMaterialsTabPage.ResumeLayout(false);
this.ToolsDetailsTabPage.ResumeLayout(false);
this.ToolsOptionsTabPage.ResumeLayout(false);
this.ToolsOptionsTabPage.PerformLayout();
@ -665,7 +759,7 @@
private System.Windows.Forms.Button ToolsPanelShowButton;
private System.Windows.Forms.TabControl ToolsTabControl;
private System.Windows.Forms.TabPage ToolsModelsTabPage;
private System.Windows.Forms.TabPage ToolsTexturesTabPage;
private System.Windows.Forms.TabPage ToolsMaterialsTabPage;
private System.Windows.Forms.TabPage ToolsDetailsTabPage;
private WinForms.TreeViewFix ModelsTreeView;
private WinForms.ReadOnlyPropertyGrid DetailsPropertyGrid;
@ -696,5 +790,13 @@
private System.Windows.Forms.TrackBar TimeOfDayTrackBar;
private System.Windows.Forms.CheckBox SkeletonsCheckBox;
private System.Windows.Forms.Button TextureViewerButton;
private System.Windows.Forms.CheckBox HDTexturesCheckBox;
private System.Windows.Forms.Button MaterialEditorButton;
private System.Windows.Forms.Panel MainToolbarPanel;
private System.Windows.Forms.ToolStrip MainToolbar;
private System.Windows.Forms.ToolStripSplitButton SaveButton;
private System.Windows.Forms.ToolStripMenuItem SaveMenuButton;
private System.Windows.Forms.ToolStripMenuItem SaveAsMenuButton;
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
}
}

View File

@ -100,10 +100,19 @@ namespace CodeWalker.Forms
bool updateArchetypeStatus = true;
ModelMatForm materialForm = null;
private bool modelModified = false;
ExploreForm exploreForm = null;
RpfFileEntry rpfFileEntry = null;
public ModelForm(ExploreForm ExpForm = null)
{
InitializeComponent();
exploreForm = ExpForm;
gameFileCache = ExpForm?.GetFileCache();
@ -519,7 +528,14 @@ namespace CodeWalker.Forms
{
var f = Yft.Fragment;
hash = Yft?.RpfFileEntry?.ShortNameHash ?? 0;
hash = Yft.RpfFileEntry?.ShortNameHash ?? 0;
var namelower = Yft.RpfFileEntry?.GetShortNameLower();
if (namelower?.EndsWith("_hi") ?? false)
{
hash = JenkHash.GenHash(namelower.Substring(0, namelower.Length - 3));
}
arch = TryGetArchetype(hash);
Renderer.RenderFragment(arch, null, f, hash);
@ -557,6 +573,7 @@ namespace CodeWalker.Forms
FileName = ydr.Name;
Ydr = ydr;
rpfFileEntry = Ydr.RpfFileEntry;
if (ydr.Drawable != null)
{
@ -571,6 +588,7 @@ namespace CodeWalker.Forms
FileName = ydd.Name;
Ydd = ydd;
rpfFileEntry = Ydd.RpfFileEntry;
UpdateModelsUI(ydd.Dict);
@ -582,6 +600,7 @@ namespace CodeWalker.Forms
FileName = yft.Name;
Yft = yft;
rpfFileEntry = Yft.RpfFileEntry;
var dr = yft.Fragment?.Drawable;
if (dr != null)
@ -597,6 +616,7 @@ namespace CodeWalker.Forms
FileName = ybn.Name;
Ybn = ybn;
rpfFileEntry = Ybn.RpfFileEntry;
if (Ybn.Bounds != null)
{
@ -611,6 +631,7 @@ namespace CodeWalker.Forms
FileName = ypt.Name;
Ypt = ypt;
rpfFileEntry = Ypt.RpfFileEntry;
UpdateModelsUI(ypt.DrawableDict);
@ -622,6 +643,7 @@ namespace CodeWalker.Forms
FileName = ynv.Name;
Ynv = ynv;
rpfFileEntry = Ynv.RpfFileEntry;
if (ynv.Nav.SectorTree != null)
{
@ -643,7 +665,7 @@ namespace CodeWalker.Forms
private void UpdateFormTitle()
{
Text = fileName + " - CodeWalker by dexyfex";
Text = fileName + (modelModified ? "*" : "") + " - CodeWalker by dexyfex";
}
@ -817,6 +839,30 @@ namespace CodeWalker.Forms
AddDrawableModelsTreeNodes(drawable.DrawableModelsLow, "Low Detail", false);
AddDrawableModelsTreeNodes(drawable.DrawableModelsVeryLow, "Very Low Detail", false);
//AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsX, "X Detail", false);
var fdrawable = drawable as FragDrawable;
if (fdrawable != null)
{
var plod1 = fdrawable.OwnerFragment?.PhysicsLODGroup?.PhysicsLOD1;
if ((plod1 != null) && (plod1.Children?.data_items != null))
{
foreach (var child in plod1.Children.data_items)
{
var cdrwbl = child.Drawable1;
if ((cdrwbl != null) && (cdrwbl.AllModels?.Length > 0))
{
if (cdrwbl.Owner is FragDrawable) continue; //it's a copied drawable... eg a wheel
var dname = child.GroupNameHash.ToString();
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsHigh, dname + " - High Detail", true);
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsMedium, dname + " - Medium Detail", false);
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsLow, dname + " - Low Detail", false);
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsVeryLow, dname + " - Very Low Detail", false);
}
}
}
}
}
}
private void UpdateModelsUI(FragType frag)
@ -838,6 +884,29 @@ namespace CodeWalker.Forms
AddDrawableModelsTreeNodes(drawable.DrawableModelsLow, "Low Detail", false);
AddDrawableModelsTreeNodes(drawable.DrawableModelsVeryLow, "Very Low Detail", false);
//AddSelectionDrawableModelsTreeNodes(item.Drawable.DrawableModelsX, "X Detail", false);
var fdrawable = drawable as FragDrawable;
if (fdrawable != null)
{
var plod1 = fdrawable.OwnerFragment?.PhysicsLODGroup?.PhysicsLOD1;
if ((plod1 != null) && (plod1.Children?.data_items != null))
{
foreach (var child in plod1.Children.data_items)
{
var cdrwbl = child.Drawable1;
if ((cdrwbl != null) && (cdrwbl.AllModels?.Length > 0))
{
if (cdrwbl.Owner is FragDrawable) continue; //it's a copied drawable... eg a wheel
var dname = child.GroupNameHash.ToString();
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsHigh, dname + " - High Detail", true);
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsMedium, dname + " - Medium Detail", false);
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsLow, dname + " - Low Detail", false);
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsVeryLow, dname + " - Very Low Detail", false);
}
}
}
}
}
}
private void UpdateModelsUI(Dictionary<uint, Drawable> dict)
@ -1012,6 +1081,166 @@ namespace CodeWalker.Forms
public void OnMaterialFormClosed()
{
materialForm = null;
}
public void OnModelModified()
{
modelModified = true;
UpdateFormTitle();
}
private void Save(bool saveAs = false)
{
var editMode = exploreForm?.EditMode ?? false;
if (string.IsNullOrEmpty(FilePath))
{
if (!editMode) saveAs = true;
if (rpfFileEntry?.Parent == null) saveAs = true;
}
else
{
if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
if (!File.Exists(FilePath)) saveAs = true;
}
var fn = FilePath;
if (saveAs)
{
if (!string.IsNullOrEmpty(fn))
{
var dir = new FileInfo(fn).DirectoryName;
if (!Directory.Exists(dir)) dir = "";
SaveFileDialog.InitialDirectory = dir;
}
SaveFileDialog.FileName = FileName;
var fileExt = Path.GetExtension(FileName);
if ((fileExt.Length > 1) && fileExt.StartsWith("."))
{
fileExt = fileExt.Substring(1);
}
SaveFileDialog.Filter = fileExt.ToUpperInvariant() + " files|*." + fileExt + "|All files|*.*";
if (SaveFileDialog.ShowDialog() != DialogResult.OK) return;
fn = SaveFileDialog.FileName;
}
byte[] fileBytes = null;
#if !DEBUG
try
{
#endif
if (Ydr != null)
{
fileBytes = Ydr.Save();
}
else if (Ydd != null)
{
fileBytes = Ydd.Save();
}
else if (Yft != null)
{
fileBytes = Yft.Save();
}
else if (Ybn != null)
{
fileBytes = Ybn.Save();
}
else if (Ypt != null)
{
fileBytes = Ypt.Save();
}
else if (Ynv != null)
{
fileBytes = Ynv.Save();
}
#if !DEBUG
}
catch(Exception ex)
{
MessageBox.Show("Error saving file!\n" + ex.ToString());
return;
}
#endif
if (fileBytes == null)
{
MessageBox.Show("Error saving file!\n fileBytes was null!");
return;
}
var rpfSave = editMode && (rpfFileEntry?.Parent != null) && !saveAs;
if (rpfSave)
{
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
{
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return;//that was a close one
}
}
try
{
if (!(exploreForm?.EnsureRpfValidEncryption(rpfFileEntry.File) ?? false)) return;
var newentry = RpfFile.CreateFile(rpfFileEntry.Parent, rpfFileEntry.Name, fileBytes);
if (newentry != rpfFileEntry)
{ }
rpfFileEntry = newentry;
exploreForm?.RefreshMainListViewInvoke(); //update the file details in explorer...
StatusLabel.Text = rpfFileEntry.Name + " saved successfully at " + DateTime.Now.ToString();
//victory!
}
catch (Exception ex)
{
MessageBox.Show("Error saving file to RPF! The RPF archive may be corrupted...\r\n" + ex.ToString(), "Really Bad Error");
}
}
else
{
try
{
File.WriteAllBytes(fn, fileBytes);
fileName = Path.GetFileName(fn);
FilePath = fn;
StatusLabel.Text = fileName + " saved successfully at " + DateTime.Now.ToString();
}
catch (Exception ex)
{
MessageBox.Show("Error writing file to disk!\n" + ex.ToString());
return;
}
}
modelModified = false;
UpdateFormTitle();
}
@ -1392,6 +1621,11 @@ namespace CodeWalker.Forms
Renderer.shaders.AnisotropicFiltering = AnisotropicFilteringCheckBox.Checked;
}
private void HDTexturesCheckBox_CheckedChanged(object sender, EventArgs e)
{
Renderer.renderhdtextures = HDTexturesCheckBox.Checked;
}
private void RenderModeComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
TextureSamplerComboBox.Enabled = false;
@ -1532,5 +1766,75 @@ namespace CodeWalker.Forms
MessageBox.Show("Couldn't find embedded texture dict.");
}
}
private void MaterialEditorButton_Click(object sender, EventArgs e)
{
DrawableBase drawable = null;
Dictionary<uint, Drawable> dict = null;
if ((Ydr != null) && (Ydr.Loaded))
{
drawable = Ydr.Drawable;
}
else if ((Ydd != null) && (Ydd.Loaded))
{
dict = Ydd.Dict;
}
else if ((Yft != null) && (Yft.Loaded))
{
drawable = Yft.Fragment?.Drawable;
}
else if ((Ypt != null) && (Ypt.Loaded))
{
dict = Ypt.DrawableDict;
}
else
{
MessageBox.Show("Material editor not supported for the current file.");
return;
}
if (materialForm == null)
{
materialForm = new ModelMatForm(this);
if (drawable != null)
{
materialForm.LoadModel(drawable);
}
else if (dict != null)
{
materialForm.LoadModels(dict);
}
materialForm.Show(this);
}
else
{
if (materialForm.WindowState == FormWindowState.Minimized)
{
materialForm.WindowState = FormWindowState.Normal;
}
materialForm.Focus();
}
}
private void SaveButton_ButtonClick(object sender, EventArgs e)
{
Save();
}
private void SaveMenuButton_Click(object sender, EventArgs e)
{
Save();
}
private void SaveAsMenuButton_Click(object sender, EventArgs e)
{
Save(true);
}
}
}

View File

@ -123,7 +123,32 @@
<metadata name="StatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>166, 17</value>
</metadata>
<metadata name="MainToolbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>276, 17</value>
</metadata>
<metadata name="MainToolbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>276, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="SaveButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABWSURBVDhPY6AK+Pbt238S8PsvX74YQLVCAEjCyckJjj+8
/wjHyGIguq2tDdMQUgwAYZghUO2kGwDCID1Q7fgNQMbIamhrADF41IBBaQA5GKqdEsDAAADtDPd9n5qK
lQAAAABJRU5ErkJggg==
</value>
</data>
<data name="SaveMenuButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABWSURBVDhPY6AK+Pbt238S8PsvX74YQLVCAEjCyckJjj+8
/wjHyGIguq2tDdMQUgwAYZghUO2kGwDCID1Q7fgNQMbIamhrADF41IBBaQA5GKqdEsDAAADtDPd9n5qK
lQAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>397, 17</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA

120
Forms/ModelMatForm.Designer.cs generated Normal file
View File

@ -0,0 +1,120 @@
namespace CodeWalker.Forms
{
partial class ModelMatForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ModelMatForm));
this.MainSplitContainer = new System.Windows.Forms.SplitContainer();
this.label1 = new System.Windows.Forms.Label();
this.ModelsTreeView = new CodeWalker.WinForms.TreeViewFix();
this.MaterialPropertiesPanel = new System.Windows.Forms.Panel();
((System.ComponentModel.ISupportInitialize)(this.MainSplitContainer)).BeginInit();
this.MainSplitContainer.Panel1.SuspendLayout();
this.MainSplitContainer.Panel2.SuspendLayout();
this.MainSplitContainer.SuspendLayout();
this.SuspendLayout();
//
// MainSplitContainer
//
this.MainSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill;
this.MainSplitContainer.Location = new System.Drawing.Point(0, 0);
this.MainSplitContainer.Name = "MainSplitContainer";
//
// MainSplitContainer.Panel1
//
this.MainSplitContainer.Panel1.Controls.Add(this.label1);
this.MainSplitContainer.Panel1.Controls.Add(this.ModelsTreeView);
//
// MainSplitContainer.Panel2
//
this.MainSplitContainer.Panel2.Controls.Add(this.MaterialPropertiesPanel);
this.MainSplitContainer.Size = new System.Drawing.Size(593, 404);
this.MainSplitContainer.SplitterDistance = 191;
this.MainSplitContainer.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(5, 7);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(86, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Select geometry:";
//
// ModelsTreeView
//
this.ModelsTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ModelsTreeView.FullRowSelect = true;
this.ModelsTreeView.HideSelection = false;
this.ModelsTreeView.Location = new System.Drawing.Point(3, 24);
this.ModelsTreeView.Name = "ModelsTreeView";
this.ModelsTreeView.ShowRootLines = false;
this.ModelsTreeView.Size = new System.Drawing.Size(185, 377);
this.ModelsTreeView.TabIndex = 2;
this.ModelsTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.ModelsTreeView_AfterSelect);
//
// MaterialPropertiesPanel
//
this.MaterialPropertiesPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.MaterialPropertiesPanel.AutoScroll = true;
this.MaterialPropertiesPanel.Location = new System.Drawing.Point(3, 24);
this.MaterialPropertiesPanel.Name = "MaterialPropertiesPanel";
this.MaterialPropertiesPanel.Size = new System.Drawing.Size(392, 377);
this.MaterialPropertiesPanel.TabIndex = 0;
//
// ModelMatForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(593, 404);
this.Controls.Add(this.MainSplitContainer);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "ModelMatForm";
this.Text = "Model Material Editor - CodeWalker by dexyfex";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ModelMatForm_FormClosed);
this.MainSplitContainer.Panel1.ResumeLayout(false);
this.MainSplitContainer.Panel1.PerformLayout();
this.MainSplitContainer.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.MainSplitContainer)).EndInit();
this.MainSplitContainer.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.SplitContainer MainSplitContainer;
private System.Windows.Forms.Label label1;
private WinForms.TreeViewFix ModelsTreeView;
private System.Windows.Forms.Panel MaterialPropertiesPanel;
}
}

284
Forms/ModelMatForm.cs Normal file
View File

@ -0,0 +1,284 @@
using CodeWalker.GameFiles;
using SharpDX;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.Forms
{
public partial class ModelMatForm : Form
{
private ModelForm ModelForm;
private DrawableBase Drawable;
private Dictionary<uint, Drawable> DrawableDict;
public ModelMatForm(ModelForm modelForm)
{
InitializeComponent();
ModelForm = modelForm;
}
public void LoadModel(DrawableBase drawable)
{
Drawable = drawable;
ModelsTreeView.Nodes.Clear();
ModelsTreeView.ShowRootLines = false;
if (drawable != null)
{
AddDrawableModelsTreeNodes(drawable.DrawableModelsHigh, "High Detail");
AddDrawableModelsTreeNodes(drawable.DrawableModelsMedium, "Medium Detail");
AddDrawableModelsTreeNodes(drawable.DrawableModelsLow, "Low Detail");
AddDrawableModelsTreeNodes(drawable.DrawableModelsVeryLow, "Very Low Detail");
var fdrawable = drawable as FragDrawable;
if (fdrawable != null)
{
var plod1 = fdrawable.OwnerFragment?.PhysicsLODGroup?.PhysicsLOD1;
if ((plod1 != null) && (plod1.Children?.data_items != null))
{
foreach (var child in plod1.Children.data_items)
{
var cdrwbl = child.Drawable1;
if ((cdrwbl != null) && (cdrwbl.AllModels?.Length > 0))
{
if (cdrwbl.Owner is FragDrawable) continue; //it's a copied drawable... eg a wheel
var dname = child.GroupNameHash.ToString();
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsHigh, dname + " - High Detail");
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsMedium, dname + " - Medium Detail");
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsLow, dname + " - Low Detail");
AddDrawableModelsTreeNodes(cdrwbl.DrawableModelsVeryLow, dname + " - Very Low Detail");
}
}
}
}
}
}
public void LoadModels(Dictionary<uint, Drawable> dict)
{
DrawableDict = dict;
ModelsTreeView.Nodes.Clear();
//ModelsTreeView.ShowRootLines = true;
if (dict != null)
{
foreach (var kvp in dict)
{
MetaHash mhash = new MetaHash(kvp.Key);
var drawable = kvp.Value;
var dnode = ModelsTreeView.Nodes.Add(mhash.ToString());
dnode.Tag = drawable;
AddDrawableModelsTreeNodes(drawable.DrawableModelsHigh, "High Detail", dnode);
AddDrawableModelsTreeNodes(drawable.DrawableModelsMedium, "Medium Detail", dnode);
AddDrawableModelsTreeNodes(drawable.DrawableModelsLow, "Low Detail", dnode);
AddDrawableModelsTreeNodes(drawable.DrawableModelsVeryLow, "Very Low Detail", dnode);
dnode.Expand();
}
}
}
private void AddDrawableModelsTreeNodes(ResourcePointerList64<DrawableModel> models, string prefix, TreeNode parentDrawableNode = null)
{
if (models == null) return;
if (models.data_items == null) return;
for (int mi = 0; mi < models.data_items.Length; mi++)
{
var tnc = (parentDrawableNode != null) ? parentDrawableNode.Nodes : ModelsTreeView.Nodes;
var model = models.data_items[mi];
string mprefix = prefix + " " + (mi + 1).ToString();
var mnode = tnc.Add(mprefix + " " + model.ToString());
mnode.Tag = model;
if ((model.Geometries == null) || (model.Geometries.data_items == null)) continue;
foreach (var geom in model.Geometries.data_items)
{
var gname = geom.ToString();
var gnode = mnode.Nodes.Add(gname);
gnode.Tag = geom;
}
mnode.Expand();
}
}
private void SelectGeometry(DrawableGeometry geom)
{
MaterialPropertiesPanel.Controls.Clear();
var pl = geom?.Shader?.ParametersList;
if (pl == null) return;
var tmpPanel = new Panel(); //need this so textboxes resize correctly in case of scrollbar
tmpPanel.Size = new Size(MaterialPropertiesPanel.Width, 10);
tmpPanel.Location = new System.Drawing.Point(0, 0);
tmpPanel.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
var w = MaterialPropertiesPanel.Width - 140;
var h = pl.Hashes;
var p = pl.Parameters;
for (int ip = 0; ip < h.Length; ip++)
{
var hash = pl.Hashes[ip];
var parm = pl.Parameters[ip];
var data = parm?.Data;
tmpPanel.Height += 25;
var l = new Label();
l.AutoSize = true;
l.Location = new System.Drawing.Point(5, 5 + ip * 25);
l.Text = hash.ToString();
tmpPanel.Controls.Add(l);
var t = new TextBox();
t.Size = new Size(w, 20);
t.Location = new System.Drawing.Point(130, 2 + ip * 25);
t.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
t.Tag = parm;
tmpPanel.Controls.Add(t);
if (data is Vector4)
{
t.Text = FloatUtil.GetVector4String((Vector4)data);
}
else if (data is Vector4[])
{
var txt = "";
var vecs = (Vector4[])data;
foreach (var vec in vecs)
{
if (txt.Length > 0) txt += "; ";
txt += FloatUtil.GetVector4String(vec);
}
t.Text = txt;
}
else if (data is TextureBase)
{
var tex = (TextureBase)data;
t.Text = tex.Name;
if(tex is Texture)
{
t.Text += " (embedded)";
t.ReadOnly = true;
}
}
t.TextChanged += ParamTextBox_TextChanged;
}
MaterialPropertiesPanel.Controls.Add(tmpPanel);
}
private void ParamTextBox_TextChanged(object sender, EventArgs e)
{
var tb = sender as TextBox;
var parm = tb?.Tag as ShaderParameter;
var txt = tb?.Text;
if (parm == null) return;
if (parm.DataType == 0)//texture
{
var tex = parm.Data as TextureBase;
var ttex = tex as Texture;
if (ttex == null)//don't do this for embedded textures!
{
tex.Name = txt;
tex.NameHash = JenkHash.GenHash(txt.ToLowerInvariant());
}
else
{
//TODO: modify embedded textures!
}
}
else if (parm.DataType == 1)//Vector4
{
parm.Data = FloatUtil.ParseVector4String(txt);
}
else //Vector4 array
{
var strs = txt.Split(';');
var vecs = new Vector4[parm.DataType];
for (int i = 0; i < parm.DataType; i++)
{
var vec = Vector4.Zero;
if (i < strs.Length)
{
vec = FloatUtil.ParseVector4String(strs[i].Trim());
}
vecs[i] = vec;
}
parm.Data = vecs;
}
var geom = ModelsTreeView.SelectedNode?.Tag as DrawableGeometry;
if (geom != null)
{
if (Drawable != null)
{
UpdateRenderableParams(Drawable, geom.Shader);
}
if (DrawableDict != null)
{
foreach (var dwbl in DrawableDict.Values)
{
UpdateRenderableParams(dwbl, geom.Shader);
}
}
}
ModelForm.OnModelModified();
}
private void UpdateRenderableParams(DrawableBase dwbl, ShaderFX shader)
{
foreach (var model in dwbl.AllModels)
{
if (model?.Geometries?.data_items == null) continue;
foreach (var geom in model.Geometries.data_items)
{
if (geom.Shader == shader)
{
geom.UpdateRenderableParameters = true;
}
}
}
}
private void ModelMatForm_FormClosed(object sender, FormClosedEventArgs e)
{
ModelForm.OnMaterialFormClosed();
}
private void ModelsTreeView_AfterSelect(object sender, TreeViewEventArgs e)
{
SelectGeometry(e.Node.Tag as DrawableGeometry);
}
}
}

View File

@ -28,16 +28,51 @@
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RelForm));
this.RelPropertyGrid = new CodeWalker.WinForms.PropertyGridFix();
this.MainTabControl = new System.Windows.Forms.TabControl();
this.NameTableTabPage = new System.Windows.Forms.TabPage();
this.XmlTabPage = new System.Windows.Forms.TabPage();
this.XmlTextBox = new FastColoredTextBoxNS.FastColoredTextBox();
this.DetailsTabPage = new System.Windows.Forms.TabPage();
this.NameTableTabPage = new System.Windows.Forms.TabPage();
this.MainTextBox = new CodeWalker.WinForms.TextBoxFix();
this.CloseButton = new System.Windows.Forms.Button();
this.SearchTabPage = new System.Windows.Forms.TabPage();
this.SearchTextRadio = new System.Windows.Forms.RadioButton();
this.SearchHashRadio = new System.Windows.Forms.RadioButton();
this.label12 = new System.Windows.Forms.Label();
this.SearchTextBox = new System.Windows.Forms.TextBox();
this.SearchButton = new System.Windows.Forms.Button();
this.SearchResultsGrid = new CodeWalker.WinForms.PropertyGridFix();
this.MainToolbar = new System.Windows.Forms.ToolStrip();
this.NewButton = new System.Windows.Forms.ToolStripSplitButton();
this.OpenButton = new System.Windows.Forms.ToolStripSplitButton();
this.SaveButton = new System.Windows.Forms.ToolStripSplitButton();
this.MainStatusStrip = new System.Windows.Forms.StatusStrip();
this.StatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this.MainMenu = new System.Windows.Forms.MenuStrip();
this.FileMenu = new System.Windows.Forms.ToolStripMenuItem();
this.FileNewMenu = new System.Windows.Forms.ToolStripMenuItem();
this.FileOpenMenu = new System.Windows.Forms.ToolStripMenuItem();
this.FileSaveMenu = new System.Windows.Forms.ToolStripMenuItem();
this.FileSaveAsMenu = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.FileCloseMenu = new System.Windows.Forms.ToolStripMenuItem();
this.EditMenu = new System.Windows.Forms.ToolStripMenuItem();
this.wIPToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ViewMenu = new System.Windows.Forms.ToolStripMenuItem();
this.wIPToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.OpenFileDialog = new System.Windows.Forms.OpenFileDialog();
this.SaveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.MainTabControl.SuspendLayout();
this.NameTableTabPage.SuspendLayout();
this.XmlTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.XmlTextBox)).BeginInit();
this.DetailsTabPage.SuspendLayout();
this.NameTableTabPage.SuspendLayout();
this.SearchTabPage.SuspendLayout();
this.MainToolbar.SuspendLayout();
this.MainStatusStrip.SuspendLayout();
this.MainMenu.SuspendLayout();
this.SuspendLayout();
//
// RelPropertyGrid
@ -48,33 +83,75 @@
this.RelPropertyGrid.HelpVisible = false;
this.RelPropertyGrid.Location = new System.Drawing.Point(6, 6);
this.RelPropertyGrid.Name = "RelPropertyGrid";
this.RelPropertyGrid.Size = new System.Drawing.Size(644, 356);
this.RelPropertyGrid.Size = new System.Drawing.Size(819, 448);
this.RelPropertyGrid.TabIndex = 0;
//
// MainTabControl
//
this.MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.MainTabControl.Controls.Add(this.NameTableTabPage);
this.MainTabControl.Controls.Add(this.XmlTabPage);
this.MainTabControl.Controls.Add(this.DetailsTabPage);
this.MainTabControl.Location = new System.Drawing.Point(5, 5);
this.MainTabControl.Controls.Add(this.NameTableTabPage);
this.MainTabControl.Controls.Add(this.SearchTabPage);
this.MainTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.MainTabControl.Location = new System.Drawing.Point(0, 49);
this.MainTabControl.Margin = new System.Windows.Forms.Padding(0);
this.MainTabControl.Name = "MainTabControl";
this.MainTabControl.SelectedIndex = 0;
this.MainTabControl.Size = new System.Drawing.Size(664, 394);
this.MainTabControl.Size = new System.Drawing.Size(839, 486);
this.MainTabControl.TabIndex = 1;
//
// NameTableTabPage
// XmlTabPage
//
this.NameTableTabPage.Controls.Add(this.MainTextBox);
this.NameTableTabPage.Location = new System.Drawing.Point(4, 22);
this.NameTableTabPage.Name = "NameTableTabPage";
this.NameTableTabPage.Padding = new System.Windows.Forms.Padding(3);
this.NameTableTabPage.Size = new System.Drawing.Size(656, 368);
this.NameTableTabPage.TabIndex = 0;
this.NameTableTabPage.Text = "Names";
this.NameTableTabPage.UseVisualStyleBackColor = true;
this.XmlTabPage.Controls.Add(this.XmlTextBox);
this.XmlTabPage.Location = new System.Drawing.Point(4, 22);
this.XmlTabPage.Name = "XmlTabPage";
this.XmlTabPage.Padding = new System.Windows.Forms.Padding(3);
this.XmlTabPage.Size = new System.Drawing.Size(831, 460);
this.XmlTabPage.TabIndex = 3;
this.XmlTabPage.Text = "XML";
this.XmlTabPage.UseVisualStyleBackColor = true;
//
// XmlTextBox
//
this.XmlTextBox.AutoCompleteBracketsList = new char[] {
'(',
')',
'{',
'}',
'[',
']',
'\"',
'\"',
'\'',
'\''};
this.XmlTextBox.AutoIndentChars = false;
this.XmlTextBox.AutoIndentCharsPatterns = "";
this.XmlTextBox.AutoIndentExistingLines = false;
this.XmlTextBox.AutoScrollMinSize = new System.Drawing.Size(27, 14);
this.XmlTextBox.BackBrush = null;
this.XmlTextBox.CharHeight = 14;
this.XmlTextBox.CharWidth = 8;
this.XmlTextBox.CommentPrefix = null;
this.XmlTextBox.Cursor = System.Windows.Forms.Cursors.IBeam;
this.XmlTextBox.DelayedEventsInterval = 1;
this.XmlTextBox.DisabledColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))));
this.XmlTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.XmlTextBox.IsReplaceMode = false;
this.XmlTextBox.Language = FastColoredTextBoxNS.Language.XML;
this.XmlTextBox.LeftBracket = '<';
this.XmlTextBox.LeftBracket2 = '(';
this.XmlTextBox.Location = new System.Drawing.Point(3, 3);
this.XmlTextBox.Name = "XmlTextBox";
this.XmlTextBox.Paddings = new System.Windows.Forms.Padding(0);
this.XmlTextBox.RightBracket = '>';
this.XmlTextBox.RightBracket2 = ')';
this.XmlTextBox.SelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(60)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(255)))));
this.XmlTextBox.ServiceColors = ((FastColoredTextBoxNS.ServiceColors)(resources.GetObject("XmlTextBox.ServiceColors")));
this.XmlTextBox.Size = new System.Drawing.Size(825, 454);
this.XmlTextBox.TabIndex = 2;
this.XmlTextBox.Zoom = 100;
this.XmlTextBox.TextChanged += new System.EventHandler<FastColoredTextBoxNS.TextChangedEventArgs>(this.XmlTextBox_TextChanged);
this.XmlTextBox.VisibleRangeChangedDelayed += new System.EventHandler(this.XmlTextBox_VisibleRangeChangedDelayed);
//
// DetailsTabPage
//
@ -82,11 +159,22 @@
this.DetailsTabPage.Location = new System.Drawing.Point(4, 22);
this.DetailsTabPage.Name = "DetailsTabPage";
this.DetailsTabPage.Padding = new System.Windows.Forms.Padding(3);
this.DetailsTabPage.Size = new System.Drawing.Size(656, 368);
this.DetailsTabPage.Size = new System.Drawing.Size(831, 460);
this.DetailsTabPage.TabIndex = 1;
this.DetailsTabPage.Text = "Details";
this.DetailsTabPage.UseVisualStyleBackColor = true;
//
// NameTableTabPage
//
this.NameTableTabPage.Controls.Add(this.MainTextBox);
this.NameTableTabPage.Location = new System.Drawing.Point(4, 22);
this.NameTableTabPage.Name = "NameTableTabPage";
this.NameTableTabPage.Padding = new System.Windows.Forms.Padding(3);
this.NameTableTabPage.Size = new System.Drawing.Size(831, 460);
this.NameTableTabPage.TabIndex = 0;
this.NameTableTabPage.Text = "Names";
this.NameTableTabPage.UseVisualStyleBackColor = true;
//
// MainTextBox
//
this.MainTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -98,36 +186,281 @@
this.MainTextBox.Multiline = true;
this.MainTextBox.Name = "MainTextBox";
this.MainTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
this.MainTextBox.Size = new System.Drawing.Size(644, 356);
this.MainTextBox.Size = new System.Drawing.Size(819, 448);
this.MainTextBox.TabIndex = 1;
this.MainTextBox.WordWrap = false;
//
// CloseButton
// SearchTabPage
//
this.CloseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.CloseButton.Location = new System.Drawing.Point(584, 409);
this.CloseButton.Name = "CloseButton";
this.CloseButton.Size = new System.Drawing.Size(75, 23);
this.CloseButton.TabIndex = 2;
this.CloseButton.Text = "Close";
this.CloseButton.UseVisualStyleBackColor = true;
this.CloseButton.Click += new System.EventHandler(this.CloseButton_Click);
this.SearchTabPage.Controls.Add(this.SearchTextRadio);
this.SearchTabPage.Controls.Add(this.SearchHashRadio);
this.SearchTabPage.Controls.Add(this.label12);
this.SearchTabPage.Controls.Add(this.SearchTextBox);
this.SearchTabPage.Controls.Add(this.SearchButton);
this.SearchTabPage.Controls.Add(this.SearchResultsGrid);
this.SearchTabPage.Location = new System.Drawing.Point(4, 22);
this.SearchTabPage.Name = "SearchTabPage";
this.SearchTabPage.Size = new System.Drawing.Size(831, 460);
this.SearchTabPage.TabIndex = 2;
this.SearchTabPage.Text = "Search";
this.SearchTabPage.UseVisualStyleBackColor = true;
//
// SearchTextRadio
//
this.SearchTextRadio.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.SearchTextRadio.AutoSize = true;
this.SearchTextRadio.Location = new System.Drawing.Point(518, 4);
this.SearchTextRadio.Name = "SearchTextRadio";
this.SearchTextRadio.Size = new System.Drawing.Size(46, 17);
this.SearchTextRadio.TabIndex = 36;
this.SearchTextRadio.Text = "Text";
this.SearchTextRadio.UseVisualStyleBackColor = true;
//
// SearchHashRadio
//
this.SearchHashRadio.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.SearchHashRadio.AutoSize = true;
this.SearchHashRadio.Checked = true;
this.SearchHashRadio.Location = new System.Drawing.Point(462, 4);
this.SearchHashRadio.Name = "SearchHashRadio";
this.SearchHashRadio.Size = new System.Drawing.Size(50, 17);
this.SearchHashRadio.TabIndex = 35;
this.SearchHashRadio.TabStop = true;
this.SearchHashRadio.Text = "Hash";
this.SearchHashRadio.UseVisualStyleBackColor = true;
//
// label12
//
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(8, 6);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(30, 13);
this.label12.TabIndex = 32;
this.label12.Text = "Find:";
//
// SearchTextBox
//
this.SearchTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.SearchTextBox.Location = new System.Drawing.Point(44, 3);
this.SearchTextBox.Name = "SearchTextBox";
this.SearchTextBox.Size = new System.Drawing.Size(412, 20);
this.SearchTextBox.TabIndex = 33;
this.SearchTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.SearchTextBox_KeyDown);
//
// SearchButton
//
this.SearchButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.SearchButton.Location = new System.Drawing.Point(570, 2);
this.SearchButton.Name = "SearchButton";
this.SearchButton.Size = new System.Drawing.Size(68, 23);
this.SearchButton.TabIndex = 34;
this.SearchButton.Text = "Search";
this.SearchButton.UseVisualStyleBackColor = true;
this.SearchButton.Click += new System.EventHandler(this.SearchButton_Click);
//
// SearchResultsGrid
//
this.SearchResultsGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.SearchResultsGrid.HelpVisible = false;
this.SearchResultsGrid.Location = new System.Drawing.Point(3, 31);
this.SearchResultsGrid.Name = "SearchResultsGrid";
this.SearchResultsGrid.Size = new System.Drawing.Size(822, 423);
this.SearchResultsGrid.TabIndex = 1;
//
// MainToolbar
//
this.MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.NewButton,
this.OpenButton,
this.SaveButton});
this.MainToolbar.Location = new System.Drawing.Point(0, 24);
this.MainToolbar.Name = "MainToolbar";
this.MainToolbar.Size = new System.Drawing.Size(839, 25);
this.MainToolbar.TabIndex = 9;
this.MainToolbar.Text = "Main Toolbar";
//
// NewButton
//
this.NewButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.NewButton.Image = ((System.Drawing.Image)(resources.GetObject("NewButton.Image")));
this.NewButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this.NewButton.Name = "NewButton";
this.NewButton.Size = new System.Drawing.Size(32, 22);
this.NewButton.Text = "New...";
this.NewButton.ButtonClick += new System.EventHandler(this.NewButton_ButtonClick);
//
// OpenButton
//
this.OpenButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.OpenButton.Image = ((System.Drawing.Image)(resources.GetObject("OpenButton.Image")));
this.OpenButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this.OpenButton.Name = "OpenButton";
this.OpenButton.Size = new System.Drawing.Size(32, 22);
this.OpenButton.Text = "Open...";
this.OpenButton.ButtonClick += new System.EventHandler(this.OpenButton_ButtonClick);
//
// SaveButton
//
this.SaveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.SaveButton.Image = ((System.Drawing.Image)(resources.GetObject("SaveButton.Image")));
this.SaveButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this.SaveButton.Name = "SaveButton";
this.SaveButton.Size = new System.Drawing.Size(32, 22);
this.SaveButton.Text = "Save";
this.SaveButton.ButtonClick += new System.EventHandler(this.SaveButton_ButtonClick);
//
// MainStatusStrip
//
this.MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.StatusLabel});
this.MainStatusStrip.Location = new System.Drawing.Point(0, 535);
this.MainStatusStrip.Name = "MainStatusStrip";
this.MainStatusStrip.Size = new System.Drawing.Size(839, 22);
this.MainStatusStrip.TabIndex = 7;
this.MainStatusStrip.Text = "Main Status Strip";
//
// StatusLabel
//
this.StatusLabel.Name = "StatusLabel";
this.StatusLabel.Size = new System.Drawing.Size(824, 17);
this.StatusLabel.Spring = true;
this.StatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// MainMenu
//
this.MainMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.FileMenu,
this.EditMenu,
this.ViewMenu});
this.MainMenu.Location = new System.Drawing.Point(0, 0);
this.MainMenu.Name = "MainMenu";
this.MainMenu.Size = new System.Drawing.Size(839, 24);
this.MainMenu.TabIndex = 8;
this.MainMenu.Text = "Main Menu";
//
// FileMenu
//
this.FileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.FileNewMenu,
this.FileOpenMenu,
this.FileSaveMenu,
this.FileSaveAsMenu,
this.toolStripSeparator1,
this.FileCloseMenu});
this.FileMenu.Name = "FileMenu";
this.FileMenu.Size = new System.Drawing.Size(37, 20);
this.FileMenu.Text = "File";
//
// FileNewMenu
//
this.FileNewMenu.Name = "FileNewMenu";
this.FileNewMenu.Size = new System.Drawing.Size(145, 22);
this.FileNewMenu.Text = "New";
this.FileNewMenu.Click += new System.EventHandler(this.FileNewMenu_Click);
//
// FileOpenMenu
//
this.FileOpenMenu.Name = "FileOpenMenu";
this.FileOpenMenu.Size = new System.Drawing.Size(145, 22);
this.FileOpenMenu.Text = "Open...";
this.FileOpenMenu.Click += new System.EventHandler(this.FileOpenMenu_Click);
//
// FileSaveMenu
//
this.FileSaveMenu.Name = "FileSaveMenu";
this.FileSaveMenu.Size = new System.Drawing.Size(145, 22);
this.FileSaveMenu.Text = "Save";
this.FileSaveMenu.Click += new System.EventHandler(this.FileSaveMenu_Click);
//
// FileSaveAsMenu
//
this.FileSaveAsMenu.Name = "FileSaveAsMenu";
this.FileSaveAsMenu.Size = new System.Drawing.Size(145, 22);
this.FileSaveAsMenu.Text = "Save As...";
this.FileSaveAsMenu.Click += new System.EventHandler(this.FileSaveAsMenu_Click);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(142, 6);
//
// FileCloseMenu
//
this.FileCloseMenu.Name = "FileCloseMenu";
this.FileCloseMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F4)));
this.FileCloseMenu.Size = new System.Drawing.Size(145, 22);
this.FileCloseMenu.Text = "Close";
this.FileCloseMenu.Click += new System.EventHandler(this.FileCloseMenu_Click);
//
// EditMenu
//
this.EditMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.wIPToolStripMenuItem});
this.EditMenu.Enabled = false;
this.EditMenu.Name = "EditMenu";
this.EditMenu.Size = new System.Drawing.Size(39, 20);
this.EditMenu.Text = "Edit";
//
// wIPToolStripMenuItem
//
this.wIPToolStripMenuItem.Name = "wIPToolStripMenuItem";
this.wIPToolStripMenuItem.Size = new System.Drawing.Size(106, 22);
this.wIPToolStripMenuItem.Text = "[WIP!]";
//
// ViewMenu
//
this.ViewMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.wIPToolStripMenuItem1});
this.ViewMenu.Enabled = false;
this.ViewMenu.Name = "ViewMenu";
this.ViewMenu.Size = new System.Drawing.Size(44, 20);
this.ViewMenu.Text = "View";
//
// wIPToolStripMenuItem1
//
this.wIPToolStripMenuItem1.Name = "wIPToolStripMenuItem1";
this.wIPToolStripMenuItem1.Size = new System.Drawing.Size(106, 22);
this.wIPToolStripMenuItem1.Text = "[WIP!]";
//
// OpenFileDialog
//
this.OpenFileDialog.Filter = "XML files|*.xml|All files|*.*";
//
// SaveFileDialog
//
this.SaveFileDialog.Filter = "XML files|*.xml|All files|*.*";
//
// RelForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(671, 441);
this.Controls.Add(this.CloseButton);
this.ClientSize = new System.Drawing.Size(839, 557);
this.Controls.Add(this.MainTabControl);
this.Controls.Add(this.MainToolbar);
this.Controls.Add(this.MainStatusStrip);
this.Controls.Add(this.MainMenu);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "RelForm";
this.Text = "REL Viewer - CodeWalker by dexyfex";
this.Text = "Audio dat.rel Editor - CodeWalker by dexyfex";
this.MainTabControl.ResumeLayout(false);
this.XmlTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.XmlTextBox)).EndInit();
this.DetailsTabPage.ResumeLayout(false);
this.NameTableTabPage.ResumeLayout(false);
this.NameTableTabPage.PerformLayout();
this.DetailsTabPage.ResumeLayout(false);
this.SearchTabPage.ResumeLayout(false);
this.SearchTabPage.PerformLayout();
this.MainToolbar.ResumeLayout(false);
this.MainToolbar.PerformLayout();
this.MainStatusStrip.ResumeLayout(false);
this.MainStatusStrip.PerformLayout();
this.MainMenu.ResumeLayout(false);
this.MainMenu.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
@ -138,6 +471,34 @@
private System.Windows.Forms.TabPage NameTableTabPage;
private System.Windows.Forms.TabPage DetailsTabPage;
private WinForms.TextBoxFix MainTextBox;
private System.Windows.Forms.Button CloseButton;
private System.Windows.Forms.TabPage SearchTabPage;
private WinForms.PropertyGridFix SearchResultsGrid;
private System.Windows.Forms.RadioButton SearchTextRadio;
private System.Windows.Forms.RadioButton SearchHashRadio;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.TextBox SearchTextBox;
private System.Windows.Forms.Button SearchButton;
private System.Windows.Forms.TabPage XmlTabPage;
private FastColoredTextBoxNS.FastColoredTextBox XmlTextBox;
private System.Windows.Forms.ToolStrip MainToolbar;
private System.Windows.Forms.ToolStripSplitButton NewButton;
private System.Windows.Forms.ToolStripSplitButton OpenButton;
private System.Windows.Forms.ToolStripSplitButton SaveButton;
private System.Windows.Forms.StatusStrip MainStatusStrip;
private System.Windows.Forms.ToolStripStatusLabel StatusLabel;
private System.Windows.Forms.MenuStrip MainMenu;
private System.Windows.Forms.ToolStripMenuItem FileMenu;
private System.Windows.Forms.ToolStripMenuItem FileNewMenu;
private System.Windows.Forms.ToolStripMenuItem FileOpenMenu;
private System.Windows.Forms.ToolStripMenuItem FileSaveMenu;
private System.Windows.Forms.ToolStripMenuItem FileSaveAsMenu;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripMenuItem FileCloseMenu;
private System.Windows.Forms.ToolStripMenuItem EditMenu;
private System.Windows.Forms.ToolStripMenuItem wIPToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem ViewMenu;
private System.Windows.Forms.ToolStripMenuItem wIPToolStripMenuItem1;
private System.Windows.Forms.OpenFileDialog OpenFileDialog;
private System.Windows.Forms.SaveFileDialog SaveFileDialog;
}
}

View File

@ -1,18 +1,31 @@
using CodeWalker.GameFiles;
using FastColoredTextBoxNS;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
namespace CodeWalker.Forms
{
public partial class RelForm : Form
{
private string xml;
public string Xml
{
get { return xml; }
set
{
xml = value;
UpdateTextBoxFromData();
}
}
private string fileName;
@ -27,10 +40,22 @@ namespace CodeWalker.Forms
}
public string FilePath { get; set; }
private RelFile CurrentFile { get; set; }
public RelForm()
private bool modified = false;
private bool LoadingXml = false;
private bool DelayHighlight = false;
private ExploreForm exploreForm = null;
public RpfFileEntry rpfFileEntry { get; private set; } = null;
private MetaFormat metaFormat = MetaFormat.XML;
public RelForm(ExploreForm owner)
{
exploreForm = owner;
InitializeComponent();
}
@ -38,7 +63,49 @@ namespace CodeWalker.Forms
private void UpdateFormTitle()
{
Text = fileName + " - REL Viewer - CodeWalker by dexyfex";
Text = fileName + " - Audio dat.rel Editor - CodeWalker by dexyfex";
}
private void UpdateTextBoxFromData()
{
LoadingXml = true;
XmlTextBox.Text = "";
XmlTextBox.Language = Language.XML;
DelayHighlight = false;
if (string.IsNullOrEmpty(xml))
{
LoadingXml = false;
return;
}
//if (xml.Length > (1048576 * 5))
//{
// XmlTextBox.Language = Language.Custom;
// XmlTextBox.Text = "[XML size > 10MB - Not shown due to performance limitations - Please use an external viewer for this file.]";
// return;
//}
//else
if (xml.Length > (1024 * 512))
{
XmlTextBox.Language = Language.Custom;
DelayHighlight = true;
}
//else
//{
// XmlTextBox.Language = Language.XML;
//}
Cursor = Cursors.WaitCursor;
XmlTextBox.Text = xml;
//XmlTextBox.IsChanged = false;
XmlTextBox.ClearUndo();
Cursor = Cursors.Default;
LoadingXml = false;
}
@ -55,6 +122,13 @@ namespace CodeWalker.Forms
RelPropertyGrid.SelectedObject = rel;
CurrentFile = rel;
rpfFileEntry = rel?.RpfFileEntry;
Xml = RelXml.GetXml(rel);
metaFormat = MetaFormat.AudioRel;
StringBuilder sb = new StringBuilder();
if (rel != null)
@ -100,9 +174,349 @@ namespace CodeWalker.Forms
}
private void CloseButton_Click(object sender, EventArgs e)
private bool SaveRel(XmlDocument doc)
{
if (!(exploreForm?.EditMode ?? false)) return false;
if (rpfFileEntry?.Parent == null) return false;
byte[] data = null;
#if !DEBUG
try
#endif
{
switch (metaFormat)
{
default:
case MetaFormat.XML:
return false;//what are we even doing here?
case MetaFormat.AudioRel:
var rel = XmlRel.GetRel(doc);
if ((rel?.RelDatasSorted == null) || (rel.RelDatasSorted.Length == 0))
{
MessageBox.Show("Schema not supported.", "Cannot import REL XML");
return false;
}
data = rel.Save();
break;
}
}
#if !DEBUG
catch (Exception ex)
{
MessageBox.Show("Exception encountered!\r\n" + ex.ToString(), "Cannot convert XML");
return false;
}
#endif
if (data == null)
{
MessageBox.Show("Schema not supported. (Unspecified error - data was null!)", "Cannot convert XML");
return false;
}
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
{
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return false;//that was a close one
}
}
try
{
if (!(exploreForm?.EnsureRpfValidEncryption(rpfFileEntry.File) ?? false)) return false;
var newentry = RpfFile.CreateFile(rpfFileEntry.Parent, rpfFileEntry.Name, data);
if (newentry != rpfFileEntry)
{ }
rpfFileEntry = newentry;
exploreForm?.RefreshMainListViewInvoke(); //update the file details in explorer...
modified = false;
StatusLabel.Text = metaFormat.ToString() + " file saved successfully at " + DateTime.Now.ToString();
return true; //victory!
}
catch (Exception ex)
{
MessageBox.Show("Error saving file to RPF! The RPF archive may be corrupted...\r\n" + ex.ToString(), "Really Bad Error");
}
return false;
}
private bool CloseDocument()
{
if (modified)
{
var res = MessageBox.Show("Do you want to save the current document before closing it?", "Save before closing", MessageBoxButtons.YesNoCancel);
switch (res)
{
case DialogResult.Yes:
SaveDocument();
break;
case DialogResult.Cancel:
return false;
}
}
FilePath = "";
FileName = "";
Xml = "";
RelPropertyGrid.SelectedObject = null;
MainTextBox.Text = "";
modified = false;
rpfFileEntry = null;
return true;
}
private void NewDocument()
{
if (!CloseDocument()) return;
FileName = "New.xml";
rpfFileEntry = null;
//TODO: decide XML/REL format..?
}
private void OpenDocument()
{
if (OpenFileDialog.ShowDialog() != DialogResult.OK) return;
if (!CloseDocument()) return;
var fn = OpenFileDialog.FileName;
if (!File.Exists(fn)) return; //couldn't find file?
Xml = File.ReadAllText(fn);
modified = false;
FilePath = fn;
FileName = new FileInfo(fn).Name;
RelPropertyGrid.SelectedObject = null;
MainTextBox.Text = "";
rpfFileEntry = null;
//TODO: open raw REL..?
}
private void SaveDocument(bool saveAs = false)
{
if ((metaFormat != MetaFormat.XML) && (saveAs == false))
{
var doc = new XmlDocument();
try
{
doc.LoadXml(xml);
}
catch (Exception ex)
{
MessageBox.Show("There's something wrong with your XML document:\r\n" + ex.Message, "Unable to parse XML");
return;
}
if (SaveRel(doc))
{
return;
}
//if REL saving failed for whatever reason, fallback to saving the XML in the filesystem.
saveAs = true;
}
if (string.IsNullOrEmpty(FileName)) saveAs = true;
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
if (!File.Exists(FilePath)) saveAs = true;
var fn = FilePath;
if (saveAs)
{
if (!string.IsNullOrEmpty(fn))
{
var dir = new FileInfo(fn).DirectoryName;
if (!Directory.Exists(dir)) dir = "";
SaveFileDialog.InitialDirectory = dir;
}
SaveFileDialog.FileName = FileName;
if (SaveFileDialog.ShowDialog() != DialogResult.OK) return;
fn = SaveFileDialog.FileName;
}
File.WriteAllText(fn, xml);
modified = false;
FilePath = fn;
FileName = new FileInfo(fn).Name;
metaFormat = MetaFormat.XML;
}
Style BlueStyle = new TextStyle(Brushes.Blue, null, FontStyle.Regular);
Style RedStyle = new TextStyle(Brushes.Red, null, FontStyle.Regular);
Style MaroonStyle = new TextStyle(Brushes.Maroon, null, FontStyle.Regular);
private void HTMLSyntaxHighlight(Range range)
{
//clear style of changed range
range.ClearStyle(BlueStyle, MaroonStyle, RedStyle);
//tag brackets highlighting
range.SetStyle(BlueStyle, @"<|/>|</|>");
//tag name
range.SetStyle(MaroonStyle, @"<(?<range>[!\w]+)");
//end of tag
range.SetStyle(MaroonStyle, @"</(?<range>\w+)>");
//attributes
range.SetStyle(RedStyle, @"(?<range>\S+?)='[^']*'|(?<range>\S+)=""[^""]*""|(?<range>\S+)=\S+");
//attribute values
range.SetStyle(BlueStyle, @"\S+?=(?<range>'[^']*')|\S+=(?<range>""[^""]*"")|\S+=(?<range>\S+)");
}
private void Search()
{
SearchResultsGrid.SelectedObject = null;
if (CurrentFile?.RelDatasSorted == null) return;
bool textsearch = SearchTextRadio.Checked;
var text = SearchTextBox.Text;
var textl = text.ToLowerInvariant();
uint hash = 0;
uint hashl = 0;
if (!uint.TryParse(text, out hash))//don't re-hash hashes
{
hash = JenkHash.GenHash(text);
JenkIndex.Ensure(text);
hashl = JenkHash.GenHash(textl);
JenkIndex.Ensure(textl);
}
else
{
hashl = hash;
}
var results = new List<RelData>();
foreach (var rd in CurrentFile.RelDatasSorted)
{
if (textsearch)
{
if (((rd.Name?.ToLowerInvariant().Contains(textl))??false) || (rd.NameHash == hash) || (rd.NameHash == hashl) ||
(rd.NameHash.ToString().ToLowerInvariant().Contains(textl)))
{
results.Add(rd);
}
}
else
{
if ((rd.NameHash == hash)||(rd.NameHash == hashl))
{
SearchResultsGrid.SelectedObject = rd;
return;
}
}
}
if (textsearch && (results.Count > 0))
{
SearchResultsGrid.SelectedObject = results.ToArray();
}
else
{
SearchResultsGrid.SelectedObject = null;
}
}
private void SearchButton_Click(object sender, EventArgs e)
{
Search();
}
private void SearchTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
Search();
}
}
private void FileNewMenu_Click(object sender, EventArgs e)
{
NewDocument();
}
private void FileOpenMenu_Click(object sender, EventArgs e)
{
OpenDocument();
}
private void FileSaveMenu_Click(object sender, EventArgs e)
{
SaveDocument();
}
private void FileSaveAsMenu_Click(object sender, EventArgs e)
{
SaveDocument(true);
}
private void FileCloseMenu_Click(object sender, EventArgs e)
{
Close();
}
private void NewButton_ButtonClick(object sender, EventArgs e)
{
NewDocument();
}
private void OpenButton_ButtonClick(object sender, EventArgs e)
{
OpenDocument();
}
private void SaveButton_ButtonClick(object sender, EventArgs e)
{
SaveDocument();
}
private void XmlTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (!LoadingXml)
{
xml = XmlTextBox.Text;
modified = true;
}
}
private void XmlTextBox_VisibleRangeChangedDelayed(object sender, EventArgs e)
{
//this approach is much faster to load, but no outlining is available
//highlight only visible area of text
if (DelayHighlight)
{
HTMLSyntaxHighlight(XmlTextBox.VisibleRange);
}
}
}
}

View File

@ -117,7 +117,69 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="XmlTextBox.ServiceColors" mimetype="application/x-microsoft.net.object.binary.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFdGYXN0Q29sb3JlZFRleHRCb3gsIFZlcnNpb249Mi4xNi4yNC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWZiOGFhMTJiOTk0ZWY2MWIMAwAAAFFTeXN0
ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2Vu
PWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACJGYXN0Q29sb3JlZFRleHRCb3hOUy5TZXJ2aWNlQ29sb3JzBgAA
ACg8Q29sbGFwc2VNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxDb2xsYXBzZU1hcmtlckJh
Y2tDb2xvcj5rX19CYWNraW5nRmllbGQqPENvbGxhcHNlTWFya2VyQm9yZGVyQ29sb3I+a19fQmFja2lu
Z0ZpZWxkJjxFeHBhbmRNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkJjxFeHBhbmRNYXJrZXJC
YWNrQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxFeHBhbmRNYXJrZXJCb3JkZXJDb2xvcj5rX19CYWNraW5n
RmllbGQEBAQEBAQUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5EcmF3aW5nLkNvbG9yAwAA
ABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAAUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5E
cmF3aW5nLkNvbG9yAwAAABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAACAAAABfz///8UU3lzdGVtLkRy
YXdpbmcuQ29sb3IEAAAABG5hbWUFdmFsdWUKa25vd25Db2xvcgVzdGF0ZQEAAAAJBwcDAAAACgAAAAAA
AAAAlgABAAH7/////P///woAAAAAAAAAAKQAAQAB+v////z///8KAAAAAAAAAACWAAEAAfn////8////
CgAAAAAAAAAATgABAAH4/////P///woAAAAAAAAAAKQAAQAB9/////z///8KAAAAAAAAAACWAAEACw==
</value>
</data>
<metadata name="MainToolbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>22, 15</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="NewButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADESURBVDhPzZI7DgIhGIQ5grUnsPQMnMgLWMo1bDyJiYUV
h7CxEo1Aiw7+E9ldWF+Nk0w2wMy3/z5UqRDCwjk3iTEmGmvsS6Ste2gtJYvrdjklJK9xLtGhcAeEdqtZ
Ouw3uUgA1tgXSH0SGdsyfD0dcwHXAmqRk0pXCNMsN+y893OpPYVDjFw8d9JaD2yMqUNYgjkBCmd36bgJ
6b+DMUAJkXr9K9QANM6QkfpD/f/gYwCESfgnfgWg/gcw5peAdyzxX6TUDfMCML1omZa9AAAAAElFTkSu
QmCC
</value>
</data>
<data name="OpenButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEcSURBVDhPlZKxqsIwFIb7Bvc+idxHuPQVXFpQcOhe8Amc
OqqzCBdU6HQfQIfunVwKoi7FQQeF9GrajufmhDYkTaMY+EjPyf//TZtY9aCUfhVFQRggQbBfSV4PFJ8v
GekMf8HqzqE3jXhIhRwsqKyWxYpJ3bzcMpBD4jgG27Y1RACaZ+sEPvoLbmqCa/f7AzLyJ2gGcDO+bXe6
ajugDypMiBJQluU3f2DiZ+YmT3eANWIyIyKgFsv/AOs2k4wSgIXneRBFEaRpyhew10ZbwNb3fU1oYrPe
qAF5no/CMNSEJsbjiRqAty9JEk1ownEcNaA6BeK6riY2cdgf+SwC2Gf8BEGgCU2slis+iwB2mQZ4Ak3h
K0QAIeQTi/cp4B9tCZE2c6oRhQAAAABJRU5ErkJggg==
</value>
</data>
<data name="SaveButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABWSURBVDhPY6AK+Pbt238S8PsvX74YQLVCAEjCyckJjj+8
/wjHyGIguq2tDdMQUgwAYZghUO2kGwDCID1Q7fgNQMbIamhrADF41IBBaQA5GKqdEsDAAADtDPd9n5qK
lQAAAABJRU5ErkJggg==
</value>
</data>
<metadata name="MainStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>143, 15</value>
</metadata>
<metadata name="MainMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>281, 15</value>
</metadata>
<metadata name="OpenFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>391, 15</value>
</metadata>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>526, 15</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA

View File

@ -1,4 +1,5 @@
using CodeWalker.Properties;
using CodeWalker.GameFiles;
using CodeWalker.Properties;
using FastColoredTextBoxNS;
using System;
using System.Collections.Generic;
@ -40,19 +41,26 @@ namespace CodeWalker.Forms
private bool modified = false;
private ExploreForm exploreForm = null;
public RpfFileEntry rpfFileEntry { get; private set; } = null;
public TextForm()
public TextForm(ExploreForm owner)
{
exploreForm = owner;
InitializeComponent();
}
public void LoadText(string filename, string filepath, string text)
public void LoadText(string filename, string filepath, string text, RpfFileEntry e)
{
FileName = filename;
FilePath = filepath;
TextValue = text;
rpfFileEntry = e;
modified = false;
}
@ -128,6 +136,16 @@ namespace CodeWalker.Forms
}
private void SaveDocument(bool saveAs = false)
{
if (saveAs == false)
{
if (SaveToRPF(textValue))
{
return;
}
//if saving to RPF failed for whatever reason, fallback to saving the file in the filesystem.
saveAs = true;
}
if (string.IsNullOrEmpty(FileName)) saveAs = true;
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
@ -154,6 +172,62 @@ namespace CodeWalker.Forms
FileName = new FileInfo(fn).Name;
}
private bool SaveToRPF(string txt)
{
if (!(exploreForm?.EditMode ?? false)) return false;
if (rpfFileEntry?.Parent == null) return false;
byte[] data = null;
data = Encoding.UTF8.GetBytes(txt);
if (data == null)
{
MessageBox.Show("Unspecified error - data was null!", "Cannot save file");
return false;
}
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
{
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return false;//that was a close one
}
}
try
{
if (!(exploreForm?.EnsureRpfValidEncryption(rpfFileEntry.File) ?? false)) return false;
var newentry = RpfFile.CreateFile(rpfFileEntry.Parent, rpfFileEntry.Name, data);
if (newentry != rpfFileEntry)
{ }
rpfFileEntry = newentry;
exploreForm?.RefreshMainListViewInvoke(); //update the file details in explorer...
modified = false;
StatusLabel.Text = "Text file saved successfully at " + DateTime.Now.ToString();
return true; //victory!
}
catch (Exception ex)
{
MessageBox.Show("Error saving file to RPF! The RPF archive may be corrupted...\r\n" + ex.ToString(), "Really Bad Error");
}
return false;
}
private void MainTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
textValue = MainTextBox.Text;

View File

@ -1,4 +1,5 @@
using CodeWalker.Properties;
using CodeWalker.GameFiles;
using CodeWalker.Properties;
using FastColoredTextBoxNS;
using System;
using System.Collections.Generic;
@ -10,6 +11,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
namespace CodeWalker.Forms
{
@ -42,19 +44,25 @@ namespace CodeWalker.Forms
private bool LoadingXml = false;
private bool DelayHighlight = false;
private ExploreForm exploreForm = null;
public RpfFileEntry rpfFileEntry { get; private set; } = null;
public XmlForm()
public XmlForm(ExploreForm owner)
{
exploreForm = owner;
InitializeComponent();
}
public void LoadXml(string filename, string filepath, string xml)
public void LoadXml(string filename, string filepath, string xml, RpfFileEntry e)
{
FileName = filename;
FilePath = filepath;
Xml = xml;
rpfFileEntry = e;
modified = false;
}
@ -153,6 +161,26 @@ namespace CodeWalker.Forms
}
private void SaveDocument(bool saveAs = false)
{
if (saveAs == false)
{
var doc = new XmlDocument();
try
{
doc.LoadXml(xml);
}
catch (Exception ex)
{
MessageBox.Show("There's something wrong with your XML document:\r\n" + ex.Message, "Unable to parse XML");
return;
}
if (SaveToRPF(xml))
{
return;
}
//if saving to RPF failed for whatever reason, fallback to saving the file in the filesystem.
saveAs = true;
}
if (string.IsNullOrEmpty(FileName)) saveAs = true;
if (string.IsNullOrEmpty(FilePath)) saveAs = true;
else if ((FilePath.ToLowerInvariant().StartsWith(GTAFolder.CurrentGTAFolder.ToLowerInvariant()))) saveAs = true;
@ -183,6 +211,58 @@ namespace CodeWalker.Forms
private bool SaveToRPF(string txt)
{
if (!(exploreForm?.EditMode ?? false)) return false;
if (rpfFileEntry?.Parent == null) return false;
byte[] data = null;
data = Encoding.UTF8.GetBytes(txt);
if (data == null)
{
MessageBox.Show("Unspecified error - data was null!", "Cannot save XML file");
return false;
}
if (!rpfFileEntry.Path.ToLowerInvariant().StartsWith("mods"))
{
if (MessageBox.Show("This file is NOT located in the mods folder - Are you SURE you want to save this file?\r\nWARNING: This could cause permanent damage to your game!!!", "WARNING: Are you sure about this?", MessageBoxButtons.YesNo) != DialogResult.Yes)
{
return false;//that was a close one
}
}
try
{
if (!(exploreForm?.EnsureRpfValidEncryption(rpfFileEntry.File) ?? false)) return false;
var newentry = RpfFile.CreateFile(rpfFileEntry.Parent, rpfFileEntry.Name, data);
if (newentry != rpfFileEntry)
{ }
rpfFileEntry = newentry;
exploreForm?.RefreshMainListViewInvoke(); //update the file details in explorer...
modified = false;
StatusLabel.Text = "XML file saved successfully at " + DateTime.Now.ToString();
return true; //victory!
}
catch (Exception ex)
{
MessageBox.Show("Error saving file to RPF! The RPF archive may be corrupted...\r\n" + ex.ToString(), "Really Bad Error");
}
return false;
}
Style BlueStyle = new TextStyle(Brushes.Blue, null, FontStyle.Regular);

View File

@ -1,215 +0,0 @@
# CodeWalker Collision Material Colours File
# Material Name ABGR (hex)
DEFAULT FFCCCCCC
CONCRETE FFDDDDDD
CONCRETE_POTHOLE FFDDDDDD
CONCRETE_DUSTY FFDDDDDD
TARMAC FF333333
TARMAC_PAINTED FF333355
TARMAC_POTHOLE FF303030
RUMBLE_STRIP FF444444
BREEZE_BLOCK FF555555
ROCK FF228899
ROCK_MOSSY FF22CC88
STONE FFAAAAAA
COBBLESTONE FFAAAAAA
BRICK FF332299
MARBLE FF666699
PAVING_SLAB FFCCCCCC
SANDSTONE_SOLID FF48EFEF
SANDSTONE_BRITTLE FF47ECEC
SAND_LOOSE FF46F0F0
SAND_COMPACT FF44EEEE
SAND_WET FF22CCCC
SAND_TRACK FF40E0E0
SAND_UNDERWATER FF30D0D0
SAND_DRY_DEEP FF46F0F0
SAND_WET_DEEP FF22CCCC
ICE FFEEDDCC
ICE_TARMAC FFBBAFAF
SNOW_LOOSE FFFFFCFC
SNOW_COMPACT FFFFF0F0
SNOW_DEEP FFFFFAFA
SNOW_TARMAC FFFAF0F0
GRAVEL_SMALL FF99CCDD
GRAVEL_LARGE FF9BDFDF
GRAVEL_DEEP FF95D9D9
GRAVEL_TRAIN_TRACK FF9A9A9A
DIRT_TRACK FF36479C
MUD_HARD FF334499
MUD_POTHOLE FF27388D
MUD_SOFT FF223388
MUD_UNDERWATER FF1F3085
MUD_DEEP FF1D2883
MARSH FF20DD80
MARSH_DEEP FF1CD97C
SOIL FF112266
CLAY_HARD FF334477
CLAY_SOFT FF304174
GRASS_LONG FF0FA81F
GRASS FF11AA11
GRASS_SHORT FF22AA22
HAY FF40F5F5
BUSHES FF009900
TWIGS FF00CC44
LEAVES FF22CC22
WOODCHIPS FF33AACC
TREE_BARK FF1199BB
METAL_SOLID_SMALL FFDDDDDD
METAL_SOLID_MEDIUM FFDDDDDD
METAL_SOLID_LARGE FFDDDDDD
METAL_HOLLOW_SMALL FFDDDDDD
METAL_HOLLOW_MEDIUM FFDDDDDD
METAL_HOLLOW_LARGE FFDDDDDD
METAL_CHAINLINK_SMALL FFDDDDDD
METAL_CHAINLINK_LARGE FFDDDDDD
METAL_CORRUGATED_IRON FFDDDDDD
METAL_GRILLE FFDDDDDD
METAL_RAILING FFDDDDDD
METAL_DUCT FFDDDDDD
METAL_GARAGE_DOOR FFDDDDDD
METAL_MANHOLE FFDDDDDD
WOOD_SOLID_SMALL FF117799
WOOD_SOLID_MEDIUM FF117799
WOOD_SOLID_LARGE FF117799
WOOD_SOLID_POLISHED FF117799
WOOD_FLOOR_DUSTY FF117799
WOOD_HOLLOW_SMALL FF117799
WOOD_HOLLOW_MEDIUM FF117799
WOOD_HOLLOW_LARGE FF117799
WOOD_CHIPBOARD FF117799
WOOD_OLD_CREAKY FF117799
WOOD_HIGH_DENSITY FF117799
WOOD_LATTICE FF117799
CERAMIC FFEEEEEE
ROOF_TILE FF111177
ROOF_FELT FF666666
FIBREGLASS FF99BBDD
TARPAULIN FFEE4411
PLASTIC FFEE5522
PLASTIC_HOLLOW FFEE5522
PLASTIC_HIGH_DENSITY FFEE5533
PLASTIC_CLEAR FFFE6543
PLASTIC_HOLLOW_CLEAR FFFE6543
PLASTIC_HIGH_DENSITY_CLEAR FFFE5543
FIBREGLASS_HOLLOW FF9ABCDE
RUBBER FF111111
RUBBER_HOLLOW FF111111
LINOLEUM FFAAAAAA
LAMINATE FFBBBBBB
CARPET_SOLID FFDDDDDD
CARPET_SOLID_DUSTY FFDEDEDE
CARPET_FLOORBOARD FFD0D0D0
CLOTH FFEEEEEE
PLASTER_SOLID FFEEEEEE
PLASTER_BRITTLE FFEEEEEE
CARDBOARD_SHEET FF11AACC
CARDBOARD_BOX FF11AACC
PAPER FFF4F4F4
FOAM FFEFEFEF
FEATHER_PILLOW FFEEEEEE
POLYSTYRENE FFFFFFFF
LEATHER FF111122
TVSCREEN FF111111
SLATTED_BLINDS FFCCCCCC
GLASS_SHOOT_THROUGH 77EECCCC
GLASS_BULLETPROOF 77EFCDCD
GLASS_OPAQUE DDEECCCC
PERSPEX 66EEDDDD
CAR_METAL FFDDDDDD
CAR_PLASTIC FFEE5522
CAR_SOFTTOP FF333333
CAR_SOFTTOP_CLEAR 55DDDDDD
CAR_GLASS_WEAK 77EECCCC
CAR_GLASS_MEDIUM 77EECCCC
CAR_GLASS_STRONG 77EECCCC
CAR_GLASS_BULLETPROOF 77EECCCC
CAR_GLASS_OPAQUE 77EECCCC
WATER 77EECCAA
BLOOD FF0000CC
OIL EE112233
PETROL 77CCDDEE
FRESH_MEAT FFCCDDEE
DRIED_MEAT FFDDEEFF
EMISSIVE_GLASS EEEEDDDD
EMISSIVE_PLASTIC FFEE7744
VFX_METAL_ELECTRIFIED FFFFEEEE
VFX_METAL_WATER_TOWER FFCCCCCC
VFX_METAL_STEAM FFBBBBBB
VFX_METAL_FLAME FFBBBBFF
PHYS_NO_FRICTION FF00DD00
PHYS_GOLF_BALL FFFFFFFF
PHYS_TENNIS_BALL FFCCFFCC
PHYS_CASTER FF050505
PHYS_CASTER_RUSTY FF050535
PHYS_CAR_VOID FF000000
PHYS_PED_CAPSULE FFDDDDDD
PHYS_ELECTRIC_FENCE FFFFDDCC
PHYS_ELECTRIC_METAL FFFFEEDD
PHYS_BARBED_WIRE FFCCCCDC
PHYS_POOLTABLE_SURFACE FF116611
PHYS_POOLTABLE_CUSHION FF156815
PHYS_POOLTABLE_BALL FFCCCCCC
BUTTOCKS FFFFFFFF
THIGH_LEFT FFFFFFFF
SHIN_LEFT FFFFFFFF
FOOT_LEFT FFFFFFFF
THIGH_RIGHT FFFFFFFF
SHIN_RIGHT FFFFFFFF
FOOT_RIGHT FFFFFFFF
SPINE0 FFFFFFFF
SPINE1 FFFFFFFF
SPINE2 FFFFFFFF
SPINE3 FFFFFFFF
CLAVICLE_LEFT FFFFFFFF
UPPER_ARM_LEFT FFFFFFFF
LOWER_ARM_LEFT FFFFFFFF
HAND_LEFT FFFFFFFF
CLAVICLE_RIGHT FFFFFFFF
UPPER_ARM_RIGHT FFFFFFFF
LOWER_ARM_RIGHT FFFFFFFF
HAND_RIGHT FFFFFFFF
NECK FFFFFFFF
HEAD FFFFFFFF
ANIMAL_DEFAULT FFFFFFFF
CAR_ENGINE FFFFFFFF
PUDDLE CCFFDDDD
CONCRETE_PAVEMENT FFDEDEDE
BRICK_PAVEMENT FF332299
PHYS_DYNAMIC_COVER_BOUND FFFFFFFF
VFX_WOOD_BEER_BARREL FF117799
WOOD_HIGH_FRICTION FF117799
ROCK_NOINST FF228899
BUSHES_NOINST FF009900
METAL_SOLID_ROAD_SURFACE FF444455
TEMP_01 FFFFFFFF
TEMP_02 FFFFFFFF
TEMP_03 FFFFFFFF
TEMP_04 FFFFFFFF
TEMP_05 FFFFFFFF
TEMP_06 FFFFFFFF
TEMP_07 FFFFFFFF
TEMP_08 FFFFFFFF
TEMP_09 FFFFFFFF
TEMP_10 FFFFFFFF
TEMP_11 FFFFFFFF
TEMP_12 FFFFFFFF
TEMP_13 FFFFFFFF
TEMP_14 FFFFFFFF
TEMP_15 FFFFFFFF
TEMP_16 FFFFFFFF
TEMP_17 FFFFFFFF
TEMP_18 FFFFFFFF
TEMP_19 FFFFFFFF
TEMP_20 FFFFFFFF
TEMP_21 FFFFFFFF
TEMP_22 FFFFFFFF
TEMP_23 FFFFFFFF
TEMP_24 FFFFFFFF
TEMP_25 FFFFFFFF
TEMP_26 FFFFFFFF
TEMP_27 FFFFFFFF
TEMP_28 FFFFFFFF
TEMP_29 FFFFFFFF
TEMP_30 FFFFFFFF

Some files were not shown because too many files have changed in this diff Show More