mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-27 01:12:54 +08:00
YNV/XML conversion
This commit is contained in:
parent
6268298207
commit
4751818703
@ -4,6 +4,7 @@ using System.ComponentModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
using SharpDX;
|
using SharpDX;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
@ -29,6 +30,9 @@ namespace CodeWalker.GameFiles
|
|||||||
public bool HasChanged { get; set; } = false;
|
public bool HasChanged { get; set; } = false;
|
||||||
public List<string> SaveWarnings = null;
|
public List<string> SaveWarnings = null;
|
||||||
|
|
||||||
|
public bool BuildStructsOnSave { get; set; } = true;
|
||||||
|
|
||||||
|
|
||||||
public PathBVH BVH { get; set; }
|
public PathBVH BVH { get; set; }
|
||||||
|
|
||||||
|
|
||||||
@ -92,102 +96,7 @@ namespace CodeWalker.GameFiles
|
|||||||
Nav = rd.ReadBlock<NavMesh>();
|
Nav = rd.ReadBlock<NavMesh>();
|
||||||
|
|
||||||
|
|
||||||
if (Nav != null)
|
InitFromNav();
|
||||||
{
|
|
||||||
Vector3 posoffset = Nav.SectorTree?.AABBMin.XYZ() ?? Vector3.Zero;
|
|
||||||
Vector3 aabbsize = Nav.AABBSize;
|
|
||||||
|
|
||||||
if (Nav.Vertices != null)
|
|
||||||
{
|
|
||||||
var verts = Nav.Vertices.GetFullList();
|
|
||||||
Vertices = new List<Vector3>(verts.Count);
|
|
||||||
for (int i = 0; i < verts.Count; i++)
|
|
||||||
{
|
|
||||||
var ov = verts[i].ToVector3();
|
|
||||||
Vertices.Add(posoffset + ov * aabbsize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Nav.Indices != null)
|
|
||||||
{
|
|
||||||
Indices = Nav.Indices.GetFullList();
|
|
||||||
}
|
|
||||||
if (Nav.Edges != null)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
var polys = Nav.Polys.GetFullList();
|
|
||||||
Polys = new List<YnvPoly>(polys.Count);
|
|
||||||
for (int i = 0; i < polys.Count; i++)
|
|
||||||
{
|
|
||||||
YnvPoly poly = new YnvPoly();
|
|
||||||
poly.Init(this, polys[i]);
|
|
||||||
poly.Index = i;
|
|
||||||
Polys.Add(poly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Nav.Portals != null)
|
|
||||||
{
|
|
||||||
var portals = Nav.Portals;
|
|
||||||
Portals = new List<YnvPortal>(portals.Length);
|
|
||||||
for (int i = 0; i < portals.Length; i++)
|
|
||||||
{
|
|
||||||
YnvPortal portal = new YnvPortal();
|
|
||||||
portal.Init(this, portals[i]);
|
|
||||||
portal.Index = i;
|
|
||||||
portal.PositionFrom = posoffset + portal._RawData.PositionFrom.ToVector3() * aabbsize;
|
|
||||||
portal.PositionTo = posoffset + portal._RawData.PositionTo.ToVector3() * aabbsize;
|
|
||||||
Portals.Add(portal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////### add points to the list and calculate positions...
|
|
||||||
var treestack = new Stack<NavMeshSector>();
|
|
||||||
var pointi = 0;
|
|
||||||
if (Nav.SectorTree != null)
|
|
||||||
{
|
|
||||||
treestack.Push(Nav.SectorTree);
|
|
||||||
}
|
|
||||||
while (treestack.Count > 0)
|
|
||||||
{
|
|
||||||
var sector = treestack.Pop();
|
|
||||||
if (sector.Data != null)
|
|
||||||
{
|
|
||||||
var points = sector.Data.Points;
|
|
||||||
if (points != null)
|
|
||||||
{
|
|
||||||
if (Points == null)
|
|
||||||
{
|
|
||||||
Points = new List<YnvPoint>();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < points.Length; i++)
|
|
||||||
{
|
|
||||||
YnvPoint point = new YnvPoint();
|
|
||||||
point.Init(this, points[i]);
|
|
||||||
point.Index = pointi; pointi++;
|
|
||||||
point.Position = posoffset + point._RawData.Position * aabbsize;
|
|
||||||
Points.Add(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sector.SubTree1 != null) treestack.Push(sector.SubTree1);
|
|
||||||
if (sector.SubTree2 != null) treestack.Push(sector.SubTree2);
|
|
||||||
if (sector.SubTree3 != null) treestack.Push(sector.SubTree3);
|
|
||||||
if (sector.SubTree4 != null) treestack.Push(sector.SubTree4);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UpdateAllNodePositions();
|
UpdateAllNodePositions();
|
||||||
|
|
||||||
@ -200,16 +109,119 @@ namespace CodeWalker.GameFiles
|
|||||||
LoadQueued = true;
|
LoadQueued = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void InitFromNav()
|
||||||
|
{
|
||||||
|
if (Nav == null) return;
|
||||||
|
|
||||||
|
Vector3 posoffset = Nav.SectorTree?.AABBMin.XYZ() ?? Vector3.Zero;
|
||||||
|
Vector3 aabbsize = Nav.AABBSize;
|
||||||
|
|
||||||
|
if (Nav.Vertices != null)
|
||||||
|
{
|
||||||
|
var verts = Nav.Vertices.GetFullList();
|
||||||
|
Vertices = new List<Vector3>(verts.Count);
|
||||||
|
for (int i = 0; i < verts.Count; i++)
|
||||||
|
{
|
||||||
|
var ov = verts[i].ToVector3();
|
||||||
|
Vertices.Add(posoffset + ov * aabbsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Nav.Indices != null)
|
||||||
|
{
|
||||||
|
Indices = Nav.Indices.GetFullList();
|
||||||
|
}
|
||||||
|
if (Nav.Edges != null)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
var polys = Nav.Polys.GetFullList();
|
||||||
|
Polys = new List<YnvPoly>(polys.Count);
|
||||||
|
for (int i = 0; i < polys.Count; i++)
|
||||||
|
{
|
||||||
|
YnvPoly poly = new YnvPoly();
|
||||||
|
poly.Init(this, polys[i]);
|
||||||
|
poly.Index = i;
|
||||||
|
Polys.Add(poly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Nav.Portals != null)
|
||||||
|
{
|
||||||
|
var portals = Nav.Portals;
|
||||||
|
Portals = new List<YnvPortal>(portals.Length);
|
||||||
|
for (int i = 0; i < portals.Length; i++)
|
||||||
|
{
|
||||||
|
YnvPortal portal = new YnvPortal();
|
||||||
|
portal.Init(this, portals[i]);
|
||||||
|
portal.Index = i;
|
||||||
|
portal.PositionFrom = posoffset + portal._RawData.PositionFrom.ToVector3() * aabbsize;
|
||||||
|
portal.PositionTo = posoffset + portal._RawData.PositionTo.ToVector3() * aabbsize;
|
||||||
|
Portals.Add(portal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////### add points to the list and calculate positions...
|
||||||
|
var treestack = new Stack<NavMeshSector>();
|
||||||
|
var pointi = 0;
|
||||||
|
if (Nav.SectorTree != null)
|
||||||
|
{
|
||||||
|
treestack.Push(Nav.SectorTree);
|
||||||
|
}
|
||||||
|
while (treestack.Count > 0)
|
||||||
|
{
|
||||||
|
var sector = treestack.Pop();
|
||||||
|
if (sector.Data != null)
|
||||||
|
{
|
||||||
|
var points = sector.Data.Points;
|
||||||
|
if (points != null)
|
||||||
|
{
|
||||||
|
if (Points == null)
|
||||||
|
{
|
||||||
|
Points = new List<YnvPoint>();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < points.Length; i++)
|
||||||
|
{
|
||||||
|
YnvPoint point = new YnvPoint();
|
||||||
|
point.Init(this, points[i]);
|
||||||
|
point.Index = pointi; pointi++;
|
||||||
|
point.Position = posoffset + point._RawData.Position * aabbsize;
|
||||||
|
Points.Add(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sector.SubTree1 != null) treestack.Push(sector.SubTree1);
|
||||||
|
if (sector.SubTree2 != null) treestack.Push(sector.SubTree2);
|
||||||
|
if (sector.SubTree3 != null) treestack.Push(sector.SubTree3);
|
||||||
|
if (sector.SubTree4 != null) treestack.Push(sector.SubTree4);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] Save()
|
public byte[] Save()
|
||||||
{
|
{
|
||||||
BuildStructs();
|
if (BuildStructsOnSave)
|
||||||
|
{
|
||||||
|
BuildStructs();
|
||||||
|
}
|
||||||
|
|
||||||
byte[] data = ResourceBuilder.Build(Nav, 2); //ynv is version 2...
|
byte[] data = ResourceBuilder.Build(Nav, 2); //ynv is version 2...
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void BuildStructs()
|
private void BuildStructs()
|
||||||
{
|
{
|
||||||
Vector3 posoffset = Nav.SectorTree?.AABBMin.XYZ() ?? Vector3.Zero;
|
Vector3 posoffset = Nav.SectorTree?.AABBMin.XYZ() ?? Vector3.Zero;
|
||||||
@ -326,7 +338,8 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
var point = Points[i];
|
var point = Points[i];
|
||||||
var pdata = point.RawData;
|
var pdata = point.RawData;
|
||||||
pdata.Position = point.Position;
|
pdata.Position = (point.Position - posoffset) * aabbsizeinv;
|
||||||
|
point.RawData = pdata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,8 +411,9 @@ namespace CodeWalker.GameFiles
|
|||||||
root.SetAABBs(orig.AABBMin.XYZ(), orig.AABBMax.XYZ());
|
root.SetAABBs(orig.AABBMin.XYZ(), orig.AABBMax.XYZ());
|
||||||
|
|
||||||
uint pointindex = 0;
|
uint pointindex = 0;
|
||||||
|
var pointflags = new bool[Points?.Count ?? 0];
|
||||||
|
|
||||||
BuildSectorTree(root, depth, ref pointindex);
|
BuildSectorTree(root, depth, ref pointindex, pointflags);
|
||||||
|
|
||||||
Nav.SectorTree = root;
|
Nav.SectorTree = root;
|
||||||
|
|
||||||
@ -418,13 +432,12 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void BuildSectorTree(NavMeshSector node, int depth, ref uint pointindex)
|
private void BuildSectorTree(NavMeshSector node, int depth, ref uint pointindex, bool[] pointflags)
|
||||||
{
|
{
|
||||||
Vector3 min = node.AABBMin.XYZ();
|
Vector3 min = node.AABBMin.XYZ();
|
||||||
Vector3 max = node.AABBMax.XYZ();
|
Vector3 max = node.AABBMax.XYZ();
|
||||||
Vector3 cen = (min + max) * 0.5f;
|
Vector3 cen = (min + max) * 0.5f;
|
||||||
|
|
||||||
//totbytes += (uint)node.BlockLength;
|
|
||||||
|
|
||||||
if (depth <= 0)
|
if (depth <= 0)
|
||||||
{
|
{
|
||||||
@ -434,7 +447,6 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
data.PointsStartID = pointindex;
|
data.PointsStartID = pointindex;
|
||||||
|
|
||||||
//totbytes += (uint)data.BlockLength;
|
|
||||||
|
|
||||||
if (Polys != null)
|
if (Polys != null)
|
||||||
{
|
{
|
||||||
@ -452,7 +464,6 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
data.PolyIDs = polyids.ToArray();
|
data.PolyIDs = polyids.ToArray();
|
||||||
}
|
}
|
||||||
//totbytes += (uint)(polyids.Count * 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Points != null)
|
if (Points != null)
|
||||||
@ -461,17 +472,18 @@ namespace CodeWalker.GameFiles
|
|||||||
for (int i = 0; i < Points.Count; i++)
|
for (int i = 0; i < Points.Count; i++)
|
||||||
{
|
{
|
||||||
var point = Points[i];
|
var point = Points[i];
|
||||||
if (IsInBox(point.Position, min, max))
|
if (IsInBox(point.Position, min, max, true) && (pointflags[i] == false))
|
||||||
{
|
{
|
||||||
points.Add(point.RawData);
|
points.Add(point.RawData);
|
||||||
|
pointflags[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (points.Count > 0)
|
if (points.Count > 0)
|
||||||
{
|
{
|
||||||
data.Points = points.ToArray();
|
data.Points = points.ToArray();
|
||||||
|
data.PointsCount = (ushort)points.Count;
|
||||||
pointindex += (uint)points.Count;
|
pointindex += (uint)points.Count;
|
||||||
}
|
}
|
||||||
//totbytes += (uint)(points.Count * 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -487,18 +499,97 @@ namespace CodeWalker.GameFiles
|
|||||||
node.SubTree2.SetAABBs(new Vector3(cen.X, min.Y, 0.0f), new Vector3(max.X, cen.Y, 0.0f));
|
node.SubTree2.SetAABBs(new Vector3(cen.X, min.Y, 0.0f), new Vector3(max.X, cen.Y, 0.0f));
|
||||||
node.SubTree3.SetAABBs(new Vector3(min.X, min.Y, min.Z), new Vector3(cen.X, cen.Y, cen.Z));
|
node.SubTree3.SetAABBs(new Vector3(min.X, min.Y, min.Z), new Vector3(cen.X, cen.Y, cen.Z));
|
||||||
node.SubTree4.SetAABBs(new Vector3(min.X, cen.Y, 0.0f), new Vector3(cen.X, max.Y, 0.0f));
|
node.SubTree4.SetAABBs(new Vector3(min.X, cen.Y, 0.0f), new Vector3(cen.X, max.Y, 0.0f));
|
||||||
BuildSectorTree(node.SubTree1, cdepth, ref pointindex);
|
BuildSectorTree(node.SubTree1, cdepth, ref pointindex, pointflags);
|
||||||
BuildSectorTree(node.SubTree2, cdepth, ref pointindex);
|
BuildSectorTree(node.SubTree2, cdepth, ref pointindex, pointflags);
|
||||||
BuildSectorTree(node.SubTree3, cdepth, ref pointindex);
|
BuildSectorTree(node.SubTree3, cdepth, ref pointindex, pointflags);
|
||||||
BuildSectorTree(node.SubTree4, cdepth, ref pointindex);
|
BuildSectorTree(node.SubTree4, cdepth, ref pointindex, pointflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsInBox(Vector3 p, Vector3 min, Vector3 max)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void WriteXml(StringBuilder sb, int indent)
|
||||||
{
|
{
|
||||||
return (p.X >= min.X) && (p.X < max.X) &&
|
YnvXml.StringTag(sb, indent, "ContentFlags", Nav.ContentFlags.ToString());
|
||||||
(p.Y >= min.Y) && (p.Y < max.Y);// &&
|
YnvXml.ValueTag(sb, indent, "AreaID", AreaID.ToString());
|
||||||
//(p.Z >= min.Z) && (p.Z < max.Z);
|
YnvXml.SelfClosingTag(sb, indent, "BBMin " + FloatUtil.GetVector3XmlString(Nav.AABBMin));
|
||||||
|
YnvXml.SelfClosingTag(sb, indent, "BBMax " + FloatUtil.GetVector3XmlString(Nav.AABBMax));
|
||||||
|
YnvXml.SelfClosingTag(sb, indent, "BBSize " + FloatUtil.GetVector3XmlString(Nav.AABBSize));
|
||||||
|
YnvXml.WriteItemArray(sb, AllPolys, indent, "Polygons");
|
||||||
|
YnvXml.WriteItemArray(sb, AllPortals, indent, "Portals");
|
||||||
|
YnvXml.WriteItemArray(sb, AllPoints, indent, "Points");
|
||||||
|
}
|
||||||
|
public void ReadXml(XmlNode node)
|
||||||
|
{
|
||||||
|
Nav = new NavMesh();
|
||||||
|
Nav.SectorTree = new NavMeshSector();
|
||||||
|
Nav.ContentFlags = Xml.GetChildEnumInnerText<NavMeshFlags>(node, "ContentFlags");
|
||||||
|
Nav.AreaID = Xml.GetChildUIntAttribute(node, "AreaID");
|
||||||
|
Nav.AABBMin = Xml.GetChildVector3Attributes(node, "BBMin");
|
||||||
|
Nav.AABBMax = Xml.GetChildVector3Attributes(node, "BBMax");
|
||||||
|
Nav.AABBSize = Xml.GetChildVector3Attributes(node, "BBSize");
|
||||||
|
Polys = XmlYnv.ReadItemList<YnvPoly>(node, "Polygons");
|
||||||
|
Portals = XmlYnv.ReadItemList<YnvPortal>(node, "Portals");
|
||||||
|
Points = XmlYnv.ReadItemList<YnvPoint>(node, "Points");
|
||||||
|
|
||||||
|
if (Polys != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Polys.Count; i++)
|
||||||
|
{
|
||||||
|
var poly = Polys[i];
|
||||||
|
poly.Ynv = this;
|
||||||
|
poly.Index = i;
|
||||||
|
poly.AreaID = (ushort)AreaID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Portals != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Portals.Count; i++)
|
||||||
|
{
|
||||||
|
var portal = Portals[i];
|
||||||
|
portal.Ynv = this;
|
||||||
|
portal.Index = i;
|
||||||
|
portal.AreaIDFrom = (ushort)AreaID;
|
||||||
|
portal.AreaIDTo = (ushort)AreaID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Points != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Points.Count; i++)
|
||||||
|
{
|
||||||
|
var point = Points[i];
|
||||||
|
point.Ynv = this;
|
||||||
|
point.Index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool vehicle = ((Nav.ContentFlags & NavMeshFlags.Vehicle) != 0);
|
||||||
|
Nav.VersionUnk1 = 0x00010011;
|
||||||
|
Nav.VersionUnk2 = vehicle ? 0 : 0x85CB3561;
|
||||||
|
Nav.Transform = Matrix.Identity;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private bool IsInBox(Vector3 p, Vector3 min, Vector3 max, bool outer)
|
||||||
|
{
|
||||||
|
if (outer)
|
||||||
|
return (p.X >= min.X) && (p.X <= max.X) &&
|
||||||
|
(p.Y >= min.Y) && (p.Y <= max.Y);// &&
|
||||||
|
//(p.Z >= min.Z) && (p.Z < max.Z);
|
||||||
|
else
|
||||||
|
return (p.X >= min.X) && (p.X < max.X) &&
|
||||||
|
(p.Y >= min.Y) && (p.Y < max.Y);// &&
|
||||||
|
//(p.Z >= min.Z) && (p.Z < max.Z);
|
||||||
}
|
}
|
||||||
private bool BoxOverlaps(Vector3 bmin, Vector3 bmax, Vector3 min, Vector3 max)
|
private bool BoxOverlaps(Vector3 bmin, Vector3 bmax, Vector3 min, Vector3 max)
|
||||||
{
|
{
|
||||||
@ -528,19 +619,6 @@ 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()
|
public void UpdateAllNodePositions()
|
||||||
{
|
{
|
||||||
@ -636,6 +714,19 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdateContentFlags(bool vehicle)
|
||||||
|
{
|
||||||
|
NavMeshFlags f = NavMeshFlags.None;
|
||||||
|
if (Polys?.Count > 0) f = f | NavMeshFlags.Polygons;
|
||||||
|
if (Portals?.Count > 0) f = f | NavMeshFlags.Portals;
|
||||||
|
if (vehicle) f = f | NavMeshFlags.Vehicle;
|
||||||
|
else f = f | NavMeshFlags.Unknown8; //what exactly is this?
|
||||||
|
Nav.ContentFlags = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void BuildBVH()
|
public void BuildBVH()
|
||||||
{
|
{
|
||||||
var nodes = new List<BasePathNode>();
|
var nodes = new List<BasePathNode>();
|
||||||
@ -662,7 +753,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoly
|
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoly : IMetaXmlItem
|
||||||
{
|
{
|
||||||
public NavMeshPoly _RawData;
|
public NavMeshPoly _RawData;
|
||||||
public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } }
|
public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } }
|
||||||
@ -673,45 +764,45 @@ namespace CodeWalker.GameFiles
|
|||||||
public ushort PartID { get { return _RawData.PartID; } set { _RawData.PartID = value; } }
|
public ushort PartID { get { return _RawData.PartID; } set { _RawData.PartID = value; } }
|
||||||
public uint PortalLinkID { get { return _RawData.PortalLinkID; } set { _RawData.PortalLinkID = 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 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 Flags1 { get { return _RawData.Flags1; } set { _RawData.Flags1 = value; } }
|
||||||
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 Flags2 { get { return _RawData.Flags2; } set { _RawData.Flags2 = value; } }
|
||||||
public byte Flags3 { get { return (byte)((_RawData.Unknown_24h.Value >> 9) & 0xFF); } set { _RawData.Unknown_24h = ((_RawData.Unknown_24h.Value & 0xFFFE01FFu) | ((value & 0xFFu) << 9)); } }
|
public byte Flags3 { get { return _RawData.Flags3; } set { _RawData.Flags3 = value; } }
|
||||||
public byte Flags4 { get { return (byte)((_RawData.Unknown_28h.Value >> 16) & 0xFF); } set { _RawData.Unknown_28h = ((_RawData.Unknown_28h.Value & 0x0000FFFFu) | ((value & 0xFFu) << 16)); } }
|
public byte Flags4 { get { return _RawData.Flags4; } set { _RawData.Flags4 = value; } }
|
||||||
public bool B00_AvoidUnk { get { return (_RawData.Unknown_00h & 1) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 0, value); } }
|
public bool B00_AvoidUnk { get { return (_RawData.PolyFlags0 & 1) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 0, value); } }
|
||||||
public bool B01_AvoidUnk { get { return (_RawData.Unknown_00h & 2) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 1, value); } }
|
public bool B01_AvoidUnk { get { return (_RawData.PolyFlags0 & 2) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 1, value); } }
|
||||||
public bool B02_IsFootpath { get { return (_RawData.Unknown_00h & 4) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 2, value); } }
|
public bool B02_IsFootpath { get { return (_RawData.PolyFlags0 & 4) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 2, value); } }
|
||||||
public bool B03_IsUnderground { get { return (_RawData.Unknown_00h & 8) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 3, value); } }
|
public bool B03_IsUnderground { get { return (_RawData.PolyFlags0 & 8) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 3, value); } }
|
||||||
//public bool B04_Unused { get { return (_RawData.Unknown_00h & 16) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 4, value); } }
|
public bool B04_Unused { get { return (_RawData.PolyFlags0 & 16) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 4, value); } }
|
||||||
//public bool B05_Unused { get { return (_RawData.Unknown_00h & 32) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 5, value); } }
|
public bool B05_Unused { get { return (_RawData.PolyFlags0 & 32) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 5, value); } }
|
||||||
public bool B06_SteepSlope { get { return (_RawData.Unknown_00h & 64) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 6, value); } }
|
public bool B06_SteepSlope { get { return (_RawData.PolyFlags0 & 64) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 6, value); } }
|
||||||
public bool B07_IsWater { get { return (_RawData.Unknown_00h & 128) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 7, value); } }
|
public bool B07_IsWater { get { return (_RawData.PolyFlags0 & 128) > 0; } set { _RawData.PolyFlags0 = (ushort)BitUtil.UpdateBit(_RawData.PolyFlags0, 7, value); } }
|
||||||
public bool B08_UndergroundUnk0 { get { return (_RawData.Unknown_24h.Value & 1) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 0, value); } }
|
public bool B08_UndergroundUnk0 { get { return (_RawData.PolyFlags1 & 1) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 0, value); } }
|
||||||
public bool B09_UndergroundUnk1 { get { return (_RawData.Unknown_24h.Value & 2) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 1, value); } }
|
public bool B09_UndergroundUnk1 { get { return (_RawData.PolyFlags1 & 2) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 1, value); } }
|
||||||
public bool B10_UndergroundUnk2 { get { return (_RawData.Unknown_24h.Value & 4) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 2, value); } }
|
public bool B10_UndergroundUnk2 { get { return (_RawData.PolyFlags1 & 4) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 2, value); } }
|
||||||
public bool B11_UndergroundUnk3 { get { return (_RawData.Unknown_24h.Value & 8) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 3, value); } }
|
public bool B11_UndergroundUnk3 { get { return (_RawData.PolyFlags1 & 8) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 3, value); } }
|
||||||
//public bool B12_Unused { get { return (_RawData.Unknown_24h.Value & 16) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 4, value); } }
|
public bool B12_Unused { get { return (_RawData.PolyFlags1 & 16) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 4, value); } }
|
||||||
public bool B13_HasPathNode { get { return (_RawData.Unknown_24h.Value & 32) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 5, value); } }
|
public bool B13_HasPathNode { get { return (_RawData.PolyFlags1 & 32) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 5, value); } }
|
||||||
public bool B14_IsInterior { get { return (_RawData.Unknown_24h.Value & 64) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 6, value); } }
|
public bool B14_IsInterior { get { return (_RawData.PolyFlags1 & 64) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 6, value); } }
|
||||||
public bool B15_InteractionUnk { get { return (_RawData.Unknown_24h.Value & 128) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 7, value); } }
|
public bool B15_InteractionUnk { get { return (_RawData.PolyFlags1 & 128) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 7, value); } }
|
||||||
//public bool B16_Unused { get { return (_RawData.Unknown_24h.Value & 256) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 8, value); } }
|
public bool B16_Unused { get { return (_RawData.PolyFlags1 & 256) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 8, value); } }
|
||||||
public bool B17_IsFlatGround { get { return (_RawData.Unknown_24h.Value & 512) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 9, value); } }
|
public bool B17_IsFlatGround { get { return (_RawData.PolyFlags1 & 512) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 9, value); } }
|
||||||
public bool B18_IsRoad { get { return (_RawData.Unknown_24h.Value & 1024) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 10, value); } }
|
public bool B18_IsRoad { get { return (_RawData.PolyFlags1 & 1024) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 10, value); } }
|
||||||
public bool B19_IsCellEdge { get { return (_RawData.Unknown_24h.Value & 2048) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 11, value); } }
|
public bool B19_IsCellEdge { get { return (_RawData.PolyFlags1 & 2048) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 11, value); } }
|
||||||
public bool B20_IsTrainTrack { get { return (_RawData.Unknown_24h.Value & 4096) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 12, value); } }
|
public bool B20_IsTrainTrack { get { return (_RawData.PolyFlags1 & 4096) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 12, value); } }
|
||||||
public bool B21_IsShallowWater { get { return (_RawData.Unknown_24h.Value & 8192) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 13, value); } }
|
public bool B21_IsShallowWater { get { return (_RawData.PolyFlags1 & 8192) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 13, value); } }
|
||||||
public bool B22_FootpathUnk1 { get { return (_RawData.Unknown_24h.Value & 16384) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 14, value); } }
|
public bool B22_FootpathUnk1 { get { return (_RawData.PolyFlags1 & 16384) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 14, value); } }
|
||||||
public bool B23_FootpathUnk2 { get { return (_RawData.Unknown_24h.Value & 32768) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 15, value); } }
|
public bool B23_FootpathUnk2 { get { return (_RawData.PolyFlags1 & 32768) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 15, value); } }
|
||||||
public bool B24_FootpathMall { get { return (_RawData.Unknown_24h.Value & 65536) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 16, value); } }
|
public bool B24_FootpathMall { get { return (_RawData.PolyFlags1 & 65536) > 0; } set { _RawData.PolyFlags1 = BitUtil.UpdateBit(_RawData.PolyFlags1, 16, value); } }
|
||||||
public bool B25_SlopeSouth { get { return (_RawData.Unknown_28h.Value & 65536) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 16, value); } }
|
public bool B25_SlopeSouth { get { return (_RawData.PolyFlags2 & 65536) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 16, value); } }
|
||||||
public bool B26_SlopeSouthEast { get { return (_RawData.Unknown_28h.Value & 131072) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 17, value); } }
|
public bool B26_SlopeSouthEast { get { return (_RawData.PolyFlags2 & 131072) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 17, value); } }
|
||||||
public bool B27_SlopeEast { get { return (_RawData.Unknown_28h.Value & 262144) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 18, value); } }
|
public bool B27_SlopeEast { get { return (_RawData.PolyFlags2 & 262144) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 18, value); } }
|
||||||
public bool B28_SlopeNorthEast { get { return (_RawData.Unknown_28h.Value & 524288) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 19, value); } }
|
public bool B28_SlopeNorthEast { get { return (_RawData.PolyFlags2 & 524288) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 19, value); } }
|
||||||
public bool B29_SlopeNorth { get { return (_RawData.Unknown_28h.Value & 1048576) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 20, value); } }
|
public bool B29_SlopeNorth { get { return (_RawData.PolyFlags2 & 1048576) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 20, value); } }
|
||||||
public bool B30_SlopeNorthWest { get { return (_RawData.Unknown_28h.Value & 2097152) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 21, value); } }
|
public bool B30_SlopeNorthWest { get { return (_RawData.PolyFlags2 & 2097152) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 21, value); } }
|
||||||
public bool B31_SlopeWest { get { return (_RawData.Unknown_28h.Value & 4194304) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 22, value); } }
|
public bool B31_SlopeWest { get { return (_RawData.PolyFlags2 & 4194304) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 22, value); } }
|
||||||
public bool B32_SlopeSouthWest { get { return (_RawData.Unknown_28h.Value & 8388608) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 23, value); } }
|
public bool B32_SlopeSouthWest { get { return (_RawData.PolyFlags2 & 8388608) > 0; } set { _RawData.PolyFlags2 = BitUtil.UpdateBit(_RawData.PolyFlags2, 23, value); } }
|
||||||
public byte UnkX { get { return _RawData.Unknown_28h_8a; } set { _RawData.Unknown_28h_8a = value; } }
|
public byte UnkX { get { return _RawData.UnkX; } set { _RawData.UnkX = value; } }
|
||||||
public byte UnkY { get { return _RawData.Unknown_28h_8b; } set { _RawData.Unknown_28h_8b = value; } }
|
public byte UnkY { get { return _RawData.UnkY; } set { _RawData.UnkY = value; } }
|
||||||
|
|
||||||
|
|
||||||
public Vector3 Position { get; set; }
|
public Vector3 Position { get; set; }
|
||||||
@ -805,7 +896,7 @@ namespace CodeWalker.GameFiles
|
|||||||
public Color4 GetColour()
|
public Color4 GetColour()
|
||||||
{
|
{
|
||||||
var colour = new Color4();
|
var colour = new Color4();
|
||||||
var u0 = _RawData.Unknown_00h;
|
var u0 = _RawData.PolyFlags0;
|
||||||
if ((u0 & 1) > 0) colour.Red += 0.01f;//avoid? loiter?
|
if ((u0 & 1) > 0) colour.Red += 0.01f;//avoid? loiter?
|
||||||
if ((u0 & 2) > 0) colour.Red += 0.01f; //avoid?
|
if ((u0 & 2) > 0) colour.Red += 0.01f; //avoid?
|
||||||
if ((u0 & 4) > 0) colour.Green += 0.25f; //ped/footpath
|
if ((u0 & 4) > 0) colour.Green += 0.25f; //ped/footpath
|
||||||
@ -816,7 +907,7 @@ namespace CodeWalker.GameFiles
|
|||||||
if ((u0 & 128) > 0) colour.Blue += 0.25f; //water
|
if ((u0 & 128) > 0) colour.Blue += 0.25f; //water
|
||||||
//if (u0 >= 256) colour.Green += 1.0f;//other bits unused...
|
//if (u0 >= 256) colour.Green += 1.0f;//other bits unused...
|
||||||
|
|
||||||
var u2 = _RawData.Unknown_24h.Value;
|
var u2 = _RawData.PolyFlags1;
|
||||||
//colour.Green = (u2 & 15) / 15.0f; //maybe underground amount..?
|
//colour.Green = (u2 & 15) / 15.0f; //maybe underground amount..?
|
||||||
//if ((u2 & 1) > 0) colour.Blue += 1.0f; //peds interact with something? underground?
|
//if ((u2 & 1) > 0) colour.Blue += 1.0f; //peds interact with something? underground?
|
||||||
//if ((u2 & 2) > 0) colour.Green += 1.0f;//underneath something?
|
//if ((u2 & 2) > 0) colour.Green += 1.0f;//underneath something?
|
||||||
@ -837,7 +928,7 @@ namespace CodeWalker.GameFiles
|
|||||||
if ((u2 & 65536) > 0) colour.Green = 0.2f;//footpaths - mall areas? eg mall, vinewood blvd
|
if ((u2 & 65536) > 0) colour.Green = 0.2f;//footpaths - mall areas? eg mall, vinewood blvd
|
||||||
//if (u2 >= 131072) { }//other bits unused
|
//if (u2 >= 131072) { }//other bits unused
|
||||||
|
|
||||||
var u5 = _RawData.Unknown_28h.Value; //32 bits
|
var u5 = _RawData.PolyFlags2; //32 bits
|
||||||
//colour.Red = poly.Unknown_28h_8a / 255.0f; //heuristic vals..?
|
//colour.Red = poly.Unknown_28h_8a / 255.0f; //heuristic vals..?
|
||||||
//colour.Green = poly.Unknown_28h_8b / 255.0f; //heuristic vals..?
|
//colour.Green = poly.Unknown_28h_8b / 255.0f; //heuristic vals..?
|
||||||
//if ((u5 & 65536) > 0) colour.Red += 1.0f; //slope facing -Y (south)
|
//if ((u5 & 65536) > 0) colour.Red += 1.0f; //slope facing -Y (south)
|
||||||
@ -904,13 +995,83 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void WriteXml(StringBuilder sb, int indent)
|
||||||
|
{
|
||||||
|
byte[] flags = { Flags1, Flags2, Flags3, Flags4, UnkX, UnkY };
|
||||||
|
YnvXml.WriteRawArray(sb, flags, indent, "Flags", "");
|
||||||
|
YnvXml.WriteRawArray(sb, Vertices, indent, "Vertices", "", YnvXml.FormatVector3, 1);
|
||||||
|
var cind = indent + 1;
|
||||||
|
YnvXml.OpenTag(sb, indent, "Edges");
|
||||||
|
foreach (var e in Edges)
|
||||||
|
{
|
||||||
|
YnvXml.Indent(sb, cind);
|
||||||
|
sb.AppendFormat("{0}:{1}, {2}:{3}", e.AreaID1, e.PolyID1, e.AreaID2, e.PolyID2);
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
YnvXml.CloseTag(sb, indent, "Edges");
|
||||||
|
if ((PortalLinks != null) && (PortalLinks.Length > 0))
|
||||||
|
{
|
||||||
|
YnvXml.WriteRawArray(sb, PortalLinks, indent, "Portals", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void ReadXml(XmlNode node)
|
||||||
|
{
|
||||||
|
var flags = Xml.GetChildRawByteArrayNullable(node, "Flags", 10);
|
||||||
|
if (flags != null)
|
||||||
|
{
|
||||||
|
Flags1 = (flags.Length > 0) ? flags[0] : (byte)0;
|
||||||
|
Flags2 = (flags.Length > 1) ? flags[1] : (byte)0;
|
||||||
|
Flags3 = (flags.Length > 2) ? flags[2] : (byte)0;
|
||||||
|
Flags4 = (flags.Length > 3) ? flags[3] : (byte)0;
|
||||||
|
UnkX = (flags.Length > 4) ? flags[4] : (byte)0;
|
||||||
|
UnkY = (flags.Length > 5) ? flags[5] : (byte)0;
|
||||||
|
}
|
||||||
|
Vertices = Xml.GetChildRawVector3Array(node, "Vertices");
|
||||||
|
Indices = new ushort[Vertices?.Length ?? 0];//needs to be present for later
|
||||||
|
var edgesstr = Xml.GetChildInnerText(node, "Edges");
|
||||||
|
var edgesstrarr = edgesstr.Trim().Split('\n');
|
||||||
|
var edges = new List<YnvEdge>();
|
||||||
|
foreach (var edgestr in edgesstrarr)
|
||||||
|
{
|
||||||
|
var estrparts = edgestr.Trim().Split(',');
|
||||||
|
if (estrparts.Length != 2)
|
||||||
|
{ continue; }
|
||||||
|
var estrp0 = estrparts[0].Trim().Split(':');
|
||||||
|
var estrp1 = estrparts[1].Trim().Split(':');
|
||||||
|
if (estrp0.Length != 2)
|
||||||
|
{ continue; }
|
||||||
|
if (estrp1.Length != 2)
|
||||||
|
{ continue; }
|
||||||
|
|
||||||
|
uint aid1, aid2, pid1, pid2;
|
||||||
|
uint.TryParse(estrp0[0].Trim(), out aid1);
|
||||||
|
uint.TryParse(estrp0[1].Trim(), out pid1);
|
||||||
|
uint.TryParse(estrp1[0].Trim(), out aid2);
|
||||||
|
uint.TryParse(estrp1[1].Trim(), out pid2);
|
||||||
|
|
||||||
|
var e = new YnvEdge();
|
||||||
|
e.AreaID1 = aid1;
|
||||||
|
e.AreaID2 = aid2;
|
||||||
|
e.PolyID1 = pid1;
|
||||||
|
e.PolyID2 = pid2;
|
||||||
|
edges.Add(e);
|
||||||
|
}
|
||||||
|
if (edges.Count > 0)
|
||||||
|
{
|
||||||
|
Edges = edges.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
PortalLinks = Xml.GetChildRawUshortArrayNullable(node, "Portals");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return AreaID.ToString() + ", " + Index.ToString();
|
return AreaID.ToString() + ", " + Index.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPortal : BasePathNode
|
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPortal : BasePathNode, IMetaXmlItem
|
||||||
{
|
{
|
||||||
public NavMeshPortal _RawData;
|
public NavMeshPortal _RawData;
|
||||||
|
|
||||||
@ -930,7 +1091,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Angle = (byte)(value * 255.0f / ((float)Math.PI * 2.0f));
|
Angle = (byte)Math.Round(value * 255.0f / ((float)Math.PI * 2.0f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Quaternion Orientation
|
public Quaternion Orientation
|
||||||
@ -945,15 +1106,15 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
public byte Type { get { return _RawData.Type; } set { _RawData.Type = value; } }
|
public byte Type { get { return _RawData.Type; } set { _RawData.Type = value; } }//1,2,3
|
||||||
public ushort AreaIDFrom { get { return _RawData.AreaIDFrom; } set { _RawData.AreaIDFrom = value; } }
|
public ushort AreaIDFrom { get { return _RawData.AreaIDFrom; } set { _RawData.AreaIDFrom = value; } }//always Ynv.AreaID
|
||||||
public ushort AreaIDTo { get { return _RawData.AreaIDTo; } set { _RawData.AreaIDTo = value; } }
|
public ushort AreaIDTo { get { return _RawData.AreaIDTo; } set { _RawData.AreaIDTo = value; } }//always Ynv.AreaID
|
||||||
public ushort PolyIDFrom1 { get { return _RawData.PolyIDFrom1; } set { _RawData.PolyIDFrom1 = value; } }
|
public ushort PolyIDFrom1 { get { return _RawData.PolyIDFrom1; } set { _RawData.PolyIDFrom1 = value; } }
|
||||||
public ushort PolyIDFrom2 { get { return _RawData.PolyIDFrom2; } set { _RawData.PolyIDFrom2 = value; } }
|
public ushort PolyIDFrom2 { get { return _RawData.PolyIDFrom2; } set { _RawData.PolyIDFrom2 = value; } }
|
||||||
public ushort PolyIDTo1 { get { return _RawData.PolyIDTo1; } set { _RawData.PolyIDTo1 = value; } }
|
public ushort PolyIDTo1 { get { return _RawData.PolyIDTo1; } set { _RawData.PolyIDTo1 = value; } }
|
||||||
public ushort PolyIDTo2 { get { return _RawData.PolyIDTo2; } set { _RawData.PolyIDTo2 = value; } }
|
public ushort PolyIDTo2 { get { return _RawData.PolyIDTo2; } set { _RawData.PolyIDTo2 = value; } }
|
||||||
public ushort Unk1 { get { return _RawData.FlagsUnk; } set { _RawData.FlagsUnk = value; } }
|
public ushort Unk1 { get { return _RawData.FlagsUnk; } set { _RawData.FlagsUnk = value; } }//always 0
|
||||||
public byte Unk2 { get { return _RawData.AreaUnk; } set { _RawData.AreaUnk = value; } }
|
public byte Unk2 { get { return _RawData.AreaUnk; } set { _RawData.AreaUnk = value; } }//always 0
|
||||||
|
|
||||||
|
|
||||||
public void Init(YnvFile ynv, NavMeshPortal portal)
|
public void Init(YnvFile ynv, NavMeshPortal portal)
|
||||||
@ -974,13 +1135,32 @@ namespace CodeWalker.GameFiles
|
|||||||
Orientation = orientation;
|
Orientation = orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WriteXml(StringBuilder sb, int indent)
|
||||||
|
{
|
||||||
|
YnvXml.ValueTag(sb, indent, "Type", Type.ToString());
|
||||||
|
YnvXml.ValueTag(sb, indent, "Angle", FloatUtil.ToString(Direction));
|
||||||
|
YnvXml.ValueTag(sb, indent, "PolyFrom", PolyIDFrom1.ToString());
|
||||||
|
YnvXml.ValueTag(sb, indent, "PolyTo", PolyIDTo1.ToString());
|
||||||
|
YnvXml.SelfClosingTag(sb, indent, "PositionFrom " + FloatUtil.GetVector3XmlString(PositionFrom));
|
||||||
|
YnvXml.SelfClosingTag(sb, indent, "PositionTo " + FloatUtil.GetVector3XmlString(PositionTo));
|
||||||
|
}
|
||||||
|
public void ReadXml(XmlNode node)
|
||||||
|
{
|
||||||
|
Type = (byte)Xml.GetChildUIntAttribute(node, "Type");
|
||||||
|
Direction = Xml.GetChildFloatAttribute(node, "Angle");
|
||||||
|
PolyIDFrom1 = PolyIDFrom2 = (ushort)Xml.GetChildUIntAttribute(node, "PolyFrom");
|
||||||
|
PolyIDTo1 = PolyIDTo2 = (ushort)Xml.GetChildUIntAttribute(node, "PolyTo");
|
||||||
|
PositionFrom = Xml.GetChildVector3Attributes(node, "PositionFrom");
|
||||||
|
PositionTo = Xml.GetChildVector3Attributes(node, "PositionTo");
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Index.ToString();
|
return Index.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoint : BasePathNode
|
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoint : BasePathNode, IMetaXmlItem
|
||||||
{
|
{
|
||||||
public NavMeshPoint _RawData;
|
public NavMeshPoint _RawData;
|
||||||
|
|
||||||
@ -997,7 +1177,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Angle = (byte)(value * 255.0f / ((float)Math.PI * 2.0f));
|
Angle = (byte)Math.Round(value * 255.0f / ((float)Math.PI * 2.0f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Quaternion Orientation
|
public Quaternion Orientation
|
||||||
@ -1012,7 +1192,7 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
public byte Type { get { return _RawData.Type; } set { _RawData.Type = value; } }
|
public byte Type { get { return _RawData.Type; } set { _RawData.Type = value; } }//0,1,2,3,4,5,128,171,254
|
||||||
|
|
||||||
public void Init(YnvFile ynv, NavMeshPoint point)
|
public void Init(YnvFile ynv, NavMeshPoint point)
|
||||||
{
|
{
|
||||||
@ -1030,11 +1210,23 @@ namespace CodeWalker.GameFiles
|
|||||||
Orientation = orientation;
|
Orientation = orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WriteXml(StringBuilder sb, int indent)
|
||||||
|
{
|
||||||
|
YnvXml.ValueTag(sb, indent, "Type", Type.ToString());
|
||||||
|
YnvXml.ValueTag(sb, indent, "Angle", FloatUtil.ToString(Direction));
|
||||||
|
YnvXml.SelfClosingTag(sb, indent, "Position " + FloatUtil.GetVector3XmlString(Position));
|
||||||
|
}
|
||||||
|
public void ReadXml(XmlNode node)
|
||||||
|
{
|
||||||
|
Type = (byte)Xml.GetChildUIntAttribute(node, "Type");
|
||||||
|
Direction = Xml.GetChildFloatAttribute(node, "Angle");
|
||||||
|
Position = Xml.GetChildVector3Attributes(node, "Position");
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Index.ToString() + ": " + Type.ToString();
|
return Index.ToString() + ": " + Type.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1090,4 +1282,83 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class YnvXml : MetaXmlBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public static string GetXml(YnvFile ynv)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendLine(XmlHeader);
|
||||||
|
|
||||||
|
if ((ynv != null) && (ynv.Nav != null))
|
||||||
|
{
|
||||||
|
var name = "NavMesh";
|
||||||
|
|
||||||
|
OpenTag(sb, 0, name);
|
||||||
|
|
||||||
|
ynv.WriteXml(sb, 1);
|
||||||
|
|
||||||
|
CloseTag(sb, 0, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class XmlYnv
|
||||||
|
{
|
||||||
|
|
||||||
|
public static YnvFile GetYnv(string xml)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.LoadXml(xml);
|
||||||
|
return GetYnv(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YnvFile GetYnv(XmlDocument doc)
|
||||||
|
{
|
||||||
|
YnvFile ynv = new YnvFile();
|
||||||
|
ynv.ReadXml(doc.DocumentElement);
|
||||||
|
return ynv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<T> ReadItemList<T>(XmlNode node, string name) where T : IMetaXmlItem, new()
|
||||||
|
{
|
||||||
|
var vnode2 = node.SelectSingleNode(name);
|
||||||
|
if (vnode2 != null)
|
||||||
|
{
|
||||||
|
var inodes = vnode2.SelectNodes("Item");
|
||||||
|
if (inodes?.Count > 0)
|
||||||
|
{
|
||||||
|
var vlist = new List<T>();
|
||||||
|
foreach (XmlNode inode in inodes)
|
||||||
|
{
|
||||||
|
var v = new T();
|
||||||
|
v.ReadXml(inode);
|
||||||
|
vlist.Add(v);
|
||||||
|
}
|
||||||
|
return vlist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -195,6 +195,7 @@ namespace CodeWalker.GameFiles
|
|||||||
//TestYdds();
|
//TestYdds();
|
||||||
//TestYfts();
|
//TestYfts();
|
||||||
//TestYpts();
|
//TestYpts();
|
||||||
|
//TestYnvs();
|
||||||
//TestYmaps();
|
//TestYmaps();
|
||||||
//TestPlacements();
|
//TestPlacements();
|
||||||
//TestDrawables();
|
//TestDrawables();
|
||||||
@ -4057,6 +4058,80 @@ namespace CodeWalker.GameFiles
|
|||||||
if (errorfiles.Count > 0)
|
if (errorfiles.Count > 0)
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
public void TestYnvs()
|
||||||
|
{
|
||||||
|
bool xmltest = true;
|
||||||
|
var savetest = false;
|
||||||
|
var errorfiles = new List<RpfEntry>();
|
||||||
|
foreach (RpfFile file in AllRpfs)
|
||||||
|
{
|
||||||
|
foreach (RpfEntry entry in file.AllEntries)
|
||||||
|
{
|
||||||
|
//try
|
||||||
|
{
|
||||||
|
if (entry.NameLower.EndsWith(".ynv"))
|
||||||
|
{
|
||||||
|
UpdateStatus(string.Format(entry.Path));
|
||||||
|
YnvFile ynv = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ynv = RpfMan.GetFile<YnvFile>(entry);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
UpdateStatus("Error! " + ex.ToString());
|
||||||
|
errorfiles.Add(entry);
|
||||||
|
}
|
||||||
|
if (xmltest && (ynv != null) && (ynv.Nav != null))
|
||||||
|
{
|
||||||
|
var xml = YnvXml.GetXml(ynv);
|
||||||
|
if (xml != null)
|
||||||
|
{ }
|
||||||
|
var ynv2 = XmlYnv.GetYnv(xml);
|
||||||
|
if (ynv2 != null)
|
||||||
|
{ }
|
||||||
|
var ynv2b = ynv2.Save();
|
||||||
|
if (ynv2b != null)
|
||||||
|
{ }
|
||||||
|
var ynv3 = new YnvFile();
|
||||||
|
RpfFile.LoadResourceFile(ynv3, ynv2b, 2);
|
||||||
|
var xml3 = YnvXml.GetXml(ynv3);
|
||||||
|
if (xml.Length != xml3.Length)
|
||||||
|
{ }
|
||||||
|
var xmllines = xml.Split('\n');
|
||||||
|
var xml3lines = xml3.Split('\n');
|
||||||
|
if (xmllines.Length != xml3lines.Length)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
if (savetest && (ynv != null) && (ynv.Nav != null))
|
||||||
|
{
|
||||||
|
var fentry = entry as RpfFileEntry;
|
||||||
|
if (fentry == null)
|
||||||
|
{ continue; } //shouldn't happen
|
||||||
|
|
||||||
|
var bytes = ynv.Save();
|
||||||
|
|
||||||
|
string origlen = TextUtil.GetBytesReadable(fentry.FileSize);
|
||||||
|
string bytelen = TextUtil.GetBytesReadable(bytes.Length);
|
||||||
|
|
||||||
|
var ynv2 = new YnvFile();
|
||||||
|
RpfFile.LoadResourceFile(ynv2, bytes, 2);
|
||||||
|
|
||||||
|
if (ynv2.Nav == null)
|
||||||
|
{ continue; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//catch (Exception ex)
|
||||||
|
//{
|
||||||
|
// UpdateStatus("Error! " + ex.ToString());
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorfiles.Count > 0)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
public void TestYmaps()
|
public void TestYmaps()
|
||||||
{
|
{
|
||||||
foreach (RpfFile file in AllRpfs)
|
foreach (RpfFile file in AllRpfs)
|
||||||
|
@ -62,6 +62,11 @@ namespace CodeWalker.GameFiles
|
|||||||
YndFile ynd = RpfFile.GetFile<YndFile>(e, data);
|
YndFile ynd = RpfFile.GetFile<YndFile>(e, data);
|
||||||
return GetXml(ynd, out filename);
|
return GetXml(ynd, out filename);
|
||||||
}
|
}
|
||||||
|
else if (fnl.EndsWith(".ynv"))
|
||||||
|
{
|
||||||
|
YnvFile ynv = RpfFile.GetFile<YnvFile>(e, data);
|
||||||
|
return GetXml(ynv, out filename);
|
||||||
|
}
|
||||||
else if (fnl.EndsWith(".ycd"))
|
else if (fnl.EndsWith(".ycd"))
|
||||||
{
|
{
|
||||||
YcdFile ycd = RpfFile.GetFile<YcdFile>(e, data);
|
YcdFile ycd = RpfFile.GetFile<YcdFile>(e, data);
|
||||||
@ -172,6 +177,12 @@ namespace CodeWalker.GameFiles
|
|||||||
filename = fn + ".xml";
|
filename = fn + ".xml";
|
||||||
return YndXml.GetXml(ynd);
|
return YndXml.GetXml(ynd);
|
||||||
}
|
}
|
||||||
|
public static string GetXml(YnvFile ynv, out string filename)
|
||||||
|
{
|
||||||
|
var fn = (ynv?.RpfFileEntry?.Name) ?? "";
|
||||||
|
filename = fn + ".xml";
|
||||||
|
return YnvXml.GetXml(ynv);
|
||||||
|
}
|
||||||
public static string GetXml(YcdFile ycd, out string filename)
|
public static string GetXml(YcdFile ycd, out string filename)
|
||||||
{
|
{
|
||||||
var fn = (ycd?.RpfFileEntry?.Name) ?? "";
|
var fn = (ycd?.RpfFileEntry?.Name) ?? "";
|
||||||
@ -2127,15 +2138,16 @@ namespace CodeWalker.GameFiles
|
|||||||
CacheFile = 4,
|
CacheFile = 4,
|
||||||
AudioRel = 5,
|
AudioRel = 5,
|
||||||
Ynd = 6,
|
Ynd = 6,
|
||||||
Ycd = 7,
|
Ynv = 7,
|
||||||
Ybn = 8,
|
Ycd = 8,
|
||||||
Ytd = 9,
|
Ybn = 9,
|
||||||
Ydr = 10,
|
Ytd = 10,
|
||||||
Ydd = 11,
|
Ydr = 11,
|
||||||
Yft = 12,
|
Ydd = 12,
|
||||||
Ypt = 13,
|
Yft = 13,
|
||||||
Yld = 14,
|
Ypt = 14,
|
||||||
Awc = 15,
|
Yld = 15,
|
||||||
|
Awc = 16,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ using System.ComponentModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
{
|
{
|
||||||
@ -44,12 +45,12 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
public NavMeshFlags ContentFlags { get; set; }
|
public NavMeshFlags ContentFlags { get; set; }
|
||||||
public uint VersionUnk1 { get; set; } // 0x00010011
|
public uint VersionUnk1 { get; set; } = 0x00010011; // 0x00010011
|
||||||
public uint Unused_018h { get; set; } // 0x00000000
|
public uint Unused_018h { get; set; } // 0x00000000
|
||||||
public uint Unused_01Ch { get; set; } // 0x00000000
|
public uint Unused_01Ch { get; set; } // 0x00000000
|
||||||
public Matrix Transform { get; set; } //(1,0,0,NaN),(0,1,0,NaN),(0,0,1,NaN),(0,0,0,NaN)
|
public Matrix Transform { get; set; } //(1,0,0,NaN),(0,1,0,NaN),(0,0,1,NaN),(0,0,0,NaN)
|
||||||
public Vector3 AABBSize { get; set; }
|
public Vector3 AABBSize { get; set; }
|
||||||
public float AABBUnk { get; set; } // 0x7F800001 //NaN
|
public uint AABBUnk { get; set; } = 0x7F800001; // 0x7F800001 //NaN
|
||||||
public ulong VerticesPointer { get; set; }
|
public ulong VerticesPointer { get; set; }
|
||||||
public uint Unused_078h { get; set; } // 0x00000000
|
public uint Unused_078h { get; set; } // 0x00000000
|
||||||
public uint Unused_07Ch { get; set; } // 0x00000000
|
public uint Unused_07Ch { get; set; } // 0x00000000
|
||||||
@ -71,7 +72,7 @@ namespace CodeWalker.GameFiles
|
|||||||
public uint Unused_154h { get; set; } // 0x00000000
|
public uint Unused_154h { get; set; } // 0x00000000
|
||||||
public uint Unused_158h { get; set; } // 0x00000000
|
public uint Unused_158h { get; set; } // 0x00000000
|
||||||
public uint Unused_15Ch { get; set; } // 0x00000000
|
public uint Unused_15Ch { get; set; } // 0x00000000
|
||||||
public uint VersionUnk2 { get; set; } //2244687201 (0x85CB3561) for grid ynv's
|
public MetaHash VersionUnk2 { get; set; } //2244687201 (0x85CB3561) for grid ynv's
|
||||||
public uint Unused_164h { get; set; } // 0x00000000
|
public uint Unused_164h { get; set; } // 0x00000000
|
||||||
public uint Unused_168h { get; set; } // 0x00000000
|
public uint Unused_168h { get; set; } // 0x00000000
|
||||||
public uint Unused_16Ch { get; set; } // 0x00000000
|
public uint Unused_16Ch { get; set; } // 0x00000000
|
||||||
@ -92,6 +93,37 @@ namespace CodeWalker.GameFiles
|
|||||||
private ResourceSystemStructBlock<ushort> PortalLinksBlock = null;
|
private ResourceSystemStructBlock<ushort> PortalLinksBlock = null;
|
||||||
|
|
||||||
|
|
||||||
|
public Vector3 AABBMin
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (SectorTree != null) return SectorTree.AABBMin.XYZ();
|
||||||
|
return AABBSize * -0.5f;//shouldn't get here
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SectorTree != null)
|
||||||
|
{
|
||||||
|
SectorTree.AABBMin = new Vector4(value, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Vector3 AABBMax
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (SectorTree != null) return SectorTree.AABBMax.XYZ();
|
||||||
|
return AABBSize * 0.5f;//shouldn't get here
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SectorTree != null)
|
||||||
|
{
|
||||||
|
SectorTree.AABBMax = new Vector4(value, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||||
@ -104,7 +136,7 @@ namespace CodeWalker.GameFiles
|
|||||||
Unused_01Ch = reader.ReadUInt32();
|
Unused_01Ch = reader.ReadUInt32();
|
||||||
Transform = reader.ReadMatrix();
|
Transform = reader.ReadMatrix();
|
||||||
AABBSize = reader.ReadVector3();
|
AABBSize = reader.ReadVector3();
|
||||||
AABBUnk = reader.ReadSingle();
|
AABBUnk = reader.ReadUInt32();
|
||||||
VerticesPointer = reader.ReadUInt64();
|
VerticesPointer = reader.ReadUInt64();
|
||||||
Unused_078h = reader.ReadUInt32();
|
Unused_078h = reader.ReadUInt32();
|
||||||
Unused_07Ch = reader.ReadUInt32();
|
Unused_07Ch = reader.ReadUInt32();
|
||||||
@ -142,6 +174,43 @@ namespace CodeWalker.GameFiles
|
|||||||
PortalLinks = reader.ReadUshortsAt(PortalLinksPointer, PortalLinksCount);
|
PortalLinks = reader.ReadUshortsAt(PortalLinksPointer, PortalLinksCount);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////testing!
|
||||||
|
//if (VersionUnk1 != 0x00010011)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_018h != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_01Ch != 0)
|
||||||
|
//{ }
|
||||||
|
//if (AABBUnk != 0x7F800001)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_078h != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_07Ch != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_154h != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_158h != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_15Ch != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_164h != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_168h != 0)
|
||||||
|
//{ }
|
||||||
|
//if (Unused_16Ch != 0)
|
||||||
|
//{ }
|
||||||
|
//switch (VersionUnk2.Hash)
|
||||||
|
//{
|
||||||
|
// case 0: //vehicle
|
||||||
|
// break;
|
||||||
|
// case 0x85CB3561: //grid
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
//}
|
||||||
|
//UpdateCounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
public override void Write(ResourceDataWriter writer, params object[] parameters)
|
||||||
@ -157,38 +226,7 @@ namespace CodeWalker.GameFiles
|
|||||||
PortalLinksPointer = (ulong)(PortalLinksBlock?.FilePosition ?? 0);
|
PortalLinksPointer = (ulong)(PortalLinksBlock?.FilePosition ?? 0);
|
||||||
|
|
||||||
|
|
||||||
|
UpdateCounts();
|
||||||
//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((uint)ContentFlags);
|
||||||
@ -225,13 +263,6 @@ namespace CodeWalker.GameFiles
|
|||||||
writer.Write(Unused_16Ch);
|
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()
|
public override IResourceBlock[] GetReferences()
|
||||||
{
|
{
|
||||||
var list = new List<IResourceBlock>(base.GetReferences());
|
var list = new List<IResourceBlock>(base.GetReferences());
|
||||||
@ -261,6 +292,54 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdateCounts()
|
||||||
|
{
|
||||||
|
EdgesIndicesCount = Indices?.ItemCount ?? 0;
|
||||||
|
VerticesCount = Vertices?.ItemCount ?? 0;
|
||||||
|
PolysCount = Polys?.ItemCount ?? 0;
|
||||||
|
PortalsCount = (uint)(Portals?.Length ?? 0);
|
||||||
|
PortalLinksCount = (uint)(PortalLinks?.Length ?? 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint totbytes = 0;
|
||||||
|
uint pointcount = 0;
|
||||||
|
var treestack = new Stack<NavMeshSector>();
|
||||||
|
if (SectorTree != null)
|
||||||
|
{
|
||||||
|
treestack.Push(SectorTree);
|
||||||
|
}
|
||||||
|
while (treestack.Count > 0)
|
||||||
|
{
|
||||||
|
var sector = treestack.Pop();
|
||||||
|
totbytes += sector.ByteCount;
|
||||||
|
pointcount += sector.PointCount;
|
||||||
|
if (sector.SubTree1 != null) treestack.Push(sector.SubTree1);
|
||||||
|
if (sector.SubTree2 != null) treestack.Push(sector.SubTree2);
|
||||||
|
if (sector.SubTree3 != null) treestack.Push(sector.SubTree3);
|
||||||
|
if (sector.SubTree4 != null) treestack.Push(sector.SubTree4);
|
||||||
|
}
|
||||||
|
|
||||||
|
totbytes += Vertices?.ByteCount ?? 0;
|
||||||
|
totbytes += Indices?.ByteCount ?? 0;
|
||||||
|
totbytes += Edges?.ByteCount ?? 0;
|
||||||
|
totbytes += Polys?.ByteCount ?? 0;
|
||||||
|
totbytes += PortalsCount * 28;
|
||||||
|
if ((TotalBytes != totbytes) && (TotalBytes != 0))
|
||||||
|
{ }
|
||||||
|
TotalBytes = totbytes;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ((PointsCount != pointcount) && (PointsCount != 0))
|
||||||
|
{ }
|
||||||
|
PointsCount = pointcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void SetDefaults(bool vehicle)
|
public void SetDefaults(bool vehicle)
|
||||||
{
|
{
|
||||||
VersionUnk1 = 0x00010011;
|
VersionUnk1 = 0x00010011;
|
||||||
@ -449,6 +528,16 @@ namespace CodeWalker.GameFiles
|
|||||||
private ResourceSystemStructBlock<uint> ListOffsetsBlock = null;
|
private ResourceSystemStructBlock<uint> ListOffsetsBlock = null;
|
||||||
public int ItemSize { get { return System.Runtime.InteropServices.Marshal.SizeOf<T>(); } }
|
public int ItemSize { get { return System.Runtime.InteropServices.Marshal.SizeOf<T>(); } }
|
||||||
|
|
||||||
|
public uint ByteCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ItemCount * (uint)ItemSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||||
{
|
{
|
||||||
VFT = reader.ReadUInt32();
|
VFT = reader.ReadUInt32();
|
||||||
@ -635,9 +724,9 @@ namespace CodeWalker.GameFiles
|
|||||||
public void FromVector3(Vector3 v)
|
public void FromVector3(Vector3 v)
|
||||||
{
|
{
|
||||||
const float usmax = ushort.MaxValue;
|
const float usmax = ushort.MaxValue;
|
||||||
X = (ushort)(v.X * usmax);
|
X = (ushort)Math.Round(v.X * usmax);
|
||||||
Y = (ushort)(v.Y * usmax);
|
Y = (ushort)Math.Round(v.Y * usmax);
|
||||||
Z = (ushort)(v.Z * usmax);
|
Z = (ushort)Math.Round(v.Z * usmax);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NavMeshVertex Create(Vector3 v)
|
public static NavMeshVertex Create(Vector3 v)
|
||||||
@ -665,12 +754,12 @@ namespace CodeWalker.GameFiles
|
|||||||
public Vector3 Min
|
public Vector3 Min
|
||||||
{
|
{
|
||||||
get { return new Vector3(MinX / 4.0f, MinY / 4.0f, MinZ / 4.0f); }
|
get { return new Vector3(MinX / 4.0f, MinY / 4.0f, MinZ / 4.0f); }
|
||||||
set { var v = value * 4.0f; MinX = (short)v.X; MinY = (short)v.Y; MinZ = (short)v.Z; }
|
set { var v = value * 4.0f; MinX = (short)Math.Floor(v.X); MinY = (short)Math.Floor(v.Y); MinZ = (short)Math.Floor(v.Z); }
|
||||||
}
|
}
|
||||||
public Vector3 Max
|
public Vector3 Max
|
||||||
{
|
{
|
||||||
get { return new Vector3(MaxX / 4.0f, MaxY / 4.0f, MaxZ / 4.0f); }
|
get { return new Vector3(MaxX / 4.0f, MaxY / 4.0f, MaxZ / 4.0f); }
|
||||||
set { var v = value * 4.0f; MaxX = (short)v.X; MaxY = (short)v.Y; MaxZ = (short)v.Z; }
|
set { var v = value * 4.0f; MaxX = (short)Math.Ceiling(v.X); MaxY = (short)Math.Ceiling(v.Y); MaxZ = (short)Math.Ceiling(v.Z); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -726,17 +815,17 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPoly
|
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPoly
|
||||||
{
|
{
|
||||||
public ushort Unknown_00h { get; set; }
|
public ushort PolyFlags0 { get; set; }
|
||||||
public ushort IndexFlags { get; set; }
|
public ushort IndexFlags { get; set; }
|
||||||
public ushort IndexID { get; set; }
|
public ushort IndexID { get; set; }
|
||||||
public ushort AreaID { get; set; }
|
public ushort AreaID { get; set; } //always current ynv's AreaID
|
||||||
public uint Unused_08h { get; set; } // 0x00000000
|
public uint Unused_08h { get; set; } // 0x00000000
|
||||||
public uint Unused_0Ch { get; set; } // 0x00000000
|
public uint Unused_0Ch { get; set; } // 0x00000000
|
||||||
public uint Unused_10h { get; set; } // 0x00000000
|
public uint Unused_10h { get; set; } // 0x00000000
|
||||||
public uint Unused_14h { get; set; } // 0x00000000
|
public uint Unused_14h { get; set; } // 0x00000000
|
||||||
public NavMeshAABB CellAABB { get; set; }
|
public NavMeshAABB CellAABB { get; set; }
|
||||||
public FlagsUint Unknown_24h { get; set; }
|
public uint PolyFlags1 { get; set; }
|
||||||
public FlagsUint Unknown_28h { get; set; }
|
public uint PolyFlags2 { get; set; }
|
||||||
public uint PartFlags { get; set; }
|
public uint PartFlags { get; set; }
|
||||||
|
|
||||||
|
|
||||||
@ -749,22 +838,29 @@ namespace CodeWalker.GameFiles
|
|||||||
public uint PortalLinkID { get { return ((PartFlags >> 15) & 0x1FFFF); } set { PartFlags = ((PartFlags & 0x7FFF) | ((value & 0x1FFFF) << 15)); } }
|
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); } }
|
public byte UnkX { get { return (byte)((PolyFlags2 >> 0) & 0xFF); } set { PolyFlags2 = (PolyFlags2 & 0xFFFFFF00) | ((value & 0xFFu)<<0); } }
|
||||||
public byte Unknown_28h_8a { get { return (byte)((Unknown_28h.Value >> 0) & 0xFF); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFFFF00) | ((value & 0xFFu)<<0); } }
|
public byte UnkY { get { return (byte)((PolyFlags2 >> 8) & 0xFF); } set { PolyFlags2 = (PolyFlags2 & 0xFFFF00FF) | ((value & 0xFFu)<<8); } }
|
||||||
public byte Unknown_28h_8b { get { return (byte)((Unknown_28h.Value >> 8) & 0xFF); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFF00FF) | ((value & 0xFFu)<<8); } }
|
|
||||||
|
public byte Flags1 { get { return (byte)(PolyFlags0 & 0xFF); } set { PolyFlags0 = (ushort)((PolyFlags0 & 0xFF00) | (value & 0xFF)); } }
|
||||||
|
public byte Flags2 { get { return (byte)((PolyFlags1 >> 0) & 0xFF); } set { PolyFlags1 = ((PolyFlags1 & 0xFFFFFF00u) | ((value & 0xFFu) << 0)); } }
|
||||||
|
public byte Flags3 { get { return (byte)((PolyFlags1 >> 9) & 0xFF); } set { PolyFlags1 = ((PolyFlags1 & 0xFFFE01FFu) | ((value & 0xFFu) << 9)); } }
|
||||||
|
public byte Flags4 { get { return (byte)((PolyFlags2 >> 16) & 0xFF); } set { PolyFlags2 = ((PolyFlags2 & 0xFF00FFFFu) | ((value & 0xFFu) << 16)); } }
|
||||||
|
|
||||||
|
//public uint UnkFlags0 { get { return (uint)((PolyFlags0 >> 8) & 0xFF); } } //always 0
|
||||||
|
//public uint UnkFlags1 { get { return (uint)((PolyFlags1 >> 17) & 0xFFFF); } } //always 0
|
||||||
|
//public uint UnkFlags2 { get { return (uint)((PolyFlags2 >> 24) & 0xFF); } } //always 0
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
//Unknown_28h.Bin + ", (" + Unknown_28h_8a.ToString() + ", " + Unknown_28h_8b.ToString() + "), " +
|
PolyFlags0.ToString() + ", " +
|
||||||
Unknown_00h.ToString() + ", " +
|
|
||||||
//IndexFlags.ToString() + ", " +
|
//IndexFlags.ToString() + ", " +
|
||||||
IndexCount.ToString() + ", " + //IndexUnk.ToString() + ", " +
|
IndexCount.ToString() + ", " + //IndexUnk.ToString() + ", " +
|
||||||
IndexID.ToString() + ", " + AreaID.ToString() + ", " +
|
IndexID.ToString() + ", " + AreaID.ToString() + ", " +
|
||||||
CellAABB.ToString() + ", " +
|
CellAABB.ToString() + ", " +
|
||||||
Unknown_24h.Hex + ", " +
|
//PolyFlags1.ToString() + ", " +
|
||||||
Unknown_28h.Hex + ", " +
|
//PolyFlags2.ToString() + ", " +
|
||||||
//PartFlags.ToString() + ", " + //PartUnk1.ToString() + ", " +
|
//PartFlags.ToString() + ", " + //PartUnk1.ToString() + ", " +
|
||||||
PartID.ToString() + ", " +
|
PartID.ToString() + ", " +
|
||||||
PortalLinkCount.ToString() + ", " +
|
PortalLinkCount.ToString() + ", " +
|
||||||
@ -799,6 +895,29 @@ namespace CodeWalker.GameFiles
|
|||||||
public NavMeshSector SubTree3 { get; set; }
|
public NavMeshSector SubTree3 { get; set; }
|
||||||
public NavMeshSector SubTree4 { get; set; }
|
public NavMeshSector SubTree4 { get; set; }
|
||||||
|
|
||||||
|
public uint ByteCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
uint totbytes = (uint)BlockLength;
|
||||||
|
if (Data != null)
|
||||||
|
{
|
||||||
|
totbytes += ((uint)Data.BlockLength);
|
||||||
|
totbytes += ((uint)Data.PolyIDsCount * 2);
|
||||||
|
totbytes += ((uint)Data.PointsCount * 8);
|
||||||
|
}
|
||||||
|
return totbytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public uint PointCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Data == null) return 0;
|
||||||
|
return Data.PointsCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Read(ResourceDataReader reader, params object[] parameters)
|
public override void Read(ResourceDataReader reader, params object[] parameters)
|
||||||
{
|
{
|
||||||
AABBMin = reader.ReadVector4();
|
AABBMin = reader.ReadVector4();
|
||||||
@ -951,7 +1070,7 @@ namespace CodeWalker.GameFiles
|
|||||||
public ushort Y { get; set; }
|
public ushort Y { get; set; }
|
||||||
public ushort Z { get; set; }
|
public ushort Z { get; set; }
|
||||||
public byte Angle { get; set; }
|
public byte Angle { get; set; }
|
||||||
public byte Type { get; set; }
|
public byte Type { get; set; }//0,1,2,3,4,5,128,171,254
|
||||||
|
|
||||||
|
|
||||||
public Vector3 Position
|
public Vector3 Position
|
||||||
@ -964,9 +1083,9 @@ namespace CodeWalker.GameFiles
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
const float usmax = ushort.MaxValue;
|
const float usmax = ushort.MaxValue;
|
||||||
X = (ushort)(value.X * usmax);
|
X = (ushort)Math.Round(value.X * usmax);
|
||||||
Y = (ushort)(value.Y * usmax);
|
Y = (ushort)Math.Round(value.Y * usmax);
|
||||||
Z = (ushort)(value.Z * usmax);
|
Z = (ushort)Math.Round(value.Z * usmax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -982,20 +1101,20 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPortal
|
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshPortal
|
||||||
{
|
{
|
||||||
public byte Type { get; set; }
|
public byte Type { get; set; }//1,2,3
|
||||||
public byte Angle { get; set; }
|
public byte Angle { get; set; }
|
||||||
public ushort FlagsUnk { get; set; }
|
public ushort FlagsUnk { get; set; }//always 0
|
||||||
public NavMeshVertex PositionFrom { get; set; }
|
public NavMeshVertex PositionFrom { get; set; }
|
||||||
public NavMeshVertex PositionTo { get; set; }
|
public NavMeshVertex PositionTo { get; set; }
|
||||||
public ushort PolyIDFrom1 { get; set; }
|
public ushort PolyIDFrom1 { get; set; }
|
||||||
public ushort PolyIDFrom2 { get; set; }
|
public ushort PolyIDFrom2 { get; set; } //always same as PolyIDFrom1
|
||||||
public ushort PolyIDTo1 { get; set; }
|
public ushort PolyIDTo1 { get; set; }
|
||||||
public ushort PolyIDTo2 { get; set; }
|
public ushort PolyIDTo2 { get; set; } //always same as PolyIDTo1
|
||||||
public uint AreaFlags { get; set; }
|
public uint AreaFlags { get; set; }
|
||||||
|
|
||||||
public ushort AreaIDFrom { get { return (ushort)(AreaFlags & 0x3FFF); } set { AreaFlags = (AreaFlags & 0xFFFFC000) | (value & 0x3FFFu); } }
|
public ushort AreaIDFrom { get { return (ushort)(AreaFlags & 0x3FFF); } set { AreaFlags = (AreaFlags & 0xFFFFC000) | (value & 0x3FFFu); } }//always Ynv.AreaID
|
||||||
public ushort AreaIDTo { get { return (ushort)((AreaFlags >> 14) & 0x3FFF); } set { AreaFlags = (AreaFlags & 0xF0003FFF) | ((value & 0x3FFFu) << 14); } }
|
public ushort AreaIDTo { get { return (ushort)((AreaFlags >> 14) & 0x3FFF); } set { AreaFlags = (AreaFlags & 0xF0003FFF) | ((value & 0x3FFFu) << 14); } }//always Ynv.AreaID
|
||||||
public byte AreaUnk { get { return (byte)((AreaFlags >> 28) & 0xF); } set { AreaFlags = (AreaFlags & 0x0FFFFFFF) | ((value & 0xFu) << 28); } }
|
public byte AreaUnk { get { return (byte)((AreaFlags >> 28) & 0xF); } set { AreaFlags = (AreaFlags & 0x0FFFFFFF) | ((value & 0xFu) << 28); } }//always 0
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
@ -1013,7 +1132,7 @@ namespace CodeWalker.GameFiles
|
|||||||
[Flags] public enum NavMeshFlags : uint
|
[Flags] public enum NavMeshFlags : uint
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Vertices = 1,
|
Polygons = 1,
|
||||||
Portals = 2,
|
Portals = 2,
|
||||||
Vehicle = 4,
|
Vehicle = 4,
|
||||||
Unknown8 = 8,
|
Unknown8 = 8,
|
||||||
|
@ -274,7 +274,7 @@ namespace CodeWalker
|
|||||||
InitFileType(".pso", "Metadata (PSO)", 6, FileTypeAction.ViewJPso, true);
|
InitFileType(".pso", "Metadata (PSO)", 6, FileTypeAction.ViewJPso, true);
|
||||||
InitFileType(".gfx", "Scaleform Flash", 7);
|
InitFileType(".gfx", "Scaleform Flash", 7);
|
||||||
InitFileType(".ynd", "Path Nodes", 8, FileTypeAction.ViewYnd, true);
|
InitFileType(".ynd", "Path Nodes", 8, FileTypeAction.ViewYnd, true);
|
||||||
InitFileType(".ynv", "Nav Mesh", 9, FileTypeAction.ViewModel);
|
InitFileType(".ynv", "Nav Mesh", 9, FileTypeAction.ViewModel, true);
|
||||||
InitFileType(".yvr", "Vehicle Record", 9, FileTypeAction.ViewYvr);
|
InitFileType(".yvr", "Vehicle Record", 9, FileTypeAction.ViewYvr);
|
||||||
InitFileType(".ywr", "Waypoint Record", 9, FileTypeAction.ViewYwr);
|
InitFileType(".ywr", "Waypoint Record", 9, FileTypeAction.ViewYwr);
|
||||||
InitFileType(".fxc", "Compiled Shaders", 9, FileTypeAction.ViewFxc);
|
InitFileType(".fxc", "Compiled Shaders", 9, FileTypeAction.ViewFxc);
|
||||||
@ -2603,6 +2603,10 @@ namespace CodeWalker
|
|||||||
{
|
{
|
||||||
mformat = MetaFormat.Ynd;
|
mformat = MetaFormat.Ynd;
|
||||||
}
|
}
|
||||||
|
if (fnamel.EndsWith(".ynv.xml"))
|
||||||
|
{
|
||||||
|
mformat = MetaFormat.Ynv;
|
||||||
|
}
|
||||||
if (fnamel.EndsWith(".ycd.xml"))
|
if (fnamel.EndsWith(".ycd.xml"))
|
||||||
{
|
{
|
||||||
mformat = MetaFormat.Ycd;
|
mformat = MetaFormat.Ycd;
|
||||||
@ -2711,6 +2715,17 @@ namespace CodeWalker
|
|||||||
data = ynd.Save();
|
data = ynd.Save();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MetaFormat.Ynv:
|
||||||
|
{
|
||||||
|
var ynv = XmlYnv.GetYnv(doc);
|
||||||
|
if (ynv.Nav == null)
|
||||||
|
{
|
||||||
|
MessageBox.Show(fname + ": Schema not supported.", "Cannot import YNV XML");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
data = ynv.Save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MetaFormat.Ycd:
|
case MetaFormat.Ycd:
|
||||||
{
|
{
|
||||||
var ycd = XmlYcd.GetYcd(doc);
|
var ycd = XmlYcd.GetYcd(doc);
|
||||||
|
24
CodeWalker/Project/Panels/EditYnvPanel.Designer.cs
generated
24
CodeWalker/Project/Panels/EditYnvPanel.Designer.cs
generated
@ -47,7 +47,7 @@
|
|||||||
this.YnvFlagsUnknownCheckBox = new System.Windows.Forms.CheckBox();
|
this.YnvFlagsUnknownCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.YnvFlagsVehicleCheckBox = new System.Windows.Forms.CheckBox();
|
this.YnvFlagsVehicleCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.YnvFlagsPortalsCheckBox = new System.Windows.Forms.CheckBox();
|
this.YnvFlagsPortalsCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.YnvFlagsVerticesCheckBox = new System.Windows.Forms.CheckBox();
|
this.YnvFlagsPolygonsCheckBox = new System.Windows.Forms.CheckBox();
|
||||||
this.YnvVersionUnkHashTextBox = new System.Windows.Forms.TextBox();
|
this.YnvVersionUnkHashTextBox = new System.Windows.Forms.TextBox();
|
||||||
this.label1 = new System.Windows.Forms.Label();
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
this.label2 = new System.Windows.Forms.Label();
|
this.label2 = new System.Windows.Forms.Label();
|
||||||
@ -200,7 +200,7 @@
|
|||||||
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsUnknownCheckBox);
|
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsUnknownCheckBox);
|
||||||
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsVehicleCheckBox);
|
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsVehicleCheckBox);
|
||||||
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsPortalsCheckBox);
|
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsPortalsCheckBox);
|
||||||
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsVerticesCheckBox);
|
this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsPolygonsCheckBox);
|
||||||
this.YnvFlagsGroupBox.Location = new System.Drawing.Point(247, 48);
|
this.YnvFlagsGroupBox.Location = new System.Drawing.Point(247, 48);
|
||||||
this.YnvFlagsGroupBox.Name = "YnvFlagsGroupBox";
|
this.YnvFlagsGroupBox.Name = "YnvFlagsGroupBox";
|
||||||
this.YnvFlagsGroupBox.Size = new System.Drawing.Size(103, 115);
|
this.YnvFlagsGroupBox.Size = new System.Drawing.Size(103, 115);
|
||||||
@ -241,16 +241,16 @@
|
|||||||
this.YnvFlagsPortalsCheckBox.UseVisualStyleBackColor = true;
|
this.YnvFlagsPortalsCheckBox.UseVisualStyleBackColor = true;
|
||||||
this.YnvFlagsPortalsCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsPortalsCheckBox_CheckedChanged);
|
this.YnvFlagsPortalsCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsPortalsCheckBox_CheckedChanged);
|
||||||
//
|
//
|
||||||
// YnvFlagsVerticesCheckBox
|
// YnvFlagsPolygonsCheckBox
|
||||||
//
|
//
|
||||||
this.YnvFlagsVerticesCheckBox.AutoSize = true;
|
this.YnvFlagsPolygonsCheckBox.AutoSize = true;
|
||||||
this.YnvFlagsVerticesCheckBox.Location = new System.Drawing.Point(12, 19);
|
this.YnvFlagsPolygonsCheckBox.Location = new System.Drawing.Point(12, 19);
|
||||||
this.YnvFlagsVerticesCheckBox.Name = "YnvFlagsVerticesCheckBox";
|
this.YnvFlagsPolygonsCheckBox.Name = "YnvFlagsPolygonsCheckBox";
|
||||||
this.YnvFlagsVerticesCheckBox.Size = new System.Drawing.Size(64, 17);
|
this.YnvFlagsPolygonsCheckBox.Size = new System.Drawing.Size(69, 17);
|
||||||
this.YnvFlagsVerticesCheckBox.TabIndex = 0;
|
this.YnvFlagsPolygonsCheckBox.TabIndex = 0;
|
||||||
this.YnvFlagsVerticesCheckBox.Text = "Vertices";
|
this.YnvFlagsPolygonsCheckBox.Text = "Polygons";
|
||||||
this.YnvFlagsVerticesCheckBox.UseVisualStyleBackColor = true;
|
this.YnvFlagsPolygonsCheckBox.UseVisualStyleBackColor = true;
|
||||||
this.YnvFlagsVerticesCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsVerticesCheckBox_CheckedChanged);
|
this.YnvFlagsPolygonsCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsVerticesCheckBox_CheckedChanged);
|
||||||
//
|
//
|
||||||
// YnvVersionUnkHashTextBox
|
// YnvVersionUnkHashTextBox
|
||||||
//
|
//
|
||||||
@ -402,7 +402,7 @@
|
|||||||
private System.Windows.Forms.CheckBox YnvFlagsUnknownCheckBox;
|
private System.Windows.Forms.CheckBox YnvFlagsUnknownCheckBox;
|
||||||
private System.Windows.Forms.CheckBox YnvFlagsVehicleCheckBox;
|
private System.Windows.Forms.CheckBox YnvFlagsVehicleCheckBox;
|
||||||
private System.Windows.Forms.CheckBox YnvFlagsPortalsCheckBox;
|
private System.Windows.Forms.CheckBox YnvFlagsPortalsCheckBox;
|
||||||
private System.Windows.Forms.CheckBox YnvFlagsVerticesCheckBox;
|
private System.Windows.Forms.CheckBox YnvFlagsPolygonsCheckBox;
|
||||||
private System.Windows.Forms.TextBox YnvVersionUnkHashTextBox;
|
private System.Windows.Forms.TextBox YnvVersionUnkHashTextBox;
|
||||||
private System.Windows.Forms.Label label1;
|
private System.Windows.Forms.Label label1;
|
||||||
private System.Windows.Forms.Label label2;
|
private System.Windows.Forms.Label label2;
|
||||||
|
@ -87,7 +87,7 @@ namespace CodeWalker.Project.Panels
|
|||||||
YnvAreaIDYUpDown.Value = Ynv.CellY;
|
YnvAreaIDYUpDown.Value = Ynv.CellY;
|
||||||
YnvAreaIDInfoLabel.Text = "ID: " + Ynv.AreaID.ToString();
|
YnvAreaIDInfoLabel.Text = "ID: " + Ynv.AreaID.ToString();
|
||||||
YnvAABBSizeTextBox.Text = FloatUtil.GetVector3String(nv.AABBSize);
|
YnvAABBSizeTextBox.Text = FloatUtil.GetVector3String(nv.AABBSize);
|
||||||
YnvFlagsVerticesCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Vertices);
|
YnvFlagsPolygonsCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Polygons);
|
||||||
YnvFlagsPortalsCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Portals);
|
YnvFlagsPortalsCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Portals);
|
||||||
YnvFlagsVehicleCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Vehicle);
|
YnvFlagsVehicleCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Vehicle);
|
||||||
YnvFlagsUnknownCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Unknown8);
|
YnvFlagsUnknownCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Unknown8);
|
||||||
@ -97,7 +97,7 @@ namespace CodeWalker.Project.Panels
|
|||||||
YnvPortalLinkCountLabel.Text = "Portal link count: " + nv.PortalLinksCount.ToString();
|
YnvPortalLinkCountLabel.Text = "Portal link count: " + nv.PortalLinksCount.ToString();
|
||||||
YnvPointCountLabel.Text = "Point count: " + nv.PointsCount.ToString();
|
YnvPointCountLabel.Text = "Point count: " + nv.PointsCount.ToString();
|
||||||
YnvByteCountLabel.Text = "Byte count: " + nv.TotalBytes.ToString();
|
YnvByteCountLabel.Text = "Byte count: " + nv.TotalBytes.ToString();
|
||||||
YnvVersionUnkHashTextBox.Text = nv.VersionUnk2.ToString();
|
YnvVersionUnkHashTextBox.Text = nv.VersionUnk2.Hash.ToString();
|
||||||
YnvAdjAreaIDsTextBox.Text = GetAdjAreaIDsString(nv.AdjAreaIDs.Values);
|
YnvAdjAreaIDsTextBox.Text = GetAdjAreaIDsString(nv.AdjAreaIDs.Values);
|
||||||
populatingui = false;
|
populatingui = false;
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ namespace CodeWalker.Project.Panels
|
|||||||
{
|
{
|
||||||
if (populatingui) return;
|
if (populatingui) return;
|
||||||
if (Ynv?.Nav == null) return;
|
if (Ynv?.Nav == null) return;
|
||||||
var verts = YnvFlagsVerticesCheckBox.Checked ? NavMeshFlags.Vertices : NavMeshFlags.None;
|
var verts = YnvFlagsPolygonsCheckBox.Checked ? NavMeshFlags.Polygons : NavMeshFlags.None;
|
||||||
var ports = YnvFlagsPortalsCheckBox.Checked ? NavMeshFlags.Portals : NavMeshFlags.None;
|
var ports = YnvFlagsPortalsCheckBox.Checked ? NavMeshFlags.Portals : NavMeshFlags.None;
|
||||||
var vehcs = YnvFlagsVehicleCheckBox.Checked ? NavMeshFlags.Vehicle : NavMeshFlags.None;
|
var vehcs = YnvFlagsVehicleCheckBox.Checked ? NavMeshFlags.Vehicle : NavMeshFlags.None;
|
||||||
var unk8s = YnvFlagsUnknownCheckBox.Checked ? NavMeshFlags.Unknown8 : NavMeshFlags.None;
|
var unk8s = YnvFlagsUnknownCheckBox.Checked ? NavMeshFlags.Unknown8 : NavMeshFlags.None;
|
||||||
|
Loading…
Reference in New Issue
Block a user