mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-26 08:52:52 +08:00
Merge branch 'master' into ImportUnknownModelsetScenarios
This commit is contained in:
commit
3030e66aae
10
App.config
10
App.config
@ -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
1
CodeWalker Vehicles.cmd
Normal file
@ -0,0 +1 @@
|
||||
start codewalker vehicles
|
@ -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" />
|
||||
|
12
CodeWalker.Core/GameFiles/FileTypes/Builders/YndBuilder.cs
Normal file
12
CodeWalker.Core/GameFiles/FileTypes/Builders/YndBuilder.cs
Normal 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
|
||||
{
|
||||
}
|
||||
}
|
473
CodeWalker.Core/GameFiles/FileTypes/Builders/YnvBuilder.cs
Normal file
473
CodeWalker.Core/GameFiles/FileTypes/Builders/YnvBuilder.cs
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
1278
CodeWalker.Core/GameFiles/FileTypes/CarColsFile.cs
Normal file
1278
CodeWalker.Core/GameFiles/FileTypes/CarColsFile.cs
Normal file
File diff suppressed because it is too large
Load Diff
211
CodeWalker.Core/GameFiles/FileTypes/CarModColsFile.cs
Normal file
211
CodeWalker.Core/GameFiles/FileTypes/CarModColsFile.cs
Normal 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
261
CodeWalker.Core/GameFiles/FileTypes/CarVariationsFile.cs
Normal file
261
CodeWalker.Core/GameFiles/FileTypes/CarVariationsFile.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
|
@ -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
37
CodeWalker.Core/GameFiles/FileTypes/VehicleLayoutsFile.cs
Normal file
37
CodeWalker.Core/GameFiles/FileTypes/VehicleLayoutsFile.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
408
CodeWalker.Core/GameFiles/FileTypes/VehiclesFile.cs
Normal file
408
CodeWalker.Core/GameFiles/FileTypes/VehiclesFile.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -85,5 +85,12 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
}
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
byte[] data = ResourceBuilder.Build(DrawableDict, 165); //ydd is type/version 165...
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,13 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
}
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
byte[] data = ResourceBuilder.Build(Drawable, 165); //ydr is type/version 165...
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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>();
|
||||
foreach (var ypoly in Polys)
|
||||
{
|
||||
var poly = ypoly.RawData;
|
||||
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();
|
||||
foreach (var ypoly in Polys)
|
||||
{
|
||||
if ((ypoly.Vertices == null) || (ypoly.Vertices.Length < 3))
|
||||
{ continue; }
|
||||
|
||||
var colour = ypoly.GetColour();
|
||||
var colourval = (uint)colour.ToRgba();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,13 @@ namespace CodeWalker.GameFiles
|
||||
}
|
||||
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
byte[] data = ResourceBuilder.Build(PtfxList, 68); //ypt is type/version 68...
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,5 +45,13 @@ namespace CodeWalker.GameFiles
|
||||
}
|
||||
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
byte[] data = ResourceBuilder.Build(TextureDict, 13); //ytd is type/version 13...
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,6 +49,13 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
}
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
byte[] data = ResourceBuilder.Build(Records, 1); //yvr is type/version 1...
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,13 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
}
|
||||
|
||||
public byte[] Save()
|
||||
{
|
||||
byte[] data = ResourceBuilder.Build(Waypoints, 1); //ywr is type/version 1...
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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; }
|
||||
@ -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,13 +317,43 @@ 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];
|
||||
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; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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?
|
||||
|
||||
if (StructureInfos.Count > 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (EnumInfos.Count > 0)
|
||||
{
|
||||
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.DataBlocks = new ResourceSimpleArray<MetaDataBlock>();
|
||||
foreach (var bb in Blocks)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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}
|
||||
@ -2429,6 +2448,8 @@ namespace CodeWalker.GameFiles
|
||||
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
|
||||
|
@ -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,8 +1044,15 @@ namespace CodeWalker.GameFiles
|
||||
for (int n = 0; n < aCount; n++)
|
||||
{
|
||||
var ptrVal = ptrArr[n];
|
||||
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);
|
||||
}
|
||||
break;
|
||||
@ -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,14 +1289,22 @@ namespace CodeWalker.GameFiles
|
||||
var kOffset = sOffset + kEntry.DataOffset;
|
||||
var iOffset = sOffset + iEntry.DataOffset;
|
||||
var kStr = GetStringValue(cont.Pso, kEntry, data, kOffset);
|
||||
if (iEntry.ReferenceKey != 0)//(xBlock.NameHash != MetaName.ARRAYINFO)//257,258,259
|
||||
{
|
||||
//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 iPtr = MetaTypes.ConvertData<PsoPOINTER>(data, iOffset);
|
||||
iPtr.SwapEnd();
|
||||
var iBlock = cont.Pso.GetBlock(iPtr.BlockID);
|
||||
if (iBlock == null)
|
||||
{
|
||||
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);
|
||||
CloseTag(sb, aind, "Item");
|
||||
ErrorXml(sb, aind, ename + ": Could not find iBlock for Map entry!");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1262,6 +1323,7 @@ namespace CodeWalker.GameFiles
|
||||
CloseTag(sb, aind, "Item");
|
||||
}
|
||||
}
|
||||
}
|
||||
xOffset2 += xStruct.StructureLength;
|
||||
if ((n < (xCount - 1)) && (xBlock != null) && (xOffset >= xBlock.Length))
|
||||
{
|
||||
@ -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,
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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()
|
||||
|
504
CodeWalker.Core/GameFiles/MetaTypes/PsoBuilder.cs
Normal file
504
CodeWalker.Core/GameFiles/MetaTypes/PsoBuilder.cs
Normal 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
@ -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;
|
||||
}
|
||||
|
||||
@ -177,23 +194,27 @@ namespace CodeWalker.GameFiles
|
||||
case MetaStructureEntryDataType.IntEnum:
|
||||
case MetaStructureEntryDataType.IntFlags1:
|
||||
case MetaStructureEntryDataType.IntFlags2:
|
||||
{
|
||||
if (entry.ReferenceKey != 0)
|
||||
{
|
||||
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
|
||||
|
||||
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:
|
||||
{
|
||||
if (entry.ReferenceKey != 0)
|
||||
{
|
||||
var _infos = MetaTypes.GetEnumInfo(entry.ReferenceKey);
|
||||
|
||||
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,68 +335,82 @@ 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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]);
|
||||
float val;// = FloatUtil.Parse(split[j]);
|
||||
if (FloatUtil.TryParse(split[j].Trim(), out val))
|
||||
{
|
||||
Write(val, data, offset);
|
||||
offset += sizeof(float);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -565,15 +605,36 @@ 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;
|
||||
|
||||
var cnodes = node.SelectNodes("Item");
|
||||
if (cnodes.Count > 0)
|
||||
{
|
||||
foreach (XmlNode cnode in cnodes)
|
||||
{
|
||||
var str = cnode.InnerText;
|
||||
var strs = str.Split(',');
|
||||
if (strs.Length >= 3)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
@ -600,6 +661,7 @@ namespace CodeWalker.GameFiles
|
||||
items.Add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return mb.AddPaddedVector3ArrayPtr(items.ToArray());
|
||||
@ -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,16 +749,54 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
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++)
|
||||
{
|
||||
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];
|
||||
@ -704,6 +806,7 @@ namespace CodeWalker.GameFiles
|
||||
return entry.EntryValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1246
CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs
Normal file
1246
CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,7 +387,9 @@ namespace CodeWalker.GameFiles
|
||||
JenkIndex.Ensure(entry.Name);
|
||||
JenkIndex.Ensure(nlow);
|
||||
}
|
||||
if (nlow.EndsWith(".ydr") || nlow.EndsWith(".yft"))
|
||||
if (BuildExtendedJenkIndex)
|
||||
{
|
||||
if (nlow.EndsWith(".ydr"))// || nlow.EndsWith(".yft")) //do yft's get lods?
|
||||
{
|
||||
var sname = nlow.Substring(0, nlow.Length - 4);
|
||||
JenkIndex.Ensure(sname + "_lod");
|
||||
@ -417,6 +425,10 @@ namespace CodeWalker.GameFiles
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nlow.EndsWith(".sps"))
|
||||
{
|
||||
JenkIndex.Ensure(nlow);//for shader preset filename hashes!
|
||||
}
|
||||
if (nlow.EndsWith(".awc")) //create audio container path hashes...
|
||||
{
|
||||
string[] parts = entry.Path.Split('\\');
|
||||
@ -479,6 +491,7 @@ namespace CodeWalker.GameFiles
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
|
39
CodeWalker.Core/Utils/BoundingBoxes.cs
Normal file
39
CodeWalker.Core/Utils/BoundingBoxes.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
1877
CodeWalker.Core/Utils/Fbx.cs
Normal file
File diff suppressed because it is too large
Load Diff
996
CodeWalker.Core/Utils/FbxConverter.cs
Normal file
996
CodeWalker.Core/Utils/FbxConverter.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -420,13 +420,8 @@ 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)
|
||||
{
|
||||
AddRpfYnds(rpffile, yndentries);
|
||||
}
|
||||
}
|
||||
var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load nodes from patch area...
|
||||
if (updrpf != null)
|
||||
{
|
||||
@ -435,6 +430,15 @@ namespace CodeWalker.World
|
||||
AddRpfYnds(rpffile, yndentries);
|
||||
}
|
||||
}
|
||||
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load nodes from current dlc rpfs
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vector3 corner = new Vector3(-8192, -8192, -2048);
|
||||
@ -721,13 +725,8 @@ 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)
|
||||
{
|
||||
AddRpfYnvs(rpffile, ynventries);
|
||||
}
|
||||
}
|
||||
var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load navmeshes from patch area...
|
||||
if (updrpf != null)
|
||||
{
|
||||
@ -736,6 +735,14 @@ namespace CodeWalker.World
|
||||
AddRpfYnvs(rpffile, ynventries);
|
||||
}
|
||||
}
|
||||
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load navmeshes from current dlc rpfs
|
||||
{
|
||||
foreach (var rpffile in dlcrpf.Children)
|
||||
{
|
||||
AddRpfYnvs(rpffile, ynventries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int x = 0; x < NavGrid.CellCountX; x++)
|
||||
@ -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
|
||||
{
|
||||
|
@ -69,6 +69,8 @@ namespace CodeWalker.World
|
||||
get
|
||||
{
|
||||
int sc = 0;
|
||||
if (Nodes != null)
|
||||
{
|
||||
foreach (var node in Nodes)
|
||||
{
|
||||
if ((node.NodeType == 1) || (node.NodeType == 2) || (node.NodeType == 5))
|
||||
@ -76,6 +78,7 @@ namespace CodeWalker.World
|
||||
sc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
}
|
||||
|
6
CodeWalker.ErrorReport/App.config
Normal file
6
CodeWalker.ErrorReport/App.config
Normal 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>
|
BIN
CodeWalker.ErrorReport/CW.ico
Normal file
BIN
CodeWalker.ErrorReport/CW.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
88
CodeWalker.ErrorReport/CodeWalker.ErrorReport.csproj
Normal file
88
CodeWalker.ErrorReport/CodeWalker.ErrorReport.csproj
Normal 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>
|
22
CodeWalker.ErrorReport/Program.cs
Normal file
22
CodeWalker.ErrorReport/Program.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
36
CodeWalker.ErrorReport/Properties/AssemblyInfo.cs
Normal file
36
CodeWalker.ErrorReport/Properties/AssemblyInfo.cs
Normal 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")]
|
71
CodeWalker.ErrorReport/Properties/Resources.Designer.cs
generated
Normal file
71
CodeWalker.ErrorReport/Properties/Resources.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
CodeWalker.ErrorReport/Properties/Resources.resx
Normal file
117
CodeWalker.ErrorReport/Properties/Resources.resx
Normal 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>
|
30
CodeWalker.ErrorReport/Properties/Settings.Designer.cs
generated
Normal file
30
CodeWalker.ErrorReport/Properties/Settings.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
7
CodeWalker.ErrorReport/Properties/Settings.settings
Normal file
7
CodeWalker.ErrorReport/Properties/Settings.settings
Normal 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>
|
80
CodeWalker.ErrorReport/ReportForm.Designer.cs
generated
Normal file
80
CodeWalker.ErrorReport/ReportForm.Designer.cs
generated
Normal 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;
|
||||
}
|
||||
}
|
||||
|
59
CodeWalker.ErrorReport/ReportForm.cs
Normal file
59
CodeWalker.ErrorReport/ReportForm.cs
Normal 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.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -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" />
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
CodeWalker.WinForms/app.config
Normal file
11
CodeWalker.WinForms/app.config
Normal 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>
|
@ -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>
|
@ -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" />
|
||||
|
@ -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
|
||||
|
43
ExploreForm.Designer.cs
generated
43
ExploreForm.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
334
ExploreForm.cs
334
ExploreForm.cs
@ -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);
|
||||
}
|
||||
|
||||
byte[] data = null;
|
||||
|
||||
switch (mformat)
|
||||
{
|
||||
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 XML");
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#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();
|
||||
|
@ -313,7 +313,7 @@
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
|
||||
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
|
||||
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADo
|
||||
HwAAAk1TRnQBSQFMAgEBGAEAARgBAQEYAQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
||||
HwAAAk1TRnQBSQFMAgEBGAEAATgBAQE4AQEBEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
|
||||
AwABQAMAAXADAAEBAQABCAYAARwYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
|
||||
AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
|
||||
AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
|
||||
|
@ -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,8 +309,109 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
206
Forms/ModelForm.Designer.cs
generated
206
Forms/ModelForm.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
120
Forms/ModelMatForm.Designer.cs
generated
Normal 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
284
Forms/ModelMatForm.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
431
Forms/RelForm.Designer.cs
generated
431
Forms/RelForm.Designer.cs
generated
@ -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;
|
||||
}
|
||||
}
|
420
Forms/RelForm.cs
420
Forms/RelForm.cs
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
215
Materials.txt
215
Materials.txt
@ -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
Loading…
Reference in New Issue
Block a user