OccludeModel and BoxOccluder editing basics

This commit is contained in:
dexy 2021-04-30 02:15:23 +10:00
parent 7eec785459
commit a8e212135c
16 changed files with 3527 additions and 66 deletions

View File

@ -589,6 +589,28 @@ namespace CodeWalker.GameFiles
//how to rebuild these here? the LODlights array is on the child ymap...
//for now, they are being updated as they are edited in project window
}
public void BuildBoxOccluders()
{
if (BoxOccluders == null) return;
if (BoxOccluders.Length == 0) return;
var boxes = new BoxOccluder[BoxOccluders.Length];
for (int i = 0; i < BoxOccluders.Length; i++)
{
var box = BoxOccluders[i];
box.UpdateBoxStruct();
boxes[i] = box._Box;
}
CBoxOccluders = boxes;
}
public void BuildOccludeModels()
{
if (OccludeModels == null) return;
if (OccludeModels.Length == 0) return;
//nothing to do here, has to be done later due to embedded data
}
public byte[] Save()
{
@ -601,11 +623,11 @@ namespace CodeWalker.GameFiles
BuildInstances();
BuildLodLights();
BuildDistantLodLights();
BuildBoxOccluders();
BuildOccludeModels();
//TODO:
//BuildTimecycleModifiers(); //already being saved - update them..
//BuildBoxOccluders();
//BuildOccludeModels();
//BuildContainerLods();
@ -658,14 +680,12 @@ namespace CodeWalker.GameFiles
mapdata.carGenerators = mb.AddItemArrayPtr(MetaName.CCarGen, CCarGens);
//clear everything out for now - TODO: fix
//clear everything else out for now - TODO: fix
if (mapdata.containerLods.Count1 != 0) LogSaveWarning("containerLods were not saved. (TODO!)");
if (mapdata.occludeModels.Count1 != 0) LogSaveWarning("occludeModels were not saved. (TODO!)");
if (mapdata.boxOccluders.Count1 != 0) LogSaveWarning("boxOccluders were not saved. (TODO!)");
if (mapdata.instancedData.PropInstanceList.Count1 != 0) LogSaveWarning("instancedData.PropInstanceList was not saved. (TODO!)");
mapdata.containerLods = new Array_Structure();
mapdata.occludeModels = new Array_Structure();
mapdata.boxOccluders = new Array_Structure();
if ((GrassInstanceBatches != null) && (GrassInstanceBatches.Length > 0))
{
@ -720,6 +740,32 @@ namespace CodeWalker.GameFiles
mapdata.DistantLODLightsSOA = new CDistantLODLight();
}
if ((CBoxOccluders != null) && (CBoxOccluders.Length > 0))
{
mapdata.boxOccluders = mb.AddItemArrayPtr(MetaName.BoxOccluder, CBoxOccluders);
}
else
{
mapdata.boxOccluders = new Array_Structure();
}
if ((OccludeModels != null) && (OccludeModels.Length > 0))
{
COccludeModels = new OccludeModel[OccludeModels.Length];
for (int i = 0; i < OccludeModels.Length; i++)
{
var model = OccludeModels[i];
model.BuildVertices();
model.BuildData();
var cocc = model._OccludeModel;
cocc.verts = mb.AddDataBlockPtr(model.Data, (MetaName)MetaStructureEntryDataType.UnsignedByte);//17
COccludeModels[i] = cocc;
}
mapdata.occludeModels = mb.AddItemArrayPtr(MetaName.OccludeModel, COccludeModels);
}
else
{
mapdata.occludeModels = new Array_Structure();
}
var block = new CBlockDesc();
@ -751,9 +797,17 @@ namespace CodeWalker.GameFiles
mb.AddStructureInfo(MetaName.CDistantLODLight);
mb.AddStructureInfo(MetaName.CBlockDesc);
mb.AddStructureInfo(MetaName.CMapData);
if ((AllEntities != null) && (AllEntities.Length > 0))
{
mb.AddStructureInfo(MetaName.CEntityDef);
mb.AddStructureInfo(MetaName.CMloInstanceDef);
mb.AddEnumInfo(MetaName.rage__eLodType); //LODTYPES_
mb.AddEnumInfo(MetaName.rage__ePriorityLevel); //PRI_
}
if ((CTimeCycleModifiers != null) && (CTimeCycleModifiers.Length > 0))
{
mb.AddStructureInfo(MetaName.CTimeCycleModifier);
}
if ((CCarGens != null) && (CCarGens.Length > 0))
{
mb.AddStructureInfo(MetaName.CCarGen);
@ -766,9 +820,14 @@ namespace CodeWalker.GameFiles
{
mb.AddStructureInfo(MetaName.FloatXYZ);
}
mb.AddEnumInfo(MetaName.rage__eLodType); //LODTYPES_
mb.AddEnumInfo(MetaName.rage__ePriorityLevel); //PRI_
if ((CBoxOccluders != null) && (CBoxOccluders.Length > 0))
{
mb.AddStructureInfo(MetaName.BoxOccluder);
}
if ((COccludeModels != null) && (COccludeModels.Length > 0))
{
mb.AddStructureInfo(MetaName.OccludeModel);
}
Meta meta = mb.GetMeta();
@ -1090,6 +1149,131 @@ namespace CodeWalker.GameFiles
return true;
}
public void AddBoxOccluder(YmapBoxOccluder box)
{
if (box == null) return;
var boxes = new List<YmapBoxOccluder>();
if (BoxOccluders != null) boxes.AddRange(BoxOccluders);
box.Ymap = this;
box.Index = boxes.Count;
boxes.Add(box);
BoxOccluders = boxes.ToArray();
HasChanged = true;
}
public bool RemoveBoxOccluder(YmapBoxOccluder box)
{
if (box == null) return false;
var newboxes = new List<YmapBoxOccluder>();
if (BoxOccluders != null)
{
foreach (var oldbox in BoxOccluders)
{
if (oldbox != box)
{
oldbox.Index = newboxes.Count;
newboxes.Add(oldbox);
}
}
if (newboxes.Count == BoxOccluders.Length)
{
return false;//nothing removed... wasn't present?
}
}
BoxOccluders = newboxes.ToArray();
HasChanged = true;
return true;
}
public void AddOccludeModel(YmapOccludeModel model)
{
if (model == null) return;
var models = new List<YmapOccludeModel>();
if (OccludeModels != null) models.AddRange(OccludeModels);
model.Ymap = this;
models.Add(model);
OccludeModels = models.ToArray();
HasChanged = true;
}
public bool RemoveOccludeModel(YmapOccludeModel model)
{
if (model == null) return false;
var newmodels = new List<YmapOccludeModel>();
if (OccludeModels != null)
{
foreach (var oldmodel in OccludeModels)
{
if (oldmodel != model)
{
oldmodel.Index = newmodels.Count;
newmodels.Add(oldmodel);
}
}
if (newmodels.Count == OccludeModels.Length)
{
return false;//nothing removed... wasn't present?
}
}
OccludeModels = newmodels.ToArray();
HasChanged = true;
return true;
}
public void AddOccludeModelTriangle(YmapOccludeModelTriangle tri)
{
if (tri == null) return;
if (tri.Model == null) return;
var tris = tri.Model.Triangles.ToList();
tri.Index = tris.Count;
tris.Add(tri);
tri.Model.Triangles = tris.ToArray();
//tri.Model.BuildBVH();
//...
HasChanged = true;
}
public bool RemoveOccludeModelTriangle(YmapOccludeModelTriangle tri)
{
if (tri == null) return false;
if (tri.Model == null) return false;
var newtris = new List<YmapOccludeModelTriangle>();
if (tri.Model.Triangles != null)
{
foreach (var oldtri in tri.Model.Triangles)
{
if (oldtri != tri)
{
oldtri.Index = newtris.Count;
newtris.Add(oldtri);
}
}
}
tri.Model.Triangles = newtris.ToArray();
//tri.Model.BuildBVH();
//...
HasChanged = true;
return true;
}
public void AddGrassBatch(YmapGrassInstanceBatch newbatch)
{
List<YmapGrassInstanceBatch> batches = new List<YmapGrassInstanceBatch>();
@ -1197,6 +1381,10 @@ namespace CodeWalker.GameFiles
{
flags = SetBit(flags, 1); //2
}
if ((BoxOccluders != null) || (OccludeModels != null))
{
contentFlags = SetBit(contentFlags, 5); //32
}
bool change = false;
@ -1329,6 +1517,29 @@ namespace CodeWalker.GameFiles
smax = Vector3.Max(smax, (DistantLODLights.BBMax + 3000.0f));
}
if (BoxOccluders != null)
{
foreach (var box in BoxOccluders)
{
var siz = box.Size.Length() * 0.5f;//should really use box rotation instead....
emin = Vector3.Min(emin, box.Position - siz);
emax = Vector3.Max(emax, box.Position + siz);
smin = Vector3.Min(smin, box.Position - siz);//check this! for some vanilla ymaps it seems right, others not
smax = Vector3.Max(smax, box.Position + siz);//occluders don't seem to have a loddist
}
}
if (OccludeModels != null)
{
foreach (var model in OccludeModels)
{
emin = Vector3.Min(emin, (model.BVH?.Box.Minimum ?? model._OccludeModel.bmin));//this needs to be updated!
emax = Vector3.Max(emax, (model.BVH?.Box.Maximum ?? model._OccludeModel.bmax));
smin = Vector3.Min(smin, (model.BVH?.Box.Minimum ?? model._OccludeModel.bmin));//check this! for some vanilla ymaps it seems right, others not
smax = Vector3.Max(smax, (model.BVH?.Box.Maximum ?? model._OccludeModel.bmax));//occluders don't seem to have a loddist
}
}
bool change = false;
if (_CMapData.entitiesExtentsMin != emin)
{
@ -2854,6 +3065,21 @@ namespace CodeWalker.GameFiles
public byte[] Indices { get; set; }
public int Index { get; set; }
public YmapOccludeModelTriangle[] Triangles { get; set; }
public TriangleBVH BVH { get; set; }
public FlagsUint Flags
{
get
{
return _OccludeModel.flags;
}
set
{
_OccludeModel.flags = value;
}
}
public YmapOccludeModel(YmapFile ymap, OccludeModel model)
{
Ymap = ymap;
@ -2875,11 +3101,118 @@ namespace CodeWalker.GameFiles
}
public void BuildTriangles()
{
if ((Vertices == null) || (Indices == null))
{
Triangles = null;
return;
}
var tris = new List<YmapOccludeModelTriangle>();
for (int i = 0; i < Indices.Length; i += 3)
{
var tri = new YmapOccludeModelTriangle(this, Vertices[Indices[i]], Vertices[Indices[i+1]], Vertices[Indices[i+2]], tris.Count);
tris.Add(tri);
}
Triangles = tris.ToArray();
}
public void BuildBVH()
{
if (Triangles == null)
{
BVH = null;
return;
}
BVH = new TriangleBVH(Triangles);
}
public void BuildVertices()
{
//create vertices and indices arrays from Triangles
if (Triangles == null)
{
Vertices = null;
Indices = null;
return;
}
var vdict = new Dictionary<Vector3, byte>();
var verts = new List<Vector3>();
var inds = new List<byte>();
byte ensureVert(Vector3 v)
{
if (vdict.TryGetValue(v, out byte b))
{
return b;
}
if (verts.Count > 255)
{
return 0;
}
var i = (byte)verts.Count;
vdict[v] = i;
verts.Add(v);
return i;
}
for (int i = 0; i < Triangles.Length; i++)
{
var tri = Triangles[i];
inds.Add(ensureVert(tri.Corner1));
inds.Add(ensureVert(tri.Corner2));
inds.Add(ensureVert(tri.Corner3));
}
Vertices = verts.ToArray();
Indices = inds.ToArray();
}
public void BuildData()
{
//create Data from vertices and indices arrays
if (Vertices == null) return;
if (Indices == null) return;
var dlen = (Vertices.Length * 12) + (Indices.Length * 1);
var d = new byte[dlen];
var vbytes = MetaTypes.ConvertArrayToBytes(Vertices);
var ibytes = Indices;
Buffer.BlockCopy(vbytes, 0, d, 0, vbytes.Length);
Buffer.BlockCopy(ibytes, 0, d, vbytes.Length, ibytes.Length);
Data = d;
var min = new Vector3(float.MaxValue);
var 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]);
}
_OccludeModel.bmin = min;
_OccludeModel.bmax = max;
_OccludeModel.Unused0 = min.X;
_OccludeModel.Unused1 = max.X;
_OccludeModel.dataSize = (uint)dlen;
_OccludeModel.numVertsInBytes = (ushort)vbytes.Length;
_OccludeModel.numTris = (ushort)((ibytes.Length / 3) + 32768);//is this actually a flag lurking..?
//_OccludeModel.flags = ...
}
public YmapOccludeModelTriangle RayIntersect(ref Ray ray, ref float hitdist)
{
if (Triangles == null)
{
BuildTriangles();
BuildBVH();
}
else if (BVH == null)
{
BuildBVH();
}
if (BVH == null) return null;
return BVH.RayIntersect(ref ray, ref hitdist) as YmapOccludeModelTriangle;
}
public EditorVertex[] GetTriangleVertices()
{
if ((Vertices == null) || (Indices == null)) return null;
EditorVertex[] res = new EditorVertex[Indices.Length];//changing from indexed to nonindexed triangle list
var colour = new Color4(1.0f, 1.0f, 1.0f, 0.2f); //todo: colours for occlude models? currently transparent white
var colour = new Color4(1.0f, 0.0f, 0.0f, 0.8f); //todo: colours for occluders?
var colourval = (uint)colour.ToRgba();
for (int i = 0; i < Indices.Length; i++)
{
@ -2888,7 +3221,6 @@ namespace CodeWalker.GameFiles
}
return res;
}
public EditorVertex[] GetPathVertices()
{
return null;
@ -2897,10 +3229,32 @@ namespace CodeWalker.GameFiles
{
return null;
}
public override string ToString()
{
return Index.ToString() + ": " + (Vertices?.Length ?? 0).ToString() + " vertices, " + (Triangles?.Length ?? 0).ToString() + " triangles";
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class YmapBoxOccluder
public class YmapOccludeModelTriangle : TriangleBVHItem
{
public YmapOccludeModel Model { get; set; }
public YmapFile Ymap { get { return Model?.Ymap; } }
public int Index { get; set; }
public YmapOccludeModelTriangle(YmapOccludeModel model, Vector3 v1, Vector3 v2, Vector3 v3, int i)
{
Model = model;
Corner1 = v1;
Corner2 = v2;
Corner3 = v3;
Index = i;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class YmapBoxOccluder : BasePathData
{
public BoxOccluder _Box;
public BoxOccluder Box { get { return _Box; } set { _Box = value; } }
@ -2916,6 +3270,7 @@ namespace CodeWalker.GameFiles
public int Index { get; set; }
public YmapBoxOccluder(YmapFile ymap, BoxOccluder box)
{
Ymap = ymap;
@ -2934,6 +3289,68 @@ namespace CodeWalker.GameFiles
}
public void UpdateBoxStruct()
{
_Box.iCenterX = (short)Math.Round(Position.X * 4.0f);
_Box.iCenterY = (short)Math.Round(Position.Y * 4.0f);
_Box.iCenterZ = (short)Math.Round(Position.Z * 4.0f);
_Box.iLength = (short)Math.Round(Size.X * 4.0f);
_Box.iWidth = (short)Math.Round(Size.Y * 4.0f);
_Box.iHeight = (short)Math.Round(Size.Z * 4.0f);
var dir = Orientation.Multiply(Vector3.UnitX) * 0.5f;
_Box.iSinZ = (short)Math.Round(dir.X * 32767.0f);
_Box.iCosZ = (short)Math.Round(dir.Y * 32767.0f);
}
public void SetSize(Vector3 s)
{
Size = s;
BBMin = Size * -0.5f;
BBMax = Size * 0.5f;
}
public EditorVertex[] GetTriangleVertices()
{
Vector3 xform(float x, float y, float z)
{
return Orientation.Multiply(new Vector3(x, y, z)) + Position;
}
EditorVertex[] res = new EditorVertex[36];
var colour = new Color4(0.0f, 0.0f, 1.0f, 0.8f); //todo: colours for occluders?
var c = (uint)colour.ToRgba();
var s = Size * 0.5f;
var v0 = new EditorVertex() { Position = xform(-s.X, -s.Y, -s.Z), Colour = c };
var v1 = new EditorVertex() { Position = xform(-s.X, -s.Y, +s.Z), Colour = c };
var v2 = new EditorVertex() { Position = xform(-s.X, +s.Y, -s.Z), Colour = c };
var v3 = new EditorVertex() { Position = xform(-s.X, +s.Y, +s.Z), Colour = c };
var v4 = new EditorVertex() { Position = xform(+s.X, -s.Y, -s.Z), Colour = c };
var v5 = new EditorVertex() { Position = xform(+s.X, -s.Y, +s.Z), Colour = c };
var v6 = new EditorVertex() { Position = xform(+s.X, +s.Y, -s.Z), Colour = c };
var v7 = new EditorVertex() { Position = xform(+s.X, +s.Y, +s.Z), Colour = c };
res[00] = v0; res[01] = v1; res[02] = v2; res[03] = v2; res[04] = v1; res[05] = v3;
res[06] = v2; res[07] = v3; res[08] = v6; res[09] = v6; res[10] = v3; res[11] = v7;
res[12] = v1; res[13] = v5; res[14] = v3; res[15] = v3; res[16] = v5; res[17] = v7;
res[18] = v6; res[19] = v7; res[20] = v4; res[21] = v4; res[22] = v7; res[23] = v5;
res[24] = v4; res[25] = v5; res[26] = v0; res[27] = v0; res[28] = v5; res[29] = v1;
res[30] = v2; res[31] = v6; res[32] = v0; res[33] = v0; res[34] = v6; res[35] = v4;
return res;
}
public EditorVertex[] GetPathVertices()
{
return null;
}
public Vector4[] GetNodePositions()
{
return null;
}
public override string ToString()
{
return Index.ToString() + ": " + FloatUtil.GetVector3String(Position);
}
}
}

View File

@ -0,0 +1,218 @@
using SharpDX;
using System;
using System.Collections.Generic;
using System.Text;
namespace CodeWalker
{
public class TriangleBVH : TriangleBVHNode
{
public TriangleBVH(TriangleBVHItem[] tris, int depth = 8)
{
if (tris == null) return;
var min = new Vector3(float.MaxValue);
var max = new Vector3(float.MinValue);
for (int i = 0; i < tris.Length; i++)
{
var tri = tris[i];
tri.UpdateBox();
min = Vector3.Min(min, tri.Box.Minimum);
max = Vector3.Max(max, tri.Box.Maximum);
}
Box = new BoundingBox(min, max);
Build(tris, depth);
}
}
public class TriangleBVHNode
{
public TriangleBVHItem[] Triangles { get; set; }
public TriangleBVHNode Node1 { get; set; }
public TriangleBVHNode Node2 { get; set; }
public BoundingBox Box { get; set; }
public void Build(TriangleBVHItem[] tris, int depth)
{
if (tris.Length <= 10) depth = 0;
if (depth <= 0)
{
Triangles = tris;
Node1 = null;
Node2 = null;
}
else
{
var min = Box.Minimum;
var max = Box.Maximum;
var cen = Box.Center;
var siz = Box.Size;
BoundingBox b1, b2;
if ((siz.X >= siz.Y) && (siz.X >= siz.Z))
{
b1 = new BoundingBox(min, new Vector3(cen.X, max.Y, max.Z));
b2 = new BoundingBox(new Vector3(cen.X, min.Y, min.Z), max);
}
else if (siz.Y >= siz.Z)
{
b1 = new BoundingBox(min, new Vector3(max.X, cen.Y, max.Z));
b2 = new BoundingBox(new Vector3(min.X, cen.Y, min.Z), max);
}
else
{
b1 = new BoundingBox(min, new Vector3(max.X, max.Y, cen.Z));
b2 = new BoundingBox(new Vector3(min.X, min.Y, cen.Z), max);
}
var l1 = new List<TriangleBVHItem>();
var l2 = new List<TriangleBVHItem>();
for (int i = 0; i < tris.Length; i++)
{
var tri = tris[i];
if (tri.Box.Contains(b1) != ContainmentType.Disjoint)// (tri.Box.Intersects(b1))
{
l1.Add(tri);
}
if (tri.Box.Contains(b2) != ContainmentType.Disjoint)// (tri.Box.Intersects(b2))
{
l2.Add(tri);
}
}
if (l1.Count > 0)
{
Node1 = new TriangleBVHNode();
Node1.Box = b1;
Node1.Build(l1.ToArray(), depth - 1);
}
if (l2.Count > 0)
{
Node2 = new TriangleBVHNode();
Node2.Box = b2;
Node2.Build(l2.ToArray(), depth - 1);
}
}
}
public TriangleBVHItem RayIntersect(ref Ray ray, ref float hitdist)
{
if (ray.Intersects(Box) == false) return null;
TriangleBVHItem hit = null;
if (Triangles != null)
{
for (int i = 0; i < Triangles.Length; i++)
{
var tri = Triangles[i];
var v1 = tri.Corner1;
var v2 = tri.Corner2;
var v3 = tri.Corner3;
if (ray.Intersects(ref v1, ref v2, ref v3, out float d) && (d < hitdist) && (d > 0))
{
hitdist = d;
hit = tri;
}
}
}
if (Node1 != null)
{
var hd = hitdist;
var h = Node1.RayIntersect(ref ray, ref hd);
if ((h != null) && (hd < hitdist))
{
hitdist = hd;
hit = h;
}
}
if (Node2 != null)
{
var hd = hitdist;
var h = Node2.RayIntersect(ref ray, ref hd);
if ((h != null) && (hd < hitdist))
{
hitdist = hd;
hit = h;
}
}
return hit;
}
}
public abstract class TriangleBVHItem
{
public Vector3 Corner1 { get; set; }
public Vector3 Corner2 { get; set; }
public Vector3 Corner3 { get; set; }
public BoundingBox Box { get; set; }
public Vector3 Center
{
get
{
return (Corner1 + Corner2 + Corner3) * 0.3333333f;
}
set
{
var delta = value - Center;
Corner1 += delta;
Corner2 += delta;
Corner3 += delta;
}
}
public Quaternion Orientation
{
get
{
return _Orientation;
}
set
{
var inv = Quaternion.Invert(_Orientation);
var delta = value * inv;
var cen = Center;
Corner1 = cen + delta.Multiply(Corner1 - cen);
Corner2 = cen + delta.Multiply(Corner2 - cen);
Corner3 = cen + delta.Multiply(Corner3 - cen);
_Orientation = value;
}
}
private Quaternion _Orientation = Quaternion.Identity;
public Vector3 Scale
{
get
{
return _Scale;
}
set
{
var inv = Quaternion.Invert(_Orientation);
var delta = value / _Scale;
var cen = Center;
Corner1 = cen + _Orientation.Multiply(inv.Multiply(Corner1 - cen) * delta);
Corner2 = cen + _Orientation.Multiply(inv.Multiply(Corner2 - cen) * delta);
Corner3 = cen + _Orientation.Multiply(inv.Multiply(Corner3 - cen) * delta);
_Scale = value;
}
}
private Vector3 _Scale = Vector3.One;
public void UpdateBox()
{
var min = new Vector3(float.MaxValue);
var max = new Vector3(float.MinValue);
min = Vector3.Min(min, Corner1);
min = Vector3.Min(min, Corner2);
min = Vector3.Min(min, Corner3);
max = Vector3.Max(max, Corner1);
max = Vector3.Max(max, Corner2);
max = Vector3.Max(max, Corner3);
Box = new BoundingBox(min, max);
}
}
}

View File

@ -0,0 +1,166 @@

namespace CodeWalker.Project.Panels
{
partial class EditYmapBoxOccluderPanel
{
/// <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(EditYmapBoxOccluderPanel));
this.GoToButton = new System.Windows.Forms.Button();
this.CenterTextBox = new System.Windows.Forms.TextBox();
this.label31 = new System.Windows.Forms.Label();
this.DeleteButton = new System.Windows.Forms.Button();
this.AddToProjectButton = new System.Windows.Forms.Button();
this.SizeTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.SinCosZTextBox = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// GoToButton
//
this.GoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.GoToButton.Location = new System.Drawing.Point(478, 6);
this.GoToButton.Name = "GoToButton";
this.GoToButton.Size = new System.Drawing.Size(68, 23);
this.GoToButton.TabIndex = 87;
this.GoToButton.Text = "Go to";
this.GoToButton.UseVisualStyleBackColor = true;
this.GoToButton.Click += new System.EventHandler(this.GoToButton_Click);
//
// CenterTextBox
//
this.CenterTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.CenterTextBox.Location = new System.Drawing.Point(82, 8);
this.CenterTextBox.Name = "CenterTextBox";
this.CenterTextBox.Size = new System.Drawing.Size(390, 20);
this.CenterTextBox.TabIndex = 86;
this.CenterTextBox.TextChanged += new System.EventHandler(this.CenterTextBox_TextChanged);
//
// label31
//
this.label31.AutoSize = true;
this.label31.Location = new System.Drawing.Point(4, 11);
this.label31.Name = "label31";
this.label31.Size = new System.Drawing.Size(41, 13);
this.label31.TabIndex = 85;
this.label31.Text = "Center:";
//
// DeleteButton
//
this.DeleteButton.Location = new System.Drawing.Point(183, 95);
this.DeleteButton.Name = "DeleteButton";
this.DeleteButton.Size = new System.Drawing.Size(95, 23);
this.DeleteButton.TabIndex = 107;
this.DeleteButton.Text = "Delete Box";
this.DeleteButton.UseVisualStyleBackColor = true;
this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click);
//
// AddToProjectButton
//
this.AddToProjectButton.Location = new System.Drawing.Point(82, 95);
this.AddToProjectButton.Name = "AddToProjectButton";
this.AddToProjectButton.Size = new System.Drawing.Size(95, 23);
this.AddToProjectButton.TabIndex = 106;
this.AddToProjectButton.Text = "Add to Project";
this.AddToProjectButton.UseVisualStyleBackColor = true;
this.AddToProjectButton.Click += new System.EventHandler(this.AddToProjectButton_Click);
//
// SizeTextBox
//
this.SizeTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.SizeTextBox.Location = new System.Drawing.Point(82, 34);
this.SizeTextBox.Name = "SizeTextBox";
this.SizeTextBox.Size = new System.Drawing.Size(390, 20);
this.SizeTextBox.TabIndex = 109;
this.SizeTextBox.TextChanged += new System.EventHandler(this.SizeTextBox_TextChanged);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(4, 37);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(30, 13);
this.label1.TabIndex = 108;
this.label1.Text = "Size:";
//
// SinCosZTextBox
//
this.SinCosZTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.SinCosZTextBox.Location = new System.Drawing.Point(82, 60);
this.SinCosZTextBox.Name = "SinCosZTextBox";
this.SinCosZTextBox.Size = new System.Drawing.Size(390, 20);
this.SinCosZTextBox.TabIndex = 111;
this.SinCosZTextBox.TextChanged += new System.EventHandler(this.SinCosZTextBox_TextChanged);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(4, 63);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(56, 13);
this.label2.TabIndex = 110;
this.label2.Text = "Sin,Cos Z:";
//
// EditYmapBoxOccluderPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(553, 407);
this.Controls.Add(this.SinCosZTextBox);
this.Controls.Add(this.label2);
this.Controls.Add(this.SizeTextBox);
this.Controls.Add(this.label1);
this.Controls.Add(this.DeleteButton);
this.Controls.Add(this.AddToProjectButton);
this.Controls.Add(this.GoToButton);
this.Controls.Add(this.CenterTextBox);
this.Controls.Add(this.label31);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "EditYmapBoxOccluderPanel";
this.Text = "Box Occluder";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button GoToButton;
private System.Windows.Forms.TextBox CenterTextBox;
private System.Windows.Forms.Label label31;
private System.Windows.Forms.Button DeleteButton;
private System.Windows.Forms.Button AddToProjectButton;
private System.Windows.Forms.TextBox SizeTextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox SinCosZTextBox;
private System.Windows.Forms.Label label2;
}
}

View File

@ -0,0 +1,162 @@
using CodeWalker.GameFiles;
using SharpDX;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.Project.Panels
{
public partial class EditYmapBoxOccluderPanel : ProjectPanel
{
public ProjectForm ProjectForm;
public YmapBoxOccluder CurrentBoxOccluder { get; set; }
private bool populatingui = false;
public EditYmapBoxOccluderPanel(ProjectForm owner)
{
ProjectForm = owner;
InitializeComponent();
}
public void SetBoxOccluder(YmapBoxOccluder box)
{
CurrentBoxOccluder = box;
Tag = box;
LoadBoxOccluder();
UpdateFormTitle();
}
private void UpdateFormTitle()
{
Text = "BoxOccluder: " + (CurrentBoxOccluder?.Index.ToString() ?? "(none)");
}
private void LoadBoxOccluder()
{
if (CurrentBoxOccluder == null)
{
////Panel.Enabled = false;
AddToProjectButton.Enabled = false;
DeleteButton.Enabled = false;
CenterTextBox.Text = string.Empty;
SizeTextBox.Text = string.Empty;
SinCosZTextBox.Text = string.Empty;
}
else
{
populatingui = true;
var b = CurrentBoxOccluder;
////Panel.Enabled = true;
AddToProjectButton.Enabled = !ProjectForm.YmapExistsInProject(CurrentBoxOccluder.Ymap);
DeleteButton.Enabled = !AddToProjectButton.Enabled;
CenterTextBox.Text = FloatUtil.GetVector3String(b.Position);
SizeTextBox.Text = FloatUtil.GetVector3String(b.Size);
var dir = b.Orientation.Multiply(Vector3.UnitX) * 0.5f;
SinCosZTextBox.Text = FloatUtil.GetVector2String(new Vector2(dir.X, dir.Y));
populatingui = false;
if (ProjectForm.WorldForm != null)
{
ProjectForm.WorldForm.SelectObject(CurrentBoxOccluder);
}
}
}
private void UpdateGraphics()
{
if (CurrentBoxOccluder == null) return;
if (ProjectForm?.WorldForm == null) return;
ProjectForm.WorldForm.UpdateBoxOccluderGraphics(CurrentBoxOccluder);
}
private void GoToButton_Click(object sender, EventArgs e)
{
if (CurrentBoxOccluder == null) return;
if (ProjectForm?.WorldForm == null) return;
ProjectForm.WorldForm.GoToPosition(CurrentBoxOccluder.Position, CurrentBoxOccluder.Size * 2.0f);
}
private void AddToProjectButton_Click(object sender, EventArgs e)
{
if (CurrentBoxOccluder == null) return;
if (ProjectForm == null) return;
ProjectForm.SetProjectItem(CurrentBoxOccluder);
ProjectForm.AddBoxOccluderToProject();
}
private void DeleteButton_Click(object sender, EventArgs e)
{
ProjectForm.SetProjectItem(CurrentBoxOccluder);
ProjectForm.DeleteBoxOccluder();
}
private void CenterTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentBoxOccluder == null) return;
var v = FloatUtil.ParseVector3String(CenterTextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentBoxOccluder.Position != v)
{
CurrentBoxOccluder.Position = v;
UpdateGraphics();
ProjectForm.SetYmapHasChanged(true);
ProjectForm.WorldForm?.SetWidgetPosition(v);
}
}
ProjectForm.ProjectExplorer?.UpdateBoxOccluderTreeNode(CurrentBoxOccluder);
}
private void SizeTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentBoxOccluder == null) return;
var v = FloatUtil.ParseVector3String(SizeTextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentBoxOccluder.Size != v)
{
CurrentBoxOccluder.SetSize(v);
UpdateGraphics();
ProjectForm.SetYmapHasChanged(true);
ProjectForm.WorldForm?.SetWidgetScale(v);
}
}
}
private void SinCosZTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentBoxOccluder == null) return;
var v = FloatUtil.ParseVector2String(SinCosZTextBox.Text);
float angl = (float)Math.Atan2(v.Y, v.X);
var q = Quaternion.RotationYawPitchRoll(0.0f, 0.0f, angl);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentBoxOccluder.Orientation != q)
{
CurrentBoxOccluder.Orientation = q;
UpdateGraphics();
ProjectForm.SetYmapHasChanged(true);
ProjectForm.WorldForm?.SetWidgetRotation(q);
}
}
}
}
}

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>
AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA
AABAAAAAAQAYAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAP//////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////v8/u3v+Pn6//7+////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//7+/vX3/rzA3OHl9fz9////////////////////////////////////////////////////////////
//////////////////////////////////////////////////7//+zv+3Z6qcLI5Pr7////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////7+/+br+15in6+33vf5//////////////////7+//7+////////////////////
//////////////////////////////3+//v8//v8//3+//////////////////////7+/+Ho+1dana20
4/b4//////////z9//P2/+Tp/ezw/vz9//////////////////////////////////////////7///X4
/9Pa+tPa+/H1//z9//////////////////7+/93k+SsscaSr3PX3//////7+//L1/7W98AcWgrvC8Pj6
//////////////////////////////////////////7+/+bs/xohiAEJdrvF9+7y//z9////////////
//7+/9rh+CEkapmh0/T3//////j6/9HZ/AEHcgEEb9LZ+/r7////////////////////////////////
//////////7//+/z/3F+zAAAXwQLcZai3fb4//////////////3+/97l/E9Tmaau4fT3/////+/0/1dd
sAAAV7a/8/H1//7+//////////////////////////////////////////////r8/+jv/46Y3QUUf6Ot
5PX4//////////////3+/9zj+3Z6wLe/7fX4//////D0/212xnaAzerw//z9////////////////////
//////////////////////////////////v8/+/z/+Dm+/D0//z9//////////7+//j6/9Pd+UhLjb/H
9/D0//3+//n7/+nt/+jt//n7////////////////////////////////////////////////////////
//7///7+//7+//7+//////////r8/+7z/83W+ImU2A0UdFNarr/K9env//X4//z9//3+//7/////////
//////////////////////////////////////////////////////////////////7///j6/+Pq/255
xhckjE5XsVVftUlTqwAKeTA9nr3H8+7z//v8////////////////////////////////////////////
//////////////////////////////7+//b4/9Tc+Sc0mRonj8rV/crX/ZSb48rX/brG8wwWgQAEdJei
4efu//n7//7+//z9//z9//z9//z9//3+//////////////////////////////3+//f5/+3y/+nv/+ft
/8vV+io2mImU2M7c/7vG9yIvlQAOfCg4mM3Y/s/c/4aR1AQRfGtzwtni/ebt/9vi/tri/tXd+9Tc+O3x
/vz9//////////////////////////n6/87V+FVftkRPrFlnvSEqjQoUfmJvwWFvvg0TfQQIcxEchwAD
cy89n19rvVVitQwZgwAAaiMrkT9NqTVBoiw3mhQihig1mNLX+fv8//////////////////////////b5
/52l4EFLqoCK03yF0VBctGhyw52o5GVrvQAAaneBzsHM+jA3mhYgiTtIpJOf3ouW2AAAbmh0wbbA8bS+
7qiz5pCb16+56e/z//3+//////////////////////////v8//H1/+vw/+zx/+nv/7/J9YqP3MbP/8LM
+hwqkFZftaCp5EhRrcTQ+9jj/8rW/UJMqn6J0ebt//X3//f5//b4//X3//f5//z9////////////////
//////////7+//z9//3+//////////3+/+7z/6at64iP3aWs7XN8zRIfhyUykp2o5MHM+oKM0xonjY6X
2+jv//v8//////7+//n7//b5//r7//7///////////////////7+//f5/+rw/9Pa9fL0/v7/////////
//v8//H1/+Tr/7i/91liu0NPq0VQrS06m0NNqDdCoYqU1+nv//v8//////////n7/9zi/qSt59ri/fL1
//v8//7///////z9//D0/8rT+h0sjkVQrPD0//////////////////////z9/+7z/8LL9Jqk4aGq6LW/
8c3W9+Xs/vH1//v8//////////////f5/6at5gAAbxIfh6u16+Po/fr7//////b5/6ev5gAIeAAPernC
8fX4//////////3+//v8//z9//////3+//j6//P3//P2//b4//r8//7+//7+//v8//r8//3+//////v8
/+Xr/nuIzwAAbBseg5Sb2fb5//////f5/8DF8pWe3d/n/vT3//39//////v8/+zx/87V9+3x/v3+////
//3+//j6//X4//v8//////////n7/+Dm/snR9fD0//39//z8/fv8/+3y/8LK9aGq4dfd9/n7//////z9
//b5//X4//v8//////////7+/+7z/4aP1gEPet7k/f39//////f5/83U+ZCZ2u3x/v7+//////P3/215
wgAJd7fB8/L1//7+//////3+//j6//f5//r8//7+//////////////////////////////j6/87W/AAA
X2duue3y//7+//////D0/05asBQfidzj/P39//////X4/6Su6AAAXBccgtff/vv8////////////////
//////////////////////////////////////P3/3F8xhYli9Xe/fn6/////////+3y/1pltQAJd9be
/fv8//////z9/+rw/36I0Bknjs/W+vv8////////////////////////////////////////////////
//////f5/8HI7tnf+/X4//7+/////////+/0/3R7xgAAb9ng/Pz9//////////n7/+Ln/dLY+fP2//3+
//////////////////////////////////////////////////////3+//r7//v8//7+////////////
//b4/7/F84eP0e/0//7+//////////7+//z9//v8//3+////////////////////////////////////
//////////////////////////////////////////////////z9//b5//X4//v8////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////w////4
P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA
AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA
AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v//
/////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO
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
AAAAAAAA////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////v7//f7//P3//P3//P3/
/f7//v7/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v7//P3/
+fv/+fv/+Pr/+fv/+vv//P3//v//////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////+vv/8vb/2+P9X2OmREGLnqPd
4+v/8vb/+/z/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////+vv/8fb/
1N35bXK1JSRtbHGz5O7/8fX/+/z/////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////+vv/8fb/2OL+NjZ7AAArX2Ok
4uz/8fX/+/z/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////+vv/8fb/
2eP/LjJ1DAxKfYTE4Or/8fX/+/z//////////////////////////////v7//v7//f7//f7//v7//v//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////+vv/8PX/3OX/gILIR0eVeoHC3eb/8fX/+/z//////////////////////v7//P3/+fv/+Pr/
+Pr/+Pr/+vv//P3//v7/////////////////////////////////////////////////////////////
/////////////////////////////v7//f7//P3/+vv/+vv/+/z//f3//v7/////////////////////
////////////////////////+vv/8PX/2eP9ZWeqHx1obnOz4Or/8fX/+/z//////////////////v7/
+/z/9fj/8vb/8PX/7vT/8fb/9fj/+fr//f7/////////////////////////////////////////////
/////////////////////////////////////////v///P3/+Pr/9fj/9fj/9Pj/9Pf/9vn/+/z//v7/
////////////////////////////////////////+vv/8fb/2eP9ODp9AAA5jZDQ5O7/8PX/+/z/////
/////////v7/+/z/9Pf/7fP/5u//wsz6j5XfuMDx7fL/9vn//P3/////////////////////////////
/////////////////////////////////////////////////////////f7/+Pr/8/b/5+3/2eH/2uP/
5u3/7fP/8/b/+vv//f7/////////////////////////////////////+vv/8PX/3ef/U1ebBgVKio/O
4uz/8fX/+/z//////////v///P3/9fj/7fP/4uv/hIzZHSWPAABmU1i14ub/9/r/+/z/////////////
/////////////////////////////////////////////////////////////////////////P3/9Pf/
7/X/09z/TlSzNzWYj5bh5O7/6/L/8vb/+fv//f7/////////////////////////////////+vv/8fX/
2eP/QUWIEhBZbnSz3uj/8fb/+/z//////////f7/+Pr/7/T/6PH/iI7cAABvAABqAABncXjK6O//9fj/
+/z/////////////////////////////////////////////////////////////////////////////
////////+/z/8/f/2uD/Z27EAABnAABiBgl4jJTd5vD/6O//8vX/+fv//f7/////////////////////
////////+vv/8fb/2OP/Mjd6AQE6ZGup4er/8fX/+/z/////////+vz/8fX/6/T/xM/8ExyJAABwAABu
GySRxc387fT/9ff//P3/////////////////////////////////////////////////////////////
////////////////////////+vz/8/f/1Nr/MzqhAABhAxOBAARyBgp5jpLg5Oz/7PP/9Pf/+vz//v7/
////////////////////////+vv/8fb/2eP/KCtvBwZOjJHS4Or/8fX/+/z//////f7/9/n/7fP/3+j/
UFq3AABtAAZ3BAh6mZ/n5vD/7vP/+Pr//v7/////////////////////////////////////////////
////////////////////////////////////////+/z/9Pj/6e//sbb1KzWcAABwBhaBAAFyAgp6fITR
1d777/T/+Pr//f7/////////////////////////+vv/8PX/3+j/WF2hBglTnaTj5O3/8PX/+/z/////
/P3/9Pf/6vL/k5riAAByAAR0AABrY2vE4ur/6vH/9ff//P3/////////////////////////////////
/////////////////////////////////////////////////////////f3/9/n/7fL/5O3/ytX/RU6w
AABpAA5+AABuAABnhord6e7/+fv//f7/////////////////////////+vv/7/T/3+j/k5jbT1KdgYjJ
3uf+8fX/+/z/////+/z/9fn/4ef/NDqhAABnAABrJjCU0Nn/5/D/8fX/+vv//v7/////////////////
/////////////////////////////////////////////////////////////////////////v7/+/z/
9vn/7vP/6vP/ztb/O0CmAABpAABrQkuoxMn57PH/+Pr//f7/////////////////////////+vv/8PX/
2+X/en/CUFGak5nY3+j/8fX//P3//////P3/9fj/4en/i5DbNT2hIyuTpqzv4uz/7vP/9/n//f7/////
////////////////////////////////////////////////////////////////////////////////
/////////////v7//P3/9vn/7/P/6vL/ytH/X2i9XWi7wsf/6e//8/f/+Pr//v7/////////////////
////////+vv/8PX/3OX/WF2hW1ylvMD+3uf/8PX/+/z//////f7/9vn/7fP/4uj/j5Pgf4LV3+X/6fD/
9Pf//P3/////////////////////////////////////////////////////////////////////////
/////////////////////////////////v///P3/+Pr/8vX/7fP/5+//5u7/6vD/8PT/9vn//P3//v7/
/////////////////////f7/9/n/7fP/0tz9LDJzNjh/nqTk2uT/7fL/9/n//f7//f7/+fv/8/b/7PL/
3eX/zM//5ev/9fj/+fv//v7/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////v///f3/+vv/9/n/9vn/9fj/9vn/
+fr//P3//v7//////////////v///f7/+vv/9vn/7/T/5vD/2Ob/VFubERNdoajk4u//5O7/7vP/9vj/
+fr/+vv/+Pr/9fj/9Pj/9fj/9fj/+Pr//P3/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v///v7/
/f7//P3//P3//f3//v7//v///////////////f7/+vz/9vn/8fX/7vT/5O3/3eb/z9n/cHjICxN5d37L
z9n/2eP/5O3/6/L/8PT/9Pf/9/n/+vv/+vv/+/z//P3//f3//v7/////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////P3/+Pr/8/b/7vT/6vL/z9r+jZjeQUeq
IiuQCBN3AAFrBRB8Nj2iUViym6XlydH/4+z/6/L/8PT/9/n/+/z//f7//v//////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////f3/9/n/8fX/6/L/3uf/
mKTkLzibAABoAAB0Fx+HDBh7FSGDAg16AABYAABlCBB/Ji2UhYza1+D/6PL/7fL/9Pf/+vv//f7/////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////v7//P3/9/n/
8PT/7PT/z9j/XmO+AABtAABcMDSXoajsu8X7VV+5hYzblZ/fTVSxFSKMAABkAABnAAN2Qkmpsbrz5e3/
6vH/8fX/+Pr//P3//v//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////P3/9/n/8PX/7PT/vcn3LTOZAABaAgR1ZWzD0Nf/5vL/1OP/l53lzs3/6fP/4+7/sLzwZ23CBxSD
AABnAABlHiaSmqHo3+j/5+//7/T/9vn//P3//v7/////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////v7/
/v7//v7//v7//f7/+/z/9vj/7vP/7PX/tcLzEBeGAABkPEWlqLPt2eX/4e7/3On/uMX1gofVe3vPhYzY
z93+5/X/4e3/lJ3gHiOPAABtAABqChiEbHLIytD/5/D/7PL/8/f/+Pr/+fr/+Pr/+Pr/+Pr/+Pr/+Pr/
+Pr/+fv/+vv/+/z//f7//v7/////////////////////////////////////////////////////////
/v7//f7/+/z/+fv/9/n/9vj/9fj/9Pf/8fX/7PL/4uv/l6HgDhF7AAN4iZDe0d7/3uz/4vD/w83/VVm3
ICiSAAFyAABlAABwaHTD1N//2un/3er/w838ZW3BEyOJJzKVAQ16NDmfwsn75fD/5u7/7PL/7vP/7fP/
7fP/7fL/7fP/7vP/7/T/8fb/9Pj/9vn/+fr//f3//v//////////////////////////////////////
/////////////v7//P3/+Pr/9Pf/8fX/7vT/7PL/6/L/6fH/5u7/6vX/tsD0CQx4AAFwkZvi7ff/4vD/
4fD/z9j/OkGlAABiAABwBxWAAAt7BBN+P0uofYLUztb/4O7/6fb/6fP/qa7xQkyoBg56AABqMjugx8/+
5fH/4Ov/4On/3uj/3eb/3+j/3uj/1+L/0d3/1d7/3+f/7fL/9vj/+vz//v7/////////////////////
/////////////////////////////f7/+fr/8/f/6/L/2d//v8j6vcf5ucP1wMv8wM3+vMj6PkqoAABo
UF25usP7tsPyvsr6sLrwQ0utAABqAAV1OUameIDRKDWZAAd2GyeOLDecmaHntsL0pbLom6riq7LzUlu0
AANzBhR/AAZ0NT+ja3bBY2i/XGG6UViyWl65XGG7XGC6TVWvQU6pPkalODygqK7p8vb/+vz//v7/////
/////////////////////////////////////////////P3/9/n/7/T/wcj2R0ysExeFERmGDxuIFB6K
FBqICxSEAABsAAByDBiDCRSBBRCADhaFCRODAAh4AxF/AAl4CxeDHSaPAAp6AAN0AA19AAd3CBOBEBqH
BhGBAAh5AABwAAByAAh5BhSCAxWCAABsAABvAABlAABnAABxAABjAABmAABhAABdAABYAABhCAt/q7Lr
8/f/+vv//v7//////////////////////////////////////////////////P3/+fv/3uT/SE2vAABn
CBB/GiCMLzmfLTWcGByJFRyKGCOOMj2gHymRDxiGGyOPLDCXBRF/AAh3BhaCEyKMICqTKC2WNDqfIzCV
Awx6Eh+JHiaPAAR3AAZ5CxSDICWQX2q7Q1CqAA1+AAFxDxuHiZTbVGC4dHnQnabrTVqzY23EUV62Slau
LjaZXWm9sLjz5ez/9vn/+fv//v7//////////////////////////////////////////////////P3/
+Pv/4+n+e4LPfoPVpqv2vsf/zNX/zdb/xtH/v8v8pK7spKfysLb3vcr4ws784ej/hI/YAAZ1AAJzVF25
yM//3Of/5+//i5LcAABpMzyfp6vxoKznlqHhqbbtx9H/8fz/kpvfAABiAABph4zc5PD/2OP/193/3un/
1+D/2OH/1+D/0Nr/zNL/3+j/6/L/7/T/9vn//P3//v//////////////////////////////////////
/////////////f7/+Pr/9Pf/6vD/5u3/3+b/4uv/6PD/5+//5O3/5/P/sL3sXmS7mZzoz9f/3+z/4e//
mKLiEiKKCBF/KTWZr7T06/f/3ev/VF2zChSBipPcz9v+4u7/3ur/3ev/5/X/qrPrISmSDRJ2Xmq/3ur/
4uv/6vH/7fP/7fL/7/T/7vP/7fP/7fP/8PX/8fX/9Pf/+Pr/+/z//v7/////////////////////////
/////////////////////////////v7//P3/+Pr/9vn/9Pf/8vb/8vb/8/b/9Pf/7/T/6/L/tL/ubXLH
en/Ti43gqavy0t3/nafjMj6fJzaaAAV1GyeOYmW7Nz6fAABgNj6i1N//3uz/2uX/3Oj/5PH/wcj7FR2J
AAN0gong0tr/6fH/7/P/9vj/+Pr/+fv/+fv/+Pr/+Pr/+Pr/+fv/+vv//P3//f7//v//////////////
/////////////////////////////////////////////////v7//f7//P3/+/z/+/z/+/z//f3//f7/
+fv/8fX/5Oz/jpbfc3jObnXLcXfOk5rks7b4iY3dR1KvDhuEAABoAABlEBV9U12ytcD13Or/3en/3ej/
1eL/q7fvGR+MKDKZbnnNxc/76PD/8fX/+fr//f7//v///////v7//f7//f3//P3//f3//f7//v//////
/////////////////////////////////////////////////////v7//f7//P3//P3//f7//v7/////
/////////////////f7/9vn/7/T/yNH5lJrleoDVmZ3pmpzpc3nPfoTWf4bYVFy3HSaLZ3PGsrb8v8r8
y9n9q7jre4LRf4fUgIvXAwZ1AABrhYjb0NX/6PH/8PX/+Pr//f7//////////v///f3/+vv/+Pr/9/r/
9/n/+Pr/+/z//f7//v7//////////////////////////////////////v///f7/+/z/+fr/9vj/9/n/
+vz/+vv/+/z//v7//////////////////v7/+vz/8/f/7PL/2uT/t8H1srP6vcH+nKTnSlOxV2C7TVaz
WGS8QUqmSlSuSFOtR1GtbXTKVl23ARB5AAh2AABnd33P3eP/4ur/7/T/9/n//P3//////////////P3/
9/n/8vb/7PH/6fD/7PL/7vP/8vb/9vn/+/z//f7//////////////////////////////v7/+/z/+Pr/
8/b/7/T/8Pb/6vH/3eP97vL++fr//P3//////////////////////f7/+vv/9fj/7/T/5+//z9f+t7v4
uLn9Z2zFLzucFCGIMz6gGCCMAAd4AAl2Dx2EER+GXWK8c3XLKzKXd4LP4er/6/L/8PX/9/n//P3//v//
/////////v7/+fv/8/b/7PP/y9H/i4/erLbt4er/5e3/7fP/8/b/+fv//f3//v7/////////////////
/v7/+/z/9vj/8PT/6/L/3+n/x9H9aHTAZGvG3+b9+Pr/+/z//////////////////////////v7/+/z/
+Pr/8vb/6/H/3OX+wMn4maDmdHrPWGG6T1a1eoHWcHfOTlayUlq1SlKubHjAxMj/0dn/4+v/7PL/8vb/
+Pr//P3//v7//////////////f7/+fr/7vP/xsv5YGXAHymRKjKYYWS9rbLz4u3/6/P/8vb/+fr//f7/
/////////////v//+/z/9vj/7fL/5e3/xs7/Y23BIiiSAABeLTab3+b/9/r/+/z/////////////////
/////////////////f7/+vz/9vj/8PX/6vH/3eb/ydL8xM/6uMPyt733w8j/zNb/1Nz/3OT/4uz/5u7/
7fP/8vb/9vj/+vz//f7//////////////////////f7/+fv/7vP/jpHiAAJ1CxaBER6GAABoFRmGbXbH
0Nf/7PL/9fj//P3//////////////v7/+fv/8/f/4Of/hYvbKDGZAABuAABdAAZyi5La5+7/9vn/+/z/
/////////////////////////////////////v7//P3/+fv/9ff/8vb/7/X/7fP/6/L/5u3/5ez/6fD/
7PP/7/T/8fX/9Pf/9/n/+vv//P3//v7//v///////////////////////v7/+fv/8fb/2eH9fIbQExqH
AABrAAp6AAFyAABwS0+uztX39vn/+vz//////////////f7/+Pr/8ff/qbLpAABrAABhAABwDBWAfobX
5e3/8PX/9vn//f3//////////v///f7/+/z/+vv/+vv/+vz//P3//v7//v///v7//P3/+vz/+Pr/9/n/
9vj/9vj/9vj/9vj/9/n/+fr/+/z//P3//f7//v7//f7//P3/+/z/+vz/+/z//P3//v7//////v7/+/z/
9fj/7/T/5/H/uML1U1e1AAh5AABuAABvMjmdv8bz9vr/+vv//////////////f7/+fv/7/T/iY7aDxSA
GiONa3XHsr7w4Oj/6/H/9Pf/+vz//v7//////v///P3/+Pr/9Pf/8/f/9fj/9fj/9vn/+/z//v7/////
/////////v7//f7//P3/+/z/+/z//P3//f7//v///////////////v7/+/z/9/n/9vn/9vn/9Pj/9vn/
+/z//v7//////f7/+vz/9fj/7/T/6vL/3ef/i5PbGRqJBQl5jJbZ6vH/9Pj/+/z//////////////f7/
+fv/8fT/1Nn9t7/0wcr54er/7fT/8fX/9fj/+vv//f7//////////f3/+Pr/8PT/6/L/3uX/ztb/5Or/
8/f/+Pr//f7//////////////f7/+vz/+Pr/+fv/+fv/+vv//f3//v///////////////P3/9/n/7vL/
193/ztf/5u3/7vP/9Pf/+/z//v7//////v7//P3/+Pr/8fX/7PP/5/D/sLfxoKnk4+r/8vf/9/n//f3/
/////////////v7/+/z/9vn/9Pf/8vb/8fb/8fX/9Pf/+Pr//P3//v7//////////v7/+vv/8vb/5+7/
y9H/WWO9KSmSkZXj6vD/+Pv//P3//////////f7/+Pr/9fj/8vb/6O7/7vP/9fj/+Pr//f7/////////
/v//+vv/8vb/7PP/hYraKiqKlp7i6PD/7fP/9ff/+/z//v7//////////f7/+vv/9ff/8fX/8PX/8vb/
8/f/9vn/+/z//v7//////////////////f7/+/z/+vv/+fr/+fr/+vv//P3//v7/////////////////
/P3/9fj/7PL/1d7/RUysAABhAABlg4ja6/D/+Pr//P3/////////+/z/9fj/6e7/2eD/h4/bnaXg7PH/
9fj/+/z//////////v7/+Pr/8PX/y9X1JDGVAABaERWDoKnp6PH/7vP/9/n//P3//////////////v7/
/P3/+vv/+fv/+fv/+vv//P3//v7//////////////////////////v7//v7//v7//v7//v//////////
/////////////v7/+fv/8PX/7PX/ipPdAABsAABlQ1Cp3Ob/7vP/9/n//f7/////////+fv/9Pj/yNH5
Ule2DBJ8Ljie0df+8fb/+fv//v7//////v7/+Pr/7/X/hY3YAABxAAl7AABuEBaEs7nz6fH/8fX/+vv/
/v7//////////////////v///v7//v7//v7/////////////////////////////////////////////
/////////////////////////////f3/9vn/7PL/0tn/LzidAQFsAAB0iZHb6vP/8PT/+fv//v//////
/v7/+Pr/8vf/r7rqAAV4AABdPUen1N//7PL/9vn//f7//////v7/+fr/7/T/yc75S1G0AABrARKAAABp
Qker0df/7fP/9/n//f7/////////////////////////////////////////////////////////////
/////////////////////////////////////////////P3/9/n/5+7/cXXNAAd2AABuMDebzdT97PL/
9vj//P3//////////v7/9/n/7/X/tL/uFCCLAABqHSqRvcf46fD/9Pf//f3/////////+vv/8vX/6vH/
yM3+JC2XAABtAAV2Agx9q7Ly7vT/9vn//f7/////////////////////////////////////////////
/////////////////////////////////////////////////////////////P3/9/r/4uj/WWO1AAVx
KTaYu8T07fT/8vb/+vv//v7//////////v7/9/n/7vX/vsn1Iy2SAABrAQ99mp/o6PD/9Pf//P3/////
/////P3/9/n/7vP/6fL/s7z2DBB/AABeQ0uttrr56e7/+Pr//f7/////////////////////////////
/////////////////////////////////////////////////////////////////////////////P3/
+fv/4ef6g4zNbXfFw8v27fT/8vb/+Pr//f3//////////////v7/9/n/7vT/yNL7MjucAABtBxF/nKLo
6fH/9Pf//P3//////////v7/+/z/9fj/7fL/6/T/jZXbLzScrrP14en/7fL/+fv//v7/////////////
////////////////////////////////////////////////////////////////////////////////
/////////////f7/+vz/8PP91dr34+f/8vb/8/f/9/r//P3//v///////////////v7/+Pr/8PX/1N3/
QUqmAQRxBQ98m6Dm7PL/9fj//P3//////////////v7/+/z/9ff/8PX/5ez/ytH94ej/8vb/9vj/+/z/
/v7/////////////////////////////////////////////////////////////////////////////
/////////////////////////////v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//////////////////
/v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7//////////////////v7/+/z/9/n/9fj/9vn/
9fj/9vj/+vz//f7/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////v7//f7//f3//f3//f3//v7//v//////
////////////////////+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/////////////////////
/v7//f7/+/z/+/z/+/z//P3//v7/////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////v7//P3/+fv/+fv/+vv/+Pr/+vv/
/P3//v7/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v7//f7/
/f3//P3//f7//v7//v//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///////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
////+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,287 @@

namespace CodeWalker.Project.Panels
{
partial class EditYmapOccludeModelPanel
{
/// <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(EditYmapOccludeModelPanel));
this.OccludeModelTabControl = new System.Windows.Forms.TabControl();
this.ModelTabPage = new System.Windows.Forms.TabPage();
this.ModelDeleteButton = new System.Windows.Forms.Button();
this.ModelAddToProjectButton = new System.Windows.Forms.Button();
this.TriangleTabPage = new System.Windows.Forms.TabPage();
this.TriangleDeleteButton = new System.Windows.Forms.Button();
this.TriangleAddToProjectButton = new System.Windows.Forms.Button();
this.TriangleGoToButton = new System.Windows.Forms.Button();
this.TriangleCenterTextBox = new System.Windows.Forms.TextBox();
this.label31 = new System.Windows.Forms.Label();
this.TriangleCorner1TextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.TriangleCorner2TextBox = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.TriangleCorner3TextBox = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.ModelFlagsTextBox = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.OccludeModelTabControl.SuspendLayout();
this.ModelTabPage.SuspendLayout();
this.TriangleTabPage.SuspendLayout();
this.SuspendLayout();
//
// OccludeModelTabControl
//
this.OccludeModelTabControl.Controls.Add(this.ModelTabPage);
this.OccludeModelTabControl.Controls.Add(this.TriangleTabPage);
this.OccludeModelTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.OccludeModelTabControl.Location = new System.Drawing.Point(0, 0);
this.OccludeModelTabControl.Name = "OccludeModelTabControl";
this.OccludeModelTabControl.SelectedIndex = 0;
this.OccludeModelTabControl.Size = new System.Drawing.Size(553, 407);
this.OccludeModelTabControl.TabIndex = 0;
//
// ModelTabPage
//
this.ModelTabPage.Controls.Add(this.ModelFlagsTextBox);
this.ModelTabPage.Controls.Add(this.label4);
this.ModelTabPage.Controls.Add(this.ModelDeleteButton);
this.ModelTabPage.Controls.Add(this.ModelAddToProjectButton);
this.ModelTabPage.Location = new System.Drawing.Point(4, 22);
this.ModelTabPage.Name = "ModelTabPage";
this.ModelTabPage.Padding = new System.Windows.Forms.Padding(3);
this.ModelTabPage.Size = new System.Drawing.Size(545, 381);
this.ModelTabPage.TabIndex = 0;
this.ModelTabPage.Text = "Model";
this.ModelTabPage.UseVisualStyleBackColor = true;
//
// ModelDeleteButton
//
this.ModelDeleteButton.Location = new System.Drawing.Point(176, 89);
this.ModelDeleteButton.Name = "ModelDeleteButton";
this.ModelDeleteButton.Size = new System.Drawing.Size(95, 23);
this.ModelDeleteButton.TabIndex = 111;
this.ModelDeleteButton.Text = "Delete Model";
this.ModelDeleteButton.UseVisualStyleBackColor = true;
this.ModelDeleteButton.Click += new System.EventHandler(this.ModelDeleteButton_Click);
//
// ModelAddToProjectButton
//
this.ModelAddToProjectButton.Location = new System.Drawing.Point(75, 89);
this.ModelAddToProjectButton.Name = "ModelAddToProjectButton";
this.ModelAddToProjectButton.Size = new System.Drawing.Size(95, 23);
this.ModelAddToProjectButton.TabIndex = 110;
this.ModelAddToProjectButton.Text = "Add to Project";
this.ModelAddToProjectButton.UseVisualStyleBackColor = true;
this.ModelAddToProjectButton.Click += new System.EventHandler(this.ModelAddToProjectButton_Click);
//
// TriangleTabPage
//
this.TriangleTabPage.Controls.Add(this.TriangleCorner3TextBox);
this.TriangleTabPage.Controls.Add(this.label3);
this.TriangleTabPage.Controls.Add(this.TriangleCorner2TextBox);
this.TriangleTabPage.Controls.Add(this.label2);
this.TriangleTabPage.Controls.Add(this.TriangleCorner1TextBox);
this.TriangleTabPage.Controls.Add(this.label1);
this.TriangleTabPage.Controls.Add(this.TriangleDeleteButton);
this.TriangleTabPage.Controls.Add(this.TriangleAddToProjectButton);
this.TriangleTabPage.Controls.Add(this.TriangleGoToButton);
this.TriangleTabPage.Controls.Add(this.TriangleCenterTextBox);
this.TriangleTabPage.Controls.Add(this.label31);
this.TriangleTabPage.Location = new System.Drawing.Point(4, 22);
this.TriangleTabPage.Name = "TriangleTabPage";
this.TriangleTabPage.Padding = new System.Windows.Forms.Padding(3);
this.TriangleTabPage.Size = new System.Drawing.Size(545, 381);
this.TriangleTabPage.TabIndex = 1;
this.TriangleTabPage.Text = "Triangle";
this.TriangleTabPage.UseVisualStyleBackColor = true;
//
// TriangleDeleteButton
//
this.TriangleDeleteButton.Location = new System.Drawing.Point(176, 121);
this.TriangleDeleteButton.Name = "TriangleDeleteButton";
this.TriangleDeleteButton.Size = new System.Drawing.Size(95, 23);
this.TriangleDeleteButton.TabIndex = 109;
this.TriangleDeleteButton.Text = "Delete Triangle";
this.TriangleDeleteButton.UseVisualStyleBackColor = true;
this.TriangleDeleteButton.Click += new System.EventHandler(this.TriangleDeleteButton_Click);
//
// TriangleAddToProjectButton
//
this.TriangleAddToProjectButton.Location = new System.Drawing.Point(75, 121);
this.TriangleAddToProjectButton.Name = "TriangleAddToProjectButton";
this.TriangleAddToProjectButton.Size = new System.Drawing.Size(95, 23);
this.TriangleAddToProjectButton.TabIndex = 108;
this.TriangleAddToProjectButton.Text = "Add to Project";
this.TriangleAddToProjectButton.UseVisualStyleBackColor = true;
this.TriangleAddToProjectButton.Click += new System.EventHandler(this.TriangleAddToProjectButton_Click);
//
// TriangleGoToButton
//
this.TriangleGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.TriangleGoToButton.Location = new System.Drawing.Point(471, 4);
this.TriangleGoToButton.Name = "TriangleGoToButton";
this.TriangleGoToButton.Size = new System.Drawing.Size(68, 23);
this.TriangleGoToButton.TabIndex = 87;
this.TriangleGoToButton.Text = "Go to";
this.TriangleGoToButton.UseVisualStyleBackColor = true;
this.TriangleGoToButton.Click += new System.EventHandler(this.TriangleGoToButton_Click);
//
// TriangleCenterTextBox
//
this.TriangleCenterTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.TriangleCenterTextBox.Location = new System.Drawing.Point(75, 6);
this.TriangleCenterTextBox.Name = "TriangleCenterTextBox";
this.TriangleCenterTextBox.Size = new System.Drawing.Size(390, 20);
this.TriangleCenterTextBox.TabIndex = 86;
this.TriangleCenterTextBox.TextChanged += new System.EventHandler(this.TriangleCenterTextBox_TextChanged);
//
// label31
//
this.label31.AutoSize = true;
this.label31.Location = new System.Drawing.Point(8, 9);
this.label31.Name = "label31";
this.label31.Size = new System.Drawing.Size(41, 13);
this.label31.TabIndex = 85;
this.label31.Text = "Center:";
//
// TriangleCorner1TextBox
//
this.TriangleCorner1TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.TriangleCorner1TextBox.Location = new System.Drawing.Point(75, 32);
this.TriangleCorner1TextBox.Name = "TriangleCorner1TextBox";
this.TriangleCorner1TextBox.Size = new System.Drawing.Size(390, 20);
this.TriangleCorner1TextBox.TabIndex = 111;
this.TriangleCorner1TextBox.TextChanged += new System.EventHandler(this.TriangleCorner1TextBox_TextChanged);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(8, 35);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(50, 13);
this.label1.TabIndex = 110;
this.label1.Text = "Corner 1:";
//
// TriangleCorner2TextBox
//
this.TriangleCorner2TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.TriangleCorner2TextBox.Location = new System.Drawing.Point(75, 58);
this.TriangleCorner2TextBox.Name = "TriangleCorner2TextBox";
this.TriangleCorner2TextBox.Size = new System.Drawing.Size(390, 20);
this.TriangleCorner2TextBox.TabIndex = 113;
this.TriangleCorner2TextBox.TextChanged += new System.EventHandler(this.TriangleCorner2TextBox_TextChanged);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(8, 61);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(50, 13);
this.label2.TabIndex = 112;
this.label2.Text = "Corner 2:";
//
// TriangleCorner3TextBox
//
this.TriangleCorner3TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.TriangleCorner3TextBox.Location = new System.Drawing.Point(75, 84);
this.TriangleCorner3TextBox.Name = "TriangleCorner3TextBox";
this.TriangleCorner3TextBox.Size = new System.Drawing.Size(390, 20);
this.TriangleCorner3TextBox.TabIndex = 115;
this.TriangleCorner3TextBox.TextChanged += new System.EventHandler(this.TriangleCorner3TextBox_TextChanged);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(8, 87);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(50, 13);
this.label3.TabIndex = 114;
this.label3.Text = "Corner 3:";
//
// ModelFlagsTextBox
//
this.ModelFlagsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ModelFlagsTextBox.Location = new System.Drawing.Point(75, 6);
this.ModelFlagsTextBox.Name = "ModelFlagsTextBox";
this.ModelFlagsTextBox.Size = new System.Drawing.Size(390, 20);
this.ModelFlagsTextBox.TabIndex = 119;
this.ModelFlagsTextBox.TextChanged += new System.EventHandler(this.ModelFlagsTextBox_TextChanged);
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(8, 9);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(35, 13);
this.label4.TabIndex = 118;
this.label4.Text = "Flags:";
//
// EditYmapOccludeModelPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(553, 407);
this.Controls.Add(this.OccludeModelTabControl);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "EditYmapOccludeModelPanel";
this.Text = "Occlude Model";
this.OccludeModelTabControl.ResumeLayout(false);
this.ModelTabPage.ResumeLayout(false);
this.ModelTabPage.PerformLayout();
this.TriangleTabPage.ResumeLayout(false);
this.TriangleTabPage.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabControl OccludeModelTabControl;
private System.Windows.Forms.TabPage ModelTabPage;
private System.Windows.Forms.TabPage TriangleTabPage;
private System.Windows.Forms.Button TriangleGoToButton;
private System.Windows.Forms.TextBox TriangleCenterTextBox;
private System.Windows.Forms.Label label31;
private System.Windows.Forms.Button TriangleDeleteButton;
private System.Windows.Forms.Button TriangleAddToProjectButton;
private System.Windows.Forms.Button ModelDeleteButton;
private System.Windows.Forms.Button ModelAddToProjectButton;
private System.Windows.Forms.TextBox TriangleCorner3TextBox;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox TriangleCorner2TextBox;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox TriangleCorner1TextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox ModelFlagsTextBox;
private System.Windows.Forms.Label label4;
}
}

View File

@ -0,0 +1,245 @@
using CodeWalker.GameFiles;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CodeWalker.Project.Panels
{
public partial class EditYmapOccludeModelPanel : ProjectPanel
{
public ProjectForm ProjectForm;
public YmapOccludeModel CurrentOccludeModel { get; set; }
public YmapOccludeModelTriangle CurrentTriangle { get; set; }
private bool populatingui = false;
public EditYmapOccludeModelPanel(ProjectForm owner)
{
ProjectForm = owner;
InitializeComponent();
}
public void SetOccludeModel(YmapOccludeModel model)
{
CurrentOccludeModel = model;
CurrentTriangle = null;
Tag = model;
LoadOccludeModel();
LoadTriangle();
UpdateFormTitle();
OccludeModelTabControl.SelectedTab = ModelTabPage;
}
public void SetOccludeModelTriangle(YmapOccludeModelTriangle tri)
{
CurrentTriangle = tri;
CurrentOccludeModel = tri?.Model;
Tag = tri?.Model;
LoadOccludeModel();
LoadTriangle();
UpdateFormTitle();
OccludeModelTabControl.SelectedTab = TriangleTabPage;
}
private void UpdateGraphics()
{
var m = CurrentOccludeModel ?? CurrentTriangle?.Model;
if (m == null) return;
if (ProjectForm?.WorldForm == null) return;
ProjectForm.WorldForm.UpdateOccludeModelGraphics(m);
}
private void UpdateFormTitle()
{
Text = "OccludeModel: " + (CurrentOccludeModel?.Index.ToString() ?? "(none)");
}
private void LoadOccludeModel()
{
if (CurrentOccludeModel == null)
{
////Panel.Enabled = false;
ModelAddToProjectButton.Enabled = false;
ModelDeleteButton.Enabled = false;
ModelFlagsTextBox.Text = string.Empty;
}
else
{
populatingui = true;
var m = CurrentOccludeModel;
////Panel.Enabled = true;
ModelAddToProjectButton.Enabled = !ProjectForm.YmapExistsInProject(CurrentOccludeModel.Ymap);
ModelDeleteButton.Enabled = !ModelAddToProjectButton.Enabled;
ModelFlagsTextBox.Text = m.Flags.Value.ToString();
populatingui = false;
//if (ProjectForm.WorldForm != null)
//{
// ProjectForm.WorldForm.SelectObject(CurrentOccludeModel);
//}
}
}
private void LoadTriangle()
{
if (CurrentTriangle == null)
{
////Panel.Enabled = false;
TriangleAddToProjectButton.Enabled = false;
TriangleDeleteButton.Enabled = false;
TriangleCenterTextBox.Text = string.Empty;
TriangleCorner1TextBox.Text = string.Empty;
TriangleCorner2TextBox.Text = string.Empty;
TriangleCorner3TextBox.Text = string.Empty;
}
else
{
populatingui = true;
var t = CurrentTriangle;
////Panel.Enabled = true;
TriangleAddToProjectButton.Enabled = !ProjectForm.YmapExistsInProject(CurrentTriangle.Ymap);
TriangleDeleteButton.Enabled = !TriangleAddToProjectButton.Enabled;
TriangleCenterTextBox.Text = FloatUtil.GetVector3String(t.Center);
TriangleCorner1TextBox.Text = FloatUtil.GetVector3String(t.Corner1);
TriangleCorner2TextBox.Text = FloatUtil.GetVector3String(t.Corner2);
TriangleCorner3TextBox.Text = FloatUtil.GetVector3String(t.Corner3);
populatingui = false;
//if (ProjectForm.WorldForm != null)
//{
// ProjectForm.WorldForm.SelectObject(CurrentTriangle);
//}
}
}
private void TriangleGoToButton_Click(object sender, EventArgs e)
{
if (CurrentTriangle == null) return;
if (ProjectForm?.WorldForm == null) return;
ProjectForm.WorldForm.GoToPosition(CurrentTriangle.Center, CurrentTriangle.Box.Size * 2.0f);
}
private void TriangleAddToProjectButton_Click(object sender, EventArgs e)
{
if (CurrentTriangle == null) return;
if (ProjectForm == null) return;
ProjectForm.SetProjectItem(CurrentTriangle);
ProjectForm.AddOccludeModelTriangleToProject();
}
private void TriangleDeleteButton_Click(object sender, EventArgs e)
{
ProjectForm.SetProjectItem(CurrentTriangle);
ProjectForm.DeleteOccludeModelTriangle();
}
private void ModelAddToProjectButton_Click(object sender, EventArgs e)
{
if (CurrentOccludeModel == null) return;
if (ProjectForm == null) return;
ProjectForm.SetProjectItem(CurrentOccludeModel);
ProjectForm.AddOccludeModelToProject();
}
private void ModelDeleteButton_Click(object sender, EventArgs e)
{
ProjectForm.SetProjectItem(CurrentOccludeModel);
ProjectForm.DeleteOccludeModel();
}
private void ModelFlagsTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentOccludeModel == null) return;
uint.TryParse(ModelFlagsTextBox.Text, out uint f);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentOccludeModel.Flags != f)
{
CurrentOccludeModel.Flags = f;
ProjectForm.SetYmapHasChanged(true);
}
}
}
private void TriangleCenterTextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentTriangle == null) return;
var v = FloatUtil.ParseVector3String(TriangleCenterTextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentTriangle.Center != v)
{
CurrentTriangle.Center = v;
UpdateGraphics();
ProjectForm.SetYmapHasChanged(true);
ProjectForm.WorldForm?.SetWidgetPosition(v);
}
}
}
private void TriangleCorner1TextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentTriangle == null) return;
var v = FloatUtil.ParseVector3String(TriangleCorner1TextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentTriangle.Corner1 != v)
{
CurrentTriangle.Corner1 = v;
UpdateGraphics();
ProjectForm.SetYmapHasChanged(true);
ProjectForm.WorldForm?.SetWidgetPosition(CurrentTriangle.Center);
}
}
}
private void TriangleCorner2TextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentTriangle == null) return;
var v = FloatUtil.ParseVector3String(TriangleCorner2TextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentTriangle.Corner2 != v)
{
CurrentTriangle.Corner2 = v;
UpdateGraphics();
ProjectForm.SetYmapHasChanged(true);
ProjectForm.WorldForm?.SetWidgetPosition(CurrentTriangle.Center);
}
}
}
private void TriangleCorner3TextBox_TextChanged(object sender, EventArgs e)
{
if (populatingui) return;
if (CurrentTriangle == null) return;
var v = FloatUtil.ParseVector3String(TriangleCorner3TextBox.Text);
lock (ProjectForm.ProjectSyncRoot)
{
if (CurrentTriangle.Corner3 != v)
{
CurrentTriangle.Corner3 = v;
UpdateGraphics();
ProjectForm.SetYmapHasChanged(true);
ProjectForm.WorldForm?.SetWidgetPosition(CurrentTriangle.Center);
}
}
}
}
}

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>
AAABAAMAICAAAAAAGACoDAAANgAAABAQAAAAABgAaAMAAN4MAABAQAAAAAAYACgyAABGEAAAKAAAACAA
AABAAAAAAQAYAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAP//////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////v8/u3v+Pn6//7+////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//7+/vX3/rzA3OHl9fz9////////////////////////////////////////////////////////////
//////////////////////////////////////////////////7//+zv+3Z6qcLI5Pr7////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////7+/+br+15in6+33vf5//////////////////7+//7+////////////////////
//////////////////////////////3+//v8//v8//3+//////////////////////7+/+Ho+1dana20
4/b4//////////z9//P2/+Tp/ezw/vz9//////////////////////////////////////////7///X4
/9Pa+tPa+/H1//z9//////////////////7+/93k+SsscaSr3PX3//////7+//L1/7W98AcWgrvC8Pj6
//////////////////////////////////////////7+/+bs/xohiAEJdrvF9+7y//z9////////////
//7+/9rh+CEkapmh0/T3//////j6/9HZ/AEHcgEEb9LZ+/r7////////////////////////////////
//////////7//+/z/3F+zAAAXwQLcZai3fb4//////////////3+/97l/E9Tmaau4fT3/////+/0/1dd
sAAAV7a/8/H1//7+//////////////////////////////////////////////r8/+jv/46Y3QUUf6Ot
5PX4//////////////3+/9zj+3Z6wLe/7fX4//////D0/212xnaAzerw//z9////////////////////
//////////////////////////////////v8/+/z/+Dm+/D0//z9//////////7+//j6/9Pd+UhLjb/H
9/D0//3+//n7/+nt/+jt//n7////////////////////////////////////////////////////////
//7///7+//7+//7+//////////r8/+7z/83W+ImU2A0UdFNarr/K9env//X4//z9//3+//7/////////
//////////////////////////////////////////////////////////////////7///j6/+Pq/255
xhckjE5XsVVftUlTqwAKeTA9nr3H8+7z//v8////////////////////////////////////////////
//////////////////////////////7+//b4/9Tc+Sc0mRonj8rV/crX/ZSb48rX/brG8wwWgQAEdJei
4efu//n7//7+//z9//z9//z9//z9//3+//////////////////////////////3+//f5/+3y/+nv/+ft
/8vV+io2mImU2M7c/7vG9yIvlQAOfCg4mM3Y/s/c/4aR1AQRfGtzwtni/ebt/9vi/tri/tXd+9Tc+O3x
/vz9//////////////////////////n6/87V+FVftkRPrFlnvSEqjQoUfmJvwWFvvg0TfQQIcxEchwAD
cy89n19rvVVitQwZgwAAaiMrkT9NqTVBoiw3mhQihig1mNLX+fv8//////////////////////////b5
/52l4EFLqoCK03yF0VBctGhyw52o5GVrvQAAaneBzsHM+jA3mhYgiTtIpJOf3ouW2AAAbmh0wbbA8bS+
7qiz5pCb16+56e/z//3+//////////////////////////v8//H1/+vw/+zx/+nv/7/J9YqP3MbP/8LM
+hwqkFZftaCp5EhRrcTQ+9jj/8rW/UJMqn6J0ebt//X3//f5//b4//X3//f5//z9////////////////
//////////7+//z9//3+//////////3+/+7z/6at64iP3aWs7XN8zRIfhyUykp2o5MHM+oKM0xonjY6X
2+jv//v8//////7+//n7//b5//r7//7///////////////////7+//f5/+rw/9Pa9fL0/v7/////////
//v8//H1/+Tr/7i/91liu0NPq0VQrS06m0NNqDdCoYqU1+nv//v8//////////n7/9zi/qSt59ri/fL1
//v8//7///////z9//D0/8rT+h0sjkVQrPD0//////////////////////z9/+7z/8LL9Jqk4aGq6LW/
8c3W9+Xs/vH1//v8//////////////f5/6at5gAAbxIfh6u16+Po/fr7//////b5/6ev5gAIeAAPernC
8fX4//////////3+//v8//z9//////3+//j6//P3//P2//b4//r8//7+//7+//v8//r8//3+//////v8
/+Xr/nuIzwAAbBseg5Sb2fb5//////f5/8DF8pWe3d/n/vT3//39//////v8/+zx/87V9+3x/v3+////
//3+//j6//X4//v8//////////n7/+Dm/snR9fD0//39//z8/fv8/+3y/8LK9aGq4dfd9/n7//////z9
//b5//X4//v8//////////7+/+7z/4aP1gEPet7k/f39//////f5/83U+ZCZ2u3x/v7+//////P3/215
wgAJd7fB8/L1//7+//////3+//j6//f5//r8//7+//////////////////////////////j6/87W/AAA
X2duue3y//7+//////D0/05asBQfidzj/P39//////X4/6Su6AAAXBccgtff/vv8////////////////
//////////////////////////////////////P3/3F8xhYli9Xe/fn6/////////+3y/1pltQAJd9be
/fv8//////z9/+rw/36I0Bknjs/W+vv8////////////////////////////////////////////////
//////f5/8HI7tnf+/X4//7+/////////+/0/3R7xgAAb9ng/Pz9//////////n7/+Ln/dLY+fP2//3+
//////////////////////////////////////////////////////3+//r7//v8//7+////////////
//b4/7/F84eP0e/0//7+//////////7+//z9//v8//3+////////////////////////////////////
//////////////////////////////////////////////////z9//b5//X4//v8////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////w////4
P///+D////g8//D4MH/geCB/4Dggf+A4IH/wOCD/+DAB//hgAf//gAP//wAAB/AAAAPwAAAD8AAAA/AA
AAfjAAEHgYADAQPgBwEDEAEBAghgAQwIIEH8CCB//Bggf/wYMH/8ODD///h/////////////KAAAABAA
AAAgAAAAAQAYAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///+vv/fL1/v///wAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4+Vx7/F5v///wAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAP///4CHtrS62////////////////////wAAAAAAAAAAAP////H0/vf6/v//
/////////4yTwrrB4f///+zw+7rA6P39/////wAAAAAAAAAAAP///56l2BkcguXr/P///////42Uw8jO
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
AAAAAAAA////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////v7//f7//P3//P3//P3/
/f7//v7/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v7//P3/
+fv/+fv/+Pr/+fv/+vv//P3//v//////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////f7/+fr/8/b/7PL/5+3/6e/+9Pf/+vv//v7/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////P3/9/r/6O7/cXe1UVaet7z17fL/+Pr//f3/////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////+/z/9Pj/4Oj/NzyCUlOd2dz/6O//9Pf//P3/////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////+vv/8vb/2+P9X2OmREGLnqPd
4+v/8vb/+/z/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////+vv/8fb/
1N35bXK1JSRtbHGz5O7/8fX/+/z/////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////+vv/8PX/3Ob/U1eaDwtXjZLT4+z/8fX/+/z/////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////+vv/8fb/2eP+MjR6AAA+c3i34Or/8fX/+/z/////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////+vv/8vb/1d/7MS91AAA1UFSS4On/8vb/+/z/////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////+vv/8fb/2OL+NjZ7AAArX2Ok
4uz/8fX/+/z/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////+vv/8fb/
2eP/LjJ1DAxKfYTE4Or/8fX/+/z//////////////////////////////v7//v7//f7//f7//v7//v//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////+vv/8PX/3OX/gILIR0eVeoHC3eb/8fX/+/z//////////////////////v7//P3/+fv/+Pr/
+Pr/+Pr/+vv//P3//v7/////////////////////////////////////////////////////////////
/////////////////////////////v7//f7//P3/+vv/+vv/+/z//f3//v7/////////////////////
////////////////////////+vv/8PX/2eP9ZWeqHx1obnOz4Or/8fX/+/z//////////////////v7/
+/z/9fj/8vb/8PX/7vT/8fb/9fj/+fr//f7/////////////////////////////////////////////
/////////////////////////////////////////v///P3/+Pr/9fj/9fj/9Pj/9Pf/9vn/+/z//v7/
////////////////////////////////////////+vv/8fb/2eP9ODp9AAA5jZDQ5O7/8PX/+/z/////
/////////v7/+/z/9Pf/7fP/5u//wsz6j5XfuMDx7fL/9vn//P3/////////////////////////////
/////////////////////////////////////////////////////////f7/+Pr/8/b/5+3/2eH/2uP/
5u3/7fP/8/b/+vv//f7/////////////////////////////////////+vv/8PX/3ef/U1ebBgVKio/O
4uz/8fX/+/z//////////v///P3/9fj/7fP/4uv/hIzZHSWPAABmU1i14ub/9/r/+/z/////////////
/////////////////////////////////////////////////////////////////////////P3/9Pf/
7/X/09z/TlSzNzWYj5bh5O7/6/L/8vb/+fv//f7/////////////////////////////////+vv/8fX/
2eP/QUWIEhBZbnSz3uj/8fb/+/z//////////f7/+Pr/7/T/6PH/iI7cAABvAABqAABncXjK6O//9fj/
+/z/////////////////////////////////////////////////////////////////////////////
////////+/z/8/f/2uD/Z27EAABnAABiBgl4jJTd5vD/6O//8vX/+fv//f7/////////////////////
////////+vv/8fb/2OP/Mjd6AQE6ZGup4er/8fX/+/z/////////+vz/8fX/6/T/xM/8ExyJAABwAABu
GySRxc387fT/9ff//P3/////////////////////////////////////////////////////////////
////////////////////////+vz/8/f/1Nr/MzqhAABhAxOBAARyBgp5jpLg5Oz/7PP/9Pf/+vz//v7/
////////////////////////+vv/8fb/2eP/KCtvBwZOjJHS4Or/8fX/+/z//////f7/9/n/7fP/3+j/
UFq3AABtAAZ3BAh6mZ/n5vD/7vP/+Pr//v7/////////////////////////////////////////////
////////////////////////////////////////+/z/9Pj/6e//sbb1KzWcAABwBhaBAAFyAgp6fITR
1d777/T/+Pr//f7/////////////////////////+vv/8PX/3+j/WF2hBglTnaTj5O3/8PX/+/z/////
/P3/9Pf/6vL/k5riAAByAAR0AABrY2vE4ur/6vH/9ff//P3/////////////////////////////////
/////////////////////////////////////////////////////////f3/9/n/7fL/5O3/ytX/RU6w
AABpAA5+AABuAABnhord6e7/+fv//f7/////////////////////////+vv/7/T/3+j/k5jbT1KdgYjJ
3uf+8fX/+/z/////+/z/9fn/4ef/NDqhAABnAABrJjCU0Nn/5/D/8fX/+vv//v7/////////////////
/////////////////////////////////////////////////////////////////////////v7/+/z/
9vn/7vP/6vP/ztb/O0CmAABpAABrQkuoxMn57PH/+Pr//f7/////////////////////////+vv/8PX/
2+X/en/CUFGak5nY3+j/8fX//P3//////P3/9fj/4en/i5DbNT2hIyuTpqzv4uz/7vP/9/n//f7/////
////////////////////////////////////////////////////////////////////////////////
/////////////v7//P3/9vn/7/P/6vL/ytH/X2i9XWi7wsf/6e//8/f/+Pr//v7/////////////////
////////+vv/8PX/3OX/WF2hW1ylvMD+3uf/8PX/+/z//////f7/9vn/7fP/4uj/j5Pgf4LV3+X/6fD/
9Pf//P3/////////////////////////////////////////////////////////////////////////
/////////////////////////////////v///P3/+Pr/8vX/7fP/5+//5u7/6vD/8PT/9vn//P3//v7/
/////////////////////f7/9/n/7fP/0tz9LDJzNjh/nqTk2uT/7fL/9/n//f7//f7/+fv/8/b/7PL/
3eX/zM//5ev/9fj/+fv//v7/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////v///f3/+vv/9/n/9vn/9fj/9vn/
+fr//P3//v7//////////////v///f7/+vv/9vn/7/T/5vD/2Ob/VFubERNdoajk4u//5O7/7vP/9vj/
+fr/+vv/+Pr/9fj/9Pj/9fj/9fj/+Pr//P3/////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v///v7/
/f7//P3//P3//f3//v7//v///////////////f7/+vz/9vn/8fX/7vT/5O3/3eb/z9n/cHjICxN5d37L
z9n/2eP/5O3/6/L/8PT/9Pf/9/n/+vv/+vv/+/z//P3//f3//v7/////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////P3/+Pr/8/b/7vT/6vL/z9r+jZjeQUeq
IiuQCBN3AAFrBRB8Nj2iUViym6XlydH/4+z/6/L/8PT/9/n/+/z//f7//v//////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////f3/9/n/8fX/6/L/3uf/
mKTkLzibAABoAAB0Fx+HDBh7FSGDAg16AABYAABlCBB/Ji2UhYza1+D/6PL/7fL/9Pf/+vv//f7/////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////v7//P3/9/n/
8PT/7PT/z9j/XmO+AABtAABcMDSXoajsu8X7VV+5hYzblZ/fTVSxFSKMAABkAABnAAN2Qkmpsbrz5e3/
6vH/8fX/+Pr//P3//v//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////P3/9/n/8PX/7PT/vcn3LTOZAABaAgR1ZWzD0Nf/5vL/1OP/l53lzs3/6fP/4+7/sLzwZ23CBxSD
AABnAABlHiaSmqHo3+j/5+//7/T/9vn//P3//v7/////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////v7/
/v7//v7//v7//f7/+/z/9vj/7vP/7PX/tcLzEBeGAABkPEWlqLPt2eX/4e7/3On/uMX1gofVe3vPhYzY
z93+5/X/4e3/lJ3gHiOPAABtAABqChiEbHLIytD/5/D/7PL/8/f/+Pr/+fr/+Pr/+Pr/+Pr/+Pr/+Pr/
+Pr/+fv/+vv/+/z//f7//v7/////////////////////////////////////////////////////////
/v7//f7/+/z/+fv/9/n/9vj/9fj/9Pf/8fX/7PL/4uv/l6HgDhF7AAN4iZDe0d7/3uz/4vD/w83/VVm3
ICiSAAFyAABlAABwaHTD1N//2un/3er/w838ZW3BEyOJJzKVAQ16NDmfwsn75fD/5u7/7PL/7vP/7fP/
7fP/7fL/7fP/7vP/7/T/8fb/9Pj/9vn/+fr//f3//v//////////////////////////////////////
/////////////v7//P3/+Pr/9Pf/8fX/7vT/7PL/6/L/6fH/5u7/6vX/tsD0CQx4AAFwkZvi7ff/4vD/
4fD/z9j/OkGlAABiAABwBxWAAAt7BBN+P0uofYLUztb/4O7/6fb/6fP/qa7xQkyoBg56AABqMjugx8/+
5fH/4Ov/4On/3uj/3eb/3+j/3uj/1+L/0d3/1d7/3+f/7fL/9vj/+vz//v7/////////////////////
/////////////////////////////f7/+fr/8/f/6/L/2d//v8j6vcf5ucP1wMv8wM3+vMj6PkqoAABo
UF25usP7tsPyvsr6sLrwQ0utAABqAAV1OUameIDRKDWZAAd2GyeOLDecmaHntsL0pbLom6riq7LzUlu0
AANzBhR/AAZ0NT+ja3bBY2i/XGG6UViyWl65XGG7XGC6TVWvQU6pPkalODygqK7p8vb/+vz//v7/////
/////////////////////////////////////////////P3/9/n/7/T/wcj2R0ysExeFERmGDxuIFB6K
FBqICxSEAABsAAByDBiDCRSBBRCADhaFCRODAAh4AxF/AAl4CxeDHSaPAAp6AAN0AA19AAd3CBOBEBqH
BhGBAAh5AABwAAByAAh5BhSCAxWCAABsAABvAABlAABnAABxAABjAABmAABhAABdAABYAABhCAt/q7Lr
8/f/+vv//v7//////////////////////////////////////////////////P3/+fv/3uT/SE2vAABn
CBB/GiCMLzmfLTWcGByJFRyKGCOOMj2gHymRDxiGGyOPLDCXBRF/AAh3BhaCEyKMICqTKC2WNDqfIzCV
Awx6Eh+JHiaPAAR3AAZ5CxSDICWQX2q7Q1CqAA1+AAFxDxuHiZTbVGC4dHnQnabrTVqzY23EUV62Slau
LjaZXWm9sLjz5ez/9vn/+fv//v7//////////////////////////////////////////////////P3/
+Pv/4+n+e4LPfoPVpqv2vsf/zNX/zdb/xtH/v8v8pK7spKfysLb3vcr4ws784ej/hI/YAAZ1AAJzVF25
yM//3Of/5+//i5LcAABpMzyfp6vxoKznlqHhqbbtx9H/8fz/kpvfAABiAABph4zc5PD/2OP/193/3un/
1+D/2OH/1+D/0Nr/zNL/3+j/6/L/7/T/9vn//P3//v//////////////////////////////////////
/////////////f7/+Pr/9Pf/6vD/5u3/3+b/4uv/6PD/5+//5O3/5/P/sL3sXmS7mZzoz9f/3+z/4e//
mKLiEiKKCBF/KTWZr7T06/f/3ev/VF2zChSBipPcz9v+4u7/3ur/3ev/5/X/qrPrISmSDRJ2Xmq/3ur/
4uv/6vH/7fP/7fL/7/T/7vP/7fP/7fP/8PX/8fX/9Pf/+Pr/+/z//v7/////////////////////////
/////////////////////////////v7//P3/+Pr/9vn/9Pf/8vb/8vb/8/b/9Pf/7/T/6/L/tL/ubXLH
en/Ti43gqavy0t3/nafjMj6fJzaaAAV1GyeOYmW7Nz6fAABgNj6i1N//3uz/2uX/3Oj/5PH/wcj7FR2J
AAN0gong0tr/6fH/7/P/9vj/+Pr/+fv/+fv/+Pr/+Pr/+Pr/+fv/+vv//P3//f7//v//////////////
/////////////////////////////////////////////////v7//f7//P3/+/z/+/z/+/z//f3//f7/
+fv/8fX/5Oz/jpbfc3jObnXLcXfOk5rks7b4iY3dR1KvDhuEAABoAABlEBV9U12ytcD13Or/3en/3ej/
1eL/q7fvGR+MKDKZbnnNxc/76PD/8fX/+fr//f7//v///////v7//f7//f3//P3//f3//f7//v//////
/////////////////////////////////////////////////////v7//f7//P3//P3//f7//v7/////
/////////////////f7/9vn/7/T/yNH5lJrleoDVmZ3pmpzpc3nPfoTWf4bYVFy3HSaLZ3PGsrb8v8r8
y9n9q7jre4LRf4fUgIvXAwZ1AABrhYjb0NX/6PH/8PX/+Pr//f7//////////v///f3/+vv/+Pr/9/r/
9/n/+Pr/+/z//f7//v7//////////////////////////////////////v///f7/+/z/+fr/9vj/9/n/
+vz/+vv/+/z//v7//////////////////v7/+vz/8/f/7PL/2uT/t8H1srP6vcH+nKTnSlOxV2C7TVaz
WGS8QUqmSlSuSFOtR1GtbXTKVl23ARB5AAh2AABnd33P3eP/4ur/7/T/9/n//P3//////////////P3/
9/n/8vb/7PH/6fD/7PL/7vP/8vb/9vn/+/z//f7//////////////////////////////v7/+/z/+Pr/
8/b/7/T/8Pb/6vH/3eP97vL++fr//P3//////////////////////f7/+vv/9fj/7/T/5+//z9f+t7v4
uLn9Z2zFLzucFCGIMz6gGCCMAAd4AAl2Dx2EER+GXWK8c3XLKzKXd4LP4er/6/L/8PX/9/n//P3//v//
/////////v7/+fv/8/b/7PP/y9H/i4/erLbt4er/5e3/7fP/8/b/+fv//f3//v7/////////////////
/v7/+/z/9vj/8PT/6/L/3+n/x9H9aHTAZGvG3+b9+Pr/+/z//////////////////////////v7/+/z/
+Pr/8vb/6/H/3OX+wMn4maDmdHrPWGG6T1a1eoHWcHfOTlayUlq1SlKubHjAxMj/0dn/4+v/7PL/8vb/
+Pr//P3//v7//////////////f7/+fr/7vP/xsv5YGXAHymRKjKYYWS9rbLz4u3/6/P/8vb/+fr//f7/
/////////////v//+/z/9vj/7fL/5e3/xs7/Y23BIiiSAABeLTab3+b/9/r/+/z/////////////////
/////////////////f7/+vz/9vj/8PX/6vH/3eb/ydL8xM/6uMPyt733w8j/zNb/1Nz/3OT/4uz/5u7/
7fP/8vb/9vj/+vz//f7//////////////////////f7/+fv/7vP/jpHiAAJ1CxaBER6GAABoFRmGbXbH
0Nf/7PL/9fj//P3//////////////v7/+fv/8/f/4Of/hYvbKDGZAABuAABdAAZyi5La5+7/9vn/+/z/
/////////////////////////////////////v7//P3/+fv/9ff/8vb/7/X/7fP/6/L/5u3/5ez/6fD/
7PP/7/T/8fX/9Pf/9/n/+vv//P3//v7//v///////////////////////v7/+fv/8fb/2eH9fIbQExqH
AABrAAp6AAFyAABwS0+uztX39vn/+vz//////////////f7/+Pr/8ff/qbLpAABrAABhAABwDBWAfobX
5e3/8PX/9vn//f3//////////v///f7/+/z/+vv/+vv/+vz//P3//v7//v///v7//P3/+vz/+Pr/9/n/
9vj/9vj/9vj/9vj/9/n/+fr/+/z//P3//f7//v7//f7//P3/+/z/+vz/+/z//P3//v7//////v7/+/z/
9fj/7/T/5/H/uML1U1e1AAh5AABuAABvMjmdv8bz9vr/+vv//////////////f7/+fv/7/T/iY7aDxSA
GiONa3XHsr7w4Oj/6/H/9Pf/+vz//v7//////v///P3/+Pr/9Pf/8/f/9fj/9fj/9vn/+/z//v7/////
/////////v7//f7//P3/+/z/+/z//P3//f7//v///////////////v7/+/z/9/n/9vn/9vn/9Pj/9vn/
+/z//v7//////f7/+vz/9fj/7/T/6vL/3ef/i5PbGRqJBQl5jJbZ6vH/9Pj/+/z//////////////f7/
+fv/8fT/1Nn9t7/0wcr54er/7fT/8fX/9fj/+vv//f7//////////f3/+Pr/8PT/6/L/3uX/ztb/5Or/
8/f/+Pr//f7//////////////f7/+vz/+Pr/+fv/+fv/+vv//f3//v///////////////P3/9/n/7vL/
193/ztf/5u3/7vP/9Pf/+/z//v7//////v7//P3/+Pr/8fX/7PP/5/D/sLfxoKnk4+r/8vf/9/n//f3/
/////////////v7/+/z/9vn/9Pf/8vb/8fb/8fX/9Pf/+Pr//P3//v7//////////v7/+vv/8vb/5+7/
y9H/WWO9KSmSkZXj6vD/+Pv//P3//////////f7/+Pr/9fj/8vb/6O7/7vP/9fj/+Pr//f7/////////
/v//+vv/8vb/7PP/hYraKiqKlp7i6PD/7fP/9ff/+/z//v7//////////f7/+vv/9ff/8fX/8PX/8vb/
8/f/9vn/+/z//v7//////////////////f7/+/z/+vv/+fr/+fr/+vv//P3//v7/////////////////
/P3/9fj/7PL/1d7/RUysAABhAABlg4ja6/D/+Pr//P3/////////+/z/9fj/6e7/2eD/h4/bnaXg7PH/
9fj/+/z//////////v7/+Pr/8PX/y9X1JDGVAABaERWDoKnp6PH/7vP/9/n//P3//////////////v7/
/P3/+vv/+fv/+fv/+vv//P3//v7//////////////////////////v7//v7//v7//v7//v//////////
/////////////v7/+fv/8PX/7PX/ipPdAABsAABlQ1Cp3Ob/7vP/9/n//f7/////////+fv/9Pj/yNH5
Ule2DBJ8Ljie0df+8fb/+fv//v7//////v7/+Pr/7/X/hY3YAABxAAl7AABuEBaEs7nz6fH/8fX/+vv/
/v7//////////////////v///v7//v7//v7/////////////////////////////////////////////
/////////////////////////////f3/9vn/7PL/0tn/LzidAQFsAAB0iZHb6vP/8PT/+fv//v//////
/v7/+Pr/8vf/r7rqAAV4AABdPUen1N//7PL/9vn//f7//////v7/+fr/7/T/yc75S1G0AABrARKAAABp
Qker0df/7fP/9/n//f7/////////////////////////////////////////////////////////////
/////////////////////////////////////////////P3/9/n/5+7/cXXNAAd2AABuMDebzdT97PL/
9vj//P3//////////v7/9/n/7/X/tL/uFCCLAABqHSqRvcf46fD/9Pf//f3/////////+vv/8vX/6vH/
yM3+JC2XAABtAAV2Agx9q7Ly7vT/9vn//f7/////////////////////////////////////////////
/////////////////////////////////////////////////////////////P3/9/r/4uj/WWO1AAVx
KTaYu8T07fT/8vb/+vv//v7//////////v7/9/n/7vX/vsn1Iy2SAABrAQ99mp/o6PD/9Pf//P3/////
/////P3/9/n/7vP/6fL/s7z2DBB/AABeQ0uttrr56e7/+Pr//f7/////////////////////////////
/////////////////////////////////////////////////////////////////////////////P3/
+fv/4ef6g4zNbXfFw8v27fT/8vb/+Pr//f3//////////////v7/9/n/7vT/yNL7MjucAABtBxF/nKLo
6fH/9Pf//P3//////////v7/+/z/9fj/7fL/6/T/jZXbLzScrrP14en/7fL/+fv//v7/////////////
////////////////////////////////////////////////////////////////////////////////
/////////////f7/+vz/8PP91dr34+f/8vb/8/f/9/r//P3//v///////////////v7/+Pr/8PX/1N3/
QUqmAQRxBQ98m6Dm7PL/9fj//P3//////////////v7/+/z/9ff/8PX/5ez/ytH94ej/8vb/9vj/+/z/
/v7/////////////////////////////////////////////////////////////////////////////
/////////////////////////////v7//P3/+vz/+fv/+Pr/+Pr/+vv//f3//v//////////////////
/v//+fv/9Pf/2+L/SVGtAABsLTaZytL58fX/9/n//f7//////////////////v7/+/z/9/n/9fj/9vn/
9fj/9vj/+vz//f7/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////v7//f7//f3//f3//f3//v7//v//////
////////////////////+/z/9vn/6e//mZ7gTVarr7bp6/H/9fj/+vv//v7/////////////////////
/v7//f7/+/z/+/z/+/z//P3//v7/////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////f3/+Pr/9fj/6e7/4+n/8fb/9Pf/+Pr//f3/////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////v7//P3/+fv/+fv/+vv/+Pr/+vv/
/P3//v7/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////v7//f7/
/f3//P3//f7//v7//v//////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///////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
////+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

@ -325,17 +325,9 @@ namespace CodeWalker.Project.Panels
private void CalcYmapExtents()
{
if (populatingui) return;
if (Ymap == null) return;
var allents = Ymap.AllEntities;
var allbatches = Ymap.GrassInstanceBatches;
if ((allents == null) && (allbatches == null))
{
MessageBox.Show("No items to calculate extents from.");
return;
}
lock (ProjectForm.ProjectSyncRoot)
{
if (Ymap.CalcExtents())

View File

@ -268,6 +268,32 @@ namespace CodeWalker.Project.Panels
llnode.Tag = lodlight;
}
}
if ((ymap.BoxOccluders != null) && (ymap.BoxOccluders.Length > 0))
{
var boxocclsnode = node.Nodes.Add("Box Occluders (" + ymap.BoxOccluders.Length.ToString() + ")");
boxocclsnode.Name = "BoxOccluders";
boxocclsnode.Tag = ymap;
var boxes = ymap.BoxOccluders;
for (int i = 0; i < boxes.Length; i++)
{
var box = boxes[i];
var boxnode = boxocclsnode.Nodes.Add(box.ToString());
boxnode.Tag = box;
}
}
if ((ymap.OccludeModels != null) && (ymap.OccludeModels.Length > 0))
{
var occlmodsnode = node.Nodes.Add("Occlude Models (" + ymap.OccludeModels.Length.ToString() + ")");
occlmodsnode.Name = "OccludeModels";
occlmodsnode.Tag = ymap;
var models = ymap.OccludeModels;
for (int i = 0; i < models.Length; i++)
{
var model = models[i];
var modnode = occlmodsnode.Nodes.Add(model.ToString());
modnode.Tag = model;
}
}
if ((ymap.GrassInstanceBatches != null) && (ymap.GrassInstanceBatches.Length > 0))
{
var grassbatchesnodes = node.Nodes.Add("Grass Batches (" + ymap.GrassInstanceBatches.Length.ToString() + ")");
@ -1040,6 +1066,48 @@ namespace CodeWalker.Project.Panels
}
return null;
}
public TreeNode FindBoxOccluderTreeNode(YmapBoxOccluder box)
{
if (box == null) return null;
TreeNode ymapnode = FindYmapTreeNode(box.Ymap);
if (ymapnode == null) return null;
var boxesnode = GetChildTreeNode(ymapnode, "BoxOccluders");
if (boxesnode == null) return null;
for (int i = 0; i < boxesnode.Nodes.Count; i++)
{
TreeNode boxnode = boxesnode.Nodes[i];
if (boxnode.Tag == box) return boxnode;
}
return null;
}
public TreeNode FindOccludeModelTreeNode(YmapOccludeModel model)
{
if (model == null) return null;
TreeNode ymapnode = FindYmapTreeNode(model.Ymap);
if (ymapnode == null) return null;
var modelsnode = GetChildTreeNode(ymapnode, "OccludeModels");
if (modelsnode == null) return null;
for (int i = 0; i < modelsnode.Nodes.Count; i++)
{
TreeNode modelnode = modelsnode.Nodes[i];
if (modelnode.Tag == model) return modelnode;
}
return null;
}
public TreeNode FindOccludeModelTriangleTreeNode(YmapOccludeModelTriangle tri)
{
if (tri == null) return null;
TreeNode ymapnode = FindYmapTreeNode(tri.Ymap);
if (ymapnode == null) return null;
var modelsnode = GetChildTreeNode(ymapnode, "OccludeModels");
if (modelsnode == null) return null;
for (int i = 0; i < modelsnode.Nodes.Count; i++)
{
TreeNode modelnode = modelsnode.Nodes[i];
if (modelnode.Tag == tri.Model) return modelnode;
}
return null;
}
public TreeNode FindGrassTreeNode(YmapGrassInstanceBatch batch)
{
if (batch == null) return null;
@ -1519,6 +1587,53 @@ namespace CodeWalker.Project.Panels
}
}
}
public void TrySelectBoxOccluderTreeNode(YmapBoxOccluder box)
{
TreeNode boxnode = FindBoxOccluderTreeNode(box);
if (boxnode != null)
{
if (ProjectTreeView.SelectedNode == boxnode)
{
OnItemSelected?.Invoke(box);
}
else
{
ProjectTreeView.SelectedNode = boxnode;
}
}
}
public void TrySelectOccludeModelTreeNode(YmapOccludeModel model)
{
TreeNode modelnode = FindOccludeModelTreeNode(model);
if (modelnode != null)
{
if (ProjectTreeView.SelectedNode == modelnode)
{
OnItemSelected?.Invoke(model);
}
else
{
ProjectTreeView.SelectedNode = modelnode;
}
}
}
public void TrySelectOccludeModelTriangleTreeNode(YmapOccludeModelTriangle tri)
{
TreeNode trinode = FindOccludeModelTriangleTreeNode(tri);
if (trinode != null)
{
if (ProjectTreeView.SelectedNode == trinode)
{
OnItemSelected?.Invoke(tri);
}
else
{
trinode.Tag = tri;//hack to allow the model's node to be selected instead
ProjectTreeView.SelectedNode = trinode;
trinode.Tag = tri.Model;
}
}
}
public void TrySelectGrassBatchTreeNode(YmapGrassInstanceBatch grassBatch)
{
TreeNode grassNode = FindGrassTreeNode(grassBatch);
@ -2024,6 +2139,22 @@ namespace CodeWalker.Project.Panels
tn.Text = lodlight.ToString();
}
}
public void UpdateBoxOccluderTreeNode(YmapBoxOccluder box)
{
var tn = FindBoxOccluderTreeNode(box);
if (tn != null)
{
tn.Text = box.ToString();
}
}
public void UpdateOccludeModelTreeNode(YmapOccludeModel model)
{
var tn = FindOccludeModelTreeNode(model);
if (tn != null)
{
tn.Text = model.ToString();
}
}
public void UpdatePathNodeTreeNode(YndNode node)
{
var tn = FindPathNodeTreeNode(node);
@ -2143,6 +2274,50 @@ namespace CodeWalker.Project.Panels
}
}
}
public void RemoveBoxOccluderTreeNode(YmapBoxOccluder box)
{
var ymap = box?.Ymap;
var tn = FindBoxOccluderTreeNode(box);
if ((tn != null) && (tn.Parent != null) && (box != null))
{
var pn = tn.Parent;
var yn = pn.Parent;
yn.Nodes.Remove(pn);
pn = yn.Nodes.Add("Box Occluders (" + (ymap?.BoxOccluders?.Length.ToString() ?? "0") + ")");
pn.Name = "BoxOccluders";
pn.Tag = ymap;
if (ymap.BoxOccluders != null)
{
foreach (var b in ymap.BoxOccluders)
{
var ntn = pn.Nodes.Add(b.ToString());
ntn.Tag = b;
}
}
}
}
public void RemoveOccludeModelTreeNode(YmapOccludeModel model)
{
var ymap = model?.Ymap;
var tn = FindOccludeModelTreeNode(model);
if ((tn != null) && (tn.Parent != null) && (model != null))
{
var pn = tn.Parent;
var yn = pn.Parent;
yn.Nodes.Remove(pn);
pn = yn.Nodes.Add("Occlude Models (" + (ymap?.OccludeModels?.Length.ToString() ?? "0") + ")");
pn.Name = "OccludeModels";
pn.Tag = ymap;
if (ymap.OccludeModels != null)
{
foreach (var m in ymap.OccludeModels)
{
var ntn = pn.Nodes.Add(m.ToString());
ntn.Tag = m;
}
}
}
}
public void RemoveGrassBatchTreeNode(YmapGrassInstanceBatch batch)
{
var tn = FindGrassTreeNode(batch);

View File

@ -43,6 +43,9 @@ namespace CodeWalker.Project
private YmapEntityDef CurrentEntity;
private YmapCarGen CurrentCarGen;
private YmapLODLight CurrentLodLight;
private YmapBoxOccluder CurrentBoxOccluder;
private YmapOccludeModel CurrentOccludeModel;
private YmapOccludeModelTriangle CurrentOccludeModelTri;
private YmapGrassInstanceBatch CurrentGrassBatch;
private YtypFile CurrentYtypFile;
@ -395,6 +398,27 @@ namespace CodeWalker.Project
(panel) => { panel.SetLodLight(CurrentLodLight); }, //updateFunc
(panel) => { return panel.CurrentLodLight == CurrentLodLight; }); //findFunc
}
public void ShowEditYmapBoxOccluderPanel(bool promote)
{
ShowPanel(promote,
() => { return new EditYmapBoxOccluderPanel(this); }, //createFunc
(panel) => { panel.SetBoxOccluder(CurrentBoxOccluder); }, //updateFunc
(panel) => { return panel.CurrentBoxOccluder == CurrentBoxOccluder; }); //findFunc
}
public void ShowEditYmapOccludeModelPanel(bool promote)
{
ShowPanel(promote,
() => { return new EditYmapOccludeModelPanel(this); }, //createFunc
(panel) => { panel.SetOccludeModel(CurrentOccludeModel); }, //updateFunc
(panel) => { return panel.CurrentOccludeModel == CurrentOccludeModel; }); //findFunc
}
public void ShowEditYmapOccludeModelTrianglePanel(bool promote)
{
ShowPanel(promote,
() => { return new EditYmapOccludeModelPanel(this); }, //createFunc
(panel) => { panel.SetOccludeModelTriangle(CurrentOccludeModelTri); }, //updateFunc
(panel) => { return panel.CurrentOccludeModel == CurrentOccludeModel; }); //findFunc
}
public void ShowEditYmapGrassBatchPanel(bool promote)
{
ShowPanel(promote,
@ -642,6 +666,18 @@ namespace CodeWalker.Project
{
ShowEditYmapLodLightPanel(promote);
}
else if (CurrentBoxOccluder != null)
{
ShowEditYmapBoxOccluderPanel(promote);
}
else if (CurrentOccludeModelTri != null)
{
ShowEditYmapOccludeModelTrianglePanel(promote);
}
else if (CurrentOccludeModel != null)
{
ShowEditYmapOccludeModelPanel(promote);
}
else if (CurrentGrassBatch != null)
{
ShowEditYmapGrassBatchPanel(promote);
@ -769,6 +805,9 @@ namespace CodeWalker.Project
CurrentEntity = item as YmapEntityDef;
CurrentCarGen = item as YmapCarGen;
CurrentLodLight = item as YmapLODLight;
CurrentBoxOccluder = item as YmapBoxOccluder;
CurrentOccludeModelTri = item as YmapOccludeModelTriangle;
CurrentOccludeModel = (item as YmapOccludeModel) ?? CurrentOccludeModelTri?.Model;
CurrentGrassBatch = item as YmapGrassInstanceBatch;
CurrentYtypFile = item as YtypFile;
CurrentArchetype = item as Archetype;
@ -841,6 +880,18 @@ namespace CodeWalker.Project
{
CurrentYmapFile = CurrentLodLight.Ymap;
}
else if (CurrentBoxOccluder != null)
{
CurrentYmapFile = CurrentBoxOccluder.Ymap;
}
else if (CurrentOccludeModel != null)
{
CurrentYmapFile = CurrentOccludeModel.Ymap;
}
else if (CurrentOccludeModelTri != null)
{
CurrentYmapFile = CurrentOccludeModelTri.Ymap;
}
else if (CurrentGrassBatch != null)
{
CurrentYmapFile = CurrentGrassBatch.Ymap;
@ -1571,6 +1622,9 @@ namespace CodeWalker.Project
else if (sel.CollisionBounds != null) return NewCollisionBounds(sel.CollisionBounds.Type, sel.CollisionBounds, copyPosition, selectNew);
else if (sel.EntityDef != null) return NewEntity(sel.EntityDef, copyPosition, selectNew);
else if (sel.CarGenerator != null) return NewCarGen(sel.CarGenerator, copyPosition, selectNew);
else if (sel.LodLight != null) return NewLodLight(sel.LodLight, copyPosition, selectNew);
else if (sel.BoxOccluder != null) return NewBoxOccluder(sel.BoxOccluder, copyPosition, selectNew);
else if (sel.OccludeModelTri != null) return NewOccludeModelTriangle(sel.OccludeModelTri, copyPosition, selectNew);
else if (sel.PathNode != null) return NewPathNode(sel.PathNode, copyPosition, selectNew);
else if (sel.NavPoly != null) return NewNavPoly(sel.NavPoly, copyPosition, selectNew);
else if (sel.NavPoint != null) return NewNavPoint(sel.NavPoint, copyPosition, selectNew);
@ -1596,6 +1650,9 @@ namespace CodeWalker.Project
else if (sel.CollisionBounds != null) DeleteCollisionBounds();
else if (sel.EntityDef != null) DeleteEntity();
else if (sel.CarGenerator != null) DeleteCarGen();
else if (sel.LodLight != null) DeleteLodLight();
else if (sel.BoxOccluder != null) DeleteBoxOccluder();
else if (sel.OccludeModelTri != null) DeleteOccludeModelTriangle();
else if (sel.PathNode != null) DeletePathNode();
else if (sel.NavPoly != null) DeleteNavPoly();
else if (sel.NavPoint != null) DeleteNavPoint();
@ -1613,6 +1670,9 @@ namespace CodeWalker.Project
else if (sel.CollisionBounds != null) SetProjectItem(sel.CollisionBounds, false);
else if (sel.EntityDef != null) SetProjectItem(sel.EntityDef, false);
else if (sel.CarGenerator != null) SetProjectItem(sel.CarGenerator, false);
else if (sel.LodLight != null) SetProjectItem(sel.LodLight, false);
else if (sel.BoxOccluder != null) SetProjectItem(sel.BoxOccluder, false);
else if (sel.OccludeModelTri != null) SetProjectItem(sel.OccludeModelTri, false);
else if (sel.PathNode != null) SetProjectItem(sel.PathNode, false);
else if (sel.NavPoly != null) SetProjectItem(sel.NavPoly, false);
else if (sel.NavPoint != null) SetProjectItem(sel.NavPoint, false);
@ -2439,6 +2499,364 @@ namespace CodeWalker.Project
return CurrentLodLight == lodlight;
}
public YmapBoxOccluder NewBoxOccluder(YmapBoxOccluder copy = null, bool copyPosition = false, bool selectNew = true)
{
if (CurrentYmapFile == null) return null;
Vector3 pos = GetSpawnPos(10.0f);
YmapBoxOccluder bo;
if (copy != null)
{
bo = new YmapBoxOccluder(CurrentYmapFile, copy._Box);
}
else
{
bo = new YmapBoxOccluder(CurrentYmapFile, new BoxOccluder());
//...
}
if (!copyPosition || (copy == null))
{
bo.Position = pos;
}
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
CurrentYmapFile.AddBoxOccluder(bo);
}
WorldForm.UpdateBoxOccluderGraphics(bo);
}
else
{
CurrentYmapFile.AddBoxOccluder(bo);
}
if (selectNew)
{
LoadProjectTree();
ProjectExplorer?.TrySelectBoxOccluderTreeNode(bo);
CurrentBoxOccluder = bo;
ShowEditYmapBoxOccluderPanel(false);
}
return bo;
}
public void AddBoxOccluderToProject()
{
if (CurrentBoxOccluder == null) return;
if (!YmapExistsInProject(CurrentBoxOccluder.Ymap))
{
var box = CurrentBoxOccluder;
CurrentYmapFile = box.Ymap;
CurrentYmapFile.HasChanged = true;
AddYmapToProject(CurrentYmapFile);
CurrentBoxOccluder = box; //bug fix for some reason the treeview selects the project node here.
CurrentYmapFile = box.Ymap;
ProjectExplorer?.TrySelectBoxOccluderTreeNode(box);
}
}
public bool DeleteBoxOccluder()
{
if (CurrentYmapFile == null) return false;
if (CurrentBoxOccluder == null) return false;
if (CurrentBoxOccluder.Ymap != CurrentYmapFile) return false;
//if (MessageBox.Show("Are you sure you want to delete this box occluder?\n" + CurrentBoxOccluder.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes)
//{
// return true;
//}
var delbox = CurrentBoxOccluder;
bool res = false;
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
res = CurrentYmapFile.RemoveBoxOccluder(CurrentBoxOccluder);
//WorldForm.SelectItem(null, null, null);
}
}
else
{
res = CurrentYmapFile.RemoveBoxOccluder(CurrentBoxOccluder);
}
if (!res)
{
MessageBox.Show("Unable to delete the box occluder. This shouldn't happen!");
}
ProjectExplorer?.RemoveBoxOccluderTreeNode(CurrentBoxOccluder);
ProjectExplorer?.SetYmapHasChanged(CurrentYmapFile, true);
ClosePanel((EditYmapBoxOccluderPanel p) => { return p.Tag == delbox; });
CurrentBoxOccluder = null;
CurrentYmapFile = null;
if (WorldForm != null)
{
WorldForm.SelectItem(null);
}
return true;
}
public bool IsCurrentBoxOccluder(YmapBoxOccluder box)
{
return CurrentBoxOccluder == box;
}
public YmapOccludeModel NewOccludeModel(YmapOccludeModel copy = null, bool copyPosition = false, bool selectNew = true)
{
if (CurrentYmapFile == null) return null;
Vector3 pos = GetSpawnPos(10.0f);
YmapOccludeModel om;
if (copy != null)
{
om = new YmapOccludeModel(CurrentYmapFile, copy._OccludeModel);
}
else
{
om = new YmapOccludeModel(CurrentYmapFile, new OccludeModel());
//...
}
if (!copyPosition || (copy == null))
{
//om.Center = pos;
}
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
CurrentYmapFile.AddOccludeModel(om);
}
WorldForm.UpdateOccludeModelGraphics(om);
}
else
{
CurrentYmapFile.AddOccludeModel(om);
}
if (selectNew)
{
LoadProjectTree();
ProjectExplorer?.TrySelectOccludeModelTreeNode(om);
CurrentOccludeModel = om;
ShowEditYmapOccludeModelPanel(false);
}
return om;
}
public void AddOccludeModelToProject()
{
if (CurrentOccludeModel == null) return;
if (!YmapExistsInProject(CurrentOccludeModel.Ymap))
{
var model = CurrentOccludeModel;
CurrentYmapFile = model.Ymap;
CurrentYmapFile.HasChanged = true;
AddYmapToProject(CurrentYmapFile);
CurrentOccludeModel = model; //bug fix for some reason the treeview selects the project node here.
CurrentYmapFile = model.Ymap;
ProjectExplorer?.TrySelectOccludeModelTreeNode(model);
}
}
public bool DeleteOccludeModel()
{
if (CurrentYmapFile == null) return false;
if (CurrentOccludeModel == null) return false;
if (CurrentOccludeModel.Ymap != CurrentYmapFile) return false;
//if (MessageBox.Show("Are you sure you want to delete this occlude model?\n" + CurrentOccludeModel.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes)
//{
// return true;
//}
var delmodel = CurrentOccludeModel;
bool res = false;
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
res = CurrentYmapFile.RemoveOccludeModel(CurrentOccludeModel);
//WorldForm.SelectItem(null, null, null);
}
}
else
{
res = CurrentYmapFile.RemoveOccludeModel(CurrentOccludeModel);
}
if (!res)
{
MessageBox.Show("Unable to delete the occlude model. This shouldn't happen!");
}
ProjectExplorer?.RemoveOccludeModelTreeNode(CurrentOccludeModel);
ProjectExplorer?.SetYmapHasChanged(CurrentYmapFile, true);
ClosePanel((EditYmapOccludeModelPanel p) => { return p.Tag == delmodel; });
CurrentOccludeModel = null;
CurrentYmapFile = null;
if (WorldForm != null)
{
WorldForm.SelectItem(null);
}
return true;
}
public bool IsCurrentOccludeModel(YmapOccludeModel model)
{
return CurrentOccludeModel == model;
}
public YmapOccludeModelTriangle NewOccludeModelTriangle(YmapOccludeModelTriangle copy = null, bool copyPosition = false, bool selectNew = true)
{
if (CurrentYmapFile == null) return null;
Vector3 pos = GetSpawnPos(10.0f);
YmapOccludeModelTriangle ot;
if (copy != null)
{
ot = new YmapOccludeModelTriangle(copy.Model, copy.Corner1, copy.Corner2, copy.Corner3, copy.Model.Triangles?.Length ?? 0);
}
else
{
ot = new YmapOccludeModelTriangle(CurrentOccludeModel, pos, pos + Vector3.UnitY, pos + Vector3.UnitX, CurrentOccludeModel?.Triangles?.Length ?? 0);
//...
}
if (!copyPosition || (copy == null))
{
//om.Center = pos;
}
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
CurrentYmapFile.AddOccludeModelTriangle(ot);
}
WorldForm.UpdateOccludeModelGraphics(ot.Model);
}
else
{
CurrentYmapFile.AddOccludeModelTriangle(ot);
}
if (selectNew)
{
LoadProjectTree();
ProjectExplorer?.TrySelectOccludeModelTriangleTreeNode(ot);
CurrentOccludeModel = ot.Model;
CurrentOccludeModelTri = ot;
ShowEditYmapOccludeModelTrianglePanel(false);
}
return ot;
}
public void AddOccludeModelTriangleToProject()
{
if (CurrentOccludeModelTri == null) return;
if (!YmapExistsInProject(CurrentOccludeModelTri.Ymap))
{
var tri = CurrentOccludeModelTri;
CurrentYmapFile = tri.Ymap;
CurrentYmapFile.HasChanged = true;
AddYmapToProject(CurrentYmapFile);
CurrentOccludeModelTri = tri; //bug fix for some reason the treeview selects the project node here.
CurrentOccludeModel = tri.Model;
CurrentYmapFile = tri.Ymap;
ProjectExplorer?.TrySelectOccludeModelTriangleTreeNode(tri);
}
}
public bool DeleteOccludeModelTriangle()
{
if (CurrentYmapFile == null) return false;
if (CurrentOccludeModelTri == null) return false;
if (CurrentOccludeModelTri.Ymap != CurrentYmapFile) return false;
//if (MessageBox.Show("Are you sure you want to delete this occlude model triangle?\n" + CurrentOccludeModelTri.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes)
//{
// return true;
//}
var deltri = CurrentOccludeModelTri;
bool res = false;
if (WorldForm != null)
{
lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
{
res = CurrentYmapFile.RemoveOccludeModelTriangle(CurrentOccludeModelTri);
//WorldForm.SelectItem(null, null, null);
}
}
else
{
res = CurrentYmapFile.RemoveOccludeModelTriangle(CurrentOccludeModelTri);
}
if (!res)
{
MessageBox.Show("Unable to delete the occlude model triangle. This shouldn't happen!");
}
ProjectExplorer?.UpdateOccludeModelTreeNode(CurrentOccludeModelTri?.Model);
ProjectExplorer?.SetYmapHasChanged(CurrentYmapFile, true);
ClosePanel((EditYmapOccludeModelPanel p) => { return p.CurrentTriangle == deltri; });
CurrentOccludeModelTri = null;
CurrentOccludeModel = null;
CurrentYmapFile = null;
if (WorldForm != null)
{
WorldForm.UpdateOccludeModelGraphics(deltri.Model);
WorldForm.SelectItem(null);
}
return true;
}
public bool IsCurrentOccludeModelTriangle(YmapOccludeModelTriangle tri)
{
return CurrentOccludeModelTri == tri;
}
private void ImportMenyooXml()
{
if (CurrentProjectFile == null)
@ -7043,6 +7461,8 @@ namespace CodeWalker.Project
var ent = sel.EntityDef;
var cargen = sel.CarGenerator;
var lodlight = sel.LodLight;
var boxoccluder = sel.BoxOccluder;
var occludetri = sel.OccludeModelTri;
var grassbatch = sel.GrassBatch;
var collvert = sel.CollisionVertex;
var collpoly = sel.CollisionPoly;
@ -7058,7 +7478,7 @@ namespace CodeWalker.Project
var audiopl = sel.Audio;
Archetype arch = mlo?.Archetype ?? ent?.MloParent?.Archetype ?? ent?.Archetype;
YtypFile ytyp = mlo?.Archetype?.Ytyp ?? ent?.MloParent?.Archetype?.Ytyp ?? ent?.Archetype?.Ytyp ?? room?.OwnerMlo?.Ytyp;
YmapFile ymap = ent?.Ymap ?? cargen?.Ymap ?? lodlight?.Ymap ?? grassbatch?.Ymap ?? mlo?.Ymap;
YmapFile ymap = ent?.Ymap ?? cargen?.Ymap ?? lodlight?.Ymap ?? boxoccluder?.Ymap ?? occludetri?.Ymap ?? grassbatch?.Ymap ?? mlo?.Ymap;
YbnFile ybn = collbound?.GetRootYbn();
YndFile ynd = pathnode?.Ynd;
YnvFile ynv = navpoly?.Ynv ?? navpoint?.Ynv ?? navportal?.Ynv;
@ -7081,6 +7501,14 @@ namespace CodeWalker.Project
{
ProjectExplorer?.TrySelectLodLightTreeNode(lodlight);
}
if (wasmult || (boxoccluder != CurrentBoxOccluder))
{
ProjectExplorer?.TrySelectBoxOccluderTreeNode(boxoccluder);
}
if (wasmult || (occludetri != CurrentOccludeModelTri))
{
ProjectExplorer?.TrySelectOccludeModelTriangleTreeNode(occludetri);
}
if (wasmult || (grassbatch != CurrentGrassBatch))
{
ProjectExplorer?.TrySelectGrassBatchTreeNode(grassbatch);
@ -7185,6 +7613,9 @@ namespace CodeWalker.Project
CurrentEntity = ent ?? mlo;
CurrentCarGen = cargen;
CurrentLodLight = lodlight;
CurrentBoxOccluder = boxoccluder;
CurrentOccludeModelTri = occludetri;
CurrentOccludeModel = occludetri?.Model;
CurrentGrassBatch = grassbatch;
CurrentYbnFile = ybn;
CurrentCollisionVertex = collvert;
@ -7256,6 +7687,14 @@ namespace CodeWalker.Project
{
OnWorldLodLightModified(sel.LodLight);
}
else if (sel.BoxOccluder != null)
{
OnWorldBoxOccluderModified(sel.BoxOccluder);
}
else if (sel.OccludeModelTri != null)
{
OnWorldOccludeModelTriModified(sel.OccludeModelTri);
}
else if (sel.PathNode != null)
{
OnWorldPathNodeModified(sel.PathNode, sel.PathLink);
@ -7437,6 +7876,76 @@ namespace CodeWalker.Project
}
}
}
private void OnWorldBoxOccluderModified(YmapBoxOccluder box)
{
if (box?.Ymap == null) return;
if (CurrentProjectFile == null)
{
NewProject();
}
if (!YmapExistsInProject(box.Ymap))
{
box.Ymap.HasChanged = true;
AddYmapToProject(box.Ymap);
ProjectExplorer?.TrySelectBoxOccluderTreeNode(box);
}
if (box != CurrentBoxOccluder)
{
CurrentBoxOccluder = box;
ProjectExplorer?.TrySelectBoxOccluderTreeNode(box);
}
if (box == CurrentBoxOccluder)
{
ShowEditYmapBoxOccluderPanel(false);
ProjectExplorer?.UpdateBoxOccluderTreeNode(box);
if (box.Ymap != null)
{
SetYmapHasChanged(true);
}
}
}
private void OnWorldOccludeModelTriModified(YmapOccludeModelTriangle tri)
{
if (tri?.Ymap == null) return;
if (CurrentProjectFile == null)
{
NewProject();
}
if (!YmapExistsInProject(tri.Ymap))
{
tri.Ymap.HasChanged = true;
AddYmapToProject(tri.Ymap);
ProjectExplorer?.TrySelectOccludeModelTriangleTreeNode(tri);
}
if (tri != CurrentOccludeModelTri)
{
CurrentOccludeModelTri = tri;
ProjectExplorer?.TrySelectOccludeModelTriangleTreeNode(tri);
}
if (tri == CurrentOccludeModelTri)
{
ShowEditYmapOccludeModelTrianglePanel(false);
//ProjectExplorer?.UpdateOccludeModelTriangleTreeNode(tri);
if (tri.Ymap != null)
{
SetYmapHasChanged(true);
}
}
}
private void OnWorldCollisionVertexModified(BoundVertex vert)
{

View File

@ -597,6 +597,259 @@ namespace CodeWalker.Project
}
public abstract class BoxOccluderUndoStep : UndoStep
{
public YmapBoxOccluder BoxOccluder { get; set; }
protected void UpdateGraphics(WorldForm wf)
{
if (BoxOccluder != null)
{
wf.UpdateBoxOccluderGraphics(BoxOccluder);
}
}
}
public class BoxOccluderPositionUndoStep : BoxOccluderUndoStep
{
public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; }
public BoxOccluderPositionUndoStep(YmapBoxOccluder box, Vector3 startpos)
{
BoxOccluder = box;
StartPosition = startpos;
EndPosition = box?.Position ?? Vector3.Zero;
}
private void Update(WorldForm wf, ref MapSelection sel, Vector3 p)
{
BoxOccluder.Position = p;
if (BoxOccluder != sel.BoxOccluder) wf.SelectObject(BoxOccluder);
wf.SetWidgetPosition(p);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartPosition);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndPosition);
}
public override string ToString()
{
return "BoxOccluder " + (BoxOccluder?.Index.ToString() ?? "") + ": Position";
}
}
public class BoxOccluderRotationUndoStep : BoxOccluderUndoStep
{
public Quaternion StartRotation { get; set; }
public Quaternion EndRotation { get; set; }
public BoxOccluderRotationUndoStep(YmapBoxOccluder box, Quaternion startrot)
{
BoxOccluder = box;
StartRotation = startrot;
EndRotation = box?.Orientation ?? Quaternion.Identity;
}
private void Update(WorldForm wf, ref MapSelection sel, Quaternion q)
{
BoxOccluder.Orientation = q;
if (BoxOccluder != sel.BoxOccluder) wf.SelectObject(BoxOccluder);
wf.SetWidgetRotation(q);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartRotation);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndRotation);
}
public override string ToString()
{
return "BoxOccluder " + (BoxOccluder?.Index.ToString() ?? "") + ": Rotation";
}
}
public class BoxOccluderScaleUndoStep : BoxOccluderUndoStep
{
public Vector3 StartScale { get; set; }
public Vector3 EndScale { get; set; }
public BoxOccluderScaleUndoStep(YmapBoxOccluder box, Vector3 startscale)
{
BoxOccluder = box;
StartScale = startscale;
EndScale = box?.Size ?? new Vector3(1.0f);
}
private void Update(WorldForm wf, ref MapSelection sel, Vector3 s)
{
BoxOccluder.SetSize(s);
if (BoxOccluder != sel.BoxOccluder) wf.SelectObject(BoxOccluder);
wf.SetWidgetScale(s);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartScale);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndScale);
}
public override string ToString()
{
return "BoxOccluder " + (BoxOccluder?.Index.ToString() ?? "") + ": Scale";
}
}
public abstract class OccludeModelTriUndoStep : UndoStep
{
public YmapOccludeModelTriangle OccludeModelTri { get; set; }
protected void UpdateGraphics(WorldForm wf)
{
if (OccludeModelTri != null)
{
wf.UpdateOccludeModelGraphics(OccludeModelTri.Model);
}
}
}
public class OccludeModelTriPositionUndoStep : OccludeModelTriUndoStep
{
public Vector3 StartPosition { get; set; }
public Vector3 EndPosition { get; set; }
public OccludeModelTriPositionUndoStep(YmapOccludeModelTriangle tri, Vector3 startpos)
{
OccludeModelTri = tri;
StartPosition = startpos;
EndPosition = tri?.Center ?? Vector3.Zero;
}
private void Update(WorldForm wf, ref MapSelection sel, Vector3 p)
{
OccludeModelTri.Center = p;
if (OccludeModelTri != sel.OccludeModelTri) wf.SelectObject(OccludeModelTri);
wf.SetWidgetPosition(p);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartPosition);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndPosition);
}
public override string ToString()
{
return "OccludeModel Triangle " + (OccludeModelTri?.Index.ToString() ?? "") + ": Position";
}
}
public class OccludeModelTriRotationUndoStep : OccludeModelTriUndoStep
{
public Quaternion StartRotation { get; set; }
public Quaternion EndRotation { get; set; }
public OccludeModelTriRotationUndoStep(YmapOccludeModelTriangle tri, Quaternion startrot)
{
OccludeModelTri = tri;
StartRotation = startrot;
EndRotation = tri?.Orientation ?? Quaternion.Identity;
}
private void Update(WorldForm wf, ref MapSelection sel, Quaternion q)
{
OccludeModelTri.Orientation = q;
if (OccludeModelTri != sel.OccludeModelTri) wf.SelectObject(OccludeModelTri);
wf.SetWidgetRotation(q);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartRotation);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndRotation);
}
public override string ToString()
{
return "OccludeModel Triangle " + (OccludeModelTri?.Index.ToString() ?? "") + ": Rotation";
}
}
public class OccludeModelTriScaleUndoStep : OccludeModelTriUndoStep
{
public Vector3 StartScale { get; set; }
public Vector3 EndScale { get; set; }
public OccludeModelTriScaleUndoStep(YmapOccludeModelTriangle tri, Vector3 startscale)
{
OccludeModelTri = tri;
StartScale = startscale;
EndScale = tri?.Scale ?? new Vector3(1.0f);
}
private void Update(WorldForm wf, ref MapSelection sel, Vector3 s)
{
OccludeModelTri.Scale = s;
if (OccludeModelTri != sel.OccludeModelTri) wf.SelectObject(OccludeModelTri);
wf.SetWidgetScale(s);
UpdateGraphics(wf);
}
public override void Undo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, StartScale);
}
public override void Redo(WorldForm wf, ref MapSelection sel)
{
Update(wf, ref sel, EndScale);
}
public override string ToString()
{
return "OccludeModel Triangle " + (OccludeModelTri?.Index.ToString() ?? "") + ": Scale";
}
}
public class CollisionPositionUndoStep : UndoStep

View File

@ -936,6 +936,16 @@ namespace CodeWalker.Rendering
SelectionTriVerts.Add(v1);
}
public void RenderSelectionTriangleOutline(Vector3 p1, Vector3 p2, Vector3 p3, uint col)
{
SelectionLineVerts.Add(new VertexTypePC() { Position = p1, Colour = col });
SelectionLineVerts.Add(new VertexTypePC() { Position = p2, Colour = col });
SelectionLineVerts.Add(new VertexTypePC() { Position = p2, Colour = col });
SelectionLineVerts.Add(new VertexTypePC() { Position = p3, Colour = col });
SelectionLineVerts.Add(new VertexTypePC() { Position = p3, Colour = col });
SelectionLineVerts.Add(new VertexTypePC() { Position = p1, Colour = col });
}
public void RenderSelectionCone(Vector3 position, Vector3 ax, Vector3 ay, Vector3 dir, float radius, float height, uint col)
{
const int Reso = 36;

View File

@ -54,7 +54,7 @@ namespace CodeWalker
public YmapGrassInstanceBatch GrassBatch { get; set; }
public YmapLODLight LodLight { get; set; }
public YmapBoxOccluder BoxOccluder { get; set; }
public YmapOccludeModel OccludeModel { get; set; }
public YmapOccludeModelTriangle OccludeModelTri { get; set; }
public YmapEntityDef MloEntityDef { get; set; }
public MCMloRoomDef MloRoomDef { get; set; }
public WaterQuad WaterQuad { get; set; }
@ -110,7 +110,7 @@ namespace CodeWalker
(TrainTrackNode != null) ||
(LodLight != null) ||
(BoxOccluder != null) ||
(OccludeModel != null) ||
(OccludeModelTri != null) ||
(MloEntityDef != null) ||
(ScenarioNode != null) ||
(Audio != null) ||
@ -137,7 +137,7 @@ namespace CodeWalker
|| (LodLight != mhit.LodLight)
|| (GrassBatch != mhit.GrassBatch)
|| (BoxOccluder != mhit.BoxOccluder)
|| (OccludeModel != mhit.OccludeModel)
|| (OccludeModelTri != mhit.OccludeModelTri)
|| (WaterQuad != mhit.WaterQuad)
|| (CollisionBounds != mhit.CollisionBounds)
|| (CollisionPoly != mhit.CollisionPoly)
@ -164,7 +164,7 @@ namespace CodeWalker
|| (LodLight != null)
|| (GrassBatch != null)
|| (BoxOccluder != null)
|| (OccludeModel != null)
|| (OccludeModelTri != null)
|| (WaterQuad != null)
|| (CollisionBounds != null)
|| (CollisionPoly != null)
@ -193,7 +193,7 @@ namespace CodeWalker
CarGenerator = null;
GrassBatch = null;
BoxOccluder = null;
OccludeModel = null;
OccludeModelTri = null;
WaterQuad = null;
CollisionBounds = null;
CollisionPoly = null;
@ -269,9 +269,9 @@ namespace CodeWalker
{
name = "BoxOccluder " + (BoxOccluder.Ymap?.Name ?? "") + ": " + BoxOccluder.Index.ToString();
}
else if (OccludeModel != null)
else if (OccludeModelTri != null)
{
name = "OccludeModel " + (OccludeModel.Ymap?.Name ?? "") + ": " + OccludeModel.Index.ToString();
name = "OccludeModel " + (OccludeModelTri.Ymap?.Name ?? "") + ": " + (OccludeModelTri.Model?.Index??0).ToString() + ":" + OccludeModelTri.Index.ToString();
}
else if (WaterQuad != null)
{
@ -337,6 +337,8 @@ namespace CodeWalker
if (EntityDef != null) return true;
if (CarGenerator != null) return true;
if (LodLight != null) return true;
if (BoxOccluder != null) return true;
if (OccludeModelTri != null) return true;
if (CollisionBounds != null) return true;
if (CollisionPoly != null) return true;
if (CollisionVertex != null) return true;
@ -423,6 +425,24 @@ namespace CodeWalker
case WidgetMode.Scale: return new LodLightScaleUndoStep(LodLight, startScale);
}
}
else if (BoxOccluder != null)
{
switch (mode)
{
case WidgetMode.Position: return new BoxOccluderPositionUndoStep(BoxOccluder, startPos);
case WidgetMode.Rotation: return new BoxOccluderRotationUndoStep(BoxOccluder, startRot);
case WidgetMode.Scale: return new BoxOccluderScaleUndoStep(BoxOccluder, startScale);
}
}
else if (OccludeModelTri != null)
{
switch (mode)
{
case WidgetMode.Position: return new OccludeModelTriPositionUndoStep(OccludeModelTri, startPos);
case WidgetMode.Rotation: return new OccludeModelTriRotationUndoStep(OccludeModelTri, startRot);
case WidgetMode.Scale: return new OccludeModelTriScaleUndoStep(OccludeModelTri, startScale);
}
}
else if (PathNode != null)
{
switch (mode)
@ -498,6 +518,14 @@ namespace CodeWalker
{
res = true;
}
else if (BoxOccluder != null)
{
res = true;
}
else if (OccludeModelTri != null)
{
res = true;
}
else if (NavPoly != null)
{
res = true;
@ -576,6 +604,14 @@ namespace CodeWalker
{
return LodLight.Position;
}
else if (BoxOccluder != null)
{
return BoxOccluder.Position;
}
else if (OccludeModelTri != null)
{
return OccludeModelTri.Center;
}
else if (NavPoly != null)
{
return NavPoly.Position;
@ -642,6 +678,14 @@ namespace CodeWalker
{
return LodLight.Orientation;
}
else if (BoxOccluder != null)
{
return BoxOccluder.Orientation;
}
else if (OccludeModelTri != null)
{
return OccludeModelTri.Orientation;
}
else if (NavPoly != null)
{
return Quaternion.Identity;
@ -705,6 +749,14 @@ namespace CodeWalker
{
return WidgetAxis.XYZ;
}
else if (BoxOccluder != null)
{
return WidgetAxis.Z;
}
else if (OccludeModelTri != null)
{
return WidgetAxis.XYZ;
}
else if (NavPoly != null)
{
return WidgetAxis.XYZ;
@ -768,6 +820,14 @@ namespace CodeWalker
{
return LodLight.Scale;
}
else if (BoxOccluder != null)
{
return BoxOccluder.Size;
}
else if (OccludeModelTri != null)
{
return OccludeModelTri.Scale;
}
else if (NavPoly != null)
{
return Vector3.One;
@ -811,6 +871,14 @@ namespace CodeWalker
}
return false;
}
if (BoxOccluder != null)
{
return false;
}
if (OccludeModelTri != null)
{
return false;
}
if (CollisionBounds != null)
{
return false;
@ -841,6 +909,8 @@ namespace CodeWalker
else if (EntityDef != null) return true;
else if (CarGenerator != null) return true;
else if (LodLight != null) return true;
else if (BoxOccluder != null) return true;
else if (OccludeModelTri != null) return true;
else if (PathNode != null) return true;
else if (NavPoly != null) return true;
else if (NavPoint != null) return true;
@ -962,6 +1032,14 @@ namespace CodeWalker
{
LodLight.SetPosition(newpos);
}
else if (BoxOccluder != null)
{
BoxOccluder.Position = newpos;
}
else if (OccludeModelTri != null)
{
OccludeModelTri.Center = newpos;
}
else if (PathNode != null)
{
PathNode.SetPosition(newpos);
@ -1074,6 +1152,14 @@ namespace CodeWalker
{
LodLight.SetOrientation(newrot);
}
else if (BoxOccluder != null)
{
BoxOccluder.Orientation = newrot;
}
else if (OccludeModelTri != null)
{
OccludeModelTri.Orientation = newrot;
}
else if (ScenarioNode != null)
{
ScenarioNode.SetOrientation(newrot);
@ -1165,6 +1251,14 @@ namespace CodeWalker
{
LodLight.SetScale(newscale);
}
else if (BoxOccluder != null)
{
BoxOccluder.SetSize(newscale);
}
else if (OccludeModelTri != null)
{
OccludeModelTri.Scale = newscale;
}
}
@ -1205,12 +1299,14 @@ namespace CodeWalker
{
if (MultipleSelectionItems != null)
{
Dictionary<YndFile, int> pathYnds = new Dictionary<YndFile, int>();
Dictionary<YnvFile, int> navYnvs = new Dictionary<YnvFile, int>();
Dictionary<TrainTrack, int> trainTracks = new Dictionary<TrainTrack, int>();
Dictionary<YmtFile, int> scenarioYmts = new Dictionary<YmtFile, int>();
Dictionary<Bounds, int> bounds = new Dictionary<Bounds, int>();
Dictionary<YmapLODLights, int> lodlights = new Dictionary<YmapLODLights, int>();
var pathYnds = new Dictionary<YndFile, int>();
var navYnvs = new Dictionary<YnvFile, int>();
var trainTracks = new Dictionary<TrainTrack, int>();
var scenarioYmts = new Dictionary<YmtFile, int>();
var bounds = new Dictionary<Bounds, int>();
var lodlights = new Dictionary<YmapLODLights, int>();
var boxoccls = new Dictionary<YmapBoxOccluder, int>();
var occlmods = new Dictionary<YmapOccludeModel, int>();
foreach (var item in MultipleSelectionItems)
{
@ -1254,6 +1350,14 @@ namespace CodeWalker
{
lodlights[item.LodLight.LodLights] = 1;
}
if (item.BoxOccluder != null)
{
boxoccls[item.BoxOccluder] = 1;
}
if (item.OccludeModelTri?.Model != null)
{
occlmods[item.OccludeModelTri.Model] = 1;
}
}
foreach (var kvp in bounds)
{
@ -1282,6 +1386,14 @@ namespace CodeWalker
wf.UpdateLodLightGraphics(kvp.Key.LodLights[0]);
}
}
foreach (var kvp in boxoccls)
{
wf.UpdateBoxOccluderGraphics(kvp.Key);
}
foreach (var kvp in occlmods)
{
wf.UpdateOccludeModelGraphics(kvp.Key);
}
}
else
{
@ -1325,6 +1437,14 @@ namespace CodeWalker
{
wf.UpdateLodLightGraphics(LodLight);
}
else if (BoxOccluder != null)
{
wf.UpdateBoxOccluderGraphics(BoxOccluder);
}
else if (OccludeModelTri?.Model != null)
{
wf.UpdateOccludeModelGraphics(OccludeModelTri?.Model);
}
}
}
@ -1338,6 +1458,8 @@ namespace CodeWalker
else if (EntityDef != null) return EntityDef;
else if (CarGenerator != null) return CarGenerator;
else if (LodLight != null) return LodLight;
else if (BoxOccluder != null) return BoxOccluder;
else if (OccludeModelTri != null) return OccludeModelTri;
else if (PathNode != null) return PathNode;
else if (NavPoly != null) return NavPoly;
else if (NavPoint != null) return NavPoint;
@ -1382,6 +1504,16 @@ namespace CodeWalker
ms.LodLight = lodlight;
ms.AABB = new BoundingBox(new Vector3(-nrad), new Vector3(nrad));
}
else if (o is YmapBoxOccluder boxoccl)
{
ms.BoxOccluder = boxoccl;
ms.AABB = new BoundingBox(boxoccl.BBMin, boxoccl.BBMax);
}
else if (o is YmapOccludeModelTriangle occltri)
{
ms.OccludeModelTri = occltri;
ms.AABB = new BoundingBox(occltri.Box.Minimum, occltri.Box.Maximum);
}
else if (o is YmapGrassInstanceBatch batch)
{
ms.GrassBatch = batch;

View File

@ -117,10 +117,10 @@ namespace CodeWalker.World
SelectionEntityTabPage.Text = "Box Occluder";
SelEntityPropertyGrid.SelectedObject = item.BoxOccluder;
}
else if (item.OccludeModel != null)
else if (item.OccludeModelTri != null)
{
SelectionEntityTabPage.Text = "Occlude Model";
SelEntityPropertyGrid.SelectedObject = item.OccludeModel;
SelectionEntityTabPage.Text = "Occlude Model Triangle";
SelEntityPropertyGrid.SelectedObject = item.OccludeModelTri;
}
else if (item.WaterQuad != null)
{

View File

@ -1225,9 +1225,11 @@ namespace CodeWalker
{
ori = CurMouseHit.BoxOccluder.Orientation;
}
if (CurMouseHit.OccludeModel != null)
if (CurMouseHit.OccludeModelTri != null)
{
//ori = CurMouseHit.OccludeModel.Orientation;
var otri = CurMouseHit.OccludeModelTri;
Renderer.RenderSelectionTriangleOutline(otri.Corner1, otri.Corner2, otri.Corner3, 0xFFFFFFFF);
return;
}
if (CurMouseHit.MloEntityDef != null)
{
@ -1531,6 +1533,14 @@ namespace CodeWalker
bbmin = bo.BBMin;
bbmax = bo.BBMax;
}
if (selectionItem.OccludeModelTri != null)
{
var ot = selectionItem.OccludeModelTri;
var om = ot.Model;
bbmin = om._OccludeModel.bmin;
bbmax = om._OccludeModel.bmax;
Renderer.RenderSelectionTriangleOutline(ot.Corner1, ot.Corner2, ot.Corner3, cgrn);
}
if (selectionItem.NavPoly != null)
{
Renderer.RenderSelectionNavPoly(selectionItem.NavPoly);
@ -1961,6 +1971,23 @@ namespace CodeWalker
Renderer.Invalidate(lodlight);
}
}
public void UpdateBoxOccluderGraphics(YmapBoxOccluder box)
{
//lock (Renderer.RenderSyncRoot)
{
Renderer.Invalidate(box);
}
}
public void UpdateOccludeModelGraphics(YmapOccludeModel model)
{
model.BuildBVH();
model.BuildVertices();
//lock (Renderer.RenderSyncRoot)
{
Renderer.Invalidate(model);
}
}
public void UpdateGrassBatchGraphics(YmapGrassInstanceBatch grassBatch)
{
//lock (Renderer.RenderSyncRoot)
@ -2815,13 +2842,15 @@ namespace CodeWalker
var bo = ymap.BoxOccluders[i];
if ((bo.Position - camera.Position).Length() > dmax) continue;
Renderer.RenderBasePath(bo);
MapBox mb = new MapBox();
mb.CamRelPos = bo.Position - camera.Position;
mb.BBMin = bo.BBMin;
mb.BBMax = bo.BBMax;
mb.Orientation = bo.Orientation;
mb.Scale = Vector3.One;
Renderer.BoundingBoxes.Add(mb);
//Renderer.BoundingBoxes.Add(mb);
Quaternion orinv = Quaternion.Invert(bo.Orientation);
Ray mraytrn = new Ray();
@ -2829,10 +2858,11 @@ namespace CodeWalker
mraytrn.Direction = orinv.Multiply(mray.Direction);
bbox.Minimum = mb.BBMin;
bbox.Maximum = mb.BBMax;
if (mraytrn.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0))
if (mraytrn.Intersects(ref bbox, out float hd) && (hd < CurMouseHit.HitDist) && (hd > 0))
{
hitdist = hd;
CurMouseHit.BoxOccluder = bo;
CurMouseHit.OccludeModel = null;
CurMouseHit.OccludeModelTri = null;
CurMouseHit.HitDist = hitdist;
CurMouseHit.CamRel = mb.CamRelPos;
CurMouseHit.AABB = bbox;
@ -2847,24 +2877,14 @@ namespace CodeWalker
Renderer.RenderBasePath(om);
MapBox mb = new MapBox();
mb.CamRelPos = -camera.Position;
mb.BBMin = om._OccludeModel.bmin;
mb.BBMax = om._OccludeModel.bmax;
mb.Orientation = Quaternion.Identity;// bo.Orientation;
mb.Scale = Vector3.One;
Renderer.BoundingBoxes.Add(mb);
bbox.Minimum = mb.BBMin;
bbox.Maximum = mb.BBMax;
if (mray.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0))
var hittri = om.RayIntersect(ref mray, ref hitdist);
if ((hittri != null) && (hitdist < CurMouseHit.HitDist))
{
CurMouseHit.BoxOccluder = null;
CurMouseHit.OccludeModel = om;
CurMouseHit.OccludeModelTri = hittri;
CurMouseHit.HitDist = hitdist;
CurMouseHit.CamRel = mb.CamRelPos;
CurMouseHit.AABB = bbox;
CurMouseHit.CamRel = -camera.Position;
CurMouseHit.AABB = hittri.Box;
}
}
@ -3674,11 +3694,19 @@ namespace CodeWalker
{
SelectionEntityTabPage.Text = "BoxOccluder";
SelEntityPropertyGrid.SelectedObject = item.BoxOccluder;
ymap = item.BoxOccluder.Ymap;
ToolbarCopyButton.Enabled = true;
ToolbarDeleteItemButton.Enabled = true;
ToolbarDeleteItemButton.Text = "Delete Box Occluder";
}
else if (item.OccludeModel != null)
else if (item.OccludeModelTri != null)
{
SelectionEntityTabPage.Text = "Occlude Model";
SelEntityPropertyGrid.SelectedObject = item.OccludeModel;
SelectionEntityTabPage.Text = "OccludeTriangle";
SelEntityPropertyGrid.SelectedObject = item.OccludeModelTri;
ymap = item.OccludeModelTri.Ymap;
ToolbarCopyButton.Enabled = true;
ToolbarDeleteItemButton.Enabled = true;
ToolbarDeleteItemButton.Text = "Delete Occlude Model Triangle";
}
else if (item.WaterQuad != null)
{
@ -5058,6 +5086,9 @@ namespace CodeWalker
else if (item.CollisionBounds != null) DeleteCollisionBounds(item.CollisionBounds);
else if (item.EntityDef != null) DeleteEntity(item.EntityDef);
else if (item.CarGenerator != null) DeleteCarGen(item.CarGenerator);
else if (item.LodLight != null) DeleteLodLight(item.LodLight);
else if (item.BoxOccluder != null) DeleteBoxOccluder(item.BoxOccluder);
else if (item.OccludeModelTri != null) DeleteOccludeModelTriangle(item.OccludeModelTri);
else if (item.PathNode != null) DeletePathNode(item.PathNode);
else if (item.NavPoly != null) DeleteNavPoly(item.NavPoly);
else if (item.NavPoint != null) DeleteNavPoint(item.NavPoint);
@ -5115,6 +5146,52 @@ namespace CodeWalker
SelectItem(null);
}
}
private void DeleteLodLight(YmapLODLight lodlight)
{
if (lodlight == null) return;
//project not open, or lodlight not selected there, just remove the lodlight from the ymap...
var ymap = lodlight.Ymap;
if (!ymap.RemoveLodLight(lodlight))
{
MessageBox.Show("Unable to remove LOD light.");
}
else
{
SelectItem(null);
}
}
private void DeleteBoxOccluder(YmapBoxOccluder box)
{
if (box == null) return;
//project not open, or box not selected there, just remove the box from the ymap...
var ymap = box.Ymap;
if (!ymap.RemoveBoxOccluder(box))
{
MessageBox.Show("Unable to remove box occluder.");
}
else
{
SelectItem(null);
}
}
private void DeleteOccludeModelTriangle(YmapOccludeModelTriangle tri)
{
if (tri == null) return;
//project not open, or tri not selected there, just remove the tri from the ymap...
var ymap = tri.Ymap;
if (!ymap.RemoveOccludeModelTriangle(tri))
{
MessageBox.Show("Unable to remove occlude model triangle.");
}
else
{
UpdateOccludeModelGraphics(tri.Model);
SelectItem(null);
}
}
private void DeletePathNode(YndNode pathnode)
{
if (pathnode == null) return;