This commit is contained in:
dexy 2018-12-05 11:47:28 +11:00
commit 9f701ee44b
70 changed files with 9913 additions and 20853 deletions

View File

@ -48,6 +48,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="GameFiles\FileTypes\AwcFile.cs" /> <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\CacheDatFile.cs" />
<Compile Include="GameFiles\FileTypes\CutFile.cs" /> <Compile Include="GameFiles\FileTypes\CutFile.cs" />
<Compile Include="GameFiles\FileTypes\DlcContentFile.cs" /> <Compile Include="GameFiles\FileTypes\DlcContentFile.cs" />
@ -112,6 +114,7 @@
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
</Compile> </Compile>
<Compile Include="Utils\BoundingBoxes.cs" />
<Compile Include="Utils\Cache.cs" /> <Compile Include="Utils\Cache.cs" />
<Compile Include="Utils\Matrices.cs" /> <Compile Include="Utils\Matrices.cs" />
<Compile Include="Utils\Quaternions.cs" /> <Compile Include="Utils\Quaternions.cs" />

View File

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

View File

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

View File

@ -7,6 +7,8 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using CodeWalker.Core.Utils;
using CodeWalker.World;
namespace CodeWalker.GameFiles namespace CodeWalker.GameFiles
{ {
@ -925,6 +927,7 @@ namespace CodeWalker.GameFiles
GrassInstanceBatches = batches.ToArray(); GrassInstanceBatches = batches.ToArray();
HasChanged = true; HasChanged = true;
UpdateGrassPhysDict(true);
} }
public bool RemoveGrassBatch(YmapGrassInstanceBatch batch) public bool RemoveGrassBatch(YmapGrassInstanceBatch batch)
@ -949,6 +952,10 @@ namespace CodeWalker.GameFiles
} }
} }
if (batches.Count <= 0)
{
UpdateGrassPhysDict(false);
}
GrassInstanceBatches = batches.ToArray(); GrassInstanceBatches = batches.ToArray();
@ -1137,6 +1144,62 @@ namespace CodeWalker.GameFiles
} }
private void UpdateGrassPhysDict(bool add)
{
var physDict = physicsDictionaries?.ToList() ?? new List<MetaHash>();
var vproc1 = JenkHash.GenHash("v_proc1");
var vproc2 = JenkHash.GenHash("v_proc2"); // I think you need vproc2 as well.
var change = false;
if (!physDict.Contains(vproc1))
{
change = true;
if (add) physDict.Add(vproc1);
else physDict.Remove(vproc1);
}
if (!physDict.Contains(vproc2))
{
change = true;
if (add) physDict.Add(vproc2);
else physDict.Remove(vproc2);
}
if (change) physicsDictionaries = physDict.ToArray();
}
public void InitYmapEntityArchetypes(GameFileCache gfc)
{
if (AllEntities != null)
{
for (int i = 0; i < AllEntities.Length; i++)
{
var ent = AllEntities[i];
var arch = gfc.GetArchetype(ent.CEntityDef.archetypeName);
ent.SetArchetype(arch);
if (ent.IsMlo) ent.MloInstance.InitYmapEntityArchetypes(gfc);
}
}
if (GrassInstanceBatches != null)
{
for (int i = 0; i < GrassInstanceBatches.Length; i++)
{
var batch = GrassInstanceBatches[i];
batch.Archetype = gfc.GetArchetype(batch.Batch.archetypeName);
}
}
if (TimeCycleModifiers != null)
{
for (int i = 0; i < TimeCycleModifiers.Length; i++)
{
var tcm = TimeCycleModifiers[i];
World.TimecycleMod wtcm;
if (gfc.TimeCycleModsDict.TryGetValue(tcm.CTimeCycleModifier.name.Hash, out wtcm))
{
tcm.TimeCycleModData = wtcm;
}
}
}
}
private static uint SetBit(uint value, int bit) private static uint SetBit(uint value, int bit)
{ {
@ -1166,7 +1229,7 @@ namespace CodeWalker.GameFiles
public bool IsMlo { get; set; } public bool IsMlo { get; set; }
public MloInstanceData MloInstance { get; set; } public MloInstanceData MloInstance { get; set; }
public YmapEntityDef MloParent { get; set; } public YmapEntityDef MloParent { get; set; }
public MCMloEntitySet MloEntitySet { get; set; } public MloInstanceEntitySet MloEntitySet { get; set; }
public Vector3 MloRefPosition { get; set; } public Vector3 MloRefPosition { get; set; }
public Quaternion MloRefOrientation { get; set; } public Quaternion MloRefOrientation { get; set; }
public MetaWrapper[] Extensions { get; set; } public MetaWrapper[] Extensions { get; set; }
@ -1269,56 +1332,57 @@ namespace CodeWalker.GameFiles
{ {
MloInstance = new MloInstanceData(); MloInstance = new MloInstanceData();
} }
MloInstance.CreateYmapEntities(this, mloa); if (mloa != null)
{
if (!IsMlo)
{
IsMlo = true;
MloInstance._Instance = new CMloInstanceDef { CEntityDef = _CEntityDef };
List<YmapEntityDef> mloEntities = Ymap.MloEntities?.ToList() ?? new List<YmapEntityDef>();
mloEntities.Add(this);
Ymap.MloEntities = mloEntities.ToArray();
}
MloInstance.CreateYmapEntities(this, mloa);
}
if (BSRadius == 0.0f) if (BSRadius == 0.0f)
{ {
BSRadius = CEntityDef.lodDist;//need something so it doesn't get culled... BSRadius = CEntityDef.lodDist;//need something so it doesn't get culled...
} }
} }
else if (IsMlo) // archetype is no longer an mlo
{
IsMlo = false;
MloInstance = null;
if (Ymap.MloEntities != null)
{
List<YmapEntityDef> mloEntities = Ymap.MloEntities.ToList();
if (mloEntities.Remove(this))
{
Ymap.MloEntities = mloEntities.ToArray();
}
}
}
} }
} }
public void SetPosition(Vector3 pos) public void SetPosition(Vector3 pos)
{ {
Position = pos;
if (MloParent != null) if (MloParent != null)
{ {
//TODO: SetPosition for interior entities! _CEntityDef.position = Quaternion.Normalize(Quaternion.Invert(MloParent.Orientation)).Multiply(pos - MloParent.Position);
Position = pos; MloRefPosition = _CEntityDef.position;
var inst = MloParent.MloInstance; UpdateBB();
if (inst != null) UpdateMloArchetype();
{
//transform world position into mlo space
//MloRefPosition = ...
//MloRefOrientation = ...
}
} }
else else
{ {
Position = pos;
_CEntityDef.position = pos; _CEntityDef.position = pos;
UpdateBB();
if (Archetype != null)
{
BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale;
}
if ((Archetype != null) && (Orientation == Quaternion.Identity))
{
BBMin = (Archetype.BBMin * Scale) + Position;
BBMax = (Archetype.BBMax * Scale) + Position;
}
else
{
BBMin = Position - (BSRadius);
BBMax = Position + (BSRadius);
////not ideal: should transform all 8 corners!
}
UpdateWidgetPosition();
} }
@ -1328,40 +1392,51 @@ namespace CodeWalker.GameFiles
MloInstance.UpdateEntities(); MloInstance.UpdateEntities();
} }
UpdateWidgetPosition();
} }
public void SetOrientation(Quaternion ori) private void UpdateBB()
{ {
Quaternion inv = Quaternion.Normalize(Quaternion.Invert(ori));
Orientation = ori;
_CEntityDef.rotation = new Vector4(inv.X, inv.Y, inv.Z, inv.W);
if (MloInstance != null)
{
MloInstance.SetOrientation(ori);
}
if (Archetype != null) if (Archetype != null)
{ {
BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale; BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale;
} }
if ((Archetype != null) && (Orientation == Quaternion.Identity))
UpdateWidgetPosition(); {
UpdateWidgetOrientation(); BBMin = (Archetype.BBMin * Scale) + Position;
BBMax = (Archetype.BBMax * Scale) + Position;
}
else
{
BBMin = Position - (BSRadius);
BBMax = Position + (BSRadius);
////not ideal: should transform all 8 corners!
}
} }
public void SetOrientationInv(Quaternion inv)
public void SetOrientation(Quaternion ori, bool inverse = false)
{ {
Quaternion ori = Quaternion.Normalize(Quaternion.Invert(inv)); if (MloParent != null)
Orientation = ori; {
_CEntityDef.rotation = new Vector4(inv.X, inv.Y, inv.Z, inv.W); var mloInv = Quaternion.Normalize(Quaternion.Invert(MloParent.Orientation));
Quaternion rel = Quaternion.Normalize(Quaternion.Multiply(mloInv, ori));
Quaternion inv = Quaternion.Normalize(Quaternion.Invert(rel));
Orientation = ori;
_CEntityDef.rotation = inv.ToVector4();
}
else
{
Quaternion inv = inverse ? ori : Quaternion.Normalize(Quaternion.Invert(ori));
ori = inverse ? Quaternion.Normalize(Quaternion.Invert(ori)) : ori;
Orientation = ori;
_CEntityDef.rotation = inv.ToVector4();
}
if (MloInstance != null) if (MloInstance != null)
{ {
MloInstance.SetOrientation(ori); MloInstance.SetOrientation(ori);
} }
if (Archetype != null) if (Archetype != null)
{ {
BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale; BSCenter = Orientation.Multiply(Archetype.BSCenter) * Scale;
@ -1376,14 +1451,35 @@ namespace CodeWalker.GameFiles
Scale = new Vector3(s.X, s.X, s.Z); Scale = new Vector3(s.X, s.X, s.Z);
_CEntityDef.scaleXY = s.X; _CEntityDef.scaleXY = s.X;
_CEntityDef.scaleZ = s.Z; _CEntityDef.scaleZ = s.Z;
MloInstanceData mloInstance = MloParent?.MloInstance;
if (mloInstance != null)
{
var mcEntity = mloInstance.TryGetArchetypeEntity(this);
if (mcEntity != null)
{
mcEntity._Data.scaleXY = s.X;
mcEntity._Data.scaleZ = s.Z;
}
}
if (Archetype != null) if (Archetype != null)
{ {
float smax = Math.Max(Scale.X, Scale.Z); float smax = Math.Max(Scale.X, Scale.Z);
BSRadius = Archetype.BSRadius * smax; BSRadius = Archetype.BSRadius * smax;
} }
SetPosition(Position);//update the BB SetPosition(Position);//update the BB
} }
private void UpdateMloArchetype()
{
if (!(MloParent.Archetype is MloArchetype mloArchetype)) return;
if (Index >= mloArchetype.entities.Length) return;
MCEntityDef entity = mloArchetype.entities[Index];
entity._Data.position = _CEntityDef.position;
entity._Data.rotation = _CEntityDef.rotation;
}
public void SetPivotPosition(Vector3 pos) public void SetPivotPosition(Vector3 pos)
@ -1493,6 +1589,8 @@ namespace CodeWalker.GameFiles
[TypeConverter(typeof(ExpandableObjectConverter))] [TypeConverter(typeof(ExpandableObjectConverter))]
public class YmapGrassInstanceBatch public class YmapGrassInstanceBatch
{ {
private const float BatchVertMultiplier = 0.00001525878f;
public Archetype Archetype { get; set; } //cached by GameFileCache on loading... public Archetype Archetype { get; set; } //cached by GameFileCache on loading...
public rage__fwGrassInstanceListDef Batch { get; set; } public rage__fwGrassInstanceListDef Batch { get; set; }
public rage__fwGrassInstanceListDef__InstanceData[] Instances { get; set; } public rage__fwGrassInstanceListDef__InstanceData[] Instances { get; set; }
@ -1504,10 +1602,478 @@ namespace CodeWalker.GameFiles
public float Distance; //used for rendering public float Distance; //used for rendering
public YmapFile Ymap { get; set; } public YmapFile Ymap { get; set; }
private List<BoundingBox> grassBounds; // for brush
public bool BrushEnabled; // for brush
public float BrushRadius = 5f; // for brush
public bool HasChanged; // for brush and renderer
// TODO: Make configurable.
const float BoundingSize = 0.3F;
static readonly Vector3 GrassMinMax = Vector3.One * BoundingSize;
public override string ToString() public override string ToString()
{ {
return Batch.ToString(); return Batch.ToString();
} }
public void UpdateInstanceCount()
{
var b = Batch;
var ins = b.InstanceList;
ins.Count1 = (ushort)Instances.Length;
b.InstanceList = ins;
Batch = b;
}
public bool IsPointBlockedByInstance(Vector3 point)
{
return grassBounds.Any(bb => bb.Contains(point) == ContainmentType.Contains);
}
private void ReInitializeBoundingCache()
{
// cache is already initialized correctly.
if (grassBounds != null && (grassBounds.Count == Instances.Length))
return;
// Clear the current bounding cache.
if (grassBounds == null)
grassBounds = new List<BoundingBox>();
else grassBounds?.Clear();
foreach (var inst in Instances)
{
// create bounding box for this instance.
var worldPos = GetGrassWorldPos(inst.Position, new BoundingBox(AABBMin, AABBMax));
var bb = new BoundingBox(worldPos - GrassMinMax, worldPos + GrassMinMax);
grassBounds.Add(bb);
}
}
public bool EraseInstancesAtMouse(
YmapGrassInstanceBatch batch,
SpaceRayIntersectResult mouseRay,
float radius)
{
rage__spdAABB batchAABB = batch.Batch.BatchAABB;
var oldInstanceBounds = new BoundingBox
(
batchAABB.min.XYZ(),
batchAABB.max.XYZ()
);
var deleteSphere = new BoundingSphere(mouseRay.Position, radius);
// check each instance to see if it's in the delete sphere
// thankfully we've just avoided an O(n^2) op using this bounds stuff (doesn't mean it's super fast though,
// but it's not super slow either, even at like 50,000 instances)
var insList = new List<rage__fwGrassInstanceListDef__InstanceData>();
foreach (var instance in batch.Instances)
{
// get the world pos
var worldPos = GetGrassWorldPos(instance.Position, oldInstanceBounds);
// create a boundary around the instance.
var instanceBounds = new BoundingBox(worldPos - GrassMinMax, worldPos + GrassMinMax);
// check if the sphere contains the boundary.
var bb = new BoundingBox(instanceBounds.Minimum, instanceBounds.Maximum);
var ct = deleteSphere.Contains(ref bb);
if (ct == ContainmentType.Contains || ct == ContainmentType.Intersects)
{
//delInstances.Add(instance); // Add a copy of this instance
continue;
}
insList.Add(instance);
}
if (insList.Count == Instances.Length)
return false;
var newBounds = GetNewGrassBounds(insList, oldInstanceBounds);
// recalc instances
var b = RecalcBatch(newBounds, batch);
batch.Batch = b;
insList = RecalculateInstances(insList, oldInstanceBounds, newBounds);
batch.Instances = insList.ToArray();
return true;
}
public void CreateInstancesAtMouse(
YmapGrassInstanceBatch batch,
SpaceRayIntersectResult mouseRay,
float radius,
int amount,
Func<Vector3, SpaceRayIntersectResult> spawnRayFunc,
Color color,
int ao,
int scale,
Vector3 pad,
bool randomScale)
{
ReInitializeBoundingCache();
var spawnPosition = mouseRay.Position;
var positions = new List<Vector3>();
var normals = new List<Vector3>();
// Get rand positions.
GetSpawns(spawnPosition, spawnRayFunc, positions, normals, radius, amount);
if (positions.Count <= 0) return;
// get the instance list
var instances =
batch.Instances?.ToList() ?? new List<rage__fwGrassInstanceListDef__InstanceData>();
var batchAABB = batch.Batch.BatchAABB;
// make sure to store the old instance bounds for the original
// grass instances
var oldInstanceBounds = new BoundingBox(batchAABB.min.XYZ(), batchAABB.max.XYZ());
if (positions.Count <= 0)
return;
// Begin the spawn bounds.
var grassBound = new BoundingBox(positions[0] - GrassMinMax, positions[0] + GrassMinMax);
grassBound = EncapsulatePositions(positions, grassBound);
// Calculate the new spawn bounds.
var newInstanceBounds = new BoundingBox(oldInstanceBounds.Minimum, oldInstanceBounds.Maximum);
newInstanceBounds = instances.Count > 0
? newInstanceBounds.Encapsulate(grassBound)
: new BoundingBox(grassBound.Minimum, grassBound.Maximum);
// now we need to recalculate the position of each instance
instances = RecalculateInstances(instances, oldInstanceBounds, newInstanceBounds);
// Add new instances at each spawn position with
// the parameters in the brush.
SpawnInstances(positions, normals, instances, newInstanceBounds, color, ao, scale, pad, randomScale);
// then recalc the bounds of the grass batch
var b = RecalcBatch(newInstanceBounds, batch);
// plug our values back in and refresh the ymap.
batch.Batch = b;
// Give back the new intsances
batch.Instances = instances.ToArray();
grassBounds.Clear();
}
// bhv approach recommended by dexy.
public YmapGrassInstanceBatch[] OptimizeInstances(YmapGrassInstanceBatch batch, float minRadius)
{
// this function will return an array of grass instance batches
// that are split up into sectors (groups) with a specific size.
// say for instance we have 30,000 instances spread across a large
// distance. We will split those instances into a grid-like group
// and return the groups as an array of batches.
var oldInstanceBounds = new BoundingBox(batch.Batch.BatchAABB.min.XYZ(), batch.Batch.BatchAABB.max.XYZ());
if (oldInstanceBounds.Radius() < minRadius)
{
return new [] { batch };
}
// Get our optimized grassInstances
var split = SplitGrassRecursive(batch.Instances.ToList(), oldInstanceBounds, minRadius);
// Initiate a new batch list.
var newBatches = new List<YmapGrassInstanceBatch>();
foreach (var grassList in split)
{
// Create a new batch
var newBatch = new YmapGrassInstanceBatch
{
Archetype = batch.Archetype,
Ymap = batch.Ymap
};
// Get the boundary of the grassInstances
var newInstanceBounds = GetNewGrassBounds(grassList, oldInstanceBounds);
// Recalculate the batch boundaries.
var b = RecalcBatch(newInstanceBounds, newBatch);
newBatch.Batch = b;
var ins = RecalculateInstances(grassList, oldInstanceBounds, newInstanceBounds);
newBatch.Instances = ins.ToArray();
newBatches.Add(newBatch);
}
return newBatches.ToArray();
}
private List<List<rage__fwGrassInstanceListDef__InstanceData>> SplitGrassRecursive(
IReadOnlyList<rage__fwGrassInstanceListDef__InstanceData> grassInstances,
BoundingBox batchAABB,
float minRadius = 15F
)
{
var ret = new List<List<rage__fwGrassInstanceListDef__InstanceData>>();
var oldPoints = SplitGrass(grassInstances, batchAABB);
while (true)
{
var stop = true;
var newPoints = new List<List<rage__fwGrassInstanceListDef__InstanceData>>();
foreach (var mb in oldPoints)
{
// for some reason we got a null group?
if (mb == null)
continue;
// Get the bounds of the grassInstances list
var radius = GetNewGrassBounds(mb, batchAABB).Radius();
// check if the radius of the grassInstances
if (radius <= minRadius)
{
// this point list is within the minimum
// radius.
ret.Add(mb);
continue; // we don't need to continue.
}
// since we're here let's keep going
stop = false;
// split the grassInstances again
var s = SplitGrass(mb, batchAABB);
// add it into the new grassInstances list.
newPoints.AddRange(s);
}
// set the old grassInstances to the new grassInstances.
oldPoints = newPoints.ToArray();
// if we're done, and all grassInstances are within the desired size
// then end the loop.
if (stop) break;
}
return ret;
}
private List<rage__fwGrassInstanceListDef__InstanceData>[] SplitGrass(
IReadOnlyList<rage__fwGrassInstanceListDef__InstanceData> points,
BoundingBox batchAABB)
{
var pointGroup = new List<rage__fwGrassInstanceListDef__InstanceData>[2];
// Calculate the bounds of these grassInstances.
var m = GetNewGrassBounds(points, batchAABB);
// Get the center and size
var mm = new Vector3
{
X = Math.Abs(m.Minimum.X - m.Maximum.X),
Y = Math.Abs(m.Minimum.Y - m.Maximum.Y),
Z = Math.Abs(m.Minimum.Z - m.Maximum.Z)
};
// x is the greatest axis...
if (mm.X > mm.Y && mm.X > mm.Z)
{
// Calculate both boundaries.
var lhs = new BoundingBox(m.Minimum, m.Maximum - new Vector3(mm.X * 0.5F, 0, 0));
var rhs = new BoundingBox(m.Minimum + new Vector3(mm.X * 0.5F, 0, 0), m.Maximum);
// Set the grassInstances accordingly.
pointGroup[0] = points
.Where(p => lhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
pointGroup[1] = points
.Where(p => rhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
}
// y is the greatest axis...
else if (mm.Y > mm.X && mm.Y > mm.Z)
{
// Calculate both boundaries.
var lhs = new BoundingBox(m.Minimum, m.Maximum - new Vector3(0, mm.Y * 0.5F, 0));
var rhs = new BoundingBox(m.Minimum + new Vector3(0, mm.Y * 0.5F, 0), m.Maximum);
// Set the grassInstances accordingly.
pointGroup[0] = points
.Where(p => lhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
pointGroup[1] = points
.Where(p => rhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
}
// z is the greatest axis...
else if (mm.Z > mm.X && mm.Z > mm.Y)
{
// Calculate both boundaries.
var lhs = new BoundingBox(m.Minimum, m.Maximum - new Vector3(0, 0, mm.Z * 0.5F));
var rhs = new BoundingBox(m.Minimum + new Vector3(0, 0, mm.Z * 0.5F), m.Maximum);
// Set the grassInstances accordingly.
pointGroup[0] = points
.Where(p => lhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
pointGroup[1] = points
.Where(p => rhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
}
return pointGroup;
}
private static BoundingBox GetNewGrassBounds(IReadOnlyList<rage__fwGrassInstanceListDef__InstanceData> newGrass, BoundingBox oldAABB)
{
var grassPositions = newGrass.Select(x => GetGrassWorldPos(x.Position, oldAABB)).ToArray();
return BoundingBox.FromPoints(grassPositions).Expand(1f);
}
private void SpawnInstances(
IReadOnlyList<Vector3> positions,
IReadOnlyList<Vector3> normals,
ICollection<rage__fwGrassInstanceListDef__InstanceData> instanceList,
BoundingBox instanceBounds,
Color color,
int ao,
int scale,
Vector3 pad,
bool randomScale)
{
for (var i = 0; i < positions.Count; i++)
{
var pos = positions[i];
// create the new instance.
var newInstance = CreateNewInstance(normals[i], color, ao, scale, pad, randomScale);
// get the grass position of the new instance and add it to the
// instance list
var grassPosition = GetGrassPos(pos, instanceBounds);
newInstance.Position = grassPosition;
instanceList.Add(newInstance);
}
}
private rage__fwGrassInstanceListDef__InstanceData CreateNewInstance(Vector3 normal, Color color, int ao, int scale, Vector3 pad,
bool randomScale = false)
{
//Vector3 pad = FloatUtil.ParseVector3String(PadTextBox.Text);
//int scale = (int)ScaleNumericUpDown.Value;
var rand = new Random();
if (randomScale)
scale = rand.Next(scale / 2, scale);
var newInstance = new rage__fwGrassInstanceListDef__InstanceData
{
Ao = (byte)ao,
Scale = (byte)scale,
Color = new ArrayOfBytes3 { b0 = color.R, b1 = color.G, b2 = color.B },
Pad = new ArrayOfBytes3 { b0 = (byte)pad.X, b1 = (byte)pad.Y, b2 = (byte)pad.Z },
NormalX = (byte)((normal.X + 1) * 0.5F * 255F),
NormalY = (byte)((normal.Y + 1) * 0.5F * 255F)
};
return newInstance;
}
private rage__fwGrassInstanceListDef RecalcBatch(BoundingBox newInstanceBounds, YmapGrassInstanceBatch batch)
{
batch.AABBMax = newInstanceBounds.Maximum;
batch.AABBMin = newInstanceBounds.Minimum;
batch.Position = newInstanceBounds.Center();
batch.Radius = newInstanceBounds.Radius();
var b = batch.Batch;
b.BatchAABB = new rage__spdAABB
{
min =
new Vector4(newInstanceBounds.Minimum,
0), // Let's pass the new stuff into the batchabb as well just because.
max = new Vector4(newInstanceBounds.Maximum, 0)
};
return b;
}
private void GetSpawns(
Vector3 origin, Func<Vector3,
SpaceRayIntersectResult> spawnRayFunc,
ICollection<Vector3> positions,
ICollection<Vector3> normals,
float radius,
int resolution = 28)
{
var rand = new Random();
for (var i = 0; i < resolution; i++)
{
var randX = (float)rand.NextDouble(-radius, radius);
var randY = (float)rand.NextDouble(-radius, radius);
if (Math.Abs(randX) > 0 && Math.Abs(randY) > 0)
{
randX *= .7071f;
randY *= .7071f;
}
var posOffset = origin + new Vector3(randX, randY, 2f);
var spaceRay = spawnRayFunc.Invoke(posOffset);
if (!spaceRay.Hit) continue;
// not truly O(n^2) but may be slow...
// actually just did some testing, not slow at all.
if (IsPointBlockedByInstance(spaceRay.Position)) continue;
normals.Add(spaceRay.Normal);
positions.Add(spaceRay.Position);
}
}
private static List<rage__fwGrassInstanceListDef__InstanceData> RecalculateInstances(
List<rage__fwGrassInstanceListDef__InstanceData> instances,
BoundingBox oldInstanceBounds,
BoundingBox newInstanceBounds)
{
var refreshList = new List<rage__fwGrassInstanceListDef__InstanceData>();
foreach (var inst in instances)
{
// Copy instance
var copy =
new rage__fwGrassInstanceListDef__InstanceData
{
Position = inst.Position,
Ao = inst.Ao,
Color = inst.Color,
NormalX = inst.NormalX,
NormalY = inst.NormalY,
Pad = inst.Pad,
Scale = inst.Scale
};
// get the position from where we would be in the old bounds, and move it to
// the position it needs to be in the new bounds.
var oldPos = GetGrassWorldPos(copy.Position, oldInstanceBounds);
//var oldPos = oldInstanceBounds.min + oldInstanceBounds.Size * (grassPos * BatchVertMultiplier);
copy.Position = GetGrassPos(oldPos, newInstanceBounds);
refreshList.Add(copy);
}
instances = refreshList.ToList();
return instances;
}
private static BoundingBox EncapsulatePositions(IEnumerable<Vector3> positions, BoundingBox bounds)
{
foreach (var pos in positions)
{
var posBounds = new BoundingBox(pos - (GrassMinMax + 0.1f), pos + (GrassMinMax + 0.1f));
bounds = bounds.Encapsulate(posBounds);
}
return bounds;
}
private static ArrayOfUshorts3 GetGrassPos(Vector3 worldPos, BoundingBox batchAABB)
{
var offset = worldPos - batchAABB.Minimum;
var size = batchAABB.Size();
var percentage =
new Vector3(
offset.X / size.X,
offset.Y / size.Y,
offset.Z / size.Z
);
var instancePos = percentage / BatchVertMultiplier;
return new ArrayOfUshorts3
{
u0 = (ushort)instancePos.X,
u1 = (ushort)instancePos.Y,
u2 = (ushort)instancePos.Z
};
}
private static Vector3 GetGrassWorldPos(ArrayOfUshorts3 grassPos, BoundingBox batchAABB)
{
return batchAABB.Minimum + batchAABB.Size() * (grassPos.XYZ() * BatchVertMultiplier);
}
} }
[TypeConverter(typeof(ExpandableObjectConverter))] [TypeConverter(typeof(ExpandableObjectConverter))]
@ -1548,7 +2114,6 @@ namespace CodeWalker.GameFiles
} }
} }
[TypeConverter(typeof(ExpandableObjectConverter))] [TypeConverter(typeof(ExpandableObjectConverter))]
public class YmapTimeCycleModifier public class YmapTimeCycleModifier
{ {

View File

@ -14,7 +14,7 @@ namespace CodeWalker.GameFiles
public List<Vector3> Vertices { get; set; } public List<Vector3> Vertices { get; set; }
public List<ushort> Indices { 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<YnvPoly> Polys { get; set; }
public List<YnvPortal> Portals { get; set; } public List<YnvPortal> Portals { get; set; }
public List<YnvPoint> Points { 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) public YnvFile() : base(null, GameFileType.Ynv)
{ {
@ -101,9 +111,16 @@ namespace CodeWalker.GameFiles
{ {
Indices = Nav.Indices.GetFullList(); 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) if (Nav.Polys != null)
{ {
@ -114,16 +131,7 @@ namespace CodeWalker.GameFiles
YnvPoly poly = new YnvPoly(); YnvPoly poly = new YnvPoly();
poly.Init(this, polys[i]); poly.Init(this, polys[i]);
poly.Index = i; poly.Index = i;
poly.CalculatePosition(); //calc poly center for display purposes..
Polys.Add(poly); Polys.Add(poly);
if (poly.PortalType > 0)
{
if (poly.PortalType != 2) //seems to be what portal links need to understand..
{ }
}
} }
} }
if (Nav.Portals != null) if (Nav.Portals != null)
@ -209,23 +217,97 @@ namespace CodeWalker.GameFiles
Vector3 aabbsizeinv = 1.0f / aabbsize; Vector3 aabbsizeinv = 1.0f / aabbsize;
var vertlist = new List<NavMeshVertex>(); var vertlist = new List<NavMeshVertex>();
if (Vertices != null) var indslist = new List<ushort>();
{ var edgelist = new List<NavMeshEdge>();
for (int i = 0; i < Vertices.Count; i++)
{
vertlist.Add(NavMeshVertex.Create((Vertices[i] - posoffset) * aabbsizeinv));
}
}
var polylist = new List<NavMeshPoly>(); 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++) for (int i = 0; i < Polys.Count; i++)
{ {
Polys[i].Index = i; var poly = Polys[i];
polylist.Add(Polys[i].RawData); 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) if (Portals != null)
{ {
for (int i = 0; i < Portals.Count; i++) 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++) for (int i = 0; i < Points.Count; i++)
{ {
@ -259,10 +341,10 @@ namespace CodeWalker.GameFiles
Nav.Indices = new NavMeshList<ushort>(); Nav.Indices = new NavMeshList<ushort>();
Nav.Indices.VFT = 1080158424; Nav.Indices.VFT = 1080158424;
} }
if (Nav.AdjPolys == null) if (Nav.Edges == null)
{ {
Nav.AdjPolys = new NavMeshList<NavMeshAdjPoly>(); Nav.Edges = new NavMeshList<NavMeshEdge>();
Nav.AdjPolys.VFT = 1080158440; Nav.Edges.VFT = 1080158440;
} }
if (Nav.Polys == null) if (Nav.Polys == null)
{ {
@ -272,16 +354,24 @@ namespace CodeWalker.GameFiles
Nav.Vertices.RebuildList(vertlist); 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.Polys.RebuildList(polylist);
Nav.PolysCount = Nav.Polys.ItemCount;
Nav.Portals = (portallist.Count > 0) ? portallist.ToArray() : null; Nav.Portals = (portallist.Count > 0) ? portallist.ToArray() : null;
Nav.PortalsCount = (uint)(Nav.Portals?.Length ?? 0); 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... 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) private void BuildSectorTree(NavMeshSector node, int depth, ref uint pointindex)
{ {
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)
{ {
//go through polys and points and create new lists for this node //go through polys and points and create new lists for this node
@ -329,6 +434,8 @@ namespace CodeWalker.GameFiles
data.PointsStartID = pointindex; data.PointsStartID = pointindex;
//totbytes += (uint)data.BlockLength;
if (Polys != null) if (Polys != null)
{ {
List<ushort> polyids = new List<ushort>(); List<ushort> polyids = new List<ushort>();
@ -345,6 +452,7 @@ namespace CodeWalker.GameFiles
{ {
data.PolyIDs = polyids.ToArray(); data.PolyIDs = polyids.ToArray();
} }
//totbytes += (uint)(polyids.Count * 2);
} }
if (Points != null) if (Points != null)
@ -363,6 +471,7 @@ namespace CodeWalker.GameFiles
data.Points = points.ToArray(); data.Points = points.ToArray();
pointindex += (uint)points.Count; 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() public void UpdateAllNodePositions()
@ -474,67 +595,39 @@ namespace CodeWalker.GameFiles
//go through the nav mesh polys and generate verts to render... //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; if ((Polys == null) || (Polys.Count == 0)) return;
int vc = Vertices.Count; int vc = Vertices.Count;
List<EditorVertex> rverts = new List<EditorVertex>(); List<EditorVertex> rverts = new List<EditorVertex>();
EditorVertex p0 = new EditorVertex();
EditorVertex p1 = new EditorVertex();
EditorVertex p2 = new EditorVertex();
foreach (var ypoly in Polys) foreach (var ypoly in Polys)
{ {
var poly = ypoly.RawData; if ((ypoly.Vertices == null) || (ypoly.Vertices.Length < 3))
{ continue; }
var colour = ypoly.GetColour(); var colour = ypoly.GetColour();
var colourval = (uint)colour.ToRgba(); var colourval = (uint)colour.ToRgba();
var ic = poly.IndexCount;
var startid = poly.IndexID;
var endid = startid + ic;
if (startid >= Indices.Count)
{ continue; }
if (endid > Indices.Count)
{ continue; }
if(ic<3)
{ continue; }//not enough verts to make a triangle...
if (ic > 15)
{ }
EditorVertex p0 = new EditorVertex();
EditorVertex p1 = new EditorVertex();
EditorVertex p2 = new EditorVertex();
p0.Colour = colourval; p0.Colour = colourval;
p1.Colour = colourval; p1.Colour = colourval;
p2.Colour = colourval; p2.Colour = colourval;
var startind = Indices[startid]; p0.Position = ypoly.Vertices[0];
if (startind >= vc)
{ continue; }
p0.Position = Vertices[startind];
//build triangles for the poly. //build triangles for the poly.
int tricount = ic - 2; int tricount = ypoly.Vertices.Length - 2;
for (int t = 0; t < tricount; t++) for (int t = 0; t < tricount; t++)
{ {
int tid = startid + t; p1.Position = ypoly.Vertices[t + 1];
int ind1 = Indices[tid + 1]; p2.Position = ypoly.Vertices[t + 2];
int ind2 = Indices[tid + 2];
if ((ind1 >= vc) || (ind2 >= vc))
{ continue; }
p1.Position = Vertices[ind1];
p2.Position = Vertices[ind2];
rverts.Add(p0); rverts.Add(p0);
rverts.Add(p1); rverts.Add(p1);
rverts.Add(p2); rverts.Add(p2);
} }
} }
TriangleVerts = rverts.ToArray(); TriangleVerts = rverts.ToArray();
@ -572,14 +665,14 @@ namespace CodeWalker.GameFiles
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoly [TypeConverter(typeof(ExpandableObjectConverter))] public class YnvPoly
{ {
public NavMeshPoly _RawData; public NavMeshPoly _RawData;
public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } }
public YnvFile Ynv { get; set; } 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 AreaID { get { return _RawData.AreaID; } set { _RawData.AreaID = value; } }
public ushort PartID { get { return _RawData.PartID; } set { _RawData.PartID = value; } } public ushort PartID { get { return _RawData.PartID; } set { _RawData.PartID = value; } }
public ushort PortalLinkID { get { return _RawData.PortalLinkID; } set { _RawData.PortalLinkID = value; } } public uint PortalLinkID { get { return _RawData.PortalLinkID; } set { _RawData.PortalLinkID = value; } }
public byte PortalType { get { return _RawData.PortalType; } set { _RawData.PortalType = 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 (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 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)); } } 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 Vector3 Position { get; set; }
public int Index { 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) public void Init(YnvFile ynv, NavMeshPoly poly)
{ {
Ynv = ynv; Ynv = ynv;
RawData = poly; 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) public void SetPosition(Vector3 pos)
{ {
Vector3 delta = pos - Position; 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 & 8388608) > 0) colour.Red += 1.0f; //slope facing -X,-Y (southwest)
//if (u5 >= 16777216) { } //other bits unused //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 & 1) > 0) colour.Red += 1.0f; //portal - don't interact?
//if ((u1 & 2) > 0) colour.Green += 1.0f; //portal - ladder/fence interaction? //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? //if ((u1 & 4) > 0) colour.Blue += 1.0f; //portal - fence interaction / go away from?
@ -709,32 +872,36 @@ namespace CodeWalker.GameFiles
public void CalculatePosition() public void CalculatePosition()
{ {
//calc poly center for display purposes. //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; Vector3 pcenter = Vector3.Zero;
float pcount = 0.0f; if (Vertices != null)
for (int id = startid; id < endid; id++)
{ {
var ind = indices[id]; for (int i = 0; i < Vertices.Length; i++)
if (ind >= vc) {
{ continue; } pcenter += Vertices[i];
}
pcenter += vertices[ind];
pcount += 1.0f;
} }
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() public override string ToString()
@ -870,4 +1037,57 @@ namespace CodeWalker.GameFiles
} }
[TypeConverter(typeof(ExpandableObjectConverter))] public class YnvEdge
{
public NavMeshEdge _RawData;
public NavMeshEdge RawData { get { return _RawData; } set { _RawData = value; } }
public YnvFile Ynv { get; set; }
public uint AreaID1 { get; set; }
public uint AreaID2 { get; set; }
public uint PolyID1 { get { return _RawData._Poly1.PolyID; } set { _RawData._Poly1.PolyID = value; } }
public uint PolyID2 { get { return _RawData._Poly2.PolyID; } set { _RawData._Poly2.PolyID = value; } }
public YnvPoly Poly1 { get; set; }
public YnvPoly Poly2 { get; set; }
public YnvEdge() { }
public YnvEdge(YnvEdge copy, YnvPoly poly)
{
_RawData = copy._RawData;
_RawData._Poly1.PolyID = 0x3FFF;
_RawData._Poly2.PolyID = 0x3FFF;
Poly1 = poly;
Poly2 = poly;
AreaID1 = 0x3FFF;
AreaID2 = 0x3FFF;
}
public void Init(YnvFile ynv, NavMeshEdge edge)
{
Ynv = ynv;
RawData = edge;
if (ynv.Nav == null) return;
var n = ynv.Nav;
var ai1 = edge.Poly1.AreaIDInd;
var ai2 = edge.Poly2.AreaIDInd;
AreaID1 = (ai1 < n.AdjAreaIDs.Count) ? n.AdjAreaIDs.Get(ai1) : 16383;
AreaID2 = (ai2 < n.AdjAreaIDs.Count) ? n.AdjAreaIDs.Get(ai2) : 16383;
}
public override string ToString()
{
return AreaID1.ToString() + ", " + AreaID2.ToString() + ", " + PolyID1.ToString() + ", " + PolyID2.ToString() + ", " +
_RawData._Poly1.Unk2.ToString() + ", " + _RawData._Poly2.Unk2.ToString() + ", " +
_RawData._Poly1.Unk3.ToString() + ", " + _RawData._Poly2.Unk3.ToString();
}
}
} }

View File

@ -21,8 +21,8 @@ namespace CodeWalker.GameFiles
public uint NameHash { get; set; } public uint NameHash { get; set; }
public string[] Strings { get; set; } public string[] Strings { get; set; }
public CMapTypes _CMapTypes;
public CMapTypes CMapTypes { get; set; } public CMapTypes CMapTypes { get { return _CMapTypes; } set { _CMapTypes = value; } }
public Archetype[] AllArchetypes { get; set; } public Archetype[] AllArchetypes { get; set; }
@ -50,6 +50,111 @@ namespace CodeWalker.GameFiles
return (RpfFileEntry != null) ? RpfFileEntry.Name : string.Empty; 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.CTimeCycleModifier, 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);
mb.AddStructureInfo(MetaName.CBaseArchetypeDef);
mb.AddStructureInfo(MetaName.CMloArchetypeDef);
mb.AddStructureInfo(MetaName.CTimeArchetypeDef);
mb.AddStructureInfo(MetaName.CCompositeEntityType);
mb.AddStructureInfo(MetaName.CMloRoomDef);
mb.AddStructureInfo(MetaName.CMloPortalDef);
mb.AddStructureInfo(MetaName.CMloEntitySet);
if ((AllArchetypes != null && AllArchetypes.Length > 0))
{
mb.AddEnumInfo((MetaName)1991964615); // ASSET_TYPE_
}
if ((AllArchetypes != null) && (AllArchetypes.Any(x => x is MloArchetype m && m.entities.Length > 0)))
{
mb.AddStructureInfo(MetaName.CEntityDef);
mb.AddEnumInfo((MetaName)1264241711); //LODTYPES_
mb.AddEnumInfo((MetaName)648413703); //PRI_
}
mb.AddItem(MetaName.CMapTypes, mapTypes);
Meta meta = mb.GetMeta();
byte[] data = ResourceBuilder.Build(meta, 2);
HasChanged = false;
return data;
}
public void Load(byte[] data) public void Load(byte[] data)
{ {
@ -94,12 +199,12 @@ namespace CodeWalker.GameFiles
Meta = rd.ReadBlock<Meta>(); Meta = rd.ReadBlock<Meta>();
CMapTypes = MetaTypes.GetTypedData<CMapTypes>(Meta, MetaName.CMapTypes); _CMapTypes = MetaTypes.GetTypedData<CMapTypes>(Meta, MetaName.CMapTypes);
List<Archetype> allarchs = new List<Archetype>(); List<Archetype> allarchs = new List<Archetype>();
var ptrs = MetaTypes.GetPointerArray(Meta, CMapTypes.archetypes); var ptrs = MetaTypes.GetPointerArray(Meta, _CMapTypes.archetypes);
if (ptrs != null) if (ptrs != null)
{ {
for (int i = 0; i < ptrs.Length; i++) for (int i = 0; i < ptrs.Length; i++)
@ -151,7 +256,8 @@ namespace CodeWalker.GameFiles
AllArchetypes = allarchs.ToArray(); AllArchetypes = allarchs.ToArray();
Extensions = MetaTypes.GetExtensions(Meta, CMapTypes.extensions); Extensions = MetaTypes.GetExtensions(Meta, _CMapTypes.extensions);
if (Extensions != null) if (Extensions != null)
{ } { }
@ -163,11 +269,11 @@ namespace CodeWalker.GameFiles
//CEntityDefs = MetaTypes.GetTypedDataArray<CEntityDef>(Meta, MetaName.CEntityDef); //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) if (CompositeEntityTypes != null)
{ } { }
NameHash = CMapTypes.name; NameHash = _CMapTypes.name;
if (NameHash == 0) if (NameHash == 0)
{ {
int ind = entry.NameLower.LastIndexOf('.'); int ind = entry.NameLower.LastIndexOf('.');
@ -242,7 +348,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 = Unk_1991964615.ASSET_TYPE_DRAWABLE;
a._BaseArchetypeDef.lodDist = 60;
a._BaseArchetypeDef.hdTextureDist = 15;
a.Ytyp = this;
AddArchetype(a);
return a;
}
public bool RemoveArchetype(Archetype archetype)
{
List<Archetype> archetypes = AllArchetypes.ToList();
if (archetypes.Remove(archetype))
{
AllArchetypes = archetypes.ToArray();
return true;
}
return false;
}
} }

View File

@ -1805,116 +1805,6 @@ namespace CodeWalker.GameFiles
} }
public void InitYmapEntityArchetypes(YmapFile file)
{
if (file == null) return;
if (file.AllEntities != null)
{
for (int i = 0; i < file.AllEntities.Length; i++)
{
var ent = file.AllEntities[i];
var arch = GetArchetype(ent.CEntityDef.archetypeName);
ent.SetArchetype(arch);
if (ent.MloInstance != null)
{
var entities = ent.MloInstance.Entities;
if (entities != null)
{
for (int j = 0; j < entities.Length; j++)
{
var ient = entities[j];
var iarch = GetArchetype(ient.CEntityDef.archetypeName);
ient.SetArchetype(iarch);
if (iarch == null)
{ } //can't find archetype - des stuff eg {des_prologue_door}
}
//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;
}
}
}
}
}
if (file.GrassInstanceBatches != null)
{
for (int i = 0; i < file.GrassInstanceBatches.Length; i++)
{
var batch = file.GrassInstanceBatches[i];
batch.Archetype = GetArchetype(batch.Batch.archetypeName);
}
}
if (file.TimeCycleModifiers != null)
{
for (int i = 0; i < file.TimeCycleModifiers.Length; i++)
{
var tcm = file.TimeCycleModifiers[i];
World.TimecycleMod wtcm;
if (TimeCycleModsDict.TryGetValue(tcm.CTimeCycleModifier.name.Hash, out wtcm))
{
tcm.TimeCycleModData = wtcm;
}
}
}
}
@ -1956,8 +1846,9 @@ namespace CodeWalker.GameFiles
if (req.Loaded) AddTextureLookups(req as YtdFile); if (req.Loaded) AddTextureLookups(req as YtdFile);
break; break;
case GameFileType.Ymap: case GameFileType.Ymap:
req.Loaded = LoadFile(req as YmapFile); YmapFile y = req as YmapFile;
if (req.Loaded) InitYmapEntityArchetypes(req as YmapFile); req.Loaded = LoadFile(y);
if (req.Loaded) y.InitYmapEntityArchetypes(this);
break; break;
case GameFileType.Yft: case GameFileType.Yft:
req.Loaded = LoadFile(req as YftFile); req.Loaded = LoadFile(req as YftFile);

View File

@ -14,7 +14,7 @@ namespace CodeWalker.GameFiles
public virtual MetaName Type => MetaName.CBaseArchetypeDef; public virtual MetaName Type => MetaName.CBaseArchetypeDef;
public CBaseArchetypeDef _BaseArchetypeDef; public CBaseArchetypeDef _BaseArchetypeDef;
public CBaseArchetypeDef BaseArchetypeDef { get { return _BaseArchetypeDef; } set { _BaseArchetypeDef = value; } } public CBaseArchetypeDef BaseArchetypeDef => _BaseArchetypeDef; // for browsing.
public MetaHash Hash { get; set; } public MetaHash Hash { get; set; }
public YtypFile Ytyp { get; set; } public YtypFile Ytyp { get; set; }
@ -49,7 +49,7 @@ namespace CodeWalker.GameFiles
protected void InitVars(ref CBaseArchetypeDef arch) protected void InitVars(ref CBaseArchetypeDef arch)
{ {
BaseArchetypeDef = arch; _BaseArchetypeDef = arch;
Hash = arch.assetName; Hash = arch.assetName;
if (Hash.Hash == 0) Hash = arch.name; if (Hash.Hash == 0) Hash = arch.name;
DrawableDict = arch.drawableDictionary; DrawableDict = arch.drawableDictionary;
@ -83,10 +83,8 @@ namespace CodeWalker.GameFiles
public class TimeArchetype : Archetype public class TimeArchetype : Archetype
{ {
public override MetaName Type => MetaName.CTimeArchetypeDef; public override MetaName Type => MetaName.CTimeArchetypeDef;
public CTimeArchetypeDef _TimeArchetypeDef;
public CTimeArchetypeDefData _TimeArchetypeDef; public CTimeArchetypeDef TimeArchetypeDef => _TimeArchetypeDef; // for browsing.
public CTimeArchetypeDefData TimeArchetypeDef { get { return _TimeArchetypeDef; } set { _TimeArchetypeDef = value; } }
public uint TimeFlags { get; set; } public uint TimeFlags { get; set; }
public bool[] ActiveHours { get; set; } public bool[] ActiveHours { get; set; }
@ -98,9 +96,9 @@ namespace CodeWalker.GameFiles
{ {
Ytyp = ytyp; Ytyp = ytyp;
InitVars(ref arch._BaseArchetypeDef); InitVars(ref arch._BaseArchetypeDef);
TimeArchetypeDef = arch.TimeArchetypeDef; _TimeArchetypeDef = arch;
TimeFlags = _TimeArchetypeDef.timeFlags; TimeFlags = arch.TimeArchetypeDef.timeFlags;
ActiveHours = new bool[24]; ActiveHours = new bool[24];
ActiveHoursText = new string[24]; ActiveHoursText = new string[24];
for (int i = 0; i < 24; i++) for (int i = 0; i < 24; i++)
@ -128,8 +126,10 @@ namespace CodeWalker.GameFiles
{ {
public override MetaName Type => MetaName.CMloArchetypeDef; 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 MCEntityDef[] entities { get; set; }
public MCMloRoomDef[] rooms { get; set; } public MCMloRoomDef[] rooms { get; set; }
@ -137,36 +137,147 @@ namespace CodeWalker.GameFiles
public MCMloEntitySet[] entitySets { get; set; } public MCMloEntitySet[] entitySets { get; set; }
public CMloTimeCycleModifier[] timeCycleModifiers { get; set; } public CMloTimeCycleModifier[] timeCycleModifiers { get; set; }
public void Init(YtypFile ytyp, ref CMloArchetypeDef arch) public void Init(YtypFile ytyp, ref CMloArchetypeDef arch)
{ {
Ytyp = ytyp; Ytyp = ytyp;
InitVars(ref arch._BaseArchetypeDef); 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) 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) if (centities != null)
{ {
entities = new MCEntityDef[centities.Length]; entities = new MCEntityDef[centities.Length];
for (int i = 0; i < centities.Length; i++) 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) if (crooms != null)
{ {
rooms = new MCMloRoomDef[crooms.Length]; rooms = new MCMloRoomDef[crooms.Length];
for (int i = 0; i < crooms.Length; i++) 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) if (cportals != null)
{ {
portals = new MCMloPortalDef[cportals.Length]; portals = new MCMloPortalDef[cportals.Length];
@ -176,7 +287,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) if (centitySets != null)
{ {
entitySets = new MCMloEntitySet[centitySets.Length]; entitySets = new MCMloEntitySet[centitySets.Length];
@ -187,14 +298,44 @@ namespace CodeWalker.GameFiles
} }
timeCycleModifiers = MetaTypes.ConvertDataArray<CMloTimeCycleModifier>(meta, MetaName.CMloTimeCycleModifier, _MloArchetypeDef.timeCycleModifiers); timeCycleModifiers = MetaTypes.ConvertDataArray<CMloTimeCycleModifier>(meta, MetaName.CMloTimeCycleModifier, _MloArchetypeDefData.timeCycleModifiers);
} }
public MCMloRoomDef GetEntityRoom(MCEntityDef ent)
{
int objectIndex = -1;
for (int i = 0; i < entities.Length; i++)
{
MCEntityDef e = entities[i];
if (e == ent)
{
objectIndex = i;
break;
}
}
if (objectIndex == -1) return null;
MCMloRoomDef room = null;
for (int i = 0; i < rooms.Length; i++)
{
MCMloRoomDef r = rooms[i];
for (int j = 0; j < r.AttachedObjects.Length; j++)
{
uint ind = r.AttachedObjects[j];
if (ind == objectIndex)
{
room = r;
break;
}
}
if (room != null) break;
}
return room;
}
} }
[TypeConverter(typeof(ExpandableObjectConverter))] [TypeConverter(typeof(ExpandableObjectConverter))]
public class MloInstanceData public class MloInstanceData
{ {
@ -204,7 +345,12 @@ namespace CodeWalker.GameFiles
public uint[] defaultEntitySets { get; set; } public uint[] defaultEntitySets { get; set; }
public YmapEntityDef[] Entities { 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) public void CreateYmapEntities(YmapEntityDef owner, MloArchetype mloa)
{ {
@ -230,27 +376,182 @@ namespace CodeWalker.GameFiles
var entitySet = entitySets[i]; var entitySet = entitySets[i];
if (entitySet.Entities != null) 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++) for (int j = 0; j < entitySet.Entities.Length; j++)
{ {
YmapEntityDef e = CreateYmapEntity(owner, entitySet.Entities[j], lasti); YmapEntityDef e = CreateYmapEntity(owner, entitySet.Entities[j], lasti);
e.MloEntitySet = entitySet; EntitySets[entitySet._Data.name].Entities.Add(e);
entlist.Add(e); e.MloEntitySet = instset;
lasti++; 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(); 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.Extensions = ment.Extensions;
e.MloRefPosition = e.Position; e.MloRefPosition = e.Position;
e.MloRefOrientation = e.Orientation; e.MloRefOrientation = e.Orientation;
@ -259,9 +560,31 @@ namespace CodeWalker.GameFiles
e.Orientation = Quaternion.Multiply(owner.Orientation, e.MloRefOrientation); e.Orientation = Quaternion.Multiply(owner.Orientation, e.MloRefOrientation);
e.UpdateWidgetPosition(); e.UpdateWidgetPosition();
e.UpdateWidgetOrientation(); e.UpdateWidgetOrientation();
return e; 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) public void SetPosition(Vector3 pos)
{ {
@ -285,17 +608,52 @@ namespace CodeWalker.GameFiles
for (int i = 0; i < Entities.Length; i++) for (int i = 0; i < Entities.Length; i++)
{ {
YmapEntityDef e = Entities[i]; YmapEntityDef e = Entities[i];
e.Position = Owner.Position + Owner.Orientation.Multiply(e.MloRefPosition); UpdateEntity(e);
e.Orientation = Quaternion.Multiply(Owner.Orientation, e.MloRefOrientation);
e.UpdateWidgetPosition();
e.UpdateWidgetOrientation();
} }
} }
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();
}
} }
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MloInstanceEntitySet
{
public MloInstanceEntitySet(MCMloEntitySet entSet, MloInstanceData instance)
{
EntitySet = entSet;
Entities = new List<YmapEntityDef>();
Instance = instance;
}
public MCMloEntitySet EntitySet { get; set; }
public List<YmapEntityDef> Entities { get; set; }
public MloInstanceData Instance { get; set; }
public uint[] Locations
{
get { return EntitySet?.Locations; }
set { if (EntitySet != null) EntitySet.Locations = value; }
}
public bool Visible { get; set; }
}
} }

View File

@ -935,6 +935,10 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public struct ArrayOfUshorts3 //array of 3 ushorts [TC(typeof(EXP))] public struct ArrayOfUshorts3 //array of 3 ushorts
{ {
public ushort u0, u1, u2; public ushort u0, u1, u2;
public Vector3 XYZ()
{
return new Vector3(u0, u1, u2);
}
public override string ToString() public override string ToString()
{ {
return u0.ToString() + ", " + u1.ToString() + ", " + u2.ToString(); return u0.ToString() + ", " + u1.ToString() + ", " + u2.ToString();

View File

@ -538,6 +538,7 @@ namespace CodeWalker.GameFiles
CExtensionDefSpawnPointOverride = 2716862120, CExtensionDefSpawnPointOverride = 2716862120,
CExtensionDefWindDisturbance = 569228403, CExtensionDefWindDisturbance = 569228403,
CFiringPatternInfo = 4139644871, CFiringPatternInfo = 4139644871,
CFiringPatternInfoManager = 3698419088,
CGrabHelper__Tunables = 1898505781, CGrabHelper__Tunables = 1898505781,
Chances = 3434267272, Chances = 3434267272,
changeSetName = 3618800523, changeSetName = 3618800523,
@ -1605,6 +1606,7 @@ namespace CodeWalker.GameFiles
VEHICLE_LAYOUTS_FILE = 2004032454, VEHICLE_LAYOUTS_FILE = 2004032454,
VEHICLE_METADATA_FILE = 4125139733, VEHICLE_METADATA_FILE = 4125139733,
VEHICLE_POPULATION_FILE = 4010054647, VEHICLE_POPULATION_FILE = 4010054647,
VEHICLE_RESPONSE_DEFAULT = 3986150789,
VEHICLE_RESPONSE_ARMY_BASE = 317362887, VEHICLE_RESPONSE_ARMY_BASE = 317362887,
VEHICLE_RESPONSE_COUNTRYSIDE = 2467847847, VEHICLE_RESPONSE_COUNTRYSIDE = 2467847847,
VEHICLE_SHOP_DLC_FILE = 3203173146, VEHICLE_SHOP_DLC_FILE = 3203173146,
@ -1621,6 +1623,13 @@ namespace CodeWalker.GameFiles
VFXINTERIORINFO_FILE = 354822867, VFXINTERIORINFO_FILE = 354822867,
VFXPEDINFO_FILE = 962370952, VFXPEDINFO_FILE = 962370952,
VFXREGIONINFO_FILE = 3633596549, VFXREGIONINFO_FILE = 3633596549,
vfxregioninfo_default = 526963733,
vfxregioninfo_desert = 1202232026,
vfxregioninfo_beach = 4239901007,
vfxregioninfo_slum = 4267832995,
vfxregioninfo_woodland = 1397181648,
vfxregioninfo_mountain = 3282595980,
vfxregioninfo_countryside = 2691334223,
vfxTagHashName = 1944993828, vfxTagHashName = 1944993828,
VFXVEHICLEINFO_FILE = 1918258814, VFXVEHICLEINFO_FILE = 1918258814,
vfxVehicleInfos = 1829968483, vfxVehicleInfos = 1829968483,
@ -3528,9 +3537,15 @@ namespace CodeWalker.GameFiles
spName = 4254542050, spName = 4254542050,
//from rubidium //from rubidium / dav90 PSO XML / zonebind
mpName = 2031203854, mpName = 2031203854,
zoneName = 257000, zoneName = 257000,
vfxRegion = 3384955624,
vehDirtMin = 1831590592,
vehDirtMax = 625824556,
vehDirtGrowScale = 2919812941,
pedDirtMin = 1861946207,
pedDirtMax = 3150688023,

View File

@ -2429,6 +2429,8 @@ namespace CodeWalker.GameFiles
public Vector3 BBMin_CW { get; set; } public Vector3 BBMin_CW { get; set; }
public Vector3 BBMax_CW { get; set; } public Vector3 BBMax_CW { get; set; }
public MloArchetype Archetype { get; set; }
public int Index { get; set; }
public MCMloRoomDef() { } public MCMloRoomDef() { }
public MCMloRoomDef(Meta meta, CMloRoomDef data) public MCMloRoomDef(Meta meta, CMloRoomDef data)
@ -2610,7 +2612,7 @@ namespace CodeWalker.GameFiles
Entities = new MCEntityDef[ents.Length]; Entities = new MCEntityDef[ents.Length];
for (int i = 0; i < ents.Length; i++) for (int i = 0; i < ents.Length; i++)
{ {
Entities[i] = new MCEntityDef(meta, ents[i]); Entities[i] = new MCEntityDef(meta, ref ents[i]);
} }
} }
} }
@ -2750,23 +2752,26 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public class MCEntityDef : MetaWrapper [TC(typeof(EXP))] public class MCEntityDef : MetaWrapper
{ {
public CEntityDef _Data; public CEntityDef _Data;
public CEntityDef Data { get { return _Data; } } public CEntityDef Data { get { return _Data; } set { _Data = value; } }
public MetaWrapper[] Extensions { get; set; } public MetaWrapper[] Extensions { get; set; }
public MCEntityDef() { } public MloArchetype Archetype { get; set; } // for browsing/reference purposes
public MCEntityDef(MCEntityDef copy) public MCEntityDef(MCEntityDef copy)
{ {
if (copy != null) if (copy != null) _Data = copy.Data;
{
_Data = copy.Data;
}
} }
public MCEntityDef(Meta meta, CEntityDef d) public MCEntityDef(Meta meta, ref CEntityDef d)
{ {
_Data = d; _Data = d;
Extensions = MetaTypes.GetExtensions(meta, _Data.extensions); 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) public override void Load(Meta meta, MetaPOINTER ptr)
{ {

View File

@ -1646,7 +1646,12 @@ namespace CodeWalker.GameFiles
public static string FormatHash(MetaHash h) //for use with WriteItemArray 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 public static string FormatVector2(Vector2 v) //for use with WriteItemArray
{ {

View File

@ -23,6 +23,95 @@
//shamelessly stolen and mangled //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;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Xml; using System.Xml;
using SharpDX; using SharpDX;
@ -182,7 +183,7 @@ namespace CodeWalker.GameFiles
mb.AddEnumInfo(_infos.EnumNameHash); mb.AddEnumInfo(_infos.EnumNameHash);
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText); int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText, entry.DataType);
Write(val, data, entry.DataOffset); Write(val, data, entry.DataOffset);
break; break;
} }
@ -193,7 +194,7 @@ namespace CodeWalker.GameFiles
mb.AddEnumInfo(_infos.EnumNameHash); mb.AddEnumInfo(_infos.EnumNameHash);
int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText); int val = GetEnumInt(entry.ReferenceKey, cnode.InnerText, entry.DataType);
Write((short)val, data, entry.DataOffset); Write((short)val, data, entry.DataOffset);
break; break;
} }
@ -296,11 +297,16 @@ namespace CodeWalker.GameFiles
private static void GetParsedArrayOfBytes(XmlNode node, byte[] data, MetaStructureEntryInfo_s entry, MetaStructureEntryInfo_s arrEntry) private static void GetParsedArrayOfBytes(XmlNode node, byte[] data, MetaStructureEntryInfo_s entry, MetaStructureEntryInfo_s arrEntry)
{ {
int offset = entry.DataOffset; 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) switch (arrEntry.DataType)
{ {
default: default: //expecting hex string.
split = Split(node.InnerText, 2); split = Split(node.InnerText, 2);
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
@ -309,67 +315,81 @@ namespace CodeWalker.GameFiles
offset += sizeof(byte); offset += sizeof(byte);
} }
break; break;
case MetaStructureEntryDataType.SignedByte: case MetaStructureEntryDataType.SignedByte: //expecting space-separated array.
split = node.InnerText.Split(); //split = Split(node.InnerText, 2); to read as unsplitted HEX
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
sbyte val = Convert.ToSByte(split[j], 10); sbyte val;// = Convert.ToSByte(split[j], 10);
data[offset] = (byte)val; if (sbyte.TryParse(split[j].Trim(), ns, ic, out val))
offset += sizeof(sbyte); {
data[offset] = (byte)val;
offset += sizeof(sbyte);
}
} }
break; break;
case MetaStructureEntryDataType.UnsignedByte: case MetaStructureEntryDataType.UnsignedByte: //expecting space-separated array.
split = node.InnerText.Split();
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
byte val = Convert.ToByte(split[j], 10); byte val;// = Convert.ToByte(split[j], 10);
data[offset] = val; if (byte.TryParse(split[j].Trim(), ns, ic, out val))
offset += sizeof(byte); {
data[offset] = val;
offset += sizeof(byte);
}
} }
break; break;
case MetaStructureEntryDataType.SignedShort: case MetaStructureEntryDataType.SignedShort: //expecting space-separated array.
split = node.InnerText.Split();
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
short val = Convert.ToInt16(split[j], 10); short val;// = Convert.ToInt16(split[j], 10);
Write(val, data, offset); if (short.TryParse(split[j].Trim(), ns, ic, out val))
offset += sizeof(short); {
Write(val, data, offset);
offset += sizeof(short);
}
} }
break; break;
case MetaStructureEntryDataType.UnsignedShort: case MetaStructureEntryDataType.UnsignedShort: //expecting space-separated array.
split = node.InnerText.Split();
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
ushort val = Convert.ToUInt16(split[j], 10); ushort val;// = Convert.ToUInt16(split[j], 10);
Write(val, data, offset); if (ushort.TryParse(split[j].Trim(), ns, ic, out val))
offset += sizeof(ushort); {
Write(val, data, offset);
offset += sizeof(ushort);
}
} }
break; break;
case MetaStructureEntryDataType.SignedInt: case MetaStructureEntryDataType.SignedInt: //expecting space-separated array.
split = node.InnerText.Split();
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
int val = Convert.ToInt32(split[j], 10); int val;// = Convert.ToInt32(split[j], 10);
Write(val, data, offset); if (int.TryParse(split[j].Trim(), ns, ic, out val))
offset += sizeof(int); {
Write(val, data, offset);
offset += sizeof(int);
}
} }
break; break;
case MetaStructureEntryDataType.UnsignedInt: case MetaStructureEntryDataType.UnsignedInt: //expecting space-separated array.
split = node.InnerText.Split();
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
uint val = Convert.ToUInt32(split[j], 10); uint val;// = Convert.ToUInt32(split[j], 10);
Write(val, data, offset); if (uint.TryParse(split[j].Trim(), ns, ic, out val))
offset += sizeof(uint); {
Write(val, data, offset);
offset += sizeof(uint);
}
} }
break; break;
case MetaStructureEntryDataType.Float: case MetaStructureEntryDataType.Float: //expecting space-separated array.
split = node.InnerText.Split();
for (int j = 0; j < split.Length; j++) for (int j = 0; j < split.Length; j++)
{ {
float val = FloatUtil.Parse(split[j]); float val;// = FloatUtil.Parse(split[j]);
Write(val, data, offset); if (FloatUtil.TryParse(split[j].Trim(), out val))
offset += sizeof(float); {
Write(val, data, offset);
offset += sizeof(float);
}
} }
break; break;
} }
@ -685,9 +705,8 @@ namespace CodeWalker.GameFiles
return chunks.ToArray(); 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 infos = MetaTypes.GetEnumInfo(type);
if (infos == null) if (infos == null)
@ -695,13 +714,48 @@ namespace CodeWalker.GameFiles
return 0; return 0;
} }
for (int j = 0; j < infos.Entries.Length; j++)
{
var entry = infos.Entries[j];
if (entry.EntryNameHash == enumName) bool isFlags = (dataType == MetaStructureEntryDataType.IntFlags1) ||
(dataType == MetaStructureEntryDataType.IntFlags2);// ||
//(dataType == MetaStructureEntryDataType.ShortFlags);
if (isFlags)
{
//flags enum. (multiple values, comma-separated)
var split = enumString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
int enumVal = 0;
for (int i = 0; i < split.Length; i++)
{ {
return entry.EntryValue; var enumName = (MetaName)(uint)GetHash(split[i].Trim());
for (int j = 0; j < infos.Entries.Length; j++)
{
var entry = infos.Entries[j];
if (entry.EntryNameHash == enumName)
{
enumVal += (1 << entry.EntryValue);
break;
}
}
}
return enumVal;
}
else
{
//single value enum.
var enumName = (MetaName)(uint)GetHash(enumString);
for (int j = 0; j < infos.Entries.Length; j++)
{
var entry = infos.Entries[j];
if (entry.EntryNameHash == enumName)
{
return entry.EntryValue;
}
} }
} }

View File

@ -1283,7 +1283,7 @@ namespace CodeWalker.GameFiles
public string HeatsTyre { get; set; } public string HeatsTyre { get; set; }
public string Material { get; set; } public string Material { get; set; }
public Color4 Colour { get; set; } public Color Colour { get; set; }
public override string ToString() public override string ToString()
{ {
@ -1293,14 +1293,19 @@ namespace CodeWalker.GameFiles
public static class BoundsMaterialTypes public static class BoundsMaterialTypes
{ {
private static Dictionary<string, Color4> ColourDict; private static Dictionary<string, Color> ColourDict;
private static List<BoundsMaterialData> Materials; private static List<BoundsMaterialData> Materials;
public static void Init(GameFileCache gameFileCache) public static void Init(GameFileCache gameFileCache)
{ {
var rpfman = gameFileCache.RpfMan; var rpfman = gameFileCache.RpfMan;
InitColours(); var dic = new Dictionary<string,Color>();
string filename2 = "common.rpf\\data\\effects\\materialfx.dat";
string txt2 = rpfman.GetFileUTF8Text(filename2);
AddMaterialfxDat(txt2, dic);
ColourDict = dic;
var list = new List<BoundsMaterialData>(); var list = new List<BoundsMaterialData>();
string filename = "common.rpf\\data\\materials\\materials.dat"; string filename = "common.rpf\\data\\materials\\materials.dat";
@ -1314,25 +1319,47 @@ namespace CodeWalker.GameFiles
Materials = list; Materials = list;
} }
private static void InitColours() //Only gets the colors
private static void AddMaterialfxDat(string txt, Dictionary<string, Color> dic)
{ {
var dict = new Dictionary<string, Color4>(); dic.Clear();
string txt = File.ReadAllText("Materials.txt"); if (txt == null) return;
string[] lines = txt.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < lines.Length; i++) string[] lines = txt.Split('\n');
string startLine = "MTLFX_TABLE_START";
string endLine = "MTLFX_TABLE_END";
for (int i = 1; i < lines.Length; i++)
{ {
var line = lines[i]; var line = lines[i];
if (line.Length < 10) continue;
if (line[0] == '#') continue; if (line[0] == '#') continue;
if (line.StartsWith(startLine)) continue;
if (line.StartsWith(endLine)) break;
string[] parts = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries); string[] parts = line.Split(new[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2) continue;
string name = parts[0].Trim(); if (parts.Length < 5) continue; // FXGroup R G B ...
string cstr = parts[1].Trim();
uint cval = Convert.ToUInt32(cstr, 16); int cp = 0;
Color4 c = new Color4(cval); Color c = new Color();
dict[name] = c; c.A = 0xFF;
string fxgroup = string.Empty;
for (int p = 0; p < parts.Length; p++)
{
string part = parts[p].Trim();
if (string.IsNullOrWhiteSpace(part)) continue;
switch (cp)
{
case 0: fxgroup = part; break;
case 1: c.R = byte.Parse(part); break;
case 2: c.G = byte.Parse(part); break;
case 3: c.B = byte.Parse(part); break;
}
cp++;
}
dic.Add(fxgroup, c);
} }
ColourDict = dict;
} }
private static void AddMaterialsDat(string txt, List<BoundsMaterialData> list) private static void AddMaterialsDat(string txt, List<BoundsMaterialData> list)
@ -1384,14 +1411,14 @@ namespace CodeWalker.GameFiles
if (cp != 23) if (cp != 23)
{ } { }
Color4 c; Color c;
if ((ColourDict != null) && (ColourDict.TryGetValue(d.Name, out c))) if ((ColourDict != null) && (ColourDict.TryGetValue(d.FXGroup, out c)))
{ {
d.Colour = c; d.Colour = c;
} }
else else
{ {
d.Colour = new Color4(0xFFCCCCCC); d.Colour = new Color(0xFFCCCCCC);
} }
@ -1416,6 +1443,13 @@ namespace CodeWalker.GameFiles
return Materials[type.Index]; return Materials[type.Index];
} }
public static BoundsMaterialData GetMaterial(byte index)
{
if (Materials == null) return null;
if ((int)index >= Materials.Count) return null;
return Materials[index];
}
public static string GetMaterialName(BoundsMaterialType type) public static string GetMaterialName(BoundsMaterialType type)
{ {
var m = GetMaterial(type); var m = GetMaterial(type);
@ -1423,10 +1457,10 @@ namespace CodeWalker.GameFiles
return m.Name; return m.Name;
} }
public static Color4 GetMaterialColour(BoundsMaterialType type) public static Color GetMaterialColour(BoundsMaterialType type)
{ {
var m = GetMaterial(type); var m = GetMaterial(type);
if (m == null) return new Color4(0xFFCCCCCC); if (m == null) return new Color(0xFFCCCCCC);
return m.Colour; return m.Colour;
} }
} }

View File

@ -718,16 +718,16 @@ namespace CodeWalker.GameFiles
//public float TranslationX { get; set; } //public float TranslationX { get; set; }
//public float TranslationY { get; set; } //public float TranslationY { get; set; }
//public float TranslationZ { get; set; } //public float TranslationZ { get; set; }
public uint Unknown_1Ch { get; set; } // 0x00000000 public uint Unknown_1Ch { get; set; } // 0x00000000 RHW?
public float Unknown_20h { get; set; } // 1.0 public float ScaleX { get; set; } // 1.0
public float Unknown_24h { get; set; } // 1.0 public float ScaleY { get; set; } // 1.0
public float Unknown_28h { get; set; } // 1.0 public float ScaleZ { get; set; } // 1.0
public float Unknown_2Ch { get; set; } // 1.0 public float Unknown_2Ch { get; set; } // 1.0 RHW?
public ushort Unknown_30h { get; set; } //limb end index? IK chain? public ushort NextSiblingIndex { get; set; } //limb end index? IK chain?
public short ParentIndex { get; set; } public short ParentIndex { get; set; }
public uint Unknown_34h { get; set; } // 0x00000000 public uint Unknown_34h { get; set; } // 0x00000000
public ulong NamePointer { get; set; } public ulong NamePointer { get; set; }
public ushort Unknown_40h { get; set; } public ushort Flags { get; set; }
public ushort Unknown_42h { get; set; } public ushort Unknown_42h { get; set; }
public ushort Id { get; set; } public ushort Id { get; set; }
public ushort Unknown_46h { get; set; } public ushort Unknown_46h { get; set; }
@ -756,15 +756,15 @@ namespace CodeWalker.GameFiles
//this.TranslationY = reader.ReadSingle(); //this.TranslationY = reader.ReadSingle();
//this.TranslationZ = reader.ReadSingle(); //this.TranslationZ = reader.ReadSingle();
this.Unknown_1Ch = reader.ReadUInt32(); this.Unknown_1Ch = reader.ReadUInt32();
this.Unknown_20h = reader.ReadSingle(); this.ScaleX = reader.ReadSingle();
this.Unknown_24h = reader.ReadSingle(); this.ScaleY = reader.ReadSingle();
this.Unknown_28h = reader.ReadSingle(); this.ScaleZ = reader.ReadSingle();
this.Unknown_2Ch = reader.ReadSingle(); this.Unknown_2Ch = reader.ReadSingle();
this.Unknown_30h = reader.ReadUInt16(); this.NextSiblingIndex = reader.ReadUInt16();
this.ParentIndex = reader.ReadInt16(); this.ParentIndex = reader.ReadInt16();
this.Unknown_34h = reader.ReadUInt32(); this.Unknown_34h = reader.ReadUInt32();
this.NamePointer = reader.ReadUInt64(); this.NamePointer = reader.ReadUInt64();
this.Unknown_40h = reader.ReadUInt16(); this.Flags = reader.ReadUInt16();
this.Unknown_42h = reader.ReadUInt16(); this.Unknown_42h = reader.ReadUInt16();
this.Id = reader.ReadUInt16(); this.Id = reader.ReadUInt16();
this.Unknown_46h = reader.ReadUInt16(); this.Unknown_46h = reader.ReadUInt16();
@ -796,15 +796,15 @@ namespace CodeWalker.GameFiles
//writer.Write(this.TranslationY); //writer.Write(this.TranslationY);
//writer.Write(this.TranslationZ); //writer.Write(this.TranslationZ);
writer.Write(this.Unknown_1Ch); writer.Write(this.Unknown_1Ch);
writer.Write(this.Unknown_20h); writer.Write(this.ScaleX);
writer.Write(this.Unknown_24h); writer.Write(this.ScaleY);
writer.Write(this.Unknown_28h); writer.Write(this.ScaleZ);
writer.Write(this.Unknown_2Ch); writer.Write(this.Unknown_2Ch);
writer.Write(this.Unknown_30h); writer.Write(this.NextSiblingIndex);
writer.Write(this.ParentIndex); writer.Write(this.ParentIndex);
writer.Write(this.Unknown_34h); writer.Write(this.Unknown_34h);
writer.Write(this.NamePointer); writer.Write(this.NamePointer);
writer.Write(this.Unknown_40h); writer.Write(this.Flags);
writer.Write(this.Unknown_42h); writer.Write(this.Unknown_42h);
writer.Write(this.Id); writer.Write(this.Id);
writer.Write(this.Unknown_46h); writer.Write(this.Unknown_46h);
@ -968,12 +968,8 @@ namespace CodeWalker.GameFiles
public float Unknown_50h { get; set; } // -pi public float Unknown_50h { get; set; } // -pi
public float Unknown_54h { get; set; } // pi public float Unknown_54h { get; set; } // pi
public float Unknown_58h { get; set; } // 1.0 public float Unknown_58h { get; set; } // 1.0
public float Unknown_5Ch { get; set; } public Vector3 Min { get; set; }
public float Unknown_60h { get; set; } public Vector3 Max { get; set; }
public float Unknown_64h { get; set; }
public float Unknown_68h { get; set; }
public float Unknown_6Ch { get; set; }
public float Unknown_70h { get; set; }
public float Unknown_74h { get; set; } // pi public float Unknown_74h { get; set; } // pi
public float Unknown_78h { get; set; } // -pi public float Unknown_78h { get; set; } // -pi
public float Unknown_7Ch { get; set; } // pi public float Unknown_7Ch { get; set; } // pi

View File

@ -54,8 +54,8 @@ namespace CodeWalker.GameFiles
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
public ulong IndicesPointer { get; set; } public ulong IndicesPointer { get; set; }
public ulong AdjPolysPointer { get; set; } public ulong EdgesPointer { get; set; }
public uint AdjPolysIndicesCount { get; set; } public uint EdgesIndicesCount { get; set; }
public NavMeshUintArray AdjAreaIDs { get; set; } public NavMeshUintArray AdjAreaIDs { get; set; }
public ulong PolysPointer { get; set; } public ulong PolysPointer { get; set; }
public ulong SectorTreePointer { get; set; } public ulong SectorTreePointer { get; set; }
@ -79,7 +79,7 @@ namespace CodeWalker.GameFiles
public NavMeshList<NavMeshVertex> Vertices { get; set; } public NavMeshList<NavMeshVertex> Vertices { get; set; }
public NavMeshList<ushort> Indices { 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 NavMeshList<NavMeshPoly> Polys { get; set; }
public NavMeshSector SectorTree { get; set; } public NavMeshSector SectorTree { get; set; }
public NavMeshPortal[] Portals { get; set; } public NavMeshPortal[] Portals { get; set; }
@ -109,8 +109,8 @@ namespace CodeWalker.GameFiles
Unused_078h = reader.ReadUInt32(); Unused_078h = reader.ReadUInt32();
Unused_07Ch = reader.ReadUInt32(); Unused_07Ch = reader.ReadUInt32();
IndicesPointer = reader.ReadUInt64(); IndicesPointer = reader.ReadUInt64();
AdjPolysPointer = reader.ReadUInt64(); EdgesPointer = reader.ReadUInt64();
AdjPolysIndicesCount = reader.ReadUInt32(); EdgesIndicesCount = reader.ReadUInt32();
AdjAreaIDs = reader.ReadStruct<NavMeshUintArray>(); AdjAreaIDs = reader.ReadStruct<NavMeshUintArray>();
PolysPointer = reader.ReadUInt64(); PolysPointer = reader.ReadUInt64();
SectorTreePointer = reader.ReadUInt64(); SectorTreePointer = reader.ReadUInt64();
@ -135,7 +135,7 @@ namespace CodeWalker.GameFiles
Vertices = reader.ReadBlockAt<NavMeshList<NavMeshVertex>>(VerticesPointer); Vertices = reader.ReadBlockAt<NavMeshList<NavMeshVertex>>(VerticesPointer);
Indices = reader.ReadBlockAt<NavMeshList<ushort>>(IndicesPointer); Indices = reader.ReadBlockAt<NavMeshList<ushort>>(IndicesPointer);
AdjPolys = reader.ReadBlockAt<NavMeshList<NavMeshAdjPoly>>(AdjPolysPointer); Edges = reader.ReadBlockAt<NavMeshList<NavMeshEdge>>(EdgesPointer);
Polys = reader.ReadBlockAt<NavMeshList<NavMeshPoly>>(PolysPointer); Polys = reader.ReadBlockAt<NavMeshList<NavMeshPoly>>(PolysPointer);
SectorTree = reader.ReadBlockAt<NavMeshSector>(SectorTreePointer); SectorTree = reader.ReadBlockAt<NavMeshSector>(SectorTreePointer);
Portals = reader.ReadStructsAt<NavMeshPortal>(PortalsPointer, PortalsCount); Portals = reader.ReadStructsAt<NavMeshPortal>(PortalsPointer, PortalsCount);
@ -150,7 +150,7 @@ namespace CodeWalker.GameFiles
VerticesPointer = (ulong)(Vertices != null ? Vertices.FilePosition : 0); VerticesPointer = (ulong)(Vertices != null ? Vertices.FilePosition : 0);
IndicesPointer = (ulong)(Indices != null ? Indices.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); PolysPointer = (ulong)(Polys != null ? Polys.FilePosition : 0);
SectorTreePointer = (ulong)(SectorTree != null ? SectorTree.FilePosition : 0); SectorTreePointer = (ulong)(SectorTree != null ? SectorTree.FilePosition : 0);
PortalsPointer = (ulong)(PortalsBlock?.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((uint)ContentFlags);
writer.Write(VersionUnk1); writer.Write(VersionUnk1);
writer.Write(Unused_018h); writer.Write(Unused_018h);
@ -169,8 +202,8 @@ namespace CodeWalker.GameFiles
writer.Write(Unused_078h); writer.Write(Unused_078h);
writer.Write(Unused_07Ch); writer.Write(Unused_07Ch);
writer.Write(IndicesPointer); writer.Write(IndicesPointer);
writer.Write(AdjPolysPointer); writer.Write(EdgesPointer);
writer.Write(AdjPolysIndicesCount); writer.Write(EdgesIndicesCount);
writer.WriteStruct(AdjAreaIDs); writer.WriteStruct(AdjAreaIDs);
writer.Write(PolysPointer); writer.Write(PolysPointer);
writer.Write(SectorTreePointer); writer.Write(SectorTreePointer);
@ -192,13 +225,19 @@ 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());
if (Vertices != null) list.Add(Vertices); if (Vertices != null) list.Add(Vertices);
if (Indices != null) list.Add(Indices); 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 (Polys != null) list.Add(Polys);
if (SectorTree != null) list.Add(SectorTree); 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() public override string ToString()
{ {
return "(Size: " + FloatUtil.GetVector3String(AABBSize) + ")"; 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() public override string ToString()
{ {
@ -459,7 +551,7 @@ namespace CodeWalker.GameFiles
} }
ListParts = parts; ListParts = parts;
ListOffsets = offsets.ToArray(); 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 NavMeshEdgePart _Poly1;
public NavMeshAdjPolyPart Unknown_4h { get; set; } 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() public override string ToString()
{ {
return //Unknown_0h.Bin + " | " + Unknown_4h.Bin + " | " + return //Poly1.Bin + " | " + Poly2.Bin + " | " +
Unknown_0h.ToString() + " | " + Unknown_4h.ToString(); _Poly1.ToString() + " | " + _Poly2.ToString();
} }
} }
[TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshAdjPolyPart [TypeConverter(typeof(ExpandableObjectConverter))] public struct NavMeshEdgePart
{ {
public uint Value { get; set; } public uint Value { get; set; }
@ -616,14 +710,15 @@ namespace CodeWalker.GameFiles
} }
} }
public uint AreaIDInd { get { return (Value >> 0) & 0x1F; } } public uint AreaIDInd { get { return (Value >> 0) & 0x1F; } set { Value = (Value & 0xFFFFFFE0) | (value & 0x1F); } }
public uint PolyID { get { return (Value >> 5) & 0x3FFF; } } public uint PolyID { get { return (Value >> 5) & 0x3FFF; } set { Value = (Value & 0xFFF8001F) | ((value & 0x3FFF) << 5); } }
public uint Unk2 { get { return (Value >> 19) & 0x3; } } public uint Unk2 { get { return (Value >> 19) & 0x3; } set { Value = (Value & 0xFFE7FFFF) | ((value & 0x3) << 19); } }
public uint Unk3 { get { return (Value >> 21) & 0x7FF; } } public uint Unk3 { get { return (Value >> 21) & 0x7FF; } set { Value = (Value & 0x001FFFFF) | ((value & 0x7FF) << 21); } }
public override string ToString() 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 NavMeshAABB CellAABB { get; set; }
public FlagsUint Unknown_24h { get; set; } public FlagsUint Unknown_24h { get; set; }
public FlagsUint Unknown_28h { get; set; } public FlagsUint Unknown_28h { get; set; }
public ushort PartFlags { get; set; } public uint PartFlags { get; set; }
public ushort PortalLinkID { get; set; }
//public int IndexUnk { get { return (IndexFlags >> 0) & 31; } } //always 0 //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 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 ushort PartID { get { return (ushort)((PartFlags >> 4) & 0xFF); } set { PartFlags = ((PartFlags & 0xFFFFF00F) | (((uint)value & 0xFF) << 4)); } }
public byte PortalType { get { return (byte)((PartFlags >> 12) & 0xF); } set { PartFlags = (ushort)((PartFlags & 0x0FFF) | ((value & 0xF) << 12)); } } 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); } } 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 + ", " + Unknown_28h.Hex + ", " +
//PartFlags.ToString() + ", " + //PartUnk1.ToString() + ", " + //PartFlags.ToString() + ", " + //PartUnk1.ToString() + ", " +
PartID.ToString() + ", " + PartID.ToString() + ", " +
PortalType.ToString() + ", " + PortalLinkCount.ToString() + ", " +
PortalLinkID.ToString(); PortalLinkID.ToString();
} }
} }
@ -790,8 +885,8 @@ namespace CodeWalker.GameFiles
public ushort[] PolyIDs { get; set; } public ushort[] PolyIDs { get; set; }
public NavMeshPoint[] Points { get; set; } public NavMeshPoint[] Points { get; set; }
private ResourceSystemStructBlock<ushort> PolyIDsBlock = null; public ResourceSystemStructBlock<ushort> PolyIDsBlock = null;
private ResourceSystemStructBlock<NavMeshPoint> PointsBlock = null; public ResourceSystemStructBlock<NavMeshPoint> PointsBlock = null;
public override void Read(ResourceDataReader reader, params object[] parameters) public override void Read(ResourceDataReader reader, params object[] parameters)
{ {

View File

@ -626,6 +626,7 @@ namespace CodeWalker.GameFiles
RpfFileEntry entry = CreateResourceFileEntry(ref data, 0); RpfFileEntry entry = CreateResourceFileEntry(ref data, 0);
if ((data != null) && (entry != null)) if ((data != null) && (entry != null))
{ {
data = ResourceBuilder.Decompress(data);
file = new T(); file = new T();
file.Load(data, entry); file.Load(data, entry);
} }

View File

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

View File

@ -140,21 +140,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)); 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) public static Vector3 ParseVector3String(string s)
{ {
Vector3 p = new Vector3(0.0f); Vector3 p = new Vector3(0.0f);
string[] ss = s.Split(','); string[] ss = s.Split(',');
if (ss.Length > 0) if (ss.Length > 0)
{ {
FloatUtil.TryParse(ss[0].Trim(), out p.X); TryParse(ss[0].Trim(), out p.X);
} }
if (ss.Length > 1) if (ss.Length > 1)
{ {
FloatUtil.TryParse(ss[1].Trim(), out p.Y); TryParse(ss[1].Trim(), out p.Y);
} }
if (ss.Length > 2) if (ss.Length > 2)
{ {
FloatUtil.TryParse(ss[2].Trim(), out p.Z); TryParse(ss[2].Trim(), out p.Z);
} }
return p; return p;
} }
@ -172,19 +188,19 @@ namespace CodeWalker
string[] ss = s.Split(','); string[] ss = s.Split(',');
if (ss.Length > 0) if (ss.Length > 0)
{ {
FloatUtil.TryParse(ss[0].Trim(), out p.X); TryParse(ss[0].Trim(), out p.X);
} }
if (ss.Length > 1) if (ss.Length > 1)
{ {
FloatUtil.TryParse(ss[1].Trim(), out p.Y); TryParse(ss[1].Trim(), out p.Y);
} }
if (ss.Length > 2) if (ss.Length > 2)
{ {
FloatUtil.TryParse(ss[2].Trim(), out p.Z); TryParse(ss[2].Trim(), out p.Z);
} }
if (ss.Length > 3) if (ss.Length > 3)
{ {
FloatUtil.TryParse(ss[3].Trim(), out p.W); TryParse(ss[3].Trim(), out p.W);
} }
return p; return p;
} }

View File

@ -4,18 +4,17 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using CodeWalker.GameFiles;
namespace CodeWalker namespace CodeWalker
{ {
public static class Vectors public static class Vectors
{ {
public static Vector3 XYZ(this Vector4 v) public static Vector3 XYZ(this Vector4 v)
{ {
return new Vector3(v.X, v.Y, v.Z); return new Vector3(v.X, v.Y, v.Z);
} }
public static Vector3 Round(this Vector3 v) 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)); return new Vector3((float)Math.Round(v.X), (float)Math.Round(v.Y), (float)Math.Round(v.Z));
@ -26,6 +25,10 @@ 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)); 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 Quaternion ToQuaternion(this Vector4 v)
{
return new Quaternion(v);
}
} }

View File

@ -420,13 +420,6 @@ namespace CodeWalker.World
{ {
AddRpfYnds(rpffile, yndentries); AddRpfYnds(rpffile, yndentries);
} }
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load nodes from current dlc rpfs
{
foreach (var rpffile in dlcrpf.Children)
{
AddRpfYnds(rpffile, yndentries);
}
}
var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load nodes from patch area... var updrpf = rpfman.FindRpfFile("update\\update.rpf"); //load nodes from patch area...
if (updrpf != null) if (updrpf != null)
{ {
@ -435,6 +428,13 @@ namespace CodeWalker.World
AddRpfYnds(rpffile, yndentries); AddRpfYnds(rpffile, yndentries);
} }
} }
foreach (var dlcrpf in GameFileCache.DlcActiveRpfs) //load nodes from current dlc rpfs
{
foreach (var rpffile in dlcrpf.Children)
{
AddRpfYnds(rpffile, yndentries);
}
}
Vector3 corner = new Vector3(-8192, -8192, -2048); Vector3 corner = new Vector3(-8192, -8192, -2048);
@ -1199,7 +1199,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(); var res = new SpaceRayIntersectResult();
if (GameFileCache == null) return res; if (GameFileCache == null) return res;
@ -1225,6 +1225,7 @@ namespace CodeWalker.World
float polyhittestdist = 0; float polyhittestdist = 0;
bool hit = false; bool hit = false;
BoundPolygon hitpoly = null; BoundPolygon hitpoly = null;
BoundMaterial_s hitmat = new BoundMaterial_s();
Vector3 hitnorm = Vector3.Zero; Vector3 hitnorm = Vector3.Zero;
Vector3 hitpos = Vector3.Zero; Vector3 hitpos = Vector3.Zero;
while (cell != null) while (cell != null)
@ -1233,6 +1234,12 @@ namespace CodeWalker.World
{ {
foreach (var bound in cell.BoundsList) foreach (var bound in cell.BoundsList)
{ {
uint l = bound.Layer;
if ((layers != null) && (l < 3))
{
if (!layers[l]) continue;
}
box.Minimum = bound.Min; box.Minimum = bound.Min;
box.Maximum = bound.Max; box.Maximum = bound.Max;
float boxhitdisttest; float boxhitdisttest;
@ -1395,6 +1402,10 @@ namespace CodeWalker.World
hit = true; hit = true;
hitnorm = n1; hitnorm = n1;
hitpoly = polygon; 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++; polytestcount++;
} }
@ -1474,6 +1485,7 @@ namespace CodeWalker.World
res.Hit = hit; res.Hit = hit;
res.HitDist = itemhitdist; res.HitDist = itemhitdist;
res.HitPolygon = hitpoly; res.HitPolygon = hitpoly;
res.Material = hitmat;
res.Position = hitpos; res.Position = hitpos;
res.Normal = hitnorm; res.Normal = hitnorm;
@ -1731,7 +1743,7 @@ namespace CodeWalker.World
public const int CellCount = 500; //cells along a side, total cell count is this squared 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 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 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 CellSizeInv = 1.0f / CellSize; //inverse of the cell size.
public const float CellSizeHalf = CellSize * 0.5f; //half the cell size public const float CellSizeHalf = CellSize * 0.5f; //half the cell size
@ -2013,7 +2025,7 @@ namespace CodeWalker.World
public float CellSizeInv; //inverse of the cell size. public float CellSizeInv; //inverse of the cell size.
public int CellCountX = 100; public int CellCountX = 100;
public int CellCountY = 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 float CornerY = -6000.0f;
public SpaceNavGrid() public SpaceNavGrid()
@ -2043,7 +2055,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) public Vector2I GetCellPos(Vector3 p)
{ {
Vector3 ind = (p - new Vector3(CornerX, CornerY, 0)) * CellSizeInv; Vector3 ind = (p - new Vector3(CornerX, CornerY, 0)) * CellSizeInv;
@ -2069,7 +2084,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 public class SpaceNavGridCell
@ -2106,6 +2129,7 @@ namespace CodeWalker.World
public int TestedNodeCount; public int TestedNodeCount;
public int TestedPolyCount; public int TestedPolyCount;
public bool TestComplete; public bool TestComplete;
public BoundMaterial_s Material;
} }
public struct SpaceSphereIntersectResult public struct SpaceSphereIntersectResult
{ {

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,409 @@
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
<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" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</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" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f//
/wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA
AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc
skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU
0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq
+ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz
/eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR
p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm
+P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB
AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/
/f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/
+fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd
4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA
/v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/
9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA
AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA
/v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/
/P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/
/f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB///////
//AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA
H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A
A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA
/f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A
AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf
AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4
AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A//
///////gD/////////Af//////////////8=
</value>
</data>
</root>

View File

@ -328,6 +328,12 @@
<Compile Include="Project\Panels\EditYmapCarGenPanel.Designer.cs"> <Compile Include="Project\Panels\EditYmapCarGenPanel.Designer.cs">
<DependentUpon>EditYmapCarGenPanel.cs</DependentUpon> <DependentUpon>EditYmapCarGenPanel.cs</DependentUpon>
</Compile> </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"> <Compile Include="Project\Panels\EditYmapEntityPanel.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@ -382,12 +388,24 @@
<Compile Include="Project\Panels\EditYnvPortalPanel.Designer.cs"> <Compile Include="Project\Panels\EditYnvPortalPanel.Designer.cs">
<DependentUpon>EditYnvPortalPanel.cs</DependentUpon> <DependentUpon>EditYnvPortalPanel.cs</DependentUpon>
</Compile> </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"> <Compile Include="Project\Panels\EditYtypPanel.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="Project\Panels\EditYtypPanel.Designer.cs"> <Compile Include="Project\Panels\EditYtypPanel.Designer.cs">
<DependentUpon>EditYtypPanel.cs</DependentUpon> <DependentUpon>EditYtypPanel.cs</DependentUpon>
</Compile> </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"> <Compile Include="Project\Panels\ProjectExplorerPanel.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@ -469,12 +487,6 @@
<Compile Include="Utils\MapUtils.cs" /> <Compile Include="Utils\MapUtils.cs" />
<Compile Include="GameFiles\TextureFormats.cs" /> <Compile Include="GameFiles\TextureFormats.cs" />
<Compile Include="Utils\TextureLoader.cs" /> <Compile Include="Utils\TextureLoader.cs" />
<Compile Include="Project\ProjectFormOLD.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Project\ProjectFormOLD.Designer.cs">
<DependentUpon>ProjectFormOLD.cs</DependentUpon>
</Compile>
<Compile Include="WorldInfoForm.cs"> <Compile Include="WorldInfoForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@ -596,6 +608,9 @@
<EmbeddedResource Include="Project\Panels\EditYmapCarGenPanel.resx"> <EmbeddedResource Include="Project\Panels\EditYmapCarGenPanel.resx">
<DependentUpon>EditYmapCarGenPanel.cs</DependentUpon> <DependentUpon>EditYmapCarGenPanel.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYtypArchetypeMloRoomPanel.resx">
<DependentUpon>EditYtypArchetypeMloRoomPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYmapEntityPanel.resx"> <EmbeddedResource Include="Project\Panels\EditYmapEntityPanel.resx">
<DependentUpon>EditYmapEntityPanel.cs</DependentUpon> <DependentUpon>EditYmapEntityPanel.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@ -623,9 +638,15 @@
<EmbeddedResource Include="Project\Panels\EditYnvPortalPanel.resx"> <EmbeddedResource Include="Project\Panels\EditYnvPortalPanel.resx">
<DependentUpon>EditYnvPortalPanel.cs</DependentUpon> <DependentUpon>EditYnvPortalPanel.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYtypArchetypePanel.resx">
<DependentUpon>EditYtypArchetypePanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\EditYtypPanel.resx"> <EmbeddedResource Include="Project\Panels\EditYtypPanel.resx">
<DependentUpon>EditYtypPanel.cs</DependentUpon> <DependentUpon>EditYtypPanel.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Project\Panels\GenerateNavMeshPanel.resx">
<DependentUpon>GenerateNavMeshPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Project\Panels\ProjectExplorerPanel.resx"> <EmbeddedResource Include="Project\Panels\ProjectExplorerPanel.resx">
<DependentUpon>ProjectExplorerPanel.cs</DependentUpon> <DependentUpon>ProjectExplorerPanel.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
@ -654,9 +675,6 @@
<EmbeddedResource Include="SelectFolderForm.resx"> <EmbeddedResource Include="SelectFolderForm.resx">
<DependentUpon>SelectFolderForm.cs</DependentUpon> <DependentUpon>SelectFolderForm.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Project\ProjectFormOLD.resx">
<DependentUpon>ProjectFormOLD.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="SettingsForm.resx"> <EmbeddedResource Include="SettingsForm.resx">
<DependentUpon>SettingsForm.cs</DependentUpon> <DependentUpon>SettingsForm.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>

View File

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

View File

@ -2201,7 +2201,9 @@ namespace CodeWalker
var fpaths = OpenFileDialog.FileNames; var fpaths = OpenFileDialog.FileNames;
foreach (var fpath in fpaths) foreach (var fpath in fpaths)
{ {
#if !DEBUG
try try
#endif
{ {
if (!File.Exists(fpath)) if (!File.Exists(fpath))
{ {
@ -2254,10 +2256,13 @@ namespace CodeWalker
RpfFile.CreateFile(parentrpffldr, fname, data); RpfFile.CreateFile(parentrpffldr, fname, data);
} }
#if !DEBUG
catch (Exception ex) catch (Exception ex)
{ {
MessageBox.Show(ex.Message, "Unable to import file"); MessageBox.Show(ex.Message, "Unable to import file");
} }
#endif
} }
CurrentFolder.ListItems = null; CurrentFolder.ListItems = null;

View File

@ -138,6 +138,18 @@ namespace CodeWalker.Project.Panels
} }
} }
if (ymap.GrassInstanceBatches != null)
{
foreach (var batch in ymap.GrassInstanceBatches)
{
var ytyp = batch.Archetype?.Ytyp;
var ytypname = getYtypName(ytyp);
if (ytyp != null)
{
mapdeps[ytypname] = ytyp;
}
}
}
sb.AppendLine(" <Item>"); sb.AppendLine(" <Item>");
sb.AppendLine(" <imapName>" + ymapname + "</imapName>"); sb.AppendLine(" <imapName>" + ymapname + "</imapName>");

View File

@ -71,6 +71,7 @@
this.EntityNumChildrenTextBox = new System.Windows.Forms.TextBox(); this.EntityNumChildrenTextBox = new System.Windows.Forms.TextBox();
this.label25 = new System.Windows.Forms.Label(); this.label25 = new System.Windows.Forms.Label();
this.EntityExtensionsTabPage = new System.Windows.Forms.TabPage(); this.EntityExtensionsTabPage = new System.Windows.Forms.TabPage();
this.label1 = new System.Windows.Forms.Label();
this.EntityPivotTabPage = new System.Windows.Forms.TabPage(); this.EntityPivotTabPage = new System.Windows.Forms.TabPage();
this.label95 = new System.Windows.Forms.Label(); this.label95 = new System.Windows.Forms.Label();
this.EntityPivotEditCheckBox = new System.Windows.Forms.CheckBox(); this.EntityPivotEditCheckBox = new System.Windows.Forms.CheckBox();
@ -79,7 +80,6 @@
this.EntityPivotRotationNormalizeButton = new System.Windows.Forms.Button(); this.EntityPivotRotationNormalizeButton = new System.Windows.Forms.Button();
this.label94 = new System.Windows.Forms.Label(); this.label94 = new System.Windows.Forms.Label();
this.EntityPivotRotationTextBox = new System.Windows.Forms.TextBox(); this.EntityPivotRotationTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.EntityTabControl.SuspendLayout(); this.EntityTabControl.SuspendLayout();
this.EntityGeneralTabPage.SuspendLayout(); this.EntityGeneralTabPage.SuspendLayout();
this.EntityLodTabPage.SuspendLayout(); this.EntityLodTabPage.SuspendLayout();
@ -153,12 +153,12 @@
this.EntityFlagsCheckedListBox.CheckOnClick = true; this.EntityFlagsCheckedListBox.CheckOnClick = true;
this.EntityFlagsCheckedListBox.FormattingEnabled = true; this.EntityFlagsCheckedListBox.FormattingEnabled = true;
this.EntityFlagsCheckedListBox.Items.AddRange(new object[] { this.EntityFlagsCheckedListBox.Items.AddRange(new object[] {
"1 - Unk01", "1 - Allow full rotation",
"2 - Unk02", "2 - Unk02",
"4 - Unk03", "4 - Unk03",
"8 - Unk04", "8 - Unk04",
"16 - Unk05", "16 - Unk05",
"32 - Unk06", "32 - Static entity",
"64 - Unk07", "64 - Unk07",
"128 - Unk08", "128 - Unk08",
"256 - Unk09", "256 - Unk09",
@ -178,11 +178,11 @@
"4194304 - Unk23", "4194304 - Unk23",
"8388608 - Unk24", "8388608 - Unk24",
"16777216 - Unk25", "16777216 - Unk25",
"33554432 - Unk26", "33554432 - Interior proxy",
"67108864 - Unk27", "67108864 - Unk27",
"134217728 - Unk28", "134217728 - Reflection proxy",
"268435456 - Unk29", "268435456 - Unk29",
"536870912 - Unk30", "536870912 - Mirror proxy",
"1073741824 - Unk31", "1073741824 - Unk31",
"2147483648 - Unk32"}); "2147483648 - Unk32"});
this.EntityFlagsCheckedListBox.Location = new System.Drawing.Point(348, 113); this.EntityFlagsCheckedListBox.Location = new System.Drawing.Point(348, 113);
@ -575,6 +575,15 @@
this.EntityExtensionsTabPage.Text = "Extensions"; this.EntityExtensionsTabPage.Text = "Extensions";
this.EntityExtensionsTabPage.UseVisualStyleBackColor = true; this.EntityExtensionsTabPage.UseVisualStyleBackColor = true;
// //
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(27, 27);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(157, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Entity extensions editing TODO!";
//
// EntityPivotTabPage // EntityPivotTabPage
// //
this.EntityPivotTabPage.Controls.Add(this.label95); this.EntityPivotTabPage.Controls.Add(this.label95);
@ -660,15 +669,6 @@
this.EntityPivotRotationTextBox.TabIndex = 25; this.EntityPivotRotationTextBox.TabIndex = 25;
this.EntityPivotRotationTextBox.TextChanged += new System.EventHandler(this.EntityPivotRotationTextBox_TextChanged); this.EntityPivotRotationTextBox.TextChanged += new System.EventHandler(this.EntityPivotRotationTextBox_TextChanged);
// //
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(27, 27);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(157, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Entity extensions editing TODO!";
//
// EditYmapEntityPanel // EditYmapEntityPanel
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);

View File

@ -1,13 +1,6 @@
using CodeWalker.GameFiles; using CodeWalker.GameFiles;
using SharpDX; using SharpDX;
using System; 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; using System.Windows.Forms;
namespace CodeWalker.Project.Panels namespace CodeWalker.Project.Panels
@ -16,6 +9,7 @@ namespace CodeWalker.Project.Panels
{ {
public ProjectForm ProjectForm; public ProjectForm ProjectForm;
public YmapEntityDef CurrentEntity { get; set; } public YmapEntityDef CurrentEntity { get; set; }
public MCEntityDef CurrentMCEntity { get; set; }
private bool populatingui = false; private bool populatingui = false;
@ -29,6 +23,8 @@ namespace CodeWalker.Project.Panels
public void SetEntity(YmapEntityDef entity) public void SetEntity(YmapEntityDef entity)
{ {
CurrentEntity = entity; CurrentEntity = entity;
MloInstanceData instance = entity?.MloParent?.MloInstance;
CurrentMCEntity = instance?.TryGetArchetypeEntity(entity);
Tag = entity; Tag = entity;
LoadEntity(); LoadEntity();
UpdateFormTitle(); UpdateFormTitle();
@ -94,10 +90,10 @@ namespace CodeWalker.Project.Panels
else else
{ {
populatingui = true; populatingui = true;
var e = CurrentEntity.CEntityDef; var e = CurrentEntity._CEntityDef;
var po = CurrentEntity.PivotOrientation; var po = CurrentEntity.PivotOrientation;
//EntityPanel.Enabled = true; //EntityPanel.Enabled = true;
EntityAddToProjectButton.Enabled = !ProjectForm.YmapExistsInProject(CurrentEntity.Ymap); EntityAddToProjectButton.Enabled = CurrentEntity.Ymap != null ? !ProjectForm.YmapExistsInProject(CurrentEntity.Ymap) : !ProjectForm.YtypExistsInProject(CurrentEntity.MloParent?.Archetype?.Ytyp);
EntityDeleteButton.Enabled = !EntityAddToProjectButton.Enabled; EntityDeleteButton.Enabled = !EntityAddToProjectButton.Enabled;
EntityArchetypeTextBox.Text = e.archetypeName.ToString(); EntityArchetypeTextBox.Text = e.archetypeName.ToString();
EntityArchetypeHashLabel.Text = "Hash: " + e.archetypeName.Hash.ToString(); EntityArchetypeHashLabel.Text = "Hash: " + e.archetypeName.Hash.ToString();
@ -176,21 +172,53 @@ namespace CodeWalker.Project.Panels
{ {
tn.Text = name; tn.Text = name;
} }
else
{
tn = ProjectForm.ProjectExplorer?.FindMloEntityTreeNode(CurrentMCEntity);
if (tn != null)
{
tn.Text = name;
}
}
if (CurrentEntity != null) if (CurrentEntity != null)
{ {
lock (ProjectForm.ProjectSyncRoot) lock (ProjectForm.ProjectSyncRoot)
{ {
CurrentEntity._CEntityDef.archetypeName = new MetaHash(hash); CurrentEntity._CEntityDef.archetypeName = new MetaHash(hash);
if (CurrentMCEntity != null)
{
CurrentMCEntity._Data.archetypeName = new MetaHash(hash);
}
if (CurrentEntity.Archetype != arch) if (CurrentEntity.Archetype != arch)
{ {
CurrentEntity.SetArchetype(arch); CurrentEntity.SetArchetype(arch);
ProjectForm.SetYmapHasChanged(true);
if (CurrentEntity.IsMlo)
{
CurrentEntity.MloInstance.InitYmapEntityArchetypes(ProjectForm.GameFileCache);
}
ProjectItemChanged();
} }
} }
} }
} }
private void ProjectItemChanged()
{
if (CurrentEntity.Ymap != null)
{
ProjectForm.SetYmapHasChanged(true);
}
else if (CurrentEntity.MloParent?.Archetype?.Ytyp != null)
{
ProjectForm.SetYtypHasChanged(true);
}
}
private void EntityFlagsTextBox_TextChanged(object sender, EventArgs e) private void EntityFlagsTextBox_TextChanged(object sender, EventArgs e)
{ {
if (populatingui) return; if (populatingui) return;
@ -209,7 +237,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.flags != flags) if (CurrentEntity._CEntityDef.flags != flags)
{ {
CurrentEntity._CEntityDef.flags = flags; CurrentEntity._CEntityDef.flags = flags;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.flags = flags;
ProjectItemChanged();
} }
} }
} }
@ -244,7 +274,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.flags != flags) if (CurrentEntity._CEntityDef.flags != flags)
{ {
CurrentEntity._CEntityDef.flags = flags; CurrentEntity._CEntityDef.flags = flags;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.flags = flags;
ProjectItemChanged();
} }
} }
} }
@ -260,7 +292,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.guid != guid) if (CurrentEntity._CEntityDef.guid != guid)
{ {
CurrentEntity._CEntityDef.guid = guid; CurrentEntity._CEntityDef.guid = guid;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.guid = guid;
ProjectItemChanged();
} }
} }
} }
@ -274,14 +308,16 @@ namespace CodeWalker.Project.Panels
{ {
if (CurrentEntity.MloParent != null) if (CurrentEntity.MloParent != null)
{ {
//TODO: positioning for interior entities! v = CurrentEntity.MloParent.Position + CurrentEntity.MloParent.Orientation.Multiply(v);
CurrentEntity.SetPosition(v);
ProjectItemChanged();
} }
else else
{ {
if (CurrentEntity.Position != v) if (CurrentEntity.Position != v)
{ {
CurrentEntity.SetPosition(v); CurrentEntity.SetPosition(v);
ProjectForm.SetYmapHasChanged(true); ProjectItemChanged();
var wf = ProjectForm.WorldForm; var wf = ProjectForm.WorldForm;
if (wf != null) if (wf != null)
{ {
@ -304,17 +340,24 @@ namespace CodeWalker.Project.Panels
{ {
if (CurrentEntity._CEntityDef.rotation != v) if (CurrentEntity._CEntityDef.rotation != v)
{ {
Quaternion q = new Quaternion(v); Quaternion q = v.ToQuaternion();
CurrentEntity.SetOrientationInv(q);
ProjectForm.SetYmapHasChanged(true);
var wf = ProjectForm.WorldForm; var wf = ProjectForm.WorldForm;
if (wf != null)
if (CurrentEntity.MloParent != null)
{ {
wf.BeginInvoke(new Action(() => var world = Quaternion.Normalize(Quaternion.Multiply(q, CurrentEntity.MloParent.Orientation));
{ CurrentEntity.SetOrientation(world);
wf.SetWidgetRotation(CurrentEntity.WidgetOrientation, true);
}));
} }
else
{
CurrentEntity.SetOrientation(q, true);
}
ProjectItemChanged();
wf?.BeginInvoke(new Action(() =>
{
wf.SetWidgetRotation(CurrentEntity.WidgetOrientation, true);
}));
} }
} }
} }
@ -331,7 +374,7 @@ namespace CodeWalker.Project.Panels
{ {
Vector3 newscale = new Vector3(sxy, sxy, CurrentEntity.Scale.Z); Vector3 newscale = new Vector3(sxy, sxy, CurrentEntity.Scale.Z);
CurrentEntity.SetScale(newscale); CurrentEntity.SetScale(newscale);
ProjectForm.SetYmapHasChanged(true); ProjectItemChanged();
var wf = ProjectForm.WorldForm; var wf = ProjectForm.WorldForm;
if (wf != null) if (wf != null)
{ {
@ -356,7 +399,7 @@ namespace CodeWalker.Project.Panels
{ {
Vector3 newscale = new Vector3(CurrentEntity.Scale.X, CurrentEntity.Scale.Y, sz); Vector3 newscale = new Vector3(CurrentEntity.Scale.X, CurrentEntity.Scale.Y, sz);
CurrentEntity.SetScale(newscale); CurrentEntity.SetScale(newscale);
ProjectForm.SetYmapHasChanged(true); ProjectItemChanged();
var wf = ProjectForm.WorldForm; var wf = ProjectForm.WorldForm;
if (wf != null) if (wf != null)
{ {
@ -380,7 +423,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.parentIndex != pind) if (CurrentEntity._CEntityDef.parentIndex != pind)
{ {
CurrentEntity._CEntityDef.parentIndex = pind; //Needs more work for LOD linking! CurrentEntity._CEntityDef.parentIndex = pind; //Needs more work for LOD linking!
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.parentIndex = pind;
ProjectItemChanged();
} }
} }
} }
@ -396,7 +441,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.lodDist != lodDist) if (CurrentEntity._CEntityDef.lodDist != lodDist)
{ {
CurrentEntity._CEntityDef.lodDist = lodDist; CurrentEntity._CEntityDef.lodDist = lodDist;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.lodDist = lodDist;
ProjectItemChanged();
} }
} }
} }
@ -412,7 +459,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.childLodDist != childLodDist) if (CurrentEntity._CEntityDef.childLodDist != childLodDist)
{ {
CurrentEntity._CEntityDef.childLodDist = childLodDist; CurrentEntity._CEntityDef.childLodDist = childLodDist;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.childLodDist = childLodDist;
ProjectItemChanged();
} }
} }
} }
@ -427,7 +476,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.lodLevel != lodLevel) if (CurrentEntity._CEntityDef.lodLevel != lodLevel)
{ {
CurrentEntity._CEntityDef.lodLevel = lodLevel; CurrentEntity._CEntityDef.lodLevel = lodLevel;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.lodLevel = lodLevel;
ProjectItemChanged();
} }
} }
} }
@ -443,7 +494,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.numChildren != numChildren) if (CurrentEntity._CEntityDef.numChildren != numChildren)
{ {
CurrentEntity._CEntityDef.numChildren = numChildren; CurrentEntity._CEntityDef.numChildren = numChildren;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.numChildren = numChildren;
ProjectItemChanged();
} }
} }
} }
@ -458,7 +511,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.priorityLevel != priorityLevel) if (CurrentEntity._CEntityDef.priorityLevel != priorityLevel)
{ {
CurrentEntity._CEntityDef.priorityLevel = priorityLevel; CurrentEntity._CEntityDef.priorityLevel = priorityLevel;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.priorityLevel = priorityLevel;
ProjectItemChanged();
} }
} }
} }
@ -474,7 +529,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.ambientOcclusionMultiplier != aomult) if (CurrentEntity._CEntityDef.ambientOcclusionMultiplier != aomult)
{ {
CurrentEntity._CEntityDef.ambientOcclusionMultiplier = aomult; CurrentEntity._CEntityDef.ambientOcclusionMultiplier = aomult;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.ambientOcclusionMultiplier = aomult;
ProjectItemChanged();
} }
} }
} }
@ -490,7 +547,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.artificialAmbientOcclusion != artao) if (CurrentEntity._CEntityDef.artificialAmbientOcclusion != artao)
{ {
CurrentEntity._CEntityDef.artificialAmbientOcclusion = artao; CurrentEntity._CEntityDef.artificialAmbientOcclusion = artao;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.artificialAmbientOcclusion = artao;
ProjectItemChanged();
} }
} }
} }
@ -506,7 +565,9 @@ namespace CodeWalker.Project.Panels
if (CurrentEntity._CEntityDef.tintValue != tintValue) if (CurrentEntity._CEntityDef.tintValue != tintValue)
{ {
CurrentEntity._CEntityDef.tintValue = tintValue; CurrentEntity._CEntityDef.tintValue = tintValue;
ProjectForm.SetYmapHasChanged(true); if (CurrentMCEntity != null)
CurrentMCEntity._Data.tintValue = tintValue;
ProjectItemChanged();
} }
} }
} }
@ -515,7 +576,7 @@ namespace CodeWalker.Project.Panels
{ {
if (CurrentEntity == null) return; if (CurrentEntity == null) return;
if (ProjectForm.WorldForm == null) return; if (ProjectForm.WorldForm == null) return;
ProjectForm.WorldForm.GoToPosition(CurrentEntity.Position); ProjectForm.WorldForm.GoToPosition(CurrentEntity.Position, Vector3.One * CurrentEntity.BSRadius);
} }
private void EntityNormalizeRotationButton_Click(object sender, EventArgs e) private void EntityNormalizeRotationButton_Click(object sender, EventArgs e)

View File

@ -28,28 +28,642 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditYmapGrassPanel)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditYmapGrassPanel));
this.tabControl1 = new System.Windows.Forms.TabControl();
this.GrassBatchTab = new System.Windows.Forms.TabPage();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.label12 = new System.Windows.Forms.Label();
this.label11 = new System.Windows.Forms.Label();
this.OrientToTerrainNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.ScaleRangeTextBox = new System.Windows.Forms.TextBox();
this.label10 = new System.Windows.Forms.Label();
this.LodFadeRangeNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label9 = new System.Windows.Forms.Label();
this.LodFadeStartDistanceNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label6 = new System.Windows.Forms.Label();
this.LodDistNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.BrushTab = new System.Windows.Forms.TabPage();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.GrassColorLabel = new System.Windows.Forms.Label();
this.label15 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.AoNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.PadTextBox = new System.Windows.Forms.TextBox();
this.ScaleNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.RandomizeScaleCheckBox = new System.Windows.Forms.CheckBox();
this.brushSettingsGroupBox = new System.Windows.Forms.GroupBox();
this.DensityNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.RadiusNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label5 = new System.Windows.Forms.Label();
this.radiusLabel = new System.Windows.Forms.Label();
this.OptimizeBatchButtonTooltip = new System.Windows.Forms.ToolTip(this.components);
this.OptimizeBatchButton = new System.Windows.Forms.Button();
this.ExtentsMinTextBox = new System.Windows.Forms.TextBox();
this.label14 = new System.Windows.Forms.Label();
this.ExtentsMaxTextBox = new System.Windows.Forms.TextBox();
this.label13 = new System.Windows.Forms.Label();
this.GrassDeleteButton = new System.Windows.Forms.Button();
this.GrassAddToProjectButton = new System.Windows.Forms.Button();
this.HashLabel = new System.Windows.Forms.Label();
this.ArchetypeNameTextBox = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.PositionTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
this.GrassGoToButton = new System.Windows.Forms.Button();
this.label17 = new System.Windows.Forms.Label();
this.OptmizationThresholdNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.BrushModeCheckBox = new System.Windows.Forms.CheckBox();
this.label8 = new System.Windows.Forms.Label();
this.tabControl1.SuspendLayout();
this.GrassBatchTab.SuspendLayout();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.OrientToTerrainNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.LodFadeRangeNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.LodFadeStartDistanceNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.LodDistNumericUpDown)).BeginInit();
this.BrushTab.SuspendLayout();
this.groupBox2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.AoNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.ScaleNumericUpDown)).BeginInit();
this.brushSettingsGroupBox.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.DensityNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.RadiusNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.OptmizationThresholdNumericUpDown)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// tabControl1
//
this.tabControl1.Controls.Add(this.GrassBatchTab);
this.tabControl1.Controls.Add(this.BrushTab);
this.tabControl1.Location = new System.Drawing.Point(12, 65);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(486, 181);
this.tabControl1.TabIndex = 37;
//
// GrassBatchTab
//
this.GrassBatchTab.Controls.Add(this.groupBox1);
this.GrassBatchTab.Location = new System.Drawing.Point(4, 22);
this.GrassBatchTab.Name = "GrassBatchTab";
this.GrassBatchTab.Padding = new System.Windows.Forms.Padding(3);
this.GrassBatchTab.Size = new System.Drawing.Size(478, 155);
this.GrassBatchTab.TabIndex = 0;
this.GrassBatchTab.Text = "Grass Batch";
this.GrassBatchTab.UseVisualStyleBackColor = true;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.label12);
this.groupBox1.Controls.Add(this.label11);
this.groupBox1.Controls.Add(this.OrientToTerrainNumericUpDown);
this.groupBox1.Controls.Add(this.ScaleRangeTextBox);
this.groupBox1.Controls.Add(this.label10);
this.groupBox1.Controls.Add(this.LodFadeRangeNumericUpDown);
this.groupBox1.Controls.Add(this.label9);
this.groupBox1.Controls.Add(this.LodFadeStartDistanceNumericUpDown);
this.groupBox1.Controls.Add(this.label6);
this.groupBox1.Controls.Add(this.LodDistNumericUpDown);
this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.groupBox1.Location = new System.Drawing.Point(12, 6);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(460, 143);
this.groupBox1.TabIndex = 42;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Batch";
//
// label12
//
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(197, 24);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(69, 13);
this.label12.TabIndex = 47;
this.label12.Text = "Scale Range";
//
// label11
//
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(8, 102);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(87, 13);
this.label11.TabIndex = 7;
this.label11.Text = "Orient To Terrain";
//
// OrientToTerrainNumericUpDown
//
this.OrientToTerrainNumericUpDown.DecimalPlaces = 1;
this.OrientToTerrainNumericUpDown.Location = new System.Drawing.Point(121, 100);
this.OrientToTerrainNumericUpDown.Maximum = new decimal(new int[] {
1,
0,
0,
0});
this.OrientToTerrainNumericUpDown.Name = "OrientToTerrainNumericUpDown";
this.OrientToTerrainNumericUpDown.Size = new System.Drawing.Size(61, 20);
this.OrientToTerrainNumericUpDown.TabIndex = 6;
this.OrientToTerrainNumericUpDown.ValueChanged += new System.EventHandler(this.OrientToTerrainNumericUpDown_ValueChanged);
//
// ScaleRangeTextBox
//
this.ScaleRangeTextBox.Location = new System.Drawing.Point(270, 21);
this.ScaleRangeTextBox.Name = "ScaleRangeTextBox";
this.ScaleRangeTextBox.Size = new System.Drawing.Size(166, 20);
this.ScaleRangeTextBox.TabIndex = 46;
this.ScaleRangeTextBox.TextChanged += new System.EventHandler(this.ScaleRangeTextBox_TextChanged);
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(8, 76);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(107, 13);
this.label10.TabIndex = 5;
this.label10.Text = "Lod Inst Fade Range";
//
// LodFadeRangeNumericUpDown
//
this.LodFadeRangeNumericUpDown.DecimalPlaces = 4;
this.LodFadeRangeNumericUpDown.Increment = new decimal(new int[] {
1,
0,
0,
65536});
this.LodFadeRangeNumericUpDown.Location = new System.Drawing.Point(121, 74);
this.LodFadeRangeNumericUpDown.Maximum = new decimal(new int[] {
99999,
0,
0,
0});
this.LodFadeRangeNumericUpDown.Name = "LodFadeRangeNumericUpDown";
this.LodFadeRangeNumericUpDown.Size = new System.Drawing.Size(61, 20);
this.LodFadeRangeNumericUpDown.TabIndex = 4;
this.LodFadeRangeNumericUpDown.ValueChanged += new System.EventHandler(this.LodFadeRangeNumericUpDown_ValueChanged);
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(8, 50);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(98, 13);
this.label9.TabIndex = 3;
this.label9.Text = "Lod Fade Start Dist";
//
// LodFadeStartDistanceNumericUpDown
//
this.LodFadeStartDistanceNumericUpDown.DecimalPlaces = 4;
this.LodFadeStartDistanceNumericUpDown.Location = new System.Drawing.Point(121, 48);
this.LodFadeStartDistanceNumericUpDown.Maximum = new decimal(new int[] {
99999,
0,
0,
0});
this.LodFadeStartDistanceNumericUpDown.Name = "LodFadeStartDistanceNumericUpDown";
this.LodFadeStartDistanceNumericUpDown.Size = new System.Drawing.Size(61, 20);
this.LodFadeStartDistanceNumericUpDown.TabIndex = 2;
this.LodFadeStartDistanceNumericUpDown.ValueChanged += new System.EventHandler(this.LodFadeStartDistanceNumericUpDown_ValueChanged);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(8, 24);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(39, 13);
this.label6.TabIndex = 1;
this.label6.Text = "lodDist";
//
// LodDistNumericUpDown
//
this.LodDistNumericUpDown.Location = new System.Drawing.Point(121, 22);
this.LodDistNumericUpDown.Maximum = new decimal(new int[] {
99999,
0,
0,
0});
this.LodDistNumericUpDown.Name = "LodDistNumericUpDown";
this.LodDistNumericUpDown.Size = new System.Drawing.Size(61, 20);
this.LodDistNumericUpDown.TabIndex = 0;
this.LodDistNumericUpDown.ValueChanged += new System.EventHandler(this.LodDistNumericUpDown_ValueChanged);
//
// BrushTab
//
this.BrushTab.Controls.Add(this.groupBox2);
this.BrushTab.Controls.Add(this.brushSettingsGroupBox);
this.BrushTab.Location = new System.Drawing.Point(4, 22);
this.BrushTab.Name = "BrushTab";
this.BrushTab.Padding = new System.Windows.Forms.Padding(3);
this.BrushTab.Size = new System.Drawing.Size(478, 155);
this.BrushTab.TabIndex = 1;
this.BrushTab.Text = " Brush";
this.BrushTab.UseVisualStyleBackColor = true;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.GrassColorLabel);
this.groupBox2.Controls.Add(this.label15);
this.groupBox2.Controls.Add(this.label4);
this.groupBox2.Controls.Add(this.AoNumericUpDown);
this.groupBox2.Controls.Add(this.PadTextBox);
this.groupBox2.Controls.Add(this.ScaleNumericUpDown);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.RandomizeScaleCheckBox);
this.groupBox2.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.groupBox2.Location = new System.Drawing.Point(191, 3);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(281, 146);
this.groupBox2.TabIndex = 39;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Instance Settings";
//
// GrassColorLabel
//
this.GrassColorLabel.BackColor = System.Drawing.Color.White;
this.GrassColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.GrassColorLabel.Location = new System.Drawing.Point(50, 22);
this.GrassColorLabel.Name = "GrassColorLabel";
this.GrassColorLabel.Size = new System.Drawing.Size(119, 21);
this.GrassColorLabel.TabIndex = 12;
this.GrassColorLabel.Click += new System.EventHandler(this.GrassColorLabel_Click);
//
// label15
//
this.label15.AutoSize = true;
this.label15.Location = new System.Drawing.Point(9, 106);
this.label15.Name = "label15";
this.label15.Size = new System.Drawing.Size(26, 13);
this.label15.TabIndex = 46;
this.label15.Text = "Pad";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(9, 79);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(34, 13);
this.label4.TabIndex = 16;
this.label4.Text = "Scale";
//
// AoNumericUpDown
//
this.AoNumericUpDown.Location = new System.Drawing.Point(50, 51);
this.AoNumericUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.AoNumericUpDown.Name = "AoNumericUpDown";
this.AoNumericUpDown.Size = new System.Drawing.Size(120, 20);
this.AoNumericUpDown.TabIndex = 15;
this.AoNumericUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
//
// PadTextBox
//
this.PadTextBox.Location = new System.Drawing.Point(49, 103);
this.PadTextBox.Name = "PadTextBox";
this.PadTextBox.Size = new System.Drawing.Size(120, 20);
this.PadTextBox.TabIndex = 45;
this.PadTextBox.Text = "0, 0, 0";
//
// ScaleNumericUpDown
//
this.ScaleNumericUpDown.Location = new System.Drawing.Point(49, 77);
this.ScaleNumericUpDown.Maximum = new decimal(new int[] {
255,
0,
0,
0});
this.ScaleNumericUpDown.Name = "ScaleNumericUpDown";
this.ScaleNumericUpDown.Size = new System.Drawing.Size(120, 20);
this.ScaleNumericUpDown.TabIndex = 17;
this.ScaleNumericUpDown.Value = new decimal(new int[] {
255,
0,
0,
0});
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(9, 53);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(20, 13);
this.label2.TabIndex = 14;
this.label2.Text = "Ao";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(9, 26);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(31, 13);
this.label3.TabIndex = 13;
this.label3.Text = "Color";
//
// RandomizeScaleCheckBox
//
this.RandomizeScaleCheckBox.AutoSize = true;
this.RandomizeScaleCheckBox.Location = new System.Drawing.Point(176, 79);
this.RandomizeScaleCheckBox.Name = "RandomizeScaleCheckBox";
this.RandomizeScaleCheckBox.Size = new System.Drawing.Size(66, 17);
this.RandomizeScaleCheckBox.TabIndex = 18;
this.RandomizeScaleCheckBox.Text = "Random";
this.RandomizeScaleCheckBox.UseVisualStyleBackColor = true;
//
// brushSettingsGroupBox
//
this.brushSettingsGroupBox.Controls.Add(this.DensityNumericUpDown);
this.brushSettingsGroupBox.Controls.Add(this.RadiusNumericUpDown);
this.brushSettingsGroupBox.Controls.Add(this.label5);
this.brushSettingsGroupBox.Controls.Add(this.radiusLabel);
this.brushSettingsGroupBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.brushSettingsGroupBox.Location = new System.Drawing.Point(8, 3);
this.brushSettingsGroupBox.Name = "brushSettingsGroupBox";
this.brushSettingsGroupBox.Size = new System.Drawing.Size(177, 146);
this.brushSettingsGroupBox.TabIndex = 38;
this.brushSettingsGroupBox.TabStop = false;
this.brushSettingsGroupBox.Text = "Brush Settings";
//
// DensityNumericUpDown
//
this.DensityNumericUpDown.Location = new System.Drawing.Point(76, 57);
this.DensityNumericUpDown.Maximum = new decimal(new int[] {
128,
0,
0,
0});
this.DensityNumericUpDown.Name = "DensityNumericUpDown";
this.DensityNumericUpDown.Size = new System.Drawing.Size(84, 20);
this.DensityNumericUpDown.TabIndex = 20;
this.DensityNumericUpDown.Value = new decimal(new int[] {
28,
0,
0,
0});
//
// RadiusNumericUpDown
//
this.RadiusNumericUpDown.DecimalPlaces = 2;
this.RadiusNumericUpDown.Increment = new decimal(new int[] {
1,
0,
0,
131072});
this.RadiusNumericUpDown.Location = new System.Drawing.Point(76, 31);
this.RadiusNumericUpDown.Name = "RadiusNumericUpDown";
this.RadiusNumericUpDown.Size = new System.Drawing.Size(84, 20);
this.RadiusNumericUpDown.TabIndex = 11;
this.RadiusNumericUpDown.Value = new decimal(new int[] {
5,
0,
0,
0});
this.RadiusNumericUpDown.ValueChanged += new System.EventHandler(this.RadiusNumericUpDown_ValueChanged);
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(21, 59);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(42, 13);
this.label5.TabIndex = 19;
this.label5.Text = "Density";
//
// radiusLabel
//
this.radiusLabel.AutoSize = true;
this.radiusLabel.Location = new System.Drawing.Point(21, 33);
this.radiusLabel.Name = "radiusLabel";
this.radiusLabel.Size = new System.Drawing.Size(40, 13);
this.radiusLabel.TabIndex = 10;
this.radiusLabel.Text = "Radius";
//
// OptimizeBatchButton
//
this.OptimizeBatchButton.Location = new System.Drawing.Point(16, 280);
this.OptimizeBatchButton.Name = "OptimizeBatchButton";
this.OptimizeBatchButton.Size = new System.Drawing.Size(108, 24);
this.OptimizeBatchButton.TabIndex = 70;
this.OptimizeBatchButton.Text = "Optimize Batch";
this.OptimizeBatchButtonTooltip.SetToolTip(this.OptimizeBatchButton, "Will split your batch into multiple different batches based on the threshold. If " +
"your threshold is 5.0 then each batch will have a size of 5.0 meters.");
this.OptimizeBatchButton.UseVisualStyleBackColor = true;
this.OptimizeBatchButton.Click += new System.EventHandler(this.OptimizeBatchButton_Click);
//
// ExtentsMinTextBox
//
this.ExtentsMinTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ExtentsMinTextBox.Location = new System.Drawing.Point(84, 319);
this.ExtentsMinTextBox.Name = "ExtentsMinTextBox";
this.ExtentsMinTextBox.ReadOnly = true;
this.ExtentsMinTextBox.Size = new System.Drawing.Size(380, 20);
this.ExtentsMinTextBox.TabIndex = 55;
//
// label14
//
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(13, 349);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(68, 13);
this.label14.TabIndex = 54;
this.label14.Text = "Extents Max:";
//
// ExtentsMaxTextBox
//
this.ExtentsMaxTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ExtentsMaxTextBox.Location = new System.Drawing.Point(84, 345);
this.ExtentsMaxTextBox.Name = "ExtentsMaxTextBox";
this.ExtentsMaxTextBox.ReadOnly = true;
this.ExtentsMaxTextBox.Size = new System.Drawing.Size(380, 20);
this.ExtentsMaxTextBox.TabIndex = 53;
//
// label13
//
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(13, 322);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(65, 13);
this.label13.TabIndex = 52;
this.label13.Text = "Extents Min:";
//
// GrassDeleteButton
//
this.GrassDeleteButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.GrassDeleteButton.Location = new System.Drawing.Point(257, 397);
this.GrassDeleteButton.Name = "GrassDeleteButton";
this.GrassDeleteButton.Size = new System.Drawing.Size(95, 23);
this.GrassDeleteButton.TabIndex = 51;
this.GrassDeleteButton.Text = "Delete Batch";
this.GrassDeleteButton.UseVisualStyleBackColor = true;
this.GrassDeleteButton.Click += new System.EventHandler(this.GrassDeleteButton_Click);
//
// GrassAddToProjectButton
//
this.GrassAddToProjectButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.GrassAddToProjectButton.Location = new System.Drawing.Point(159, 397);
this.GrassAddToProjectButton.Name = "GrassAddToProjectButton";
this.GrassAddToProjectButton.Size = new System.Drawing.Size(95, 23);
this.GrassAddToProjectButton.TabIndex = 50;
this.GrassAddToProjectButton.Text = "Add to Project";
this.GrassAddToProjectButton.UseVisualStyleBackColor = true;
this.GrassAddToProjectButton.Click += new System.EventHandler(this.GrassAddToProjectButton_Click);
//
// HashLabel
//
this.HashLabel.AutoSize = true;
this.HashLabel.Location = new System.Drawing.Point(254, 14);
this.HashLabel.Name = "HashLabel";
this.HashLabel.Size = new System.Drawing.Size(44, 13);
this.HashLabel.TabIndex = 61;
this.HashLabel.Text = "Hash: 0";
//
// ArchetypeNameTextBox
//
this.ArchetypeNameTextBox.Location = new System.Drawing.Point(66, 12);
this.ArchetypeNameTextBox.Name = "ArchetypeNameTextBox";
this.ArchetypeNameTextBox.Size = new System.Drawing.Size(144, 20);
this.ArchetypeNameTextBox.TabIndex = 60;
this.ArchetypeNameTextBox.TextChanged += new System.EventHandler(this.ArchetypeNameTextBox_TextChanged);
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(16, 15);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(35, 13);
this.label7.TabIndex = 59;
this.label7.Text = "Name";
//
// PositionTextBox
//
this.PositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.PositionTextBox.Location = new System.Drawing.Point(66, 39);
this.PositionTextBox.Name = "PositionTextBox";
this.PositionTextBox.ReadOnly = true;
this.PositionTextBox.Size = new System.Drawing.Size(275, 20);
this.PositionTextBox.TabIndex = 58;
//
// label1 // label1
// //
this.label1.AutoSize = true; this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(52, 52); this.label1.Location = new System.Drawing.Point(16, 42);
this.label1.Name = "label1"; this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(105, 13); this.label1.Size = new System.Drawing.Size(44, 13);
this.label1.TabIndex = 0; this.label1.TabIndex = 57;
this.label1.Text = "Grass editing TODO!"; this.label1.Text = "Position";
//
// GrassGoToButton
//
this.GrassGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.GrassGoToButton.Location = new System.Drawing.Point(347, 36);
this.GrassGoToButton.Name = "GrassGoToButton";
this.GrassGoToButton.Size = new System.Drawing.Size(56, 23);
this.GrassGoToButton.TabIndex = 56;
this.GrassGoToButton.Text = "Go To";
this.GrassGoToButton.UseVisualStyleBackColor = true;
this.GrassGoToButton.Click += new System.EventHandler(this.GrassGoToButton_Click);
//
// label17
//
this.label17.AutoSize = true;
this.label17.Location = new System.Drawing.Point(130, 286);
this.label17.Name = "label17";
this.label17.Size = new System.Drawing.Size(54, 13);
this.label17.TabIndex = 71;
this.label17.Text = "Threshold";
//
// OptmizationThresholdNumericUpDown
//
this.OptmizationThresholdNumericUpDown.Location = new System.Drawing.Point(190, 284);
this.OptmizationThresholdNumericUpDown.Maximum = new decimal(new int[] {
999999,
0,
0,
0});
this.OptmizationThresholdNumericUpDown.Name = "OptmizationThresholdNumericUpDown";
this.OptmizationThresholdNumericUpDown.Size = new System.Drawing.Size(51, 20);
this.OptmizationThresholdNumericUpDown.TabIndex = 69;
this.OptmizationThresholdNumericUpDown.Value = new decimal(new int[] {
5,
0,
0,
0});
//
// BrushModeCheckBox
//
this.BrushModeCheckBox.AutoSize = true;
this.BrushModeCheckBox.Location = new System.Drawing.Point(16, 252);
this.BrushModeCheckBox.Name = "BrushModeCheckBox";
this.BrushModeCheckBox.Size = new System.Drawing.Size(83, 17);
this.BrushModeCheckBox.TabIndex = 68;
this.BrushModeCheckBox.Text = "Brush Mode";
this.BrushModeCheckBox.UseVisualStyleBackColor = true;
this.BrushModeCheckBox.CheckedChanged += new System.EventHandler(this.BrushModeCheckBox_CheckedChanged);
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(211, 14);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(24, 13);
this.label8.TabIndex = 72;
this.label8.Text = ".ydr";
this.label8.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
// //
// EditYmapGrassPanel // EditYmapGrassPanel
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(554, 355); this.ClientSize = new System.Drawing.Size(510, 443);
this.Controls.Add(this.label8);
this.Controls.Add(this.label17);
this.Controls.Add(this.OptmizationThresholdNumericUpDown);
this.Controls.Add(this.OptimizeBatchButton);
this.Controls.Add(this.BrushModeCheckBox);
this.Controls.Add(this.HashLabel);
this.Controls.Add(this.ExtentsMinTextBox);
this.Controls.Add(this.ArchetypeNameTextBox);
this.Controls.Add(this.ExtentsMaxTextBox);
this.Controls.Add(this.label7);
this.Controls.Add(this.PositionTextBox);
this.Controls.Add(this.label1); this.Controls.Add(this.label1);
this.Controls.Add(this.GrassGoToButton);
this.Controls.Add(this.label14);
this.Controls.Add(this.label13);
this.Controls.Add(this.GrassDeleteButton);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.GrassAddToProjectButton);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "EditYmapGrassPanel"; this.Name = "EditYmapGrassPanel";
this.Text = "Grass Batch"; this.Text = "Grass Batch";
this.tabControl1.ResumeLayout(false);
this.GrassBatchTab.ResumeLayout(false);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.OrientToTerrainNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.LodFadeRangeNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.LodFadeStartDistanceNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.LodDistNumericUpDown)).EndInit();
this.BrushTab.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.AoNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.ScaleNumericUpDown)).EndInit();
this.brushSettingsGroupBox.ResumeLayout(false);
this.brushSettingsGroupBox.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.DensityNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.RadiusNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.OptmizationThresholdNumericUpDown)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@ -57,6 +671,52 @@
#endregion #endregion
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage GrassBatchTab;
private System.Windows.Forms.TabPage BrushTab;
private System.Windows.Forms.GroupBox brushSettingsGroupBox;
private System.Windows.Forms.NumericUpDown RadiusNumericUpDown;
private System.Windows.Forms.Label radiusLabel;
private System.Windows.Forms.NumericUpDown DensityNumericUpDown;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.NumericUpDown LodDistNumericUpDown;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.NumericUpDown LodFadeStartDistanceNumericUpDown;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.NumericUpDown LodFadeRangeNumericUpDown;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.NumericUpDown OrientToTerrainNumericUpDown;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.TextBox ScaleRangeTextBox;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Label label15;
private System.Windows.Forms.TextBox PadTextBox;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label GrassColorLabel;
private System.Windows.Forms.CheckBox RandomizeScaleCheckBox;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.NumericUpDown ScaleNumericUpDown;
private System.Windows.Forms.NumericUpDown AoNumericUpDown;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.ToolTip OptimizeBatchButtonTooltip;
private System.Windows.Forms.TextBox ExtentsMinTextBox;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.TextBox ExtentsMaxTextBox;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.Button GrassDeleteButton;
private System.Windows.Forms.Button GrassAddToProjectButton;
private System.Windows.Forms.Label HashLabel;
private System.Windows.Forms.TextBox ArchetypeNameTextBox;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.TextBox PositionTextBox;
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button GrassGoToButton;
private System.Windows.Forms.Label label17;
private System.Windows.Forms.NumericUpDown OptmizationThresholdNumericUpDown;
private System.Windows.Forms.Button OptimizeBatchButton;
private System.Windows.Forms.CheckBox BrushModeCheckBox;
private System.Windows.Forms.Label label8;
} }
} }

View File

@ -1,22 +1,30 @@
using CodeWalker.GameFiles; using System;
using System;
using System.Collections.Generic; 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; using System.Windows.Forms;
using CodeWalker.GameFiles;
using CodeWalker.World;
using SharpDX;
// TODO
// - COMPLETED -- Optimization feature.
// - COMPLETED -- Remove grass instances using CTRL + SHIFT + LMB
// - Better gizmo for grass brush (like a circle with a little line in the middle sticking upwards)
// - Maybe some kind of auto coloring system? I've noticed that mostly all grass in GTA inherits it's color from the surface it's on.
// - Grass area fill (generate grass on ydr based on colision materials?)
// - Need to have a way to erase instances from other batches in the current batches ymap.
// if we optimize our instances, we'd have to go through each batch to erase, this is very monotonous.
// BUG
// - I've added a "zoom" kind of feature when hitting the goto button, but when the bounds of the
// grass batch are 0, the zoom of the camera is set to 0, which causes the end-user to have to scroll
// out a lot in order to use any movement controls. I will need to clamp that to a minimum value.
namespace CodeWalker.Project.Panels namespace CodeWalker.Project.Panels
{ {
public partial class EditYmapGrassPanel : ProjectPanel public partial class EditYmapGrassPanel : ProjectPanel
{ {
public ProjectForm ProjectForm; public ProjectForm ProjectForm;
public YmapGrassInstanceBatch CurrentBatch { get; set; }
//private bool populatingui = false;
public EditYmapGrassPanel(ProjectForm owner) public EditYmapGrassPanel(ProjectForm owner)
{ {
@ -24,12 +32,45 @@ namespace CodeWalker.Project.Panels
InitializeComponent(); InitializeComponent();
} }
public YmapGrassInstanceBatch CurrentBatch { get; set; }
#region Form
public void SetBatch(YmapGrassInstanceBatch batch) public void SetBatch(YmapGrassInstanceBatch batch)
{ {
CurrentBatch = batch; CurrentBatch = batch;
Tag = batch; Tag = batch;
LoadGrassBatch();
UpdateFormTitle(); UpdateFormTitle();
UpdateControls();
ProjectForm.WorldForm?.SelectGrassBatch(batch);
}
private void UpdateControls()
{
if (ProjectForm?.CurrentProjectFile == null) return;
if (ProjectForm.GrassBatchExistsInProject(CurrentBatch))
{
GrassAddToProjectButton.Enabled = false;
GrassDeleteButton.Enabled = true;
}
else
{
GrassAddToProjectButton.Enabled = true;
GrassDeleteButton.Enabled = false;
}
ArchetypeNameTextBox.Text = CurrentBatch.Batch.archetypeName.ToString();
PositionTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.Position);
LodDistNumericUpDown.Value = CurrentBatch.Batch.lodDist;
LodFadeRangeNumericUpDown.Value = (decimal) CurrentBatch.Batch.LodInstFadeRange;
LodFadeStartDistanceNumericUpDown.Value = (decimal) CurrentBatch.Batch.LodFadeStartDist;
ScaleRangeTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.Batch.ScaleRange);
OrientToTerrainNumericUpDown.Value = (decimal)CurrentBatch.Batch.OrientToTerrain;
OptmizationThresholdNumericUpDown.Value = 15;
BrushModeCheckBox.Checked = CurrentBatch.BrushEnabled;
RadiusNumericUpDown.Value = (decimal)CurrentBatch.BrushRadius;
ExtentsMinTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.AABBMin);
ExtentsMaxTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.AABBMax);
} }
private void UpdateFormTitle() private void UpdateFormTitle()
@ -37,11 +78,232 @@ namespace CodeWalker.Project.Panels
Text = CurrentBatch?.Batch.archetypeName.ToString() ?? "Grass Batch"; Text = CurrentBatch?.Batch.archetypeName.ToString() ?? "Grass Batch";
} }
#endregion
#region Events
private void LoadGrassBatch() #region BrushSettings
private void GrassGoToButton_Click(object sender, EventArgs e)
{ {
if (CurrentBatch == null) return;
ProjectForm.WorldForm?.GoToPosition(CurrentBatch.Position, CurrentBatch.AABBMax - CurrentBatch.AABBMin);
} }
private void GrassAddToProjectButton_Click(object sender, EventArgs e)
{
ProjectForm.SetProjectItem(CurrentBatch);
ProjectForm.AddGrassBatchToProject();
}
private void GrassDeleteButton_Click(object sender, EventArgs e)
{
ProjectForm.SetProjectItem(CurrentBatch);
var ymap = CurrentBatch?.Ymap;
if (!ProjectForm.DeleteGrassBatch()) return;
ymap?.CalcExtents(); // Recalculate the extents after deleting the grass batch.
ProjectForm.WorldForm.SelectItem();
}
private void GrassColorLabel_Click(object sender, EventArgs e)
{
var colDiag = new ColorDialog {Color = GrassColorLabel.BackColor};
if (colDiag.ShowDialog(this) == DialogResult.OK)
GrassColorLabel.BackColor = colDiag.Color;
}
private void BrushModeCheckBox_CheckedChanged(object sender, EventArgs e)
{
if (CurrentBatch == null) return;
CurrentBatch.BrushEnabled = BrushModeCheckBox.Checked;
}
private void RadiusNumericUpDown_ValueChanged(object sender, EventArgs e)
{
if (CurrentBatch == null) return;
CurrentBatch.BrushRadius = (float)RadiusNumericUpDown.Value;
}
#endregion
#region Batch Settings
private void ArchetypeNameTextBox_TextChanged(object sender, EventArgs e)
{
var archetypeHash = JenkHash.GenHash(ArchetypeNameTextBox.Text);
var archetype = ProjectForm.GameFileCache.GetArchetype(archetypeHash);
if (archetype == null)
{
HashLabel.Text = $@"Hash: {archetypeHash} (invalid)";
return;
}
CurrentBatch.Archetype = archetype;
var b = CurrentBatch.Batch;
b.archetypeName = archetypeHash;
CurrentBatch.Batch = b;
ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
HashLabel.Text = $@"Hash: {archetypeHash}";
UpdateFormTitle();
CurrentBatch.HasChanged = true;
ProjectForm.SetGrassBatchHasChanged(false);
ProjectForm.SetYmapHasChanged(true);
}
private void LodDistNumericUpDown_ValueChanged(object sender, EventArgs e)
{
var batch = CurrentBatch.Batch;
batch.lodDist = (uint) LodDistNumericUpDown.Value;
CurrentBatch.Batch = batch;
ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
ProjectForm.SetYmapHasChanged(true);
}
private void LodFadeStartDistanceNumericUpDown_ValueChanged(object sender, EventArgs e)
{
var batch = CurrentBatch.Batch;
batch.LodFadeStartDist = (float) LodFadeStartDistanceNumericUpDown.Value;
CurrentBatch.Batch = batch;
ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
ProjectForm.SetYmapHasChanged(true);
}
private void LodFadeRangeNumericUpDown_ValueChanged(object sender, EventArgs e)
{
var batch = CurrentBatch.Batch;
batch.LodInstFadeRange = (float) LodFadeRangeNumericUpDown.Value;
CurrentBatch.Batch = batch;
ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
ProjectForm.SetYmapHasChanged(true);
}
private void OrientToTerrainNumericUpDown_ValueChanged(object sender, EventArgs e)
{
var batch = CurrentBatch.Batch;
batch.OrientToTerrain = (float) OrientToTerrainNumericUpDown.Value;
CurrentBatch.Batch = batch;
ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
ProjectForm.SetYmapHasChanged(true);
}
private void ScaleRangeTextBox_TextChanged(object sender, EventArgs e)
{
var batch = CurrentBatch.Batch;
var v = FloatUtil.ParseVector3String(ScaleRangeTextBox.Text);
batch.ScaleRange = v;
CurrentBatch.Batch = batch;
ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
ProjectForm.SetYmapHasChanged(true);
}
private void OptimizeBatchButton_Click(object sender, EventArgs e)
{
if (CurrentBatch.Instances == null || CurrentBatch.Instances.Length <= 0) return;
var d = MessageBox.Show(
@"You are about to split the selected batch into multiple parts. Are you sure you want to do this?",
@"Instance Optimizer", MessageBoxButtons.YesNo);
if (d == DialogResult.No)
return;
lock (ProjectForm.WorldForm.RenderSyncRoot)
{
var newBatches = CurrentBatch?.OptimizeInstances(CurrentBatch, (float)OptmizationThresholdNumericUpDown.Value);
if (newBatches == null || newBatches.Length <= 0) return;
// Remove our batch from the ymap
CurrentBatch.Ymap.RemoveGrassBatch(CurrentBatch);
foreach (var batch in newBatches)
{
var b = batch.Batch;
b.lodDist = CurrentBatch.Batch.lodDist;
b.LodInstFadeRange = CurrentBatch.Batch.LodInstFadeRange;
b.LodFadeStartDist = CurrentBatch.Batch.LodFadeStartDist;
b.ScaleRange = CurrentBatch.Batch.ScaleRange;
b.OrientToTerrain = CurrentBatch.Batch.OrientToTerrain;
b.archetypeName = CurrentBatch.Batch.archetypeName;
batch.Batch = b;
batch.Archetype = CurrentBatch.Archetype;
batch.UpdateInstanceCount();
ProjectForm.NewGrassBatch(batch);
}
CurrentBatch.Ymap.CalcExtents();
CurrentBatch.Ymap.Save();
// TODO: Select the last grass batch in the new list on the project explorer.
ProjectForm.ProjectExplorer.TrySelectGrassBatchTreeNode(CurrentBatch.Ymap.GrassInstanceBatches[0]);
}
}
#endregion
#endregion
#region Publics
public void CreateInstancesAtMouse(SpaceRayIntersectResult mouseRay)
{
var wf = ProjectForm.WorldForm;
if (wf == null) return;
lock (wf.RenderSyncRoot)
{
CurrentBatch.CreateInstancesAtMouse(
CurrentBatch,
mouseRay,
(float) RadiusNumericUpDown.Value,
(int) DensityNumericUpDown.Value,
SpawnRayFunc,
new Color(GrassColorLabel.BackColor.R, GrassColorLabel.BackColor.G, GrassColorLabel.BackColor.B),
(int) AoNumericUpDown.Value,
(int) ScaleNumericUpDown.Value,
FloatUtil.ParseVector3String(PadTextBox.Text),
RandomizeScaleCheckBox.Checked
);
wf.UpdateGrassBatchGraphics(CurrentBatch);
}
BatchChanged();
}
public void EraseInstancesAtMouse(SpaceRayIntersectResult mouseRay)
{
var wf = ProjectForm.WorldForm;
if (wf == null) return;
var changed = false;
lock (wf.RenderSyncRoot)
{
if (CurrentBatch.EraseInstancesAtMouse(
CurrentBatch,
mouseRay,
(float) RadiusNumericUpDown.Value
))
{
wf.UpdateGrassBatchGraphics(CurrentBatch);
changed = true;
}
}
if (changed) BatchChanged();
}
#endregion
#region Privates
private SpaceRayIntersectResult SpawnRayFunc(Vector3 spawnPos)
{
var res = ProjectForm.WorldForm.Raycast(new Ray(spawnPos, -Vector3.UnitZ));
return res;
}
private void BatchChanged()
{
UpdateControls();
CurrentBatch.UpdateInstanceCount();
CurrentBatch.HasChanged = true;
ProjectForm.SetGrassBatchHasChanged(false);
}
#endregion
} }
} }

View File

@ -117,6 +117,9 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="OptimizeBatchButtonTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>

View File

@ -46,14 +46,14 @@
this.label4 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label();
this.DeletePolyButton = new System.Windows.Forms.Button(); this.DeletePolyButton = new System.Windows.Forms.Button();
this.AddToProjectButton = new System.Windows.Forms.Button(); this.AddToProjectButton = new System.Windows.Forms.Button();
this.PortalTypeUpDown = new System.Windows.Forms.NumericUpDown(); this.PortalCountUpDown = new System.Windows.Forms.NumericUpDown();
this.label6 = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.AreaIDUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.AreaIDUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.PartIDUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PartIDUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.PortalIDUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PortalIDUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.UnkXUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.UnkXUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.UnkYUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.UnkYUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.PortalTypeUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.PortalCountUpDown)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// AreaIDUpDown // AreaIDUpDown
@ -273,34 +273,34 @@
this.AddToProjectButton.UseVisualStyleBackColor = true; this.AddToProjectButton.UseVisualStyleBackColor = true;
this.AddToProjectButton.Click += new System.EventHandler(this.AddToProjectButton_Click); this.AddToProjectButton.Click += new System.EventHandler(this.AddToProjectButton_Click);
// //
// PortalTypeUpDown // PortalCountUpDown
// //
this.PortalTypeUpDown.Location = new System.Drawing.Point(495, 12); this.PortalCountUpDown.Location = new System.Drawing.Point(495, 12);
this.PortalTypeUpDown.Maximum = new decimal(new int[] { this.PortalCountUpDown.Maximum = new decimal(new int[] {
15, 15,
0, 0,
0, 0,
0}); 0});
this.PortalTypeUpDown.Name = "PortalTypeUpDown"; this.PortalCountUpDown.Name = "PortalCountUpDown";
this.PortalTypeUpDown.Size = new System.Drawing.Size(57, 20); this.PortalCountUpDown.Size = new System.Drawing.Size(57, 20);
this.PortalTypeUpDown.TabIndex = 8; this.PortalCountUpDown.TabIndex = 8;
this.PortalTypeUpDown.ValueChanged += new System.EventHandler(this.PortalTypeUpDown_ValueChanged); this.PortalCountUpDown.ValueChanged += new System.EventHandler(this.PortalCountUpDown_ValueChanged);
// //
// label6 // label6
// //
this.label6.AutoSize = true; this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(429, 14); this.label6.Location = new System.Drawing.Point(424, 14);
this.label6.Name = "label6"; this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(60, 13); this.label6.Size = new System.Drawing.Size(67, 13);
this.label6.TabIndex = 7; this.label6.TabIndex = 7;
this.label6.Text = "Portal type:"; this.label6.Text = "Portal count:";
// //
// EditYnvPolyPanel // EditYnvPolyPanel
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(562, 404); this.ClientSize = new System.Drawing.Size(562, 404);
this.Controls.Add(this.PortalTypeUpDown); this.Controls.Add(this.PortalCountUpDown);
this.Controls.Add(this.label6); this.Controls.Add(this.label6);
this.Controls.Add(this.DeletePolyButton); this.Controls.Add(this.DeletePolyButton);
this.Controls.Add(this.AddToProjectButton); this.Controls.Add(this.AddToProjectButton);
@ -327,7 +327,7 @@
((System.ComponentModel.ISupportInitialize)(this.PortalIDUpDown)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PortalIDUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.UnkXUpDown)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.UnkXUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.UnkYUpDown)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.UnkYUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.PortalTypeUpDown)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.PortalCountUpDown)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@ -352,7 +352,7 @@
private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label4;
private System.Windows.Forms.Button DeletePolyButton; private System.Windows.Forms.Button DeletePolyButton;
private System.Windows.Forms.Button AddToProjectButton; private System.Windows.Forms.Button AddToProjectButton;
private System.Windows.Forms.NumericUpDown PortalTypeUpDown; private System.Windows.Forms.NumericUpDown PortalCountUpDown;
private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label6;
} }
} }

View File

@ -48,7 +48,7 @@ namespace CodeWalker.Project.Panels
AreaIDUpDown.Value = 0; AreaIDUpDown.Value = 0;
PartIDUpDown.Value = 0; PartIDUpDown.Value = 0;
PortalIDUpDown.Value = 0; PortalIDUpDown.Value = 0;
PortalTypeUpDown.Value = 0; PortalCountUpDown.Value = 0;
SetCheckedListBoxValues(FlagsCheckedListBox1, 0); SetCheckedListBoxValues(FlagsCheckedListBox1, 0);
SetCheckedListBoxValues(FlagsCheckedListBox2, 0); SetCheckedListBoxValues(FlagsCheckedListBox2, 0);
SetCheckedListBoxValues(FlagsCheckedListBox3, 0); SetCheckedListBoxValues(FlagsCheckedListBox3, 0);
@ -65,7 +65,7 @@ namespace CodeWalker.Project.Panels
AreaIDUpDown.Value = YnvPoly.AreaID; AreaIDUpDown.Value = YnvPoly.AreaID;
PartIDUpDown.Value = YnvPoly.PartID; PartIDUpDown.Value = YnvPoly.PartID;
PortalIDUpDown.Value = YnvPoly.PortalLinkID; PortalIDUpDown.Value = YnvPoly.PortalLinkID;
PortalTypeUpDown.Value = YnvPoly.PortalType; PortalCountUpDown.Value = YnvPoly.PortalLinkCount;
SetCheckedListBoxValues(FlagsCheckedListBox1, YnvPoly.Flags1); SetCheckedListBoxValues(FlagsCheckedListBox1, YnvPoly.Flags1);
SetCheckedListBoxValues(FlagsCheckedListBox2, YnvPoly.Flags2); SetCheckedListBoxValues(FlagsCheckedListBox2, YnvPoly.Flags2);
SetCheckedListBoxValues(FlagsCheckedListBox3, YnvPoly.Flags3); SetCheckedListBoxValues(FlagsCheckedListBox3, YnvPoly.Flags3);
@ -152,16 +152,16 @@ namespace CodeWalker.Project.Panels
} }
} }
private void PortalTypeUpDown_ValueChanged(object sender, EventArgs e) private void PortalCountUpDown_ValueChanged(object sender, EventArgs e)
{ {
if (populatingui) return; if (populatingui) return;
if (YnvPoly == null) return; if (YnvPoly == null) return;
byte portalunk = (byte)PortalTypeUpDown.Value; byte portalcount = (byte)PortalCountUpDown.Value;
lock (ProjectForm.ProjectSyncRoot) lock (ProjectForm.ProjectSyncRoot)
{ {
if (YnvPoly.PortalType != portalunk) if (YnvPoly.PortalLinkCount != portalcount)
{ {
YnvPoly.PortalType = portalunk; YnvPoly.PortalLinkCount = portalcount;
ProjectForm.SetYnvHasChanged(true); ProjectForm.SetYnvHasChanged(true);
} }
} }

View File

@ -0,0 +1,173 @@
namespace CodeWalker.Project.Panels
{
partial class EditYtypArchetypeMloRoomPanel
{
/// <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(EditYtypArchetypeMloRoomPanel));
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.MinBoundsTextBox = new CodeWalker.WinForms.TextBoxFix();
this.MaxBoundsTextBox = new CodeWalker.WinForms.TextBoxFix();
this.label3 = new System.Windows.Forms.Label();
this.RoomNameTextBox = new CodeWalker.WinForms.TextBoxFix();
this.RoomFlagsCheckedListBox = new System.Windows.Forms.CheckedListBox();
this.RoomFlagsTextBox = new System.Windows.Forms.TextBox();
this.label14 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(33, 69);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(27, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Min:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(30, 95);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(30, 13);
this.label2.TabIndex = 1;
this.label2.Text = "Max:";
//
// MinBoundsTextBox
//
this.MinBoundsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.MinBoundsTextBox.Location = new System.Drawing.Point(66, 66);
this.MinBoundsTextBox.Name = "MinBoundsTextBox";
this.MinBoundsTextBox.Size = new System.Drawing.Size(275, 20);
this.MinBoundsTextBox.TabIndex = 2;
this.MinBoundsTextBox.TextChanged += new System.EventHandler(this.MinBoundsTextBox_TextChanged);
//
// MaxBoundsTextBox
//
this.MaxBoundsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.MaxBoundsTextBox.Location = new System.Drawing.Point(66, 92);
this.MaxBoundsTextBox.Name = "MaxBoundsTextBox";
this.MaxBoundsTextBox.Size = new System.Drawing.Size(275, 20);
this.MaxBoundsTextBox.TabIndex = 3;
this.MaxBoundsTextBox.TextChanged += new System.EventHandler(this.MaxBoundsTextBox_TextChanged);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(19, 43);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(41, 13);
this.label3.TabIndex = 4;
this.label3.Text = "Name: ";
//
// RoomNameTextBox
//
this.RoomNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.RoomNameTextBox.Location = new System.Drawing.Point(66, 40);
this.RoomNameTextBox.Name = "RoomNameTextBox";
this.RoomNameTextBox.Size = new System.Drawing.Size(275, 20);
this.RoomNameTextBox.TabIndex = 5;
this.RoomNameTextBox.TextChanged += new System.EventHandler(this.RoomNameTextBox_TextChanged);
//
// RoomFlagsCheckedListBox
//
this.RoomFlagsCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.RoomFlagsCheckedListBox.CheckOnClick = true;
this.RoomFlagsCheckedListBox.FormattingEnabled = true;
this.RoomFlagsCheckedListBox.Items.AddRange(new object[] {
"1 - Unk01",
"2 - Unk02",
"4 - Unk03",
"8 - Unk04",
"16 - Unk05",
"32 - Unk06",
"64 - Unk07"});
this.RoomFlagsCheckedListBox.Location = new System.Drawing.Point(352, 62);
this.RoomFlagsCheckedListBox.Name = "RoomFlagsCheckedListBox";
this.RoomFlagsCheckedListBox.Size = new System.Drawing.Size(201, 244);
this.RoomFlagsCheckedListBox.TabIndex = 35;
this.RoomFlagsCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.RoomFlagsCheckedListBox_ItemCheck);
//
// RoomFlagsTextBox
//
this.RoomFlagsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.RoomFlagsTextBox.Location = new System.Drawing.Point(406, 36);
this.RoomFlagsTextBox.Name = "RoomFlagsTextBox";
this.RoomFlagsTextBox.Size = new System.Drawing.Size(147, 20);
this.RoomFlagsTextBox.TabIndex = 34;
this.RoomFlagsTextBox.TextChanged += new System.EventHandler(this.RoomFlagsTextBox_TextChanged);
//
// label14
//
this.label14.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(365, 39);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(35, 13);
this.label14.TabIndex = 33;
this.label14.Text = "Flags:";
//
// EditYtypArchetypeMloRoomPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(565, 505);
this.Controls.Add(this.RoomFlagsCheckedListBox);
this.Controls.Add(this.RoomFlagsTextBox);
this.Controls.Add(this.label14);
this.Controls.Add(this.RoomNameTextBox);
this.Controls.Add(this.label3);
this.Controls.Add(this.MaxBoundsTextBox);
this.Controls.Add(this.MinBoundsTextBox);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "EditYtypArchetypeMloRoomPanel";
this.Text = "Room";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private WinForms.TextBoxFix MinBoundsTextBox;
private WinForms.TextBoxFix MaxBoundsTextBox;
private System.Windows.Forms.Label label3;
private WinForms.TextBoxFix RoomNameTextBox;
private System.Windows.Forms.CheckedListBox RoomFlagsCheckedListBox;
private System.Windows.Forms.TextBox RoomFlagsTextBox;
private System.Windows.Forms.Label label14;
}
}

View File

@ -0,0 +1,137 @@
using System;
using System.Windows.Forms;
using CodeWalker.GameFiles;
using SharpDX;
namespace CodeWalker.Project.Panels
{
public partial class EditYtypArchetypeMloRoomPanel : ProjectPanel
{
public ProjectForm ProjectForm;
public MCMloRoomDef CurrentRoom { get; set; }
public EditYtypArchetypeMloRoomPanel(ProjectForm owner)
{
ProjectForm = owner;
InitializeComponent();
}
public void SetRoom(MCMloRoomDef room)
{
CurrentRoom = room;
Tag = room;
UpdateFormTitle();
MloInstanceData instance = ProjectForm.TryGetMloInstance(room?.Archetype);
ProjectForm.WorldForm?.SelectMloRoom(room, instance);
UpdateControls();
}
private void UpdateControls()
{
if (CurrentRoom != null)
{
RoomNameTextBox.Text = CurrentRoom.RoomName;
MinBoundsTextBox.Text = FloatUtil.GetVector3String(CurrentRoom.BBMin);
MaxBoundsTextBox.Text = FloatUtil.GetVector3String(CurrentRoom.BBMax);
RoomFlagsTextBox.Text = CurrentRoom._Data.flags.ToString();
}
}
private void UpdateFormTitle()
{
Text = CurrentRoom?.RoomName ?? "Room";
}
private void RoomNameTextBox_TextChanged(object sender, EventArgs e)
{
if (CurrentRoom == null) return;
if (CurrentRoom.RoomName != RoomNameTextBox.Text)
{
CurrentRoom.RoomName = RoomNameTextBox.Text;
TreeNode tn = ProjectForm.ProjectExplorer?.FindMloRoomTreeNode(CurrentRoom);
if (tn != null)
{
tn.Text = CurrentRoom.RoomName;
}
UpdateFormTitle();
ProjectForm.SetYtypHasChanged(true);
}
}
private void MinBoundsTextBox_TextChanged(object sender, EventArgs e)
{
if (CurrentRoom == null) return;
Vector3 bb = FloatUtil.ParseVector3String(MinBoundsTextBox.Text);
if (CurrentRoom._Data.bbMin != bb)
{
CurrentRoom._Data.bbMin = bb;
ProjectForm.SetYtypHasChanged(true);
}
}
private void MaxBoundsTextBox_TextChanged(object sender, EventArgs e)
{
if (CurrentRoom == null) return;
Vector3 bb = FloatUtil.ParseVector3String(MaxBoundsTextBox.Text);
if (CurrentRoom._Data.bbMax != bb)
{
CurrentRoom._Data.bbMax = bb;
ProjectForm.SetYtypHasChanged(true);
}
}
private void RoomFlagsTextBox_TextChanged(object sender, EventArgs e)
{
if (CurrentRoom == null) return;
uint.TryParse(RoomFlagsTextBox.Text, out uint flags);
for (int i = 0; i < RoomFlagsCheckedListBox.Items.Count; i++)
{
var c = ((flags & (1u << i)) > 0);
RoomFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked);
}
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentRoom._Data.flags != flags)
{
CurrentRoom._Data.flags = flags;
ProjectForm.SetYtypHasChanged(true);
}
}
}
private void RoomFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (CurrentRoom == null) return;
uint flags = 0;
for (int i = 0; i < RoomFlagsCheckedListBox.Items.Count; i++)
{
if (e.Index == i)
{
if (e.NewValue == CheckState.Checked)
{
flags += (uint)(1 << i);
}
}
else
{
if (RoomFlagsCheckedListBox.GetItemChecked(i))
{
flags += (uint)(1 << i);
}
}
}
RoomFlagsTextBox.Text = flags.ToString();
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentRoom._Data.flags != flags)
{
CurrentRoom._Data.flags = flags;
ProjectForm.SetYtypHasChanged(true);
}
}
}
}
}

View File

@ -0,0 +1,409 @@
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
<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" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</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" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
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
6P///ysvjWVqtP///////wAAAAAAAAAAAP////D0/0hPpsDG6////////6y02d7k8////3qAx+/z/f//
/wAAAAAAAAAAAAAAAAAAAP///////////////8zT8V5ns1Rcrdzh9f///////////wAAAAAAAAAAAAAA
AAAAAP////////7+/6ix3nmBxFthtmdwu09WqbC54/v9//r8//j6//39/wAAAAAAAAAAAOjt/H6I0FJc
skpSqHF+wRMahFZhs4iT1AsNc1pgrm52v2RsuO/z/gAAAP////////L2/cLJ7rrD64+V4DY+ozU+mYmU
0X2Hy1hfss7V8urv/PP2/v///wAAAP///+Pp+d/k9////////+Pp/4uR3ysymW14xYOM0fD0/P///+Xq
+ri/6Pj6/wAAAOrv/j5DnbS75P////////////X4/+/0/ubr+/r7/////////9rh+hgZhKGo2QAAAPDz
/eLn+f////j6/2Nqttrg9////+Hn+P3+//3+/1hescLJ6/////L2/eru/AAAAAAAAAAAAP///8rR70tR
p/3+//v8/zY6jNPY7////09WqWpwu////wAAAAAAAAAAAAAAAAAAAAAAAPb4/vr7//////v8/5Wd1eHm
+P////v8//T3/wAAAAAAAAAAAAAAAP//AAD8PwAA/D8AAPwDAACAAwAAgAMAAIAHAADABwAAwAEAAMAB
AAAAAQAAAAEAAAABAAAAAQAAwAcAAOAPAAAoAAAAQAAAAIAAAAABABgAAAAAAAAwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//P3//P3//P3/
/f7//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/
+fv/+fv/+Pr/+fv/+vv//P3//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA/f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA/P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/2+P9X2OmREGLnqPd
4+v/8vb/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/
1N35bXK1JSRtbHGz5O7/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/AAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//AAAAAAAAAAAAAAAA
/v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7/AAAAAAAAAAAAAAAA/v7/+/z/9/n/9fj/9vn/
9fj/9vj/+vz//f7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7//f3//f3//f3//v7//v//AAAA
AAAAAAAAAAAAAAAAAAAA+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/AAAAAAAAAAAAAAAAAAAA
/v7//f7/+/z/+/z/+/z//P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//P3/+fv/+fv/+vv/+Pr/+vv/
/P3//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7//f7/
/f3//P3//f7//v7//v//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
///////4D/////////AH////////8Af////////wB/////////AH////////8Af////////wB///////
//AH////////8Af////////wB/////////AH////////8AfwP//////wB8Af//+Af/AHgB///wA/8AcA
H///AB/wBgAf//8AD/AGAB///wAH8AYAH///AAPwBAAf//8AA/AEAD///wAD8AQAP///AAPwBAB///+A
A/AEAP///8AD4AAA////4AcAAAH////wDgAAAf/////8AAAH//////gAAAf/////4AAAAf/////gAAAA
/f//+AAAAAAAD//AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+AAAAAAAAH/4AAAAAAAAf/gAAAAAAAB/+A
AAAAAAAP/4AAAAAAAB//wAAAAABAf/4HwAAAAYAf8APAAAADgA/gA+AAAAMAA8AD8AAABwADgAP8AAAf
AAOAA/4AAB8AA4ADAAAAAQADgAIAcA4AgAOABgBwDgBAA4AMAGAMADADwDwAYAwAOAfg+ABgBAAeH//4
AEAEAB////gAwAYAH///+ADABgAf///4AcAGAB////gBwAcAH///+APAB4A////8B+AHwH//////4A//
///////gD/////////Af//////////////8=
</value>
</data>
</root>

View File

@ -0,0 +1,632 @@
namespace CodeWalker.Project.Panels
{
partial class EditYtypArchetypePanel
{
/// <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(EditYtypArchetypePanel));
this.BaseArchetypeTabPage = new System.Windows.Forms.TabPage();
this.ArchetypeDeleteButton = new System.Windows.Forms.Button();
this.label13 = new System.Windows.Forms.Label();
this.BSRadiusTextBox = new System.Windows.Forms.TextBox();
this.BSCenterTextBox = new System.Windows.Forms.TextBox();
this.BBMaxTextBox = new System.Windows.Forms.TextBox();
this.BBMinTextBox = new System.Windows.Forms.TextBox();
this.ArchetypeNameTextBox = new System.Windows.Forms.TextBox();
this.ArchetypeFlagsTextBox = new System.Windows.Forms.TextBox();
this.PhysicsDictionaryTextBox = new System.Windows.Forms.TextBox();
this.ClipDictionaryTextBox = new System.Windows.Forms.TextBox();
this.AssetNameTextBox = new System.Windows.Forms.TextBox();
this.TextureDictTextBox = new System.Windows.Forms.TextBox();
this.label12 = new System.Windows.Forms.Label();
this.label11 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.PhysicsDictHashLabel = new System.Windows.Forms.Label();
this.TextureDictHashLabel = new System.Windows.Forms.Label();
this.EntityFlagsCheckedListBox = new System.Windows.Forms.CheckedListBox();
this.label14 = new System.Windows.Forms.Label();
this.SpecialAttributeNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label10 = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.AssetTypeComboBox = new System.Windows.Forms.ComboBox();
this.label8 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.HDTextureDistNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label3 = new System.Windows.Forms.Label();
this.LodDistNumericUpDown = new System.Windows.Forms.NumericUpDown();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.TabControl = new System.Windows.Forms.TabControl();
this.MloArchetypeTabPage = new System.Windows.Forms.TabPage();
this.EntitySetsListBox = new System.Windows.Forms.CheckedListBox();
this.label15 = new System.Windows.Forms.Label();
this.BaseArchetypeTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.SpecialAttributeNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.HDTextureDistNumericUpDown)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.LodDistNumericUpDown)).BeginInit();
this.TabControl.SuspendLayout();
this.MloArchetypeTabPage.SuspendLayout();
this.SuspendLayout();
//
// BaseArchetypeTabPage
//
this.BaseArchetypeTabPage.Controls.Add(this.ArchetypeDeleteButton);
this.BaseArchetypeTabPage.Controls.Add(this.label13);
this.BaseArchetypeTabPage.Controls.Add(this.BSRadiusTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.BSCenterTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.BBMaxTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.BBMinTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.ArchetypeNameTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.ArchetypeFlagsTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.PhysicsDictionaryTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.ClipDictionaryTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.AssetNameTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.TextureDictTextBox);
this.BaseArchetypeTabPage.Controls.Add(this.label12);
this.BaseArchetypeTabPage.Controls.Add(this.label11);
this.BaseArchetypeTabPage.Controls.Add(this.label5);
this.BaseArchetypeTabPage.Controls.Add(this.PhysicsDictHashLabel);
this.BaseArchetypeTabPage.Controls.Add(this.TextureDictHashLabel);
this.BaseArchetypeTabPage.Controls.Add(this.EntityFlagsCheckedListBox);
this.BaseArchetypeTabPage.Controls.Add(this.label14);
this.BaseArchetypeTabPage.Controls.Add(this.SpecialAttributeNumericUpDown);
this.BaseArchetypeTabPage.Controls.Add(this.label10);
this.BaseArchetypeTabPage.Controls.Add(this.label9);
this.BaseArchetypeTabPage.Controls.Add(this.AssetTypeComboBox);
this.BaseArchetypeTabPage.Controls.Add(this.label8);
this.BaseArchetypeTabPage.Controls.Add(this.label7);
this.BaseArchetypeTabPage.Controls.Add(this.label6);
this.BaseArchetypeTabPage.Controls.Add(this.label4);
this.BaseArchetypeTabPage.Controls.Add(this.HDTextureDistNumericUpDown);
this.BaseArchetypeTabPage.Controls.Add(this.label3);
this.BaseArchetypeTabPage.Controls.Add(this.LodDistNumericUpDown);
this.BaseArchetypeTabPage.Controls.Add(this.label2);
this.BaseArchetypeTabPage.Controls.Add(this.label1);
this.BaseArchetypeTabPage.Location = new System.Drawing.Point(4, 22);
this.BaseArchetypeTabPage.Name = "BaseArchetypeTabPage";
this.BaseArchetypeTabPage.Padding = new System.Windows.Forms.Padding(3);
this.BaseArchetypeTabPage.Size = new System.Drawing.Size(631, 479);
this.BaseArchetypeTabPage.TabIndex = 0;
this.BaseArchetypeTabPage.Text = "Base Archetype Def";
this.BaseArchetypeTabPage.UseVisualStyleBackColor = true;
//
// ArchetypeDeleteButton
//
this.ArchetypeDeleteButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.ArchetypeDeleteButton.Location = new System.Drawing.Point(270, 450);
this.ArchetypeDeleteButton.Name = "ArchetypeDeleteButton";
this.ArchetypeDeleteButton.Size = new System.Drawing.Size(126, 23);
this.ArchetypeDeleteButton.TabIndex = 79;
this.ArchetypeDeleteButton.Text = "Delete Archetype";
this.ArchetypeDeleteButton.UseVisualStyleBackColor = true;
this.ArchetypeDeleteButton.Click += new System.EventHandler(this.DeleteArchetypeButton_Click);
//
// label13
//
this.label13.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(8, 411);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(57, 13);
this.label13.TabIndex = 78;
this.label13.Text = "BSRadius:";
//
// BSRadiusTextBox
//
this.BSRadiusTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.BSRadiusTextBox.Location = new System.Drawing.Point(71, 408);
this.BSRadiusTextBox.Name = "BSRadiusTextBox";
this.BSRadiusTextBox.Size = new System.Drawing.Size(552, 20);
this.BSRadiusTextBox.TabIndex = 77;
this.BSRadiusTextBox.TextChanged += new System.EventHandler(this.BSRadiusTextBox_TextChanged);
//
// BSCenterTextBox
//
this.BSCenterTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.BSCenterTextBox.Location = new System.Drawing.Point(71, 382);
this.BSCenterTextBox.Name = "BSCenterTextBox";
this.BSCenterTextBox.Size = new System.Drawing.Size(552, 20);
this.BSCenterTextBox.TabIndex = 75;
this.BSCenterTextBox.TextChanged += new System.EventHandler(this.BSCenterTextBox_TextChanged);
//
// BBMaxTextBox
//
this.BBMaxTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.BBMaxTextBox.Location = new System.Drawing.Point(71, 356);
this.BBMaxTextBox.Name = "BBMaxTextBox";
this.BBMaxTextBox.Size = new System.Drawing.Size(552, 20);
this.BBMaxTextBox.TabIndex = 73;
this.BBMaxTextBox.TextChanged += new System.EventHandler(this.BBMaxTextBox_TextChanged);
//
// BBMinTextBox
//
this.BBMinTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.BBMinTextBox.Location = new System.Drawing.Point(71, 330);
this.BBMinTextBox.Name = "BBMinTextBox";
this.BBMinTextBox.Size = new System.Drawing.Size(552, 20);
this.BBMinTextBox.TabIndex = 71;
this.BBMinTextBox.TextChanged += new System.EventHandler(this.BBMinTextBox_TextChanged);
//
// ArchetypeNameTextBox
//
this.ArchetypeNameTextBox.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.ArchetypeNameTextBox.Location = new System.Drawing.Point(110, 9);
this.ArchetypeNameTextBox.Name = "ArchetypeNameTextBox";
this.ArchetypeNameTextBox.Size = new System.Drawing.Size(247, 20);
this.ArchetypeNameTextBox.TabIndex = 70;
this.ArchetypeNameTextBox.TextChanged += new System.EventHandler(this.ArchetypeNameTextBox_TextChanged);
//
// ArchetypeFlagsTextBox
//
this.ArchetypeFlagsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.ArchetypeFlagsTextBox.Location = new System.Drawing.Point(476, 12);
this.ArchetypeFlagsTextBox.Name = "ArchetypeFlagsTextBox";
this.ArchetypeFlagsTextBox.Size = new System.Drawing.Size(147, 20);
this.ArchetypeFlagsTextBox.TabIndex = 66;
this.ArchetypeFlagsTextBox.TextChanged += new System.EventHandler(this.ArchetypeFlagsTextBox_TextChanged);
//
// PhysicsDictionaryTextBox
//
this.PhysicsDictionaryTextBox.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.PhysicsDictionaryTextBox.Location = new System.Drawing.Point(110, 191);
this.PhysicsDictionaryTextBox.Name = "PhysicsDictionaryTextBox";
this.PhysicsDictionaryTextBox.Size = new System.Drawing.Size(206, 20);
this.PhysicsDictionaryTextBox.TabIndex = 60;
this.PhysicsDictionaryTextBox.TextChanged += new System.EventHandler(this.PhysicsDictionaryTextBox_TextChanged);
//
// ClipDictionaryTextBox
//
this.ClipDictionaryTextBox.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.ClipDictionaryTextBox.Location = new System.Drawing.Point(110, 165);
this.ClipDictionaryTextBox.Name = "ClipDictionaryTextBox";
this.ClipDictionaryTextBox.Size = new System.Drawing.Size(247, 20);
this.ClipDictionaryTextBox.TabIndex = 58;
this.ClipDictionaryTextBox.TextChanged += new System.EventHandler(this.ClipDictionaryTextBox_TextChanged);
//
// AssetNameTextBox
//
this.AssetNameTextBox.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.AssetNameTextBox.Location = new System.Drawing.Point(110, 35);
this.AssetNameTextBox.Name = "AssetNameTextBox";
this.AssetNameTextBox.Size = new System.Drawing.Size(247, 20);
this.AssetNameTextBox.TabIndex = 56;
this.AssetNameTextBox.TextChanged += new System.EventHandler(this.AssetNameTextBox_TextChanged);
//
// TextureDictTextBox
//
this.TextureDictTextBox.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.TextureDictTextBox.Location = new System.Drawing.Point(110, 139);
this.TextureDictTextBox.Name = "TextureDictTextBox";
this.TextureDictTextBox.Size = new System.Drawing.Size(206, 20);
this.TextureDictTextBox.TabIndex = 54;
this.TextureDictTextBox.TextChanged += new System.EventHandler(this.TextureDictTextBox_TextChanged);
//
// label12
//
this.label12.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(8, 385);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(55, 13);
this.label12.TabIndex = 76;
this.label12.Text = "BSCenter:";
//
// label11
//
this.label11.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(19, 359);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(44, 13);
this.label11.TabIndex = 74;
this.label11.Text = "BBMax:";
//
// label5
//
this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(24, 333);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(41, 13);
this.label5.TabIndex = 72;
this.label5.Text = "BBMin:";
//
// PhysicsDictHashLabel
//
this.PhysicsDictHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.PhysicsDictHashLabel.AutoSize = true;
this.PhysicsDictHashLabel.Location = new System.Drawing.Point(322, 194);
this.PhysicsDictHashLabel.Name = "PhysicsDictHashLabel";
this.PhysicsDictHashLabel.Size = new System.Drawing.Size(35, 13);
this.PhysicsDictHashLabel.TabIndex = 69;
this.PhysicsDictHashLabel.Text = "Hash:";
//
// TextureDictHashLabel
//
this.TextureDictHashLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.TextureDictHashLabel.AutoSize = true;
this.TextureDictHashLabel.Location = new System.Drawing.Point(322, 142);
this.TextureDictHashLabel.Name = "TextureDictHashLabel";
this.TextureDictHashLabel.Size = new System.Drawing.Size(35, 13);
this.TextureDictHashLabel.TabIndex = 68;
this.TextureDictHashLabel.Text = "Hash:";
//
// EntityFlagsCheckedListBox
//
this.EntityFlagsCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.EntityFlagsCheckedListBox.CheckOnClick = true;
this.EntityFlagsCheckedListBox.FormattingEnabled = true;
this.EntityFlagsCheckedListBox.Items.AddRange(new object[] {
"1 - Unk01",
"2 - Unk02",
"4 - Unk03",
"8 - Unk04",
"16 - Unk05",
"32 - Static",
"64 - Unk07",
"128 - Unk08",
"256 - Unk09",
"512 - Unk10",
"1024 - Unk11",
"2048 - Unk12",
"4096 - Unk13",
"8192 - Unk14",
"16384 - Unk15",
"32768 - Unk16",
"65536 - Unk17",
"131072 - Unk18",
"262144 - Unk19",
"524288 - Unk20",
"1048576 - Unk21",
"2097152 - Unk22",
"4194304 - Unk23",
"8388608 - Unk24",
"16777216 - Unk25",
"33554432 - Unk26",
"67108864 - Unk27",
"134217728 - Unk28",
"268435456 - Unk29",
"536870912 - Unk30",
"1073741824 - Unk31",
"2147483648 - Unk32"});
this.EntityFlagsCheckedListBox.Location = new System.Drawing.Point(422, 38);
this.EntityFlagsCheckedListBox.Name = "EntityFlagsCheckedListBox";
this.EntityFlagsCheckedListBox.Size = new System.Drawing.Size(201, 274);
this.EntityFlagsCheckedListBox.TabIndex = 67;
this.EntityFlagsCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.ArchetypeFlagsCheckedListBox_ItemCheck);
//
// label14
//
this.label14.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(419, 15);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(35, 13);
this.label14.TabIndex = 65;
this.label14.Text = "Flags:";
//
// SpecialAttributeNumericUpDown
//
this.SpecialAttributeNumericUpDown.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.SpecialAttributeNumericUpDown.Location = new System.Drawing.Point(110, 113);
this.SpecialAttributeNumericUpDown.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.SpecialAttributeNumericUpDown.Name = "SpecialAttributeNumericUpDown";
this.SpecialAttributeNumericUpDown.Size = new System.Drawing.Size(247, 20);
this.SpecialAttributeNumericUpDown.TabIndex = 64;
this.SpecialAttributeNumericUpDown.ValueChanged += new System.EventHandler(this.SpecialAttributeNumericUpDown_ValueChanged);
//
// label10
//
this.label10.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.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(17, 115);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(87, 13);
this.label10.TabIndex = 63;
this.label10.Text = "Special Attribute:";
//
// label9
//
this.label9.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.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(41, 220);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(63, 13);
this.label9.TabIndex = 62;
this.label9.Text = "Asset Type:";
//
// AssetTypeComboBox
//
this.AssetTypeComboBox.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.AssetTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.AssetTypeComboBox.FormattingEnabled = true;
this.AssetTypeComboBox.Location = new System.Drawing.Point(110, 217);
this.AssetTypeComboBox.Name = "AssetTypeComboBox";
this.AssetTypeComboBox.Size = new System.Drawing.Size(247, 21);
this.AssetTypeComboBox.TabIndex = 61;
//
// label8
//
this.label8.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.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(8, 194);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(96, 13);
this.label8.TabIndex = 59;
this.label8.Text = "Physics Dictionary:";
//
// label7
//
this.label7.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.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(27, 168);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(77, 13);
this.label7.TabIndex = 57;
this.label7.Text = "Clip Dictionary:";
//
// label6
//
this.label6.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.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(37, 38);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(67, 13);
this.label6.TabIndex = 55;
this.label6.Text = "Asset Name:";
//
// label4
//
this.label4.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.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(8, 142);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(96, 13);
this.label4.TabIndex = 53;
this.label4.Text = "Texture Dictionary:";
//
// HDTextureDistNumericUpDown
//
this.HDTextureDistNumericUpDown.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.HDTextureDistNumericUpDown.DecimalPlaces = 8;
this.HDTextureDistNumericUpDown.Location = new System.Drawing.Point(110, 87);
this.HDTextureDistNumericUpDown.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.HDTextureDistNumericUpDown.Name = "HDTextureDistNumericUpDown";
this.HDTextureDistNumericUpDown.Size = new System.Drawing.Size(247, 20);
this.HDTextureDistNumericUpDown.TabIndex = 52;
this.HDTextureDistNumericUpDown.ValueChanged += new System.EventHandler(this.HDTextureDistNumericUpDown_ValueChanged);
//
// label3
//
this.label3.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.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(18, 89);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(86, 13);
this.label3.TabIndex = 51;
this.label3.Text = "HD Texture Dist:";
//
// LodDistNumericUpDown
//
this.LodDistNumericUpDown.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.LodDistNumericUpDown.DecimalPlaces = 8;
this.LodDistNumericUpDown.Location = new System.Drawing.Point(110, 61);
this.LodDistNumericUpDown.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.LodDistNumericUpDown.Name = "LodDistNumericUpDown";
this.LodDistNumericUpDown.Size = new System.Drawing.Size(247, 20);
this.LodDistNumericUpDown.TabIndex = 50;
this.LodDistNumericUpDown.ValueChanged += new System.EventHandler(this.LodDistNumericUpDown_ValueChanged);
//
// label2
//
this.label2.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.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(55, 63);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(49, 13);
this.label2.TabIndex = 49;
this.label2.Text = "Lod Dist:";
//
// label1
//
this.label1.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.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(66, 12);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(38, 13);
this.label1.TabIndex = 48;
this.label1.Text = "Name:";
//
// TabControl
//
this.TabControl.Controls.Add(this.BaseArchetypeTabPage);
this.TabControl.Controls.Add(this.MloArchetypeTabPage);
this.TabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.TabControl.Location = new System.Drawing.Point(0, 0);
this.TabControl.Name = "TabControl";
this.TabControl.SelectedIndex = 0;
this.TabControl.Size = new System.Drawing.Size(639, 505);
this.TabControl.TabIndex = 48;
//
// MloArchetypeTabPage
//
this.MloArchetypeTabPage.Controls.Add(this.EntitySetsListBox);
this.MloArchetypeTabPage.Controls.Add(this.label15);
this.MloArchetypeTabPage.Location = new System.Drawing.Point(4, 22);
this.MloArchetypeTabPage.Name = "MloArchetypeTabPage";
this.MloArchetypeTabPage.Padding = new System.Windows.Forms.Padding(3);
this.MloArchetypeTabPage.Size = new System.Drawing.Size(631, 479);
this.MloArchetypeTabPage.TabIndex = 1;
this.MloArchetypeTabPage.Text = "Mlo Archetype Def";
this.MloArchetypeTabPage.UseVisualStyleBackColor = true;
//
// EntitySetsListBox
//
this.EntitySetsListBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.EntitySetsListBox.CheckOnClick = true;
this.EntitySetsListBox.FormattingEnabled = true;
this.EntitySetsListBox.Location = new System.Drawing.Point(11, 42);
this.EntitySetsListBox.Name = "EntitySetsListBox";
this.EntitySetsListBox.Size = new System.Drawing.Size(603, 214);
this.EntitySetsListBox.TabIndex = 2;
this.EntitySetsListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.EntitySetsListBox_ItemCheck);
//
// label15
//
this.label15.AutoSize = true;
this.label15.Location = new System.Drawing.Point(8, 26);
this.label15.Name = "label15";
this.label15.Size = new System.Drawing.Size(57, 13);
this.label15.TabIndex = 1;
this.label15.Text = "EntitySets:";
//
// EditYtypArchetypePanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(639, 505);
this.Controls.Add(this.TabControl);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(531, 458);
this.Name = "EditYtypArchetypePanel";
this.Text = "Edit Archetype";
this.Load += new System.EventHandler(this.EditYtypArchetypePanel_Load);
this.BaseArchetypeTabPage.ResumeLayout(false);
this.BaseArchetypeTabPage.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.SpecialAttributeNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.HDTextureDistNumericUpDown)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.LodDistNumericUpDown)).EndInit();
this.TabControl.ResumeLayout(false);
this.MloArchetypeTabPage.ResumeLayout(false);
this.MloArchetypeTabPage.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabPage BaseArchetypeTabPage;
private System.Windows.Forms.Button ArchetypeDeleteButton;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.TextBox BSRadiusTextBox;
private System.Windows.Forms.TextBox BSCenterTextBox;
private System.Windows.Forms.TextBox BBMaxTextBox;
private System.Windows.Forms.TextBox BBMinTextBox;
private System.Windows.Forms.TextBox ArchetypeNameTextBox;
private System.Windows.Forms.TextBox ArchetypeFlagsTextBox;
private System.Windows.Forms.TextBox PhysicsDictionaryTextBox;
private System.Windows.Forms.TextBox ClipDictionaryTextBox;
private System.Windows.Forms.TextBox AssetNameTextBox;
private System.Windows.Forms.TextBox TextureDictTextBox;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label PhysicsDictHashLabel;
private System.Windows.Forms.Label TextureDictHashLabel;
private System.Windows.Forms.CheckedListBox EntityFlagsCheckedListBox;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.NumericUpDown SpecialAttributeNumericUpDown;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.ComboBox AssetTypeComboBox;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.NumericUpDown HDTextureDistNumericUpDown;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.NumericUpDown LodDistNumericUpDown;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TabControl TabControl;
private System.Windows.Forms.TabPage MloArchetypeTabPage;
private System.Windows.Forms.CheckedListBox EntitySetsListBox;
private System.Windows.Forms.Label label15;
}
}

View File

@ -0,0 +1,353 @@
using System;
using System.Globalization;
using System.Windows.Forms;
using CodeWalker.GameFiles;
using SharpDX;
namespace CodeWalker.Project.Panels
{
public partial class EditYtypArchetypePanel : ProjectPanel
{
public ProjectForm ProjectForm;
private bool populatingui;
public EditYtypArchetypePanel(ProjectForm owner)
{
InitializeComponent();
ProjectForm = owner;
}
public Archetype CurrentArchetype { get; set; }
private void EditYtypArchetypePanel_Load(object sender, EventArgs e)
{
AssetTypeComboBox.Items.AddRange(Enum.GetNames(typeof(Unk_1991964615)));
}
public void SetArchetype(Archetype archetype)
{
CurrentArchetype = archetype;
Tag = archetype;
UpdateFormTitle();
UpdateControls();
}
private void UpdateFormTitle()
{
Text = CurrentArchetype?.Name ?? "Edit Archetype";
}
private void UpdateControls()
{
if (CurrentArchetype != null)
{
ArchetypeDeleteButton.Enabled = ProjectForm.YtypExistsInProject(CurrentArchetype.Ytyp);
ArchetypeNameTextBox.Text = CurrentArchetype.Name;
AssetNameTextBox.Text = CurrentArchetype.AssetName;
LodDistNumericUpDown.Value = (decimal)CurrentArchetype._BaseArchetypeDef.lodDist;
HDTextureDistNumericUpDown.Value = (decimal)CurrentArchetype._BaseArchetypeDef.hdTextureDist;
SpecialAttributeNumericUpDown.Value = CurrentArchetype._BaseArchetypeDef.specialAttribute;
ArchetypeFlagsTextBox.Text = CurrentArchetype._BaseArchetypeDef.flags.ToString();
TextureDictTextBox.Text = CurrentArchetype._BaseArchetypeDef.textureDictionary.ToCleanString();
ClipDictionaryTextBox.Text = CurrentArchetype._BaseArchetypeDef.clipDictionary.ToCleanString();
PhysicsDictionaryTextBox.Text = CurrentArchetype._BaseArchetypeDef.physicsDictionary.ToCleanString();
AssetTypeComboBox.Text = CurrentArchetype._BaseArchetypeDef.assetType.ToString();
BBMinTextBox.Text = FloatUtil.GetVector3String(CurrentArchetype._BaseArchetypeDef.bbMin);
BBMaxTextBox.Text = FloatUtil.GetVector3String(CurrentArchetype._BaseArchetypeDef.bbMax);
BSCenterTextBox.Text = FloatUtil.GetVector3String(CurrentArchetype._BaseArchetypeDef.bsCentre);
BSRadiusTextBox.Text = CurrentArchetype._BaseArchetypeDef.bsRadius.ToString(CultureInfo.InvariantCulture);
EntitySetsListBox.Items.Clear();
if (CurrentArchetype is MloArchetype MloArchetype)
{
if (!TabControl.TabPages.Contains(MloArchetypeTabPage))
{
TabControl.TabPages.Add(MloArchetypeTabPage);
}
MloInstanceData mloinstance = ProjectForm.TryGetMloInstance(MloArchetype);
if (mloinstance != null)
{
EntitySetsListBox.Enabled = true;
foreach (var sets in mloinstance.EntitySets)
{
MloInstanceEntitySet set = sets.Value;
EntitySetsListBox.Items.Add(set.EntitySet.ToString(), set.Visible);
}
}
else EntitySetsListBox.Enabled = false;
}
else TabControl.TabPages.Remove(MloArchetypeTabPage);
}
}
private void ArchetypeFlagsTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentArchetype == null) return;
uint flags = 0;
uint.TryParse(ArchetypeFlagsTextBox.Text, out flags);
populatingui = true;
for (int i = 0; i < EntityFlagsCheckedListBox.Items.Count; i++)
{
var c = ((flags & (1u << i)) > 0);
EntityFlagsCheckedListBox.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked);
}
populatingui = false;
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentArchetype._BaseArchetypeDef.flags != flags)
{
CurrentArchetype._BaseArchetypeDef.flags = flags;
ProjectForm.SetYtypHasChanged(true);
}
}
}
private void ArchetypeFlagsCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (populatingui) return;
if (CurrentArchetype == null) return;
uint flags = 0;
for (int i = 0; i < EntityFlagsCheckedListBox.Items.Count; i++)
{
if (e.Index == i)
{
if (e.NewValue == CheckState.Checked)
{
flags += (uint)(1 << i);
}
}
else
{
if (EntityFlagsCheckedListBox.GetItemChecked(i))
{
flags += (uint)(1 << i);
}
}
}
populatingui = true;
ArchetypeFlagsTextBox.Text = flags.ToString();
populatingui = false;
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentArchetype._BaseArchetypeDef.flags != flags)
{
CurrentArchetype._BaseArchetypeDef.flags = flags;
ProjectForm.SetYtypHasChanged(true);
}
}
}
private void TextureDictTextBox_TextChanged(object sender, EventArgs e)
{
// Check that the form is not null before locking...
if (ProjectForm == null)
return;
lock (ProjectForm.ProjectSyncRoot)
{
// Embedded...
if (TextureDictTextBox.Text == ArchetypeNameTextBox.Text)
{
TextureDictHashLabel.Text = "Embedded";
CurrentArchetype._BaseArchetypeDef.textureDictionary = CurrentArchetype._BaseArchetypeDef.name;
return;
}
var hash = JenkHash.GenHash(TextureDictTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.textureDictionary != hash)
{
var ytd = ProjectForm.GameFileCache.GetYtd(hash);
if (ytd == null)
{
TextureDictHashLabel.Text = "Hash: " + hash.ToString() + " (invalid)";
ProjectForm.SetYtypHasChanged(true);
return;
}
TextureDictHashLabel.Text = "Hash: " + hash.ToString();
CurrentArchetype._BaseArchetypeDef.textureDictionary = hash;
ProjectForm.SetYtypHasChanged(true);
}
}
}
private void PhysicsDictionaryTextBox_TextChanged(object sender, EventArgs e)
{
lock (ProjectForm.ProjectSyncRoot)
{
if (ProjectForm == null)
{
return;
}
// Embedded...
if (PhysicsDictionaryTextBox.Text == ArchetypeNameTextBox.Text)
{
PhysicsDictHashLabel.Text = "Embedded";
CurrentArchetype._BaseArchetypeDef.physicsDictionary = CurrentArchetype._BaseArchetypeDef.name;
return;
}
var hash = JenkHash.GenHash(PhysicsDictionaryTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.physicsDictionary != hash)
{
var ytd = ProjectForm.GameFileCache.GetYbn(hash);
if (ytd == null)
{
PhysicsDictHashLabel.Text = "Hash: " + hash.ToString() + " (invalid)";
ProjectForm.SetYtypHasChanged(true);
return;
}
PhysicsDictHashLabel.Text = "Hash: " + hash.ToString();
CurrentArchetype._BaseArchetypeDef.physicsDictionary = hash;
ProjectForm.SetYtypHasChanged(true);
}
}
}
private void ArchetypeNameTextBox_TextChanged(object sender, EventArgs e)
{
var hash = JenkHash.GenHash(ArchetypeNameTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.name != hash)
{
CurrentArchetype._BaseArchetypeDef.name = hash;
UpdateFormTitle();
TreeNode tn = ProjectForm.ProjectExplorer?.FindArchetypeTreeNode(CurrentArchetype);
if (tn != null)
tn.Text = ArchetypeNameTextBox.Text ?? "0"; // using the text box text because the name may not be in the gfc.
ProjectForm.SetYtypHasChanged(true);
}
}
private void AssetNameTextBox_TextChanged(object sender, EventArgs e)
{
var hash = JenkHash.GenHash(AssetNameTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.assetName != hash)
{
CurrentArchetype._BaseArchetypeDef.assetName = hash;
ProjectForm.SetYtypHasChanged(true);
}
}
private void ClipDictionaryTextBox_TextChanged(object sender, EventArgs e)
{
var hash = JenkHash.GenHash(ClipDictionaryTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.clipDictionary != hash)
{
CurrentArchetype._BaseArchetypeDef.clipDictionary = hash;
ProjectForm.SetYtypHasChanged(true);
}
}
private void LodDistNumericUpDown_ValueChanged(object sender, EventArgs e)
{
var loddist = (float)LodDistNumericUpDown.Value;
if (!MathUtil.NearEqual(loddist, CurrentArchetype._BaseArchetypeDef.lodDist))
{
CurrentArchetype._BaseArchetypeDef.lodDist = loddist;
ProjectForm.SetYtypHasChanged(true);
}
}
private void HDTextureDistNumericUpDown_ValueChanged(object sender, EventArgs e)
{
var hddist = (float)HDTextureDistNumericUpDown.Value;
if (!MathUtil.NearEqual(hddist, CurrentArchetype._BaseArchetypeDef.hdTextureDist))
{
CurrentArchetype._BaseArchetypeDef.hdTextureDist = hddist;
ProjectForm.SetYtypHasChanged(true);
}
}
private void SpecialAttributeNumericUpDown_ValueChanged(object sender, EventArgs e)
{
var att = (uint)SpecialAttributeNumericUpDown.Value;
if (CurrentArchetype._BaseArchetypeDef.specialAttribute != att)
{
CurrentArchetype._BaseArchetypeDef.specialAttribute = att;
ProjectForm.SetYtypHasChanged(true);
}
}
private void BBMinTextBox_TextChanged(object sender, EventArgs e)
{
Vector3 min = FloatUtil.ParseVector3String(BBMinTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.bbMin != min)
{
CurrentArchetype._BaseArchetypeDef.bbMin = min;
ProjectForm.SetYtypHasChanged(true);
}
}
private void BBMaxTextBox_TextChanged(object sender, EventArgs e)
{
Vector3 max = FloatUtil.ParseVector3String(BBMaxTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.bbMax != max)
{
CurrentArchetype._BaseArchetypeDef.bbMax = max;
ProjectForm.SetYtypHasChanged(true);
}
}
private void BSCenterTextBox_TextChanged(object sender, EventArgs e)
{
Vector3 c = FloatUtil.ParseVector3String(BSCenterTextBox.Text);
if (CurrentArchetype._BaseArchetypeDef.bsCentre != c)
{
CurrentArchetype._BaseArchetypeDef.bsCentre = c;
ProjectForm.SetYtypHasChanged(true);
}
}
private void BSRadiusTextBox_TextChanged(object sender, EventArgs e)
{
if (float.TryParse(BSRadiusTextBox.Text, out float f))
{
if (!MathUtil.NearEqual(CurrentArchetype._BaseArchetypeDef.bsRadius, f))
{
CurrentArchetype._BaseArchetypeDef.bsRadius = f;
ProjectForm.SetYtypHasChanged(true);
}
}
else
{
CurrentArchetype._BaseArchetypeDef.bsRadius = 0f;
ProjectForm.SetYtypHasChanged(true);
}
}
private void DeleteArchetypeButton_Click(object sender, EventArgs e)
{
ProjectForm.SetProjectItem(CurrentArchetype);
ProjectForm.DeleteArchetype();
}
private void EntitySetsListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (CurrentArchetype is MloArchetype MloArchetype)
{
var inst = ProjectForm.TryGetMloInstance(MloArchetype);
if (inst != null)
{
MloInstanceEntitySet mloInstanceEntitySet = inst.EntitySets[MloArchetype.entitySets[e.Index]._Data.name];
mloInstanceEntitySet.Visible = e.NewValue == CheckState.Checked;
return;
}
}
e.NewValue = CheckState.Unchecked;
}
}
}

View File

@ -0,0 +1,140 @@
<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" />
<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" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</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" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAEBAAAAAAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAD////r7/3y9f7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+P
lce/xeb///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///+Ah7a0utv/////////
//////////8AAAAAAAAAAAD////x9P73+v7///////////+Mk8K6weH////s8Pu6wOj9/f////8AAAAA
AAAAAAD///+epdgZHILl6/z///////+NlMPIzuj///8rL41larT///////8AAAAAAAAAAAD////w9P9I
T6bAxuv///////+stNne5PP///96gMfv8/3///8AAAAAAAAAAAAAAAAAAAD////////////////M0/Fe
Z7NUXK3c4fX///////////8AAAAAAAAAAAAAAAAAAAD////////+/v+osd55gcRbYbZncLtPVqmwueP7
/f/6/P/4+v/9/f8AAAAAAAAAAADo7fx+iNBSXLJKUqhxfsETGoRWYbOIk9QLDXNaYK5udr9kbLjv8/4A
AAD////////y9v3Cye66w+uPleA2PqM1PpmJlNF9h8tYX7LO1fLq7/zz9v7///8AAAD////j6fnf5Pf/
///////j6f+Lkd8rMplteMWDjNHw9Pz////l6vq4v+j4+v8AAADq7/4+Q520u+T////////////1+P/v
9P7m6/v6+//////////a4foYGYShqNkAAADw8/3i5/n////4+v9jarba4Pf////h5/j9/v/9/v9YXrHC
yev////y9v3q7vwAAAAAAAAAAAD////K0e9LUaf9/v/7/P82OozT2O////9PVqlqcLv///8AAAAAAAAA
AAAAAAAAAAAAAAD2+P76+//////7/P+VndXh5vj////7/P/09/8AAAAAAAAAAAAAAAD//wAA/D8AAPw/
AAD8AwAAgAMAAIADAACABwAAwAcAAMABAADAAQAAAAEAAAABAAAAAQAAAAEAAMAHAADgDwAA
</value>
</data>
</root>

View File

@ -29,34 +29,20 @@
private void InitializeComponent() private void InitializeComponent()
{ {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditYtypPanel)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditYtypPanel));
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout(); this.SuspendLayout();
// //
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(58, 52);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(99, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Ytyp editing TODO!";
//
// EditYtypPanel // EditYtypPanel
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(469, 292); this.ClientSize = new System.Drawing.Size(599, 406);
this.Controls.Add(this.label1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "EditYtypPanel"; this.Name = "EditYtypPanel";
this.Text = "Edit Ytyp"; this.Text = "Edit Ytyp";
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout();
} }
#endregion #endregion
private System.Windows.Forms.Label label1;
} }
} }

View File

@ -0,0 +1,146 @@
namespace CodeWalker.Project.Panels
{
partial class GenerateNavMeshPanel
{
/// <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(GenerateNavMeshPanel));
this.MinTextBox = new System.Windows.Forms.TextBox();
this.label81 = new System.Windows.Forms.Label();
this.MaxTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.GenerateButton = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.StatusLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// MinTextBox
//
this.MinTextBox.Location = new System.Drawing.Point(87, 131);
this.MinTextBox.Name = "MinTextBox";
this.MinTextBox.Size = new System.Drawing.Size(177, 20);
this.MinTextBox.TabIndex = 46;
this.MinTextBox.Text = "0, 0";
//
// label81
//
this.label81.AutoSize = true;
this.label81.Location = new System.Drawing.Point(22, 134);
this.label81.Name = "label81";
this.label81.Size = new System.Drawing.Size(56, 13);
this.label81.TabIndex = 47;
this.label81.Text = "Min: (X, Y)";
//
// MaxTextBox
//
this.MaxTextBox.Location = new System.Drawing.Point(87, 157);
this.MaxTextBox.Name = "MaxTextBox";
this.MaxTextBox.Size = new System.Drawing.Size(177, 20);
this.MaxTextBox.TabIndex = 48;
this.MaxTextBox.Text = "100, 100";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(22, 160);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(59, 13);
this.label1.TabIndex = 49;
this.label1.Text = "Max: (X, Y)";
//
// label2
//
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label2.Location = new System.Drawing.Point(12, 9);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(598, 119);
this.label2.TabIndex = 50;
this.label2.Text = resources.GetString("label2.Text");
//
// GenerateButton
//
this.GenerateButton.Location = new System.Drawing.Point(87, 196);
this.GenerateButton.Name = "GenerateButton";
this.GenerateButton.Size = new System.Drawing.Size(75, 23);
this.GenerateButton.TabIndex = 51;
this.GenerateButton.Text = "Generate";
this.GenerateButton.UseVisualStyleBackColor = true;
this.GenerateButton.Click += new System.EventHandler(this.GenerateButton_Click);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(279, 146);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(235, 13);
this.label3.TabIndex = 52;
this.label3.Text = "(Nav meshes will only be generated for this area)";
//
// StatusLabel
//
this.StatusLabel.AutoSize = true;
this.StatusLabel.Location = new System.Drawing.Point(84, 247);
this.StatusLabel.Name = "StatusLabel";
this.StatusLabel.Size = new System.Drawing.Size(95, 13);
this.StatusLabel.TabIndex = 53;
this.StatusLabel.Text = "Ready to generate";
//
// GenerateNavMeshPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(622, 340);
this.Controls.Add(this.StatusLabel);
this.Controls.Add(this.label3);
this.Controls.Add(this.GenerateButton);
this.Controls.Add(this.label2);
this.Controls.Add(this.MaxTextBox);
this.Controls.Add(this.label1);
this.Controls.Add(this.MinTextBox);
this.Controls.Add(this.label81);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "GenerateNavMeshPanel";
this.Text = "Generate Nav Meshes";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox MinTextBox;
private System.Windows.Forms.Label label81;
private System.Windows.Forms.TextBox MaxTextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button GenerateButton;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label StatusLabel;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -117,33 +117,15 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="ProjectManifestTextBox.ServiceColors" mimetype="application/x-microsoft.net.object.binary.base64"> <data name="label2.Text" xml:space="preserve">
<value> <value>This tool allows for generating GTAV nav meshes (.ynv) for a specified area.
AAEAAAD/////AQAAAAAAAAAMAgAAAFdGYXN0Q29sb3JlZFRleHRCb3gsIFZlcnNpb249Mi4xNi4yMS4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWZiOGFhMTJiOTk0ZWY2MWIMAwAAAFFTeXN0 Generation requires static collision meshes for the area to be loadable by CodeWalker World View. The usual approach to this is to add the collision meshes into a DLC, and then enable mods and DLC.
ZW0uRHJhd2luZywgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2Vu The collision material and flags will be used in generating the new nav mesh. Polygons with the "Ped" flag set will be marked as footpaths in the nav meshes, to spawn ambient peds.
PWIwM2Y1ZjdmMTFkNTBhM2EFAQAAACJGYXN0Q29sb3JlZFRleHRCb3hOUy5TZXJ2aWNlQ29sb3JzBgAA Generated .ynv files will be saved into the project folder and added to the project.
ACg8Q29sbGFwc2VNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxDb2xsYXBzZU1hcmtlckJh Note: existing .ynv files in the project folder will be overwritten!
Y2tDb2xvcj5rX19CYWNraW5nRmllbGQqPENvbGxhcHNlTWFya2VyQm9yZGVyQ29sb3I+a19fQmFja2lu
Z0ZpZWxkJjxFeHBhbmRNYXJrZXJGb3JlQ29sb3I+a19fQmFja2luZ0ZpZWxkJjxFeHBhbmRNYXJrZXJC
YWNrQ29sb3I+a19fQmFja2luZ0ZpZWxkKDxFeHBhbmRNYXJrZXJCb3JkZXJDb2xvcj5rX19CYWNraW5n
RmllbGQEBAQEBAQUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5EcmF3aW5nLkNvbG9yAwAA
ABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAAUU3lzdGVtLkRyYXdpbmcuQ29sb3IDAAAAFFN5c3RlbS5E
cmF3aW5nLkNvbG9yAwAAABRTeXN0ZW0uRHJhd2luZy5Db2xvcgMAAAACAAAABfz///8UU3lzdGVtLkRy
YXdpbmcuQ29sb3IEAAAABG5hbWUFdmFsdWUKa25vd25Db2xvcgVzdGF0ZQEAAAAJBwcDAAAACgAAAAAA
AAAAlgABAAH7/////P///woAAAAAAAAAAKQAAQAB+v////z///8KAAAAAAAAAACWAAEAAfn////8////
CgAAAAAAAAAAjQABAAH4/////P///woAAAAAAAAAAKQAAQAB9/////z///8KAAAAAAAAAACWAAEACw==
</value> </value>
</data> </data>
<metadata name="TopMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="SaveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>146, 17</value>
</metadata>
<metadata name="OpenFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>277, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>

View File

@ -248,8 +248,53 @@ namespace CodeWalker.Project.Panels
} }
} }
private void LoadYtypTreeNodes(YtypFile ytyp, TreeNode node)//TODO! private void LoadYtypTreeNodes(YtypFile ytyp, TreeNode node)
{ {
if (ytyp == null) return;
if (!string.IsNullOrEmpty(node.Name)) return;
node.Nodes.Clear();
if ((ytyp.AllArchetypes != null) && (ytyp.AllArchetypes.Length > 0))
{
var archetypesnode = node.Nodes.Add("Archetypes (" + ytyp.AllArchetypes.Length.ToString() + ")");
archetypesnode.Name = "Archetypes";
archetypesnode.Tag = ytyp;
var archetypes = ytyp.AllArchetypes;
for (int i = 0; i < archetypes.Length; i++)
{
var yarch = archetypes[i];
var tarch = archetypesnode.Nodes.Add(yarch.Name);
tarch.Tag = yarch;
if (yarch is MloArchetype mlo)
{
if ((mlo.entities.Length) > 0 && (mlo.rooms.Length > 0))
{
MCEntityDef[] entities = mlo.entities;
var roomsnode = tarch.Nodes.Add("Rooms (" + mlo.rooms.Length.ToString() + ")");
roomsnode.Name = "Rooms";
for (int j = 0; j < mlo.rooms.Length; j++)
{
MCMloRoomDef room = mlo.rooms[j];
var roomnode = roomsnode.Nodes.Add(room.RoomName);
roomnode.Tag = room;
var entitiesnode = roomnode.Nodes.Add("Attached Objects (" + room.AttachedObjects.Length + ")");
entitiesnode.Name = "Attached Objects";
for (int k = 0; k < room.AttachedObjects.Length; k++)
{
uint attachedObject = room.AttachedObjects[k];
MCEntityDef ent = entities[attachedObject];
TreeNode entnode = entitiesnode.Nodes.Add(ent.ToString());
entnode.Tag = ent;
}
}
}
}
}
}
} }
private void LoadYndTreeNodes(YndFile ynd, TreeNode node) private void LoadYndTreeNodes(YndFile ynd, TreeNode node)
{ {
@ -641,6 +686,20 @@ namespace CodeWalker.Project.Panels
} }
} }
} }
public void SetGrassBatchHasChanged(YmapGrassInstanceBatch batch, bool changed)
{
if (ProjectTreeView.Nodes.Count > 0)
{
var gbnode = FindGrassTreeNode(batch);
if (gbnode == null) return;
string changestr = changed ? "*" : "";
if (gbnode.Tag == batch)
{
string name = batch.ToString();
gbnode.Text = changestr + name;
}
}
}
@ -698,6 +757,115 @@ namespace CodeWalker.Project.Panels
} }
return null; return null;
} }
public TreeNode FindGrassTreeNode(YmapGrassInstanceBatch batch)
{
if (batch == null) return null;
TreeNode ymapnode = FindYmapTreeNode(batch.Ymap);
if (ymapnode == null) return null;
var batchnode = GetChildTreeNode(ymapnode, "GrassBatches");
if (batchnode == null) return null;
for (int i = 0; i < batchnode.Nodes.Count; i++)
{
TreeNode grassnode = batchnode.Nodes[i];
if (grassnode.Tag == batch) return grassnode;
}
return null;
}
public TreeNode FindYtypTreeNode(YtypFile ytyp)
{
if (ProjectTreeView.Nodes.Count <= 0) return null;
var projnode = ProjectTreeView.Nodes[0];
var ytypsnode = GetChildTreeNode(projnode, "Ytyp");
if (ytypsnode == null) return null;
for (int i = 0; i < ytypsnode.Nodes.Count; i++)
{
var ytypnode = ytypsnode.Nodes[i];
if (ytypnode.Tag == ytyp) return ytypnode;
}
return null;
}
public TreeNode FindArchetypeTreeNode(Archetype archetype)
{
if (archetype == null) return null;
TreeNode ytypnode = FindYtypTreeNode(archetype.Ytyp);
if (ytypnode == null) return null;
var archetypenode = GetChildTreeNode(ytypnode, "Archetypes");
if (archetypenode == null) return null;
for (int i = 0; i < archetypenode.Nodes.Count; i++)
{
TreeNode archnode = archetypenode.Nodes[i];
if (archnode.Tag == archetype) return archnode;
}
return null;
}
public TreeNode FindMloRoomTreeNode(MCMloRoomDef room)
{
if (room == null) return null;
TreeNode ytypnode = FindYtypTreeNode(room.Archetype.Ytyp);
if (ytypnode == null) return null;
TreeNode archetypesnode = GetChildTreeNode(ytypnode, "Archetypes");
if (archetypesnode == null) return null;
for (int i = 0; i < archetypesnode.Nodes.Count; i++)
{
TreeNode mloarchetypenode = archetypesnode.Nodes[i];
if (mloarchetypenode.Tag == room.Archetype)
{
TreeNode roomsnode = GetChildTreeNode(mloarchetypenode, "Rooms");
if (roomsnode == null) return null;
for (int j = 0; j < roomsnode.Nodes.Count; j++)
{
TreeNode roomnode = roomsnode.Nodes[j];
if (roomnode.Tag == room) return roomnode;
}
break;
}
}
return null;
}
public TreeNode FindMloEntityTreeNode(MCEntityDef ent)
{
MCMloRoomDef entityroom = ent?.Archetype?.GetEntityRoom(ent);
if (entityroom == null) return null;
TreeNode ytypnode = FindYtypTreeNode(ent.Archetype.Ytyp);
if (ytypnode == null) return null;
var archetypesnode = GetChildTreeNode(ytypnode, "Archetypes");
if (archetypesnode == null) return null;
for (int i = 0; i < archetypesnode.Nodes.Count; i++)
{
TreeNode mloarchetypenode = archetypesnode.Nodes[i];
if (mloarchetypenode.Tag == ent.Archetype)
{
TreeNode roomsnode = GetChildTreeNode(mloarchetypenode, "Rooms");
if (roomsnode == null) return null;
for (int j = 0; j < roomsnode.Nodes.Count; j++)
{
TreeNode roomnode = roomsnode.Nodes[j];
if (roomnode.Tag == entityroom)
{
TreeNode entitiesnode = GetChildTreeNode(roomnode, "Attached Objects");
if (entitiesnode == null) return null;
for (var k = 0; k < entitiesnode.Nodes.Count; k++)
{
TreeNode entitynode = entitiesnode.Nodes[k];
if (entitynode.Tag == ent) return entitynode;
}
break;
}
}
break;
}
}
return null;
}
public TreeNode FindYndTreeNode(YndFile ynd) public TreeNode FindYndTreeNode(YndFile ynd)
{ {
if (ProjectTreeView.Nodes.Count <= 0) return null; if (ProjectTreeView.Nodes.Count <= 0) return null;
@ -930,6 +1098,66 @@ namespace CodeWalker.Project.Panels
} }
} }
} }
public void TrySelectGrassBatchTreeNode(YmapGrassInstanceBatch grassBatch)
{
TreeNode grassNode = FindGrassTreeNode(grassBatch);
if (grassNode != null)
{
if (ProjectTreeView.SelectedNode == grassNode)
{
OnItemSelected?.Invoke(grassNode);
}
else
{
ProjectTreeView.SelectedNode = grassNode;
}
}
}
public void TrySelectMloEntityTreeNode(MCEntityDef ent)
{
TreeNode entnode = FindMloEntityTreeNode(ent);
if (entnode != null)
{
if (ProjectTreeView.SelectedNode == entnode)
{
OnItemSelected?.Invoke(ent);
}
else
{
ProjectTreeView.SelectedNode = entnode;
}
}
}
public void TrySelectMloRoomTreeNode(MCMloRoomDef room)
{
TreeNode roomnode = FindMloRoomTreeNode(room);
if (roomnode != null)
{
if (ProjectTreeView.SelectedNode == roomnode)
{
OnItemSelected?.Invoke(room);
}
else
{
ProjectTreeView.SelectedNode = roomnode;
}
}
}
public void TrySelectArchetypeTreeNode(Archetype archetype)
{
TreeNode archetypenode = FindArchetypeTreeNode(archetype);
if (archetypenode != null)
{
if (ProjectTreeView.SelectedNode == archetypenode)
{
OnItemSelected?.Invoke(archetype);
}
else
{
ProjectTreeView.SelectedNode = archetypenode;
}
}
}
public void TrySelectPathNodeTreeNode(YndNode node) public void TrySelectPathNodeTreeNode(YndNode node)
{ {
TreeNode tnode = FindPathNodeTreeNode(node); TreeNode tnode = FindPathNodeTreeNode(node);
@ -1151,6 +1379,16 @@ namespace CodeWalker.Project.Panels
} }
} }
public void UpdateArchetypeTreeNode(Archetype archetype)
{
var tn = FindArchetypeTreeNode(archetype);
if (tn != null)
{
tn.Text = archetype._BaseArchetypeDef.ToString();
}
}
public void UpdateCarGenTreeNode(YmapCarGen cargen) public void UpdateCarGenTreeNode(YmapCarGen cargen)
{ {
var tn = FindCarGenTreeNode(cargen); var tn = FindCarGenTreeNode(cargen);
@ -1222,6 +1460,7 @@ namespace CodeWalker.Project.Panels
} }
public void RemoveEntityTreeNode(YmapEntityDef ent) public void RemoveEntityTreeNode(YmapEntityDef ent)
{ {
var tn = FindEntityTreeNode(ent); var tn = FindEntityTreeNode(ent);
@ -1231,6 +1470,7 @@ namespace CodeWalker.Project.Panels
tn.Parent.Nodes.Remove(tn); tn.Parent.Nodes.Remove(tn);
} }
} }
public void RemoveCarGenTreeNode(YmapCarGen cargen) public void RemoveCarGenTreeNode(YmapCarGen cargen)
{ {
var tn = FindCarGenTreeNode(cargen); var tn = FindCarGenTreeNode(cargen);
@ -1240,6 +1480,38 @@ namespace CodeWalker.Project.Panels
tn.Parent.Nodes.Remove(tn); tn.Parent.Nodes.Remove(tn);
} }
} }
public void RemoveGrassBatchTreeNode(YmapGrassInstanceBatch batch)
{
var tn = FindGrassTreeNode(batch);
if ((tn != null) && (tn.Parent != null))
{
tn.Parent.Text = "Grass Batches (" + batch.Ymap.GrassInstanceBatches.Length.ToString() + ")";
tn.Parent.Nodes.Remove(tn);
}
}
public void RemoveArchetypeTreeNode(Archetype archetype)
{
var tn = FindArchetypeTreeNode(archetype);
if ((tn != null) && (tn.Parent != null))
{
tn.Parent.Text = "Archetypes (" + archetype.Ytyp.AllArchetypes.Length.ToString() + ")";
tn.Parent.Nodes.Remove(tn);
}
}
public void RemoveMloEntityTreeNode(MCEntityDef ent)
{
var tn = FindMloEntityTreeNode(ent);
if ((tn != null) && (tn.Parent != null))
{
var tnp = tn.Parent.Parent;
MCMloRoomDef room = null;
if (tnp != null) room = tnp.Tag as MCMloRoomDef;
tn.Parent.Text = "Attached Objects (" + (room?.AttachedObjects.Length - 1 ?? 0) + ")";
tn.Parent.Nodes.Remove(tn);
}
}
public void RemovePathNodeTreeNode(YndNode node) public void RemovePathNodeTreeNode(YndNode node)
{ {
var tn = FindPathNodeTreeNode(node); var tn = FindPathNodeTreeNode(node);

View File

@ -59,6 +59,7 @@ namespace CodeWalker.Project
Xml.AddChildWithInnerText(doc, ytypselem, "Item", ytypfilename); Xml.AddChildWithInnerText(doc, ytypselem, "Item", ytypfilename);
} }
var yndselem = Xml.AddChild(doc, projelem, "YndFilenames"); var yndselem = Xml.AddChild(doc, projelem, "YndFilenames");
foreach (string yndfilename in YndFilenames) foreach (string yndfilename in YndFilenames)
{ {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1406,7 +1406,7 @@ namespace CodeWalker.Rendering
if (poly == null) continue; if (poly == null) continue;
byte matind = ((bgeom.PolygonMaterialIndices != null) && (i < bgeom.PolygonMaterialIndices.Length)) ? bgeom.PolygonMaterialIndices[i] : (byte)0; byte matind = ((bgeom.PolygonMaterialIndices != null) && (i < bgeom.PolygonMaterialIndices.Length)) ? bgeom.PolygonMaterialIndices[i] : (byte)0;
BoundMaterial_s mat = ((bgeom.Materials != null) && (matind < bgeom.Materials.Length)) ? bgeom.Materials[matind] : new BoundMaterial_s(); BoundMaterial_s mat = ((bgeom.Materials != null) && (matind < bgeom.Materials.Length)) ? bgeom.Materials[matind] : new BoundMaterial_s();
Color4 color = BoundsMaterialTypes.GetMaterialColour(mat.Type); Color color = BoundsMaterialTypes.GetMaterialColour(mat.Type);
Vector3 p1, p2, p3, p4, a1, n1;//, n2, n3, p5, p7, p8; Vector3 p1, p2, p3, p4, a1, n1;//, n2, n3, p5, p7, p8;
Vector3 norm = Vector3.Zero; Vector3 norm = Vector3.Zero;
uint colour = (uint)color.ToRgba(); uint colour = (uint)color.ToRgba();

View File

@ -195,6 +195,14 @@ namespace CodeWalker.Rendering
} }
} }
public void Invalidate(YmapGrassInstanceBatch batch)
{
lock (updateSyncRoot)
{
instbatches.Invalidate(batch);
}
}
} }

View File

@ -98,7 +98,7 @@ namespace CodeWalker.Rendering
public bool renderinteriors = true; public bool renderinteriors = true;
public bool renderproxies = false; public bool renderproxies = false;
public bool renderchildents = false;//when rendering single ymap, render root only or not... public bool renderchildents = false;//when rendering single ymap, render root only or not...
public bool renderentities = true;
public bool rendergrass = true; public bool rendergrass = true;
public bool renderdistlodlights = true; public bool renderdistlodlights = true;
@ -380,6 +380,11 @@ namespace CodeWalker.Rendering
renderableCache.Invalidate(path); renderableCache.Invalidate(path);
} }
public void Invalidate(YmapGrassInstanceBatch batch)
{
renderableCache.Invalidate(batch);
}
public void UpdateSelectionDrawFlags(DrawableModel model, DrawableGeometry geom, bool rem) public void UpdateSelectionDrawFlags(DrawableModel model, DrawableGeometry geom, bool rem)
{ {
@ -679,6 +684,33 @@ namespace CodeWalker.Rendering
} }
public void RenderBrushRadiusOutline(Vector3 position, Vector3 dir, Vector3 up, float radius, uint col)
{
const int Reso = 36;
const float MaxDeg = 360f;
const float DegToRad = 0.0174533f;
const float Ang = MaxDeg / Reso;
var axis = Vector3.Cross(dir, up);
var c = new VertexTypePC[Reso];
for (var i = 0; i < Reso; i++)
{
var rDir = Quaternion.RotationAxis(dir, (i * Ang) * DegToRad).Multiply(axis);
c[i].Position = position + (rDir * radius);
c[i].Colour = col;
}
for (var i = 0; i < c.Length; i++)
{
SelectionLineVerts.Add(c[i]);
SelectionLineVerts.Add(c[(i + 1) % c.Length]);
}
SelectionLineVerts.Add(new VertexTypePC{Colour = col, Position = position});
SelectionLineVerts.Add(new VertexTypePC { Colour = col, Position = position + dir * 2f});
}
public void RenderSelectionArrowOutline(Vector3 pos, Vector3 dir, Vector3 up, Quaternion ori, float len, float rad, uint colour) public void RenderSelectionArrowOutline(Vector3 pos, Vector3 dir, Vector3 up, Quaternion ori, float len, float rad, uint colour)
{ {
Vector3 ax = Vector3.Cross(dir, up); Vector3 ax = Vector3.Cross(dir, up);
@ -757,7 +789,7 @@ namespace CodeWalker.Rendering
public void RenderSelectionNavPoly(YnvPoly poly) public void RenderSelectionNavPoly(YnvPoly poly)
{ {
////draw poly triangles ////draw poly triangles
var pcolour = new Color4(0.6f, 0.95f, 0.6f, 1.0f); var pcolour = new Color4(1.0f, 1.0f, 1.0f, 0.2f);
var colourval = (uint)pcolour.ToRgba(); var colourval = (uint)pcolour.ToRgba();
var ynv = poly.Ynv; var ynv = poly.Ynv;
var ic = poly._RawData.IndexCount; var ic = poly._RawData.IndexCount;
@ -792,6 +824,71 @@ namespace CodeWalker.Rendering
} }
} }
public void RenderSelectionNavPolyOutline(YnvPoly poly, uint colourval)
{
//var colourval = (uint)colour.ToRgba();
var ynv = poly.Ynv;
var ic = poly._RawData.IndexCount;
var startid = poly._RawData.IndexID;
var endid = startid + ic;
var lastid = endid - 1;
var vc = ynv.Vertices.Count;
var startind = ynv.Indices[startid];
////draw poly outline
VertexTypePC v = new VertexTypePC();
v.Colour = colourval;
VertexTypePC v0 = new VertexTypePC();
for (int id = startid; id < endid; id++)
{
var ind = ynv.Indices[id];
if (ind >= vc)
{ continue; }
v.Position = ynv.Vertices[ind];
SelectionLineVerts.Add(v);
if (id == startid)
{
v0 = v;
}
else
{
SelectionLineVerts.Add(v);
}
if (id == lastid)
{
SelectionLineVerts.Add(v0);
}
}
////draw poly triangles
//VertexTypePC v0 = new VertexTypePC();
//VertexTypePC v1 = new VertexTypePC();
//VertexTypePC v2 = new VertexTypePC();
//v0.Position = ynv.Vertices[startind];
//v0.Colour = colourval;
//v1.Colour = colourval;
//v2.Colour = colourval;
//int tricount = ic - 2;
//for (int t = 0; t < tricount; t++)
//{
// int tid = startid + t;
// int ind1 = ynv.Indices[tid + 1];
// int ind2 = ynv.Indices[tid + 2];
// if ((ind1 >= vc) || (ind2 >= vc))
// { continue; }
// v1.Position = ynv.Vertices[ind1];
// v2.Position = ynv.Vertices[ind2];
// Renderer.SelectionTriVerts.Add(v0);
// Renderer.SelectionTriVerts.Add(v1);
// Renderer.SelectionTriVerts.Add(v2);
// Renderer.SelectionTriVerts.Add(v0);
// Renderer.SelectionTriVerts.Add(v2);
// Renderer.SelectionTriVerts.Add(v1);
//}
}
public void RenderSelectionGeometry(MapSelectionMode mode) public void RenderSelectionGeometry(MapSelectionMode mode)
{ {
@ -1498,13 +1595,16 @@ namespace CodeWalker.Rendering
} }
} }
for (int i = 0; i < renderworldrenderables.Count; i++) if(renderentities)
{ {
var rent = renderworldrenderables[i]; for (int i = 0; i < renderworldrenderables.Count; i++)
var ent = rent.Entity; {
var arch = ent.Archetype; var rent = renderworldrenderables[i];
var ent = rent.Entity;
var arch = ent.Archetype;
RenderArchetype(arch, ent, rent.Renderable, false); RenderArchetype(arch, ent, rent.Renderable, false);
}
} }
@ -1645,24 +1745,55 @@ namespace CodeWalker.Rendering
if (renderinteriors && ent.IsMlo) //render Mlo child entities... if (renderinteriors && ent.IsMlo) //render Mlo child entities...
{ {
if ((ent.MloInstance != null) && (ent.MloInstance.Entities != null)) if ((ent.MloInstance != null))
{ {
for (int j = 0; j < ent.MloInstance.Entities.Length; j++) if (ent.MloInstance.Entities != null)
{ {
var intent = ent.MloInstance.Entities[j]; for (int j = 0; j < ent.MloInstance.Entities.Length; j++)
if (intent.Archetype == null) continue; //missing archetype...
if (!RenderIsEntityFinalRender(intent)) continue; //proxy or something..
intent.IsVisible = true;
var iebscent = intent.Position + intent.BSCenter - camera.Position;
float iebsrad = intent.BSRadius;
if (!camera.ViewFrustum.ContainsSphereNoClipNoOpt(ref iebscent, iebsrad))
{ {
continue; //frustum cull interior ents var intent = ent.MloInstance.Entities[j];
} if (intent.Archetype == null) continue; //missing archetype...
if (!RenderIsEntityFinalRender(intent)) continue; //proxy or something..
renderworldentities.Add(intent); intent.IsVisible = true;
var iebscent = intent.Position + intent.BSCenter - camera.Position;
float iebsrad = intent.BSRadius;
if (!camera.ViewFrustum.ContainsSphereNoClipNoOpt(ref iebscent, iebsrad))
{
continue; //frustum cull interior ents
}
renderworldentities.Add(intent);
}
}
if (ent.MloInstance.EntitySets != null)
{
foreach (var entitysets in ent.MloInstance.EntitySets)
{
var entityset = entitysets.Value;
if (!entityset.Visible) continue;
var entities = entityset.Entities;
for (int i = 0; i < entities.Count; i++)
{
var intent = entities[i];
if (intent.Archetype == null) continue; //missing archetype...
if (!RenderIsEntityFinalRender(intent)) continue; //proxy or something..
intent.IsVisible = true;
var iebscent = intent.Position + intent.BSCenter - camera.Position;
float iebsrad = intent.BSRadius;
if (!camera.ViewFrustum.ContainsSphereNoClipNoOpt(ref iebscent, iebsrad))
{
continue; //frustum cull interior ents
}
renderworldentities.Add(intent);
}
}
} }
} }
} }

View File

@ -695,6 +695,10 @@ namespace CodeWalker.Rendering
{ {
var gb = batch.Key; var gb = batch.Key;
// sanity check
if (batch.GrassInstanceBuffer == null)
return;
VSEntityVars.Vars.CamRel = new Vector4(gb.CamRel, 0.0f); VSEntityVars.Vars.CamRel = new Vector4(gb.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = Quaternion.Identity; VSEntityVars.Vars.Orientation = Quaternion.Identity;
VSEntityVars.Vars.Scale = Vector3.One; VSEntityVars.Vars.Scale = Vector3.One;

View File

@ -178,16 +178,31 @@ namespace CodeWalker.Rendering
SetInputLayout(context, VertexType.PC); SetInputLayout(context, VertexType.PC);
SetSceneVars(context, camera, null, lights); SetSceneVars(context, camera, null, lights);
vertices.Clear(); int drawn = 0;
foreach (var vert in verts) int tricount = verts.Count / 3;
int maxcount = vertices.StructCount / 3;
while (drawn < tricount)
{ {
vertices.Add(vert); vertices.Clear();
}
vertices.Update(context); int offset = drawn*3;
vertices.SetVSResource(context, 0); int bcount = Math.Min(tricount - drawn, maxcount);
for (int i = 0; i < bcount; i++)
{
int t = offset + (i * 3);
vertices.Add(verts[t + 0]);
vertices.Add(verts[t + 1]);
vertices.Add(verts[t + 2]);
}
drawn += bcount;
vertices.Update(context);
vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
context.Draw(vertices.CurrentCount, 0);
}
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;
context.Draw(vertices.CurrentCount, 0);
} }
public void RenderLines(DeviceContext context, List<VertexTypePC> verts, Camera camera, ShaderGlobalLights lights) public void RenderLines(DeviceContext context, List<VertexTypePC> verts, Camera camera, ShaderGlobalLights lights)
@ -197,16 +212,29 @@ namespace CodeWalker.Rendering
SetInputLayout(context, VertexType.PC); SetInputLayout(context, VertexType.PC);
SetSceneVars(context, camera, null, lights); SetSceneVars(context, camera, null, lights);
vertices.Clear(); int drawn = 0;
foreach (var vert in verts) int linecount = verts.Count / 2;
int maxcount = vertices.StructCount / 2;
while (drawn < linecount)
{ {
vertices.Add(vert); vertices.Clear();
}
vertices.Update(context);
vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; int offset = drawn * 2;
context.Draw(vertices.CurrentCount, 0); int bcount = Math.Min(linecount - drawn, maxcount);
for (int i = 0; i < bcount; i++)
{
int t = offset + (i * 2);
vertices.Add(verts[t + 0]);
vertices.Add(verts[t + 1]);
}
drawn += bcount;
vertices.Update(context);
vertices.SetVSResource(context, 0);
context.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
context.Draw(vertices.CurrentCount, 0);
}
} }

View File

@ -99,6 +99,12 @@ Audio stuff - do more work on .rel format (see https://github.com/CamxxCore/Rag
done: done:
[v.30]
Bug fixes for XML/Meta conversion
Collision meshes now using R* colours
Vehicle rendering improvements
[v.29] [v.29]
Nav mesh editing (YNV) - polys, points, portals Nav mesh editing (YNV) - polys, points, portals
New Project Window New Project Window

View File

@ -182,6 +182,7 @@ namespace CodeWalker
public YmapGrassInstanceBatch GrassBatch { get; set; } public YmapGrassInstanceBatch GrassBatch { get; set; }
public YmapDistantLODLights DistantLodLights { get; set; } public YmapDistantLODLights DistantLodLights { get; set; }
public YmapEntityDef MloEntityDef { get; set; } public YmapEntityDef MloEntityDef { get; set; }
public MCMloRoomDef MloRoomDef { get; set; }
public WaterQuad WaterQuad { get; set; } public WaterQuad WaterQuad { get; set; }
public Bounds CollisionBounds { get; set; } public Bounds CollisionBounds { get; set; }
public YnvPoly NavPoly { get; set; } public YnvPoly NavPoly { get; set; }
@ -227,7 +228,8 @@ namespace CodeWalker
(DistantLodLights != null) || (DistantLodLights != null) ||
(MloEntityDef != null) || (MloEntityDef != null) ||
(ScenarioNode != null) || (ScenarioNode != null) ||
(Audio != null); (Audio != null) ||
(MloRoomDef != null);
} }
} }
@ -257,7 +259,8 @@ namespace CodeWalker
|| (PathNode != mhit.PathNode) || (PathNode != mhit.PathNode)
|| (TrainTrackNode != mhit.TrainTrackNode) || (TrainTrackNode != mhit.TrainTrackNode)
|| (ScenarioNode != mhit.ScenarioNode) || (ScenarioNode != mhit.ScenarioNode)
|| (Audio != mhit.Audio); || (Audio != mhit.Audio)
|| (MloRoomDef != mhit.MloRoomDef);
} }
public bool CheckForChanges() public bool CheckForChanges()
{ {
@ -280,7 +283,8 @@ namespace CodeWalker
|| (PathLink != null) || (PathLink != null)
|| (TrainTrackNode != null) || (TrainTrackNode != null)
|| (ScenarioNode != null) || (ScenarioNode != null)
|| (Audio != null); || (Audio != null)
|| (MloRoomDef != null);
} }
@ -386,6 +390,10 @@ namespace CodeWalker
{ {
name = Audio.ShortTypeName + " " + Audio.GetNameString();// FloatUtil.GetVector3String(Audio.InnerPos); name = Audio.ShortTypeName + " " + Audio.GetNameString();// FloatUtil.GetVector3String(Audio.InnerPos);
} }
if (MloRoomDef != null)
{
name = "MloRoomDef " + MloRoomDef.RoomName;
}
return name; return name;
} }
@ -460,6 +468,10 @@ namespace CodeWalker
{ {
name = Audio.ShortTypeName + " " + Audio.GetNameString();// + FloatUtil.GetVector3String(Audio.InnerPos); name = Audio.ShortTypeName + " " + Audio.GetNameString();// + FloatUtil.GetVector3String(Audio.InnerPos);
} }
if (MloRoomDef != null)
{
name = "MloRoomDef " + MloRoomDef.RoomName;
}
return name; return name;
} }

26
WorldForm.Designer.cs generated
View File

@ -109,6 +109,7 @@ namespace CodeWalker
this.tabPage4 = new System.Windows.Forms.TabPage(); this.tabPage4 = new System.Windows.Forms.TabPage();
this.OptionsTabControl = new System.Windows.Forms.TabControl(); this.OptionsTabControl = new System.Windows.Forms.TabControl();
this.tabPage8 = new System.Windows.Forms.TabPage(); this.tabPage8 = new System.Windows.Forms.TabPage();
this.RenderEntitiesCheckBox = new System.Windows.Forms.CheckBox();
this.AdvancedSettingsButton = new System.Windows.Forms.Button(); this.AdvancedSettingsButton = new System.Windows.Forms.Button();
this.ControlSettingsButton = new System.Windows.Forms.Button(); this.ControlSettingsButton = new System.Windows.Forms.Button();
this.MapViewDetailLabel = new System.Windows.Forms.Label(); this.MapViewDetailLabel = new System.Windows.Forms.Label();
@ -1295,6 +1296,7 @@ namespace CodeWalker
// //
// tabPage8 // tabPage8
// //
this.tabPage8.Controls.Add(this.RenderEntitiesCheckBox);
this.tabPage8.Controls.Add(this.AdvancedSettingsButton); this.tabPage8.Controls.Add(this.AdvancedSettingsButton);
this.tabPage8.Controls.Add(this.ControlSettingsButton); this.tabPage8.Controls.Add(this.ControlSettingsButton);
this.tabPage8.Controls.Add(this.MapViewDetailLabel); this.tabPage8.Controls.Add(this.MapViewDetailLabel);
@ -1327,6 +1329,19 @@ namespace CodeWalker
this.tabPage8.Text = "General"; this.tabPage8.Text = "General";
this.tabPage8.UseVisualStyleBackColor = true; this.tabPage8.UseVisualStyleBackColor = true;
// //
// EntitiesCheckBox
//
this.RenderEntitiesCheckBox.AutoSize = true;
this.RenderEntitiesCheckBox.Checked = true;
this.RenderEntitiesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.RenderEntitiesCheckBox.Location = new System.Drawing.Point(10, 32);
this.RenderEntitiesCheckBox.Name = "EntitiesCheckBox";
this.RenderEntitiesCheckBox.Size = new System.Drawing.Size(89, 17);
this.RenderEntitiesCheckBox.TabIndex = 67;
this.RenderEntitiesCheckBox.Text = "Show entities";
this.RenderEntitiesCheckBox.UseVisualStyleBackColor = true;
this.RenderEntitiesCheckBox.CheckedChanged += new System.EventHandler(this.RenderEntitiesCheckBox_CheckedChanged);
//
// AdvancedSettingsButton // AdvancedSettingsButton
// //
this.AdvancedSettingsButton.Location = new System.Drawing.Point(101, 456); this.AdvancedSettingsButton.Location = new System.Drawing.Point(101, 456);
@ -1411,7 +1426,7 @@ namespace CodeWalker
this.WaterQuadsCheckBox.AutoSize = true; this.WaterQuadsCheckBox.AutoSize = true;
this.WaterQuadsCheckBox.Checked = true; this.WaterQuadsCheckBox.Checked = true;
this.WaterQuadsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; this.WaterQuadsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.WaterQuadsCheckBox.Location = new System.Drawing.Point(10, 104); this.WaterQuadsCheckBox.Location = new System.Drawing.Point(10, 129);
this.WaterQuadsCheckBox.Name = "WaterQuadsCheckBox"; this.WaterQuadsCheckBox.Name = "WaterQuadsCheckBox";
this.WaterQuadsCheckBox.Size = new System.Drawing.Size(114, 17); this.WaterQuadsCheckBox.Size = new System.Drawing.Size(114, 17);
this.WaterQuadsCheckBox.TabIndex = 39; this.WaterQuadsCheckBox.TabIndex = 39;
@ -1440,7 +1455,7 @@ namespace CodeWalker
// TimedEntitiesAlwaysOnCheckBox // TimedEntitiesAlwaysOnCheckBox
// //
this.TimedEntitiesAlwaysOnCheckBox.AutoSize = true; this.TimedEntitiesAlwaysOnCheckBox.AutoSize = true;
this.TimedEntitiesAlwaysOnCheckBox.Location = new System.Drawing.Point(131, 58); this.TimedEntitiesAlwaysOnCheckBox.Location = new System.Drawing.Point(131, 83);
this.TimedEntitiesAlwaysOnCheckBox.Name = "TimedEntitiesAlwaysOnCheckBox"; this.TimedEntitiesAlwaysOnCheckBox.Name = "TimedEntitiesAlwaysOnCheckBox";
this.TimedEntitiesAlwaysOnCheckBox.Size = new System.Drawing.Size(58, 17); this.TimedEntitiesAlwaysOnCheckBox.Size = new System.Drawing.Size(58, 17);
this.TimedEntitiesAlwaysOnCheckBox.TabIndex = 37; this.TimedEntitiesAlwaysOnCheckBox.TabIndex = 37;
@ -1453,7 +1468,7 @@ namespace CodeWalker
this.GrassCheckBox.AutoSize = true; this.GrassCheckBox.AutoSize = true;
this.GrassCheckBox.Checked = true; this.GrassCheckBox.Checked = true;
this.GrassCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; this.GrassCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.GrassCheckBox.Location = new System.Drawing.Point(10, 35); this.GrassCheckBox.Location = new System.Drawing.Point(10, 57);
this.GrassCheckBox.Name = "GrassCheckBox"; this.GrassCheckBox.Name = "GrassCheckBox";
this.GrassCheckBox.Size = new System.Drawing.Size(81, 17); this.GrassCheckBox.Size = new System.Drawing.Size(81, 17);
this.GrassCheckBox.TabIndex = 35; this.GrassCheckBox.TabIndex = 35;
@ -1466,7 +1481,7 @@ namespace CodeWalker
this.InteriorsCheckBox.AutoSize = true; this.InteriorsCheckBox.AutoSize = true;
this.InteriorsCheckBox.Checked = true; this.InteriorsCheckBox.Checked = true;
this.InteriorsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; this.InteriorsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.InteriorsCheckBox.Location = new System.Drawing.Point(10, 81); this.InteriorsCheckBox.Location = new System.Drawing.Point(10, 106);
this.InteriorsCheckBox.Name = "InteriorsCheckBox"; this.InteriorsCheckBox.Name = "InteriorsCheckBox";
this.InteriorsCheckBox.Size = new System.Drawing.Size(92, 17); this.InteriorsCheckBox.Size = new System.Drawing.Size(92, 17);
this.InteriorsCheckBox.TabIndex = 38; this.InteriorsCheckBox.TabIndex = 38;
@ -1586,7 +1601,7 @@ namespace CodeWalker
this.TimedEntitiesCheckBox.AutoSize = true; this.TimedEntitiesCheckBox.AutoSize = true;
this.TimedEntitiesCheckBox.Checked = true; this.TimedEntitiesCheckBox.Checked = true;
this.TimedEntitiesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; this.TimedEntitiesCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
this.TimedEntitiesCheckBox.Location = new System.Drawing.Point(10, 58); this.TimedEntitiesCheckBox.Location = new System.Drawing.Point(10, 83);
this.TimedEntitiesCheckBox.Name = "TimedEntitiesCheckBox"; this.TimedEntitiesCheckBox.Name = "TimedEntitiesCheckBox";
this.TimedEntitiesCheckBox.Size = new System.Drawing.Size(117, 17); this.TimedEntitiesCheckBox.Size = new System.Drawing.Size(117, 17);
this.TimedEntitiesCheckBox.TabIndex = 36; this.TimedEntitiesCheckBox.TabIndex = 36;
@ -3581,5 +3596,6 @@ namespace CodeWalker
private System.Windows.Forms.ToolStripMenuItem ToolbarSnapToGroundGridButton; private System.Windows.Forms.ToolStripMenuItem ToolbarSnapToGroundGridButton;
private System.Windows.Forms.NumericUpDown SnapGridSizeUpDown; private System.Windows.Forms.NumericUpDown SnapGridSizeUpDown;
private System.Windows.Forms.Label label26; private System.Windows.Forms.Label label26;
private System.Windows.Forms.CheckBox RenderEntitiesCheckBox;
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@ -42,6 +41,7 @@ namespace CodeWalker
PopZones popzones = new PopZones(); PopZones popzones = new PopZones();
AudioZones audiozones = new AudioZones(); AudioZones audiozones = new AudioZones();
public Space Space { get { return space; } }
bool MouseLButtonDown = false; bool MouseLButtonDown = false;
bool MouseRButtonDown = false; bool MouseRButtonDown = false;
@ -75,6 +75,11 @@ namespace CodeWalker
bool ControlFireToggle = false; bool ControlFireToggle = false;
int ControlBrushTimer = 0;
bool ControlBrushEnabled;
//float ControlBrushRadius;
Entity camEntity = new Entity(); Entity camEntity = new Entity();
PedEntity pedEntity = new PedEntity(); PedEntity pedEntity = new PedEntity();
@ -486,7 +491,7 @@ namespace CodeWalker
} }
if (ControlMode == WorldControlMode.Free) if (ControlMode == WorldControlMode.Free || ControlBrushEnabled)
{ {
if (Input.ShiftPressed) if (Input.ShiftPressed)
{ {
@ -1252,7 +1257,7 @@ namespace CodeWalker
if (MouseRayCollision.Hit) if (MouseRayCollision.Hit)
{ {
var arup = GetPerpVec(MouseRayCollision.Normal); var arup = GetPerpVec(MouseRayCollision.Normal);
Renderer.RenderSelectionArrowOutline(MouseRayCollision.Position, MouseRayCollision.Normal, arup, Quaternion.Identity, 2.0f, 0.15f, cgrn); Renderer.RenderBrushRadiusOutline(MouseRayCollision.Position, MouseRayCollision.Normal, arup, ProjectForm.GetInstanceBrushRadius(), cgrn);
} }
} }
@ -1435,7 +1440,8 @@ namespace CodeWalker
if (selectionItem.NavPoly != null) if (selectionItem.NavPoly != null)
{ {
Renderer.RenderSelectionNavPoly(selectionItem.NavPoly); Renderer.RenderSelectionNavPoly(selectionItem.NavPoly);
//return;//don't render a selection box for nav mesh? Renderer.RenderSelectionNavPolyOutline(selectionItem.NavPoly, cgrn);
return;//don't render a selection box for nav poly
} }
if (selectionItem.NavPoint != null) if (selectionItem.NavPoint != null)
{ {
@ -1823,6 +1829,14 @@ namespace CodeWalker
} }
} }
public void UpdateGrassBatchGraphics(YmapGrassInstanceBatch grassBatch)
{
lock (Renderer.RenderSyncRoot)
{
Renderer.Invalidate(grassBatch);
}
}
public Vector3 GetCameraPosition() public Vector3 GetCameraPosition()
{ {
@ -2048,8 +2062,8 @@ namespace CodeWalker
if (mode == ControlMode) return; if (mode == ControlMode) return;
bool wasfree = (ControlMode == WorldControlMode.Free); bool wasfree = (ControlMode == WorldControlMode.Free || ControlBrushEnabled);
bool isfree = (mode == WorldControlMode.Free); bool isfree = (mode == WorldControlMode.Free || ControlBrushEnabled);
if (isfree && !wasfree) if (isfree && !wasfree)
{ {
@ -2103,17 +2117,17 @@ namespace CodeWalker
//reset variables for beginning the mouse hit test //reset variables for beginning the mouse hit test
CurMouseHit.Clear(); CurMouseHit.Clear();
// Get whether or not we can brush from the project form.
MouseRayCollisionEnabled = Input.CtrlPressed; //temporary...! if (Input.CtrlPressed && ProjectForm != null && ProjectForm.CanPaintInstances())
if (MouseRayCollisionEnabled)
{ {
if (space.Inited && space.Grid != null) ControlBrushEnabled = true;
{ MouseRayCollisionEnabled = true;
Ray mray = new Ray(); MouseRayCollision = GetSpaceMouseRay();
mray.Position = camera.MouseRay.Position + camera.Position; }
mray.Direction = camera.MouseRay.Direction; else if (MouseRayCollisionEnabled)
MouseRayCollision = space.RayIntersect(mray); {
} ControlBrushEnabled = false;
MouseRayCollisionEnabled = false;
} }
@ -2126,6 +2140,25 @@ namespace CodeWalker
} }
public SpaceRayIntersectResult GetSpaceMouseRay()
{
SpaceRayIntersectResult ret = new SpaceRayIntersectResult();
if (space.Inited && space.Grid != null)
{
Ray mray = new Ray();
mray.Position = camera.MouseRay.Position + camera.Position;
mray.Direction = camera.MouseRay.Direction;
return space.RayIntersect(mray);
}
return ret;
}
public SpaceRayIntersectResult Raycast(Ray ray)
{
return space.RayIntersect(ray);
}
private void UpdateMouseHitsFromRenderer() private void UpdateMouseHitsFromRenderer()
{ {
foreach (var rd in Renderer.RenderedDrawables) foreach (var rd in Renderer.RenderedDrawables)
@ -2717,70 +2750,7 @@ namespace CodeWalker
if ((CurMouseHit.NavPoly != null) && MouseSelectEnabled) if ((CurMouseHit.NavPoly != null) && MouseSelectEnabled)
{ {
var colour = Color4.White; Renderer.RenderSelectionNavPolyOutline(CurMouseHit.NavPoly, 0xFFFFFFFF);
var colourval = (uint)colour.ToRgba();
var poly = CurMouseHit.NavPoly;
var ynv = poly.Ynv;
var ic = poly._RawData.IndexCount;
var startid = poly._RawData.IndexID;
var endid = startid + ic;
var lastid = endid - 1;
var vc = ynv.Vertices.Count;
var startind = ynv.Indices[startid];
////draw poly outline
VertexTypePC v = new VertexTypePC();
v.Colour = colourval;
VertexTypePC v0 = new VertexTypePC();
for (int id = startid; id < endid; id++)
{
var ind = ynv.Indices[id];
if (ind >= vc)
{ continue; }
v.Position = ynv.Vertices[ind];
Renderer.SelectionLineVerts.Add(v);
if (id == startid)
{
v0 = v;
}
else
{
Renderer.SelectionLineVerts.Add(v);
}
if (id == lastid)
{
Renderer.SelectionLineVerts.Add(v0);
}
}
////draw poly triangles
//VertexTypePC v0 = new VertexTypePC();
//VertexTypePC v1 = new VertexTypePC();
//VertexTypePC v2 = new VertexTypePC();
//v0.Position = ynv.Vertices[startind];
//v0.Colour = colourval;
//v1.Colour = colourval;
//v2.Colour = colourval;
//int tricount = ic - 2;
//for (int t = 0; t < tricount; t++)
//{
// int tid = startid + t;
// int ind1 = ynv.Indices[tid + 1];
// int ind2 = ynv.Indices[tid + 2];
// if ((ind1 >= vc) || (ind2 >= vc))
// { continue; }
// v1.Position = ynv.Vertices[ind1];
// v2.Position = ynv.Vertices[ind2];
// Renderer.SelectionTriVerts.Add(v0);
// Renderer.SelectionTriVerts.Add(v1);
// Renderer.SelectionTriVerts.Add(v2);
// Renderer.SelectionTriVerts.Add(v0);
// Renderer.SelectionTriVerts.Add(v2);
// Renderer.SelectionTriVerts.Add(v1);
//}
} }
} }
@ -3398,6 +3368,37 @@ namespace CodeWalker
SelectItem(ms); SelectItem(ms);
} }
} }
public void SelectGrassBatch(YmapGrassInstanceBatch batch)
{
if (batch == null)
{
SelectItem(null);
}
else
{
MapSelection ms = new MapSelection();
ms.GrassBatch = batch;
ms.AABB = new BoundingBox(batch.AABBMin, batch.AABBMax);
SelectItem(ms);
}
}
public void SelectMloRoom(MCMloRoomDef room, MloInstanceData instance)
{
if (room == null)
{
SelectItem(null);
}
else if (instance != null)
{
MapSelection ms = new MapSelection();
ms.MloRoomDef = room;
Vector3 min = instance.Owner.Position + instance.Owner.Orientation.Multiply(room.BBMin_CW);
Vector3 max = instance.Owner.Position + instance.Owner.Orientation.Multiply(room.BBMax_CW);
ms.AABB = new BoundingBox(min, max);
SelectItem(ms);
}
}
public void SelectNavPoly(YnvPoly poly) public void SelectNavPoly(YnvPoly poly)
{ {
if (poly == null) if (poly == null)
@ -3945,6 +3946,7 @@ namespace CodeWalker
{ {
ProjectForm = new ProjectForm(this); ProjectForm = new ProjectForm(this);
ProjectForm.Show(this); ProjectForm.Show(this);
ProjectForm.OnWorldSelectionChanged(SelectedItem); // so that the project form isn't stuck on the welcome window.
} }
else else
{ {
@ -4380,6 +4382,12 @@ namespace CodeWalker
{ {
camera.FollowEntity.Position = p; camera.FollowEntity.Position = p;
} }
public void GoToPosition(Vector3 p, Vector3 bound)
{
camera.FollowEntity.Position = p;
var bl = bound.Length();
camera.TargetDistance = bl > 1f ? bl : 1f;
}
private MapMarker AddMarker(Vector3 pos, string name, bool addtotxtbox = false) private MapMarker AddMarker(Vector3 pos, string name, bool addtotxtbox = false)
{ {
@ -5087,11 +5095,25 @@ namespace CodeWalker
} }
else else
{ {
//project not open, or entity not selected there, just remove the entity from the ymap... //project not open, or entity not selected there, just remove the entity from the ymap/nlo...
var ymap = ent.Ymap; var ymap = ent.Ymap;
var instance = ent.MloParent?.MloInstance;
if (ymap == null) if (ymap == null)
{ {
MessageBox.Show("Sorry, deleting interior entities is not currently supported."); if (instance != null)
{
try
{
if (!instance.DeleteEntity(ent))
{
SelectItem(null);
}
}
catch (Exception e) // various failures can happen here.
{
MessageBox.Show("Unable to remove entity..." + Environment.NewLine + e.Message);
}
}
} }
else if (!ymap.RemoveEntity(ent)) else if (!ymap.RemoveEntity(ent))
{ {
@ -5112,7 +5134,16 @@ namespace CodeWalker
{ {
if (CopiedEntity == null) return; if (CopiedEntity == null) return;
if (ProjectForm == null) return; if (ProjectForm == null) return;
ProjectForm.NewEntity(CopiedEntity); MloInstanceData instance = CopiedEntity.MloParent?.MloInstance;
MCEntityDef entdef = instance?.TryGetArchetypeEntity(CopiedEntity);
if (entdef != null)
{
ProjectForm.NewMloEntity(CopiedEntity, true);
}
else
{
ProjectForm.NewEntity(CopiedEntity, true);
}
} }
private void CloneEntity() private void CloneEntity()
{ {
@ -5960,7 +5991,7 @@ namespace CodeWalker
MouseDownPoint = e.Location; MouseDownPoint = e.Location;
MouseLastPoint = MouseDownPoint; MouseLastPoint = MouseDownPoint;
if (ControlMode == WorldControlMode.Free) if (ControlMode == WorldControlMode.Free && !ControlBrushEnabled)
{ {
if (MouseLButtonDown) if (MouseLButtonDown)
{ {
@ -6059,6 +6090,7 @@ namespace CodeWalker
SelectedMarker = null; SelectedMarker = null;
HideMarkerSelectionInfo(); HideMarkerSelectionInfo();
} }
ControlBrushTimer = 0;
} }
} }
@ -6073,47 +6105,11 @@ namespace CodeWalker
dy = -dy; dy = -dy;
} }
if (ControlMode == WorldControlMode.Free) if (ControlMode == WorldControlMode.Free && !ControlBrushEnabled)
{ {
if (MouseLButtonDown) if (MouseLButtonDown)
{ {
if (GrabbedMarker == null) RotateCam(dx, dy);
{
if (GrabbedWidget == null)
{
if (MapViewEnabled == false)
{
camera.MouseRotate(dx, dy);
}
else
{
//need to move the camera entity XY with mouse in mapview mode...
MapViewDragX += dx;
MapViewDragY += dy;
}
}
else
{
//grabbed widget will move itself in Update() when IsDragging==true
}
}
else
{
//move the grabbed marker...
//float uptx = (CurrentMap != null) ? CurrentMap.UnitsPerTexelX : 1.0f;
//float upty = (CurrentMap != null) ? CurrentMap.UnitsPerTexelY : 1.0f;
//Vector3 wpos = GrabbedMarker.WorldPos;
//wpos.X += dx * uptx;
//wpos.Y += dy * upty;
//GrabbedMarker.WorldPos = wpos;
//UpdateMarkerTexturePos(GrabbedMarker);
//if (GrabbedMarker == LocatorMarker)
//{
// LocateTextBox.Text = LocatorMarker.ToString();
// WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
// TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
//}
}
} }
if (MouseRButtonDown) if (MouseRButtonDown)
{ {
@ -6137,11 +6133,31 @@ namespace CodeWalker
} }
} }
MouseX = e.X; UpdateMousePosition(e);
MouseY = e.Y;
MouseLastPoint = e.Location;
} }
else if (ControlBrushEnabled)
{
if (MouseRButtonDown)
{
RotateCam(dx, dy);
}
UpdateMousePosition(e);
ControlBrushTimer++;
if (ControlBrushTimer > (Input.ShiftPressed ? 5 : 10))
{
lock (Renderer.RenderSyncRoot)
{
if (ProjectForm != null && MouseLButtonDown)
{
ProjectForm.PaintGrass(MouseRayCollision, Input.ShiftPressed);
}
ControlBrushTimer = 0;
}
}
}
else else
{ {
lock (MouseControlSyncRoot) lock (MouseControlSyncRoot)
@ -6182,11 +6198,59 @@ namespace CodeWalker
} }
} }
private void UpdateMousePosition(MouseEventArgs e)
{
MouseX = e.X;
MouseY = e.Y;
MouseLastPoint = e.Location;
}
private void RotateCam(int dx, int dy)
{
if (GrabbedMarker == null)
{
if (GrabbedWidget == null)
{
if (MapViewEnabled == false)
{
camera.MouseRotate(dx, dy);
}
else
{
//need to move the camera entity XY with mouse in mapview mode...
MapViewDragX += dx;
MapViewDragY += dy;
}
}
else
{
//grabbed widget will move itself in Update() when IsDragging==true
}
}
else
{
//move the grabbed marker...
//float uptx = (CurrentMap != null) ? CurrentMap.UnitsPerTexelX : 1.0f;
//float upty = (CurrentMap != null) ? CurrentMap.UnitsPerTexelY : 1.0f;
//Vector3 wpos = GrabbedMarker.WorldPos;
//wpos.X += dx * uptx;
//wpos.Y += dy * upty;
//GrabbedMarker.WorldPos = wpos;
//UpdateMarkerTexturePos(GrabbedMarker);
//if (GrabbedMarker == LocatorMarker)
//{
// LocateTextBox.Text = LocatorMarker.ToString();
// WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
// TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
//}
}
}
private void WorldForm_MouseWheel(object sender, MouseEventArgs e) private void WorldForm_MouseWheel(object sender, MouseEventArgs e)
{ {
if (e.Delta != 0) if (e.Delta != 0)
{ {
if (ControlMode == WorldControlMode.Free) if (ControlMode == WorldControlMode.Free || ControlBrushEnabled)
{ {
camera.MouseZoom(e.Delta); camera.MouseZoom(e.Delta);
} }
@ -6316,7 +6380,7 @@ namespace CodeWalker
} }
} }
if (ControlMode != WorldControlMode.Free) if (ControlMode != WorldControlMode.Free || ControlBrushEnabled)
{ {
e.Handled = true; e.Handled = true;
} }
@ -7615,8 +7679,12 @@ namespace CodeWalker
{ {
SnapGridSize = (float)SnapGridSizeUpDown.Value; SnapGridSize = (float)SnapGridSizeUpDown.Value;
} }
}
private void RenderEntitiesCheckBox_CheckedChanged(object sender, EventArgs e)
{
Renderer.renderentities = RenderEntitiesCheckBox.Checked;
}
}
public enum WorldControlMode public enum WorldControlMode
{ {