diff --git a/CodeWalker.Core/CodeWalker.Core.csproj b/CodeWalker.Core/CodeWalker.Core.csproj
index e613082..3e40522 100644
--- a/CodeWalker.Core/CodeWalker.Core.csproj
+++ b/CodeWalker.Core/CodeWalker.Core.csproj
@@ -114,6 +114,7 @@
True
Resources.resx
+
diff --git a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs
index 7e61049..839e411 100644
--- a/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs
+++ b/CodeWalker.Core/GameFiles/FileTypes/YmapFile.cs
@@ -7,6 +7,8 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
+using CodeWalker.Core.Utils;
+using CodeWalker.World;
namespace CodeWalker.GameFiles
{
@@ -925,6 +927,7 @@ namespace CodeWalker.GameFiles
GrassInstanceBatches = batches.ToArray();
HasChanged = true;
+ UpdateGrassPhysDict(true);
}
public bool RemoveGrassBatch(YmapGrassInstanceBatch batch)
@@ -949,6 +952,10 @@ namespace CodeWalker.GameFiles
}
}
+ if (batches.Count <= 0)
+ {
+ UpdateGrassPhysDict(false);
+ }
GrassInstanceBatches = batches.ToArray();
@@ -1137,6 +1144,27 @@ namespace CodeWalker.GameFiles
}
+ private void UpdateGrassPhysDict(bool add)
+ {
+ var physDict = physicsDictionaries?.ToList() ?? new List();
+ var vproc1 = JenkHash.GenHash("v_proc1");
+ var vproc2 = JenkHash.GenHash("v_proc2"); // I think you need vproc2 as well.
+ var change = false;
+ if (!physDict.Contains(vproc1))
+ {
+ change = true;
+ if (add) physDict.Add(vproc1);
+ else physDict.Remove(vproc1);
+ }
+ if (!physDict.Contains(vproc2))
+ {
+ change = true;
+ if (add) physDict.Add(vproc2);
+ else physDict.Remove(vproc2);
+ }
+ if (change) physicsDictionaries = physDict.ToArray();
+ }
+
private static uint SetBit(uint value, int bit)
{
@@ -1493,6 +1521,8 @@ namespace CodeWalker.GameFiles
[TypeConverter(typeof(ExpandableObjectConverter))]
public class YmapGrassInstanceBatch
{
+ private const float BatchVertMultiplier = 0.00001525878f;
+
public Archetype Archetype { get; set; } //cached by GameFileCache on loading...
public rage__fwGrassInstanceListDef Batch { get; set; }
public rage__fwGrassInstanceListDef__InstanceData[] Instances { get; set; }
@@ -1504,10 +1534,478 @@ namespace CodeWalker.GameFiles
public float Distance; //used for rendering
public YmapFile Ymap { get; set; }
+ private List grassBounds; // for brush
+ public bool BrushEnabled; // for brush
+ public float BrushRadius = 5f; // for brush
+ public bool HasChanged; // for brush and renderer
+
+ // TODO: Make configurable.
+ const float BoundingSize = 0.3F;
+ static readonly Vector3 GrassMinMax = Vector3.One * BoundingSize;
+
public override string ToString()
{
return Batch.ToString();
}
+
+ public void UpdateInstanceCount()
+ {
+ var b = Batch;
+ var ins = b.InstanceList;
+ ins.Count1 = (ushort)Instances.Length;
+ b.InstanceList = ins;
+ Batch = b;
+ }
+
+ public bool IsPointBlockedByInstance(Vector3 point)
+ {
+ return grassBounds.Any(bb => bb.Contains(point) == ContainmentType.Contains);
+ }
+
+ private void ReInitializeBoundingCache()
+ {
+ // cache is already initialized correctly.
+ if (grassBounds != null && (grassBounds.Count == Instances.Length))
+ return;
+
+ // Clear the current bounding cache.
+ if (grassBounds == null)
+ grassBounds = new List();
+ else grassBounds?.Clear();
+
+ foreach (var inst in Instances)
+ {
+ // create bounding box for this instance.
+ var worldPos = GetGrassWorldPos(inst.Position, new BoundingBox(AABBMin, AABBMax));
+ var bb = new BoundingBox(worldPos - GrassMinMax, worldPos + GrassMinMax);
+ grassBounds.Add(bb);
+ }
+ }
+
+ public bool EraseInstancesAtMouse(
+ YmapGrassInstanceBatch batch,
+ SpaceRayIntersectResult mouseRay,
+ float radius)
+ {
+ rage__spdAABB batchAABB = batch.Batch.BatchAABB;
+ var oldInstanceBounds = new BoundingBox
+ (
+ batchAABB.min.XYZ(),
+ batchAABB.max.XYZ()
+ );
+ var deleteSphere = new BoundingSphere(mouseRay.Position, radius);
+
+ // check each instance to see if it's in the delete sphere
+ // thankfully we've just avoided an O(n^2) op using this bounds stuff (doesn't mean it's super fast though,
+ // but it's not super slow either, even at like 50,000 instances)
+ var insList = new List();
+ foreach (var instance in batch.Instances)
+ {
+ // get the world pos
+ var worldPos = GetGrassWorldPos(instance.Position, oldInstanceBounds);
+
+ // create a boundary around the instance.
+ var instanceBounds = new BoundingBox(worldPos - GrassMinMax, worldPos + GrassMinMax);
+
+ // check if the sphere contains the boundary.
+ var bb = new BoundingBox(instanceBounds.Minimum, instanceBounds.Maximum);
+ var ct = deleteSphere.Contains(ref bb);
+ if (ct == ContainmentType.Contains || ct == ContainmentType.Intersects)
+ {
+ //delInstances.Add(instance); // Add a copy of this instance
+ continue;
+ }
+ insList.Add(instance);
+ }
+ if (insList.Count == Instances.Length)
+ return false;
+
+ var newBounds = GetNewGrassBounds(insList, oldInstanceBounds);
+ // recalc instances
+ var b = RecalcBatch(newBounds, batch);
+ batch.Batch = b;
+ insList = RecalculateInstances(insList, oldInstanceBounds, newBounds);
+ batch.Instances = insList.ToArray();
+ return true;
+ }
+
+ public void CreateInstancesAtMouse(
+ YmapGrassInstanceBatch batch,
+ SpaceRayIntersectResult mouseRay,
+ float radius,
+ int amount,
+ Func spawnRayFunc,
+ Color color,
+ int ao,
+ int scale,
+ Vector3 pad,
+ bool randomScale)
+ {
+
+ ReInitializeBoundingCache();
+ var spawnPosition = mouseRay.Position;
+ var positions = new List();
+ var normals = new List();
+
+ // Get rand positions.
+ GetSpawns(spawnPosition, spawnRayFunc, positions, normals, radius, amount);
+ if (positions.Count <= 0) return;
+
+ // get the instance list
+ var instances =
+ batch.Instances?.ToList() ?? new List();
+ var batchAABB = batch.Batch.BatchAABB;
+
+ // make sure to store the old instance bounds for the original
+ // grass instances
+ var oldInstanceBounds = new BoundingBox(batchAABB.min.XYZ(), batchAABB.max.XYZ());
+
+ if (positions.Count <= 0)
+ return;
+
+ // Begin the spawn bounds.
+ var grassBound = new BoundingBox(positions[0] - GrassMinMax, positions[0] + GrassMinMax);
+ grassBound = EncapsulatePositions(positions, grassBound);
+
+ // Calculate the new spawn bounds.
+ var newInstanceBounds = new BoundingBox(oldInstanceBounds.Minimum, oldInstanceBounds.Maximum);
+ newInstanceBounds = instances.Count > 0
+ ? newInstanceBounds.Encapsulate(grassBound)
+ : new BoundingBox(grassBound.Minimum, grassBound.Maximum);
+
+ // now we need to recalculate the position of each instance
+ instances = RecalculateInstances(instances, oldInstanceBounds, newInstanceBounds);
+
+ // Add new instances at each spawn position with
+ // the parameters in the brush.
+ SpawnInstances(positions, normals, instances, newInstanceBounds, color, ao, scale, pad, randomScale);
+
+ // then recalc the bounds of the grass batch
+ var b = RecalcBatch(newInstanceBounds, batch);
+
+ // plug our values back in and refresh the ymap.
+ batch.Batch = b;
+
+ // Give back the new intsances
+ batch.Instances = instances.ToArray();
+ grassBounds.Clear();
+ }
+
+ // bhv approach recommended by dexy.
+ public YmapGrassInstanceBatch[] OptimizeInstances(YmapGrassInstanceBatch batch, float minRadius)
+ {
+ // this function will return an array of grass instance batches
+ // that are split up into sectors (groups) with a specific size.
+ // say for instance we have 30,000 instances spread across a large
+ // distance. We will split those instances into a grid-like group
+ // and return the groups as an array of batches.
+ var oldInstanceBounds = new BoundingBox(batch.Batch.BatchAABB.min.XYZ(), batch.Batch.BatchAABB.max.XYZ());
+
+ if (oldInstanceBounds.Radius() < minRadius)
+ {
+ return new [] { batch };
+ }
+
+ // Get our optimized grassInstances
+ var split = SplitGrassRecursive(batch.Instances.ToList(), oldInstanceBounds, minRadius);
+
+ // Initiate a new batch list.
+ var newBatches = new List();
+
+ foreach (var grassList in split)
+ {
+ // Create a new batch
+ var newBatch = new YmapGrassInstanceBatch
+ {
+ Archetype = batch.Archetype,
+ Ymap = batch.Ymap
+ };
+
+ // Get the boundary of the grassInstances
+ var newInstanceBounds = GetNewGrassBounds(grassList, oldInstanceBounds);
+
+ // Recalculate the batch boundaries.
+ var b = RecalcBatch(newInstanceBounds, newBatch);
+ newBatch.Batch = b;
+
+ var ins = RecalculateInstances(grassList, oldInstanceBounds, newInstanceBounds);
+ newBatch.Instances = ins.ToArray();
+ newBatches.Add(newBatch);
+ }
+
+ return newBatches.ToArray();
+ }
+
+ private List> SplitGrassRecursive(
+ IReadOnlyList grassInstances,
+ BoundingBox batchAABB,
+ float minRadius = 15F
+ )
+ {
+ var ret = new List>();
+ var oldPoints = SplitGrass(grassInstances, batchAABB);
+ while (true)
+ {
+ var stop = true;
+ var newPoints = new List>();
+ foreach (var mb in oldPoints)
+ {
+ // for some reason we got a null group?
+ if (mb == null)
+ continue;
+
+ // Get the bounds of the grassInstances list
+ var radius = GetNewGrassBounds(mb, batchAABB).Radius();
+
+ // check if the radius of the grassInstances
+ if (radius <= minRadius)
+ {
+ // this point list is within the minimum
+ // radius.
+ ret.Add(mb);
+ continue; // we don't need to continue.
+ }
+
+ // since we're here let's keep going
+ stop = false;
+
+ // split the grassInstances again
+ var s = SplitGrass(mb, batchAABB);
+
+ // add it into the new grassInstances list.
+ newPoints.AddRange(s);
+ }
+
+ // set the old grassInstances to the new grassInstances.
+ oldPoints = newPoints.ToArray();
+
+ // if we're done, and all grassInstances are within the desired size
+ // then end the loop.
+ if (stop) break;
+ }
+ return ret;
+ }
+
+ private List[] SplitGrass(
+ IReadOnlyList points,
+ BoundingBox batchAABB)
+ {
+ var pointGroup = new List[2];
+
+ // Calculate the bounds of these grassInstances.
+ var m = GetNewGrassBounds(points, batchAABB);
+
+ // Get the center and size
+ var mm = new Vector3
+ {
+ X = Math.Abs(m.Minimum.X - m.Maximum.X),
+ Y = Math.Abs(m.Minimum.Y - m.Maximum.Y),
+ Z = Math.Abs(m.Minimum.Z - m.Maximum.Z)
+ };
+
+ // x is the greatest axis...
+ if (mm.X > mm.Y && mm.X > mm.Z)
+ {
+ // Calculate both boundaries.
+ var lhs = new BoundingBox(m.Minimum, m.Maximum - new Vector3(mm.X * 0.5F, 0, 0));
+ var rhs = new BoundingBox(m.Minimum + new Vector3(mm.X * 0.5F, 0, 0), m.Maximum);
+
+ // Set the grassInstances accordingly.
+ pointGroup[0] = points
+ .Where(p => lhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
+ pointGroup[1] = points
+ .Where(p => rhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
+ }
+ // y is the greatest axis...
+ else if (mm.Y > mm.X && mm.Y > mm.Z)
+ {
+ // Calculate both boundaries.
+ var lhs = new BoundingBox(m.Minimum, m.Maximum - new Vector3(0, mm.Y * 0.5F, 0));
+ var rhs = new BoundingBox(m.Minimum + new Vector3(0, mm.Y * 0.5F, 0), m.Maximum);
+
+ // Set the grassInstances accordingly.
+ pointGroup[0] = points
+ .Where(p => lhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
+ pointGroup[1] = points
+ .Where(p => rhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
+ }
+ // z is the greatest axis...
+ else if (mm.Z > mm.X && mm.Z > mm.Y)
+ {
+ // Calculate both boundaries.
+ var lhs = new BoundingBox(m.Minimum, m.Maximum - new Vector3(0, 0, mm.Z * 0.5F));
+ var rhs = new BoundingBox(m.Minimum + new Vector3(0, 0, mm.Z * 0.5F), m.Maximum);
+
+ // Set the grassInstances accordingly.
+ pointGroup[0] = points
+ .Where(p => lhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
+ pointGroup[1] = points
+ .Where(p => rhs.Contains(GetGrassWorldPos(p.Position, batchAABB)) == ContainmentType.Contains).ToList();
+ }
+ return pointGroup;
+ }
+
+ private static BoundingBox GetNewGrassBounds(IReadOnlyList newGrass, BoundingBox oldAABB)
+ {
+ var grassPositions = newGrass.Select(x => GetGrassWorldPos(x.Position, oldAABB)).ToArray();
+ return BoundingBox.FromPoints(grassPositions).Expand(1f);
+ }
+
+ private void SpawnInstances(
+ IReadOnlyList positions,
+ IReadOnlyList normals,
+ ICollection instanceList,
+ BoundingBox instanceBounds,
+ Color color,
+ int ao,
+ int scale,
+ Vector3 pad,
+ bool randomScale)
+ {
+ for (var i = 0; i < positions.Count; i++)
+ {
+ var pos = positions[i];
+ // create the new instance.
+ var newInstance = CreateNewInstance(normals[i], color, ao, scale, pad, randomScale);
+
+ // get the grass position of the new instance and add it to the
+ // instance list
+ var grassPosition = GetGrassPos(pos, instanceBounds);
+ newInstance.Position = grassPosition;
+ instanceList.Add(newInstance);
+ }
+ }
+
+ private rage__fwGrassInstanceListDef__InstanceData CreateNewInstance(Vector3 normal, Color color, int ao, int scale, Vector3 pad,
+ bool randomScale = false)
+ {
+ //Vector3 pad = FloatUtil.ParseVector3String(PadTextBox.Text);
+ //int scale = (int)ScaleNumericUpDown.Value;
+ var rand = new Random();
+ if (randomScale)
+ scale = rand.Next(scale / 2, scale);
+ var newInstance = new rage__fwGrassInstanceListDef__InstanceData
+ {
+ Ao = (byte)ao,
+ Scale = (byte)scale,
+ Color = new ArrayOfBytes3 { b0 = color.R, b1 = color.G, b2 = color.B },
+ Pad = new ArrayOfBytes3 { b0 = (byte)pad.X, b1 = (byte)pad.Y, b2 = (byte)pad.Z },
+ NormalX = (byte)((normal.X + 1) * 0.5F * 255F),
+ NormalY = (byte)((normal.Y + 1) * 0.5F * 255F)
+ };
+ return newInstance;
+ }
+
+ private rage__fwGrassInstanceListDef RecalcBatch(BoundingBox newInstanceBounds, YmapGrassInstanceBatch batch)
+ {
+ batch.AABBMax = newInstanceBounds.Maximum;
+ batch.AABBMin = newInstanceBounds.Minimum;
+ batch.Position = newInstanceBounds.Center();
+ batch.Radius = newInstanceBounds.Radius();
+ var b = batch.Batch;
+ b.BatchAABB = new rage__spdAABB
+ {
+ min =
+ new Vector4(newInstanceBounds.Minimum,
+ 0), // Let's pass the new stuff into the batchabb as well just because.
+ max = new Vector4(newInstanceBounds.Maximum, 0)
+ };
+ return b;
+ }
+
+ private void GetSpawns(
+ Vector3 origin, Func spawnRayFunc,
+ ICollection positions,
+ ICollection normals,
+ float radius,
+ int resolution = 28)
+ {
+ var rand = new Random();
+ for (var i = 0; i < resolution; i++)
+ {
+ var randX = (float)rand.NextDouble(-radius, radius);
+ var randY = (float)rand.NextDouble(-radius, radius);
+ if (Math.Abs(randX) > 0 && Math.Abs(randY) > 0)
+ {
+ randX *= .7071f;
+ randY *= .7071f;
+ }
+ var posOffset = origin + new Vector3(randX, randY, 2f);
+ var spaceRay = spawnRayFunc.Invoke(posOffset);
+ if (!spaceRay.Hit) continue;
+ // not truly O(n^2) but may be slow...
+ // actually just did some testing, not slow at all.
+ if (IsPointBlockedByInstance(spaceRay.Position)) continue;
+ normals.Add(spaceRay.Normal);
+ positions.Add(spaceRay.Position);
+ }
+ }
+
+ private static List RecalculateInstances(
+ List instances,
+ BoundingBox oldInstanceBounds,
+ BoundingBox newInstanceBounds)
+ {
+ var refreshList = new List();
+ foreach (var inst in instances)
+ {
+ // Copy instance
+ var copy =
+ new rage__fwGrassInstanceListDef__InstanceData
+ {
+ Position = inst.Position,
+ Ao = inst.Ao,
+ Color = inst.Color,
+ NormalX = inst.NormalX,
+ NormalY = inst.NormalY,
+ Pad = inst.Pad,
+ Scale = inst.Scale
+ };
+ // get the position from where we would be in the old bounds, and move it to
+ // the position it needs to be in the new bounds.
+ var oldPos = GetGrassWorldPos(copy.Position, oldInstanceBounds);
+ //var oldPos = oldInstanceBounds.min + oldInstanceBounds.Size * (grassPos * BatchVertMultiplier);
+ copy.Position = GetGrassPos(oldPos, newInstanceBounds);
+ refreshList.Add(copy);
+ }
+ instances = refreshList.ToList();
+ return instances;
+ }
+
+ private static BoundingBox EncapsulatePositions(IEnumerable positions, BoundingBox bounds)
+ {
+ foreach (var pos in positions)
+ {
+ var posBounds = new BoundingBox(pos - (GrassMinMax + 0.1f), pos + (GrassMinMax + 0.1f));
+ bounds = bounds.Encapsulate(posBounds);
+ }
+ return bounds;
+ }
+
+ private static ArrayOfUshorts3 GetGrassPos(Vector3 worldPos, BoundingBox batchAABB)
+ {
+ var offset = worldPos - batchAABB.Minimum;
+ var size = batchAABB.Size();
+ var percentage =
+ new Vector3(
+ offset.X / size.X,
+ offset.Y / size.Y,
+ offset.Z / size.Z
+ );
+ var instancePos = percentage / BatchVertMultiplier;
+ return new ArrayOfUshorts3
+ {
+ u0 = (ushort)instancePos.X,
+ u1 = (ushort)instancePos.Y,
+ u2 = (ushort)instancePos.Z
+ };
+ }
+
+ private static Vector3 GetGrassWorldPos(ArrayOfUshorts3 grassPos, BoundingBox batchAABB)
+ {
+ return batchAABB.Minimum + batchAABB.Size() * (grassPos.XYZ() * BatchVertMultiplier);
+ }
}
[TypeConverter(typeof(ExpandableObjectConverter))]
@@ -1548,7 +2046,6 @@ namespace CodeWalker.GameFiles
}
}
-
[TypeConverter(typeof(ExpandableObjectConverter))]
public class YmapTimeCycleModifier
{
diff --git a/CodeWalker.Core/GameFiles/MetaTypes/Meta.cs b/CodeWalker.Core/GameFiles/MetaTypes/Meta.cs
index 7ee83cc..c617940 100644
--- a/CodeWalker.Core/GameFiles/MetaTypes/Meta.cs
+++ b/CodeWalker.Core/GameFiles/MetaTypes/Meta.cs
@@ -935,6 +935,10 @@ namespace CodeWalker.GameFiles
[TC(typeof(EXP))] public struct ArrayOfUshorts3 //array of 3 ushorts
{
public ushort u0, u1, u2;
+ public Vector3 XYZ()
+ {
+ return new Vector3(u0, u1, u2);
+ }
public override string ToString()
{
return u0.ToString() + ", " + u1.ToString() + ", " + u2.ToString();
diff --git a/CodeWalker.Core/GameFiles/Resources/Bounds.cs b/CodeWalker.Core/GameFiles/Resources/Bounds.cs
index 705dad5..1f25591 100644
--- a/CodeWalker.Core/GameFiles/Resources/Bounds.cs
+++ b/CodeWalker.Core/GameFiles/Resources/Bounds.cs
@@ -1443,6 +1443,13 @@ namespace CodeWalker.GameFiles
return Materials[type.Index];
}
+ public static BoundsMaterialData GetMaterial(byte index)
+ {
+ if (Materials == null) return null;
+ if ((int)index >= Materials.Count) return null;
+ return Materials[index];
+ }
+
public static string GetMaterialName(BoundsMaterialType type)
{
var m = GetMaterial(type);
diff --git a/CodeWalker.Core/Utils/BoundingBoxes.cs b/CodeWalker.Core/Utils/BoundingBoxes.cs
new file mode 100644
index 0000000..d602c8f
--- /dev/null
+++ b/CodeWalker.Core/Utils/BoundingBoxes.cs
@@ -0,0 +1,39 @@
+using System;
+using SharpDX;
+
+namespace CodeWalker.Core.Utils
+{
+ public static class BoundingBoxExtensions
+ {
+ public static Vector3 Size(this BoundingBox bounds)
+ {
+ return new Vector3(
+ Math.Abs(bounds.Maximum.X - bounds.Minimum.X),
+ Math.Abs(bounds.Maximum.Y - bounds.Minimum.Y),
+ Math.Abs(bounds.Maximum.Z - bounds.Minimum.Z));
+ }
+
+ public static Vector3 Center(this BoundingBox bounds)
+ {
+ return (bounds.Minimum + bounds.Maximum) * 0.5F;
+ }
+
+ public static BoundingBox Encapsulate(this BoundingBox box, BoundingBox bounds)
+ {
+ box.Minimum = Vector3.Min(box.Minimum, bounds.Minimum);
+ box.Maximum = Vector3.Max(box.Maximum, bounds.Maximum);
+ return box;
+ }
+
+ public static float Radius(this BoundingBox box)
+ {
+ var extents = (box.Maximum - box.Minimum) * 0.5F;
+ return extents.Length();
+ }
+
+ public static BoundingBox Expand(this BoundingBox b, float amount)
+ {
+ return new BoundingBox(b.Minimum - Vector3.One * amount, b.Maximum + Vector3.One * amount);
+ }
+ }
+}
diff --git a/CodeWalker.Core/Utils/Vectors.cs b/CodeWalker.Core/Utils/Vectors.cs
index b953850..19b354e 100644
--- a/CodeWalker.Core/Utils/Vectors.cs
+++ b/CodeWalker.Core/Utils/Vectors.cs
@@ -4,18 +4,17 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using CodeWalker.GameFiles;
namespace CodeWalker
{
public static class Vectors
{
-
public static Vector3 XYZ(this Vector4 v)
{
return new Vector3(v.X, v.Y, v.Z);
}
-
public static Vector3 Round(this Vector3 v)
{
return new Vector3((float)Math.Round(v.X), (float)Math.Round(v.Y), (float)Math.Round(v.Z));
@@ -25,7 +24,6 @@ namespace CodeWalker
{
return new Vector4((float)Math.Floor(v.X), (float)Math.Floor(v.Y), (float)Math.Floor(v.Z), (float)Math.Floor(v.W));
}
-
}
diff --git a/Project/Panels/EditProjectManifestPanel.cs b/Project/Panels/EditProjectManifestPanel.cs
index d15cb87..a253983 100644
--- a/Project/Panels/EditProjectManifestPanel.cs
+++ b/Project/Panels/EditProjectManifestPanel.cs
@@ -138,6 +138,18 @@ namespace CodeWalker.Project.Panels
}
}
+ if (ymap.GrassInstanceBatches != null)
+ {
+ foreach (var batch in ymap.GrassInstanceBatches)
+ {
+ var ytyp = batch.Archetype?.Ytyp;
+ var ytypname = getYtypName(ytyp);
+ if (ytyp != null)
+ {
+ mapdeps[ytypname] = ytyp;
+ }
+ }
+ }
sb.AppendLine(" - ");
sb.AppendLine(" " + ymapname + "");
diff --git a/Project/Panels/EditYmapGrassPanel.Designer.cs b/Project/Panels/EditYmapGrassPanel.Designer.cs
index 824c62a..c281c66 100644
--- a/Project/Panels/EditYmapGrassPanel.Designer.cs
+++ b/Project/Panels/EditYmapGrassPanel.Designer.cs
@@ -28,28 +28,642 @@
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditYmapGrassPanel));
+ this.tabControl1 = new System.Windows.Forms.TabControl();
+ this.GrassBatchTab = new System.Windows.Forms.TabPage();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.label12 = new System.Windows.Forms.Label();
+ this.label11 = new System.Windows.Forms.Label();
+ this.OrientToTerrainNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.ScaleRangeTextBox = new System.Windows.Forms.TextBox();
+ this.label10 = new System.Windows.Forms.Label();
+ this.LodFadeRangeNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.label9 = new System.Windows.Forms.Label();
+ this.LodFadeStartDistanceNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.label6 = new System.Windows.Forms.Label();
+ this.LodDistNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.BrushTab = new System.Windows.Forms.TabPage();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.GrassColorLabel = new System.Windows.Forms.Label();
+ this.label15 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.AoNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.PadTextBox = new System.Windows.Forms.TextBox();
+ this.ScaleNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
+ this.RandomizeScaleCheckBox = new System.Windows.Forms.CheckBox();
+ this.brushSettingsGroupBox = new System.Windows.Forms.GroupBox();
+ this.DensityNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.RadiusNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.label5 = new System.Windows.Forms.Label();
+ this.radiusLabel = new System.Windows.Forms.Label();
+ this.OptimizeBatchButtonTooltip = new System.Windows.Forms.ToolTip(this.components);
+ this.OptimizeBatchButton = new System.Windows.Forms.Button();
+ this.ExtentsMinTextBox = new System.Windows.Forms.TextBox();
+ this.label14 = new System.Windows.Forms.Label();
+ this.ExtentsMaxTextBox = new System.Windows.Forms.TextBox();
+ this.label13 = new System.Windows.Forms.Label();
+ this.GrassDeleteButton = new System.Windows.Forms.Button();
+ this.GrassAddToProjectButton = new System.Windows.Forms.Button();
+ this.HashLabel = new System.Windows.Forms.Label();
+ this.ArchetypeNameTextBox = new System.Windows.Forms.TextBox();
+ this.label7 = new System.Windows.Forms.Label();
+ this.PositionTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
+ this.GrassGoToButton = new System.Windows.Forms.Button();
+ this.label17 = new System.Windows.Forms.Label();
+ this.OptmizationThresholdNumericUpDown = new System.Windows.Forms.NumericUpDown();
+ this.BrushModeCheckBox = new System.Windows.Forms.CheckBox();
+ this.label8 = new System.Windows.Forms.Label();
+ this.tabControl1.SuspendLayout();
+ this.GrassBatchTab.SuspendLayout();
+ this.groupBox1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.OrientToTerrainNumericUpDown)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.LodFadeRangeNumericUpDown)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.LodFadeStartDistanceNumericUpDown)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.LodDistNumericUpDown)).BeginInit();
+ this.BrushTab.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.AoNumericUpDown)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ScaleNumericUpDown)).BeginInit();
+ this.brushSettingsGroupBox.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.DensityNumericUpDown)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.RadiusNumericUpDown)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.OptmizationThresholdNumericUpDown)).BeginInit();
this.SuspendLayout();
//
+ // tabControl1
+ //
+ this.tabControl1.Controls.Add(this.GrassBatchTab);
+ this.tabControl1.Controls.Add(this.BrushTab);
+ this.tabControl1.Location = new System.Drawing.Point(12, 65);
+ this.tabControl1.Name = "tabControl1";
+ this.tabControl1.SelectedIndex = 0;
+ this.tabControl1.Size = new System.Drawing.Size(486, 181);
+ this.tabControl1.TabIndex = 37;
+ //
+ // GrassBatchTab
+ //
+ this.GrassBatchTab.Controls.Add(this.groupBox1);
+ this.GrassBatchTab.Location = new System.Drawing.Point(4, 22);
+ this.GrassBatchTab.Name = "GrassBatchTab";
+ this.GrassBatchTab.Padding = new System.Windows.Forms.Padding(3);
+ this.GrassBatchTab.Size = new System.Drawing.Size(478, 155);
+ this.GrassBatchTab.TabIndex = 0;
+ this.GrassBatchTab.Text = "Grass Batch";
+ this.GrassBatchTab.UseVisualStyleBackColor = true;
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.label12);
+ this.groupBox1.Controls.Add(this.label11);
+ this.groupBox1.Controls.Add(this.OrientToTerrainNumericUpDown);
+ this.groupBox1.Controls.Add(this.ScaleRangeTextBox);
+ this.groupBox1.Controls.Add(this.label10);
+ this.groupBox1.Controls.Add(this.LodFadeRangeNumericUpDown);
+ this.groupBox1.Controls.Add(this.label9);
+ this.groupBox1.Controls.Add(this.LodFadeStartDistanceNumericUpDown);
+ this.groupBox1.Controls.Add(this.label6);
+ this.groupBox1.Controls.Add(this.LodDistNumericUpDown);
+ this.groupBox1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.groupBox1.Location = new System.Drawing.Point(12, 6);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(460, 143);
+ this.groupBox1.TabIndex = 42;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Batch";
+ //
+ // label12
+ //
+ this.label12.AutoSize = true;
+ this.label12.Location = new System.Drawing.Point(197, 24);
+ this.label12.Name = "label12";
+ this.label12.Size = new System.Drawing.Size(69, 13);
+ this.label12.TabIndex = 47;
+ this.label12.Text = "Scale Range";
+ //
+ // label11
+ //
+ this.label11.AutoSize = true;
+ this.label11.Location = new System.Drawing.Point(8, 102);
+ this.label11.Name = "label11";
+ this.label11.Size = new System.Drawing.Size(87, 13);
+ this.label11.TabIndex = 7;
+ this.label11.Text = "Orient To Terrain";
+ //
+ // OrientToTerrainNumericUpDown
+ //
+ this.OrientToTerrainNumericUpDown.DecimalPlaces = 1;
+ this.OrientToTerrainNumericUpDown.Location = new System.Drawing.Point(121, 100);
+ this.OrientToTerrainNumericUpDown.Maximum = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this.OrientToTerrainNumericUpDown.Name = "OrientToTerrainNumericUpDown";
+ this.OrientToTerrainNumericUpDown.Size = new System.Drawing.Size(61, 20);
+ this.OrientToTerrainNumericUpDown.TabIndex = 6;
+ this.OrientToTerrainNumericUpDown.ValueChanged += new System.EventHandler(this.OrientToTerrainNumericUpDown_ValueChanged);
+ //
+ // ScaleRangeTextBox
+ //
+ this.ScaleRangeTextBox.Location = new System.Drawing.Point(270, 21);
+ this.ScaleRangeTextBox.Name = "ScaleRangeTextBox";
+ this.ScaleRangeTextBox.Size = new System.Drawing.Size(166, 20);
+ this.ScaleRangeTextBox.TabIndex = 46;
+ this.ScaleRangeTextBox.TextChanged += new System.EventHandler(this.ScaleRangeTextBox_TextChanged);
+ //
+ // label10
+ //
+ this.label10.AutoSize = true;
+ this.label10.Location = new System.Drawing.Point(8, 76);
+ this.label10.Name = "label10";
+ this.label10.Size = new System.Drawing.Size(107, 13);
+ this.label10.TabIndex = 5;
+ this.label10.Text = "Lod Inst Fade Range";
+ //
+ // LodFadeRangeNumericUpDown
+ //
+ this.LodFadeRangeNumericUpDown.DecimalPlaces = 4;
+ this.LodFadeRangeNumericUpDown.Increment = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 65536});
+ this.LodFadeRangeNumericUpDown.Location = new System.Drawing.Point(121, 74);
+ this.LodFadeRangeNumericUpDown.Maximum = new decimal(new int[] {
+ 99999,
+ 0,
+ 0,
+ 0});
+ this.LodFadeRangeNumericUpDown.Name = "LodFadeRangeNumericUpDown";
+ this.LodFadeRangeNumericUpDown.Size = new System.Drawing.Size(61, 20);
+ this.LodFadeRangeNumericUpDown.TabIndex = 4;
+ this.LodFadeRangeNumericUpDown.ValueChanged += new System.EventHandler(this.LodFadeRangeNumericUpDown_ValueChanged);
+ //
+ // label9
+ //
+ this.label9.AutoSize = true;
+ this.label9.Location = new System.Drawing.Point(8, 50);
+ this.label9.Name = "label9";
+ this.label9.Size = new System.Drawing.Size(98, 13);
+ this.label9.TabIndex = 3;
+ this.label9.Text = "Lod Fade Start Dist";
+ //
+ // LodFadeStartDistanceNumericUpDown
+ //
+ this.LodFadeStartDistanceNumericUpDown.DecimalPlaces = 4;
+ this.LodFadeStartDistanceNumericUpDown.Location = new System.Drawing.Point(121, 48);
+ this.LodFadeStartDistanceNumericUpDown.Maximum = new decimal(new int[] {
+ 99999,
+ 0,
+ 0,
+ 0});
+ this.LodFadeStartDistanceNumericUpDown.Name = "LodFadeStartDistanceNumericUpDown";
+ this.LodFadeStartDistanceNumericUpDown.Size = new System.Drawing.Size(61, 20);
+ this.LodFadeStartDistanceNumericUpDown.TabIndex = 2;
+ this.LodFadeStartDistanceNumericUpDown.ValueChanged += new System.EventHandler(this.LodFadeStartDistanceNumericUpDown_ValueChanged);
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(8, 24);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(39, 13);
+ this.label6.TabIndex = 1;
+ this.label6.Text = "lodDist";
+ //
+ // LodDistNumericUpDown
+ //
+ this.LodDistNumericUpDown.Location = new System.Drawing.Point(121, 22);
+ this.LodDistNumericUpDown.Maximum = new decimal(new int[] {
+ 99999,
+ 0,
+ 0,
+ 0});
+ this.LodDistNumericUpDown.Name = "LodDistNumericUpDown";
+ this.LodDistNumericUpDown.Size = new System.Drawing.Size(61, 20);
+ this.LodDistNumericUpDown.TabIndex = 0;
+ this.LodDistNumericUpDown.ValueChanged += new System.EventHandler(this.LodDistNumericUpDown_ValueChanged);
+ //
+ // BrushTab
+ //
+ this.BrushTab.Controls.Add(this.groupBox2);
+ this.BrushTab.Controls.Add(this.brushSettingsGroupBox);
+ this.BrushTab.Location = new System.Drawing.Point(4, 22);
+ this.BrushTab.Name = "BrushTab";
+ this.BrushTab.Padding = new System.Windows.Forms.Padding(3);
+ this.BrushTab.Size = new System.Drawing.Size(478, 155);
+ this.BrushTab.TabIndex = 1;
+ this.BrushTab.Text = " Brush";
+ this.BrushTab.UseVisualStyleBackColor = true;
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.GrassColorLabel);
+ this.groupBox2.Controls.Add(this.label15);
+ this.groupBox2.Controls.Add(this.label4);
+ this.groupBox2.Controls.Add(this.AoNumericUpDown);
+ this.groupBox2.Controls.Add(this.PadTextBox);
+ this.groupBox2.Controls.Add(this.ScaleNumericUpDown);
+ this.groupBox2.Controls.Add(this.label2);
+ this.groupBox2.Controls.Add(this.label3);
+ this.groupBox2.Controls.Add(this.RandomizeScaleCheckBox);
+ this.groupBox2.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.groupBox2.Location = new System.Drawing.Point(191, 3);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(281, 146);
+ this.groupBox2.TabIndex = 39;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "Instance Settings";
+ //
+ // GrassColorLabel
+ //
+ this.GrassColorLabel.BackColor = System.Drawing.Color.White;
+ this.GrassColorLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.GrassColorLabel.Location = new System.Drawing.Point(50, 22);
+ this.GrassColorLabel.Name = "GrassColorLabel";
+ this.GrassColorLabel.Size = new System.Drawing.Size(119, 21);
+ this.GrassColorLabel.TabIndex = 12;
+ this.GrassColorLabel.Click += new System.EventHandler(this.GrassColorLabel_Click);
+ //
+ // label15
+ //
+ this.label15.AutoSize = true;
+ this.label15.Location = new System.Drawing.Point(9, 106);
+ this.label15.Name = "label15";
+ this.label15.Size = new System.Drawing.Size(26, 13);
+ this.label15.TabIndex = 46;
+ this.label15.Text = "Pad";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(9, 79);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(34, 13);
+ this.label4.TabIndex = 16;
+ this.label4.Text = "Scale";
+ //
+ // AoNumericUpDown
+ //
+ this.AoNumericUpDown.Location = new System.Drawing.Point(50, 51);
+ this.AoNumericUpDown.Maximum = new decimal(new int[] {
+ 255,
+ 0,
+ 0,
+ 0});
+ this.AoNumericUpDown.Name = "AoNumericUpDown";
+ this.AoNumericUpDown.Size = new System.Drawing.Size(120, 20);
+ this.AoNumericUpDown.TabIndex = 15;
+ this.AoNumericUpDown.Value = new decimal(new int[] {
+ 255,
+ 0,
+ 0,
+ 0});
+ //
+ // PadTextBox
+ //
+ this.PadTextBox.Location = new System.Drawing.Point(49, 103);
+ this.PadTextBox.Name = "PadTextBox";
+ this.PadTextBox.Size = new System.Drawing.Size(120, 20);
+ this.PadTextBox.TabIndex = 45;
+ this.PadTextBox.Text = "0, 0, 0";
+ //
+ // ScaleNumericUpDown
+ //
+ this.ScaleNumericUpDown.Location = new System.Drawing.Point(49, 77);
+ this.ScaleNumericUpDown.Maximum = new decimal(new int[] {
+ 255,
+ 0,
+ 0,
+ 0});
+ this.ScaleNumericUpDown.Name = "ScaleNumericUpDown";
+ this.ScaleNumericUpDown.Size = new System.Drawing.Size(120, 20);
+ this.ScaleNumericUpDown.TabIndex = 17;
+ this.ScaleNumericUpDown.Value = new decimal(new int[] {
+ 255,
+ 0,
+ 0,
+ 0});
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(9, 53);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(20, 13);
+ this.label2.TabIndex = 14;
+ this.label2.Text = "Ao";
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(9, 26);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(31, 13);
+ this.label3.TabIndex = 13;
+ this.label3.Text = "Color";
+ //
+ // RandomizeScaleCheckBox
+ //
+ this.RandomizeScaleCheckBox.AutoSize = true;
+ this.RandomizeScaleCheckBox.Location = new System.Drawing.Point(176, 79);
+ this.RandomizeScaleCheckBox.Name = "RandomizeScaleCheckBox";
+ this.RandomizeScaleCheckBox.Size = new System.Drawing.Size(66, 17);
+ this.RandomizeScaleCheckBox.TabIndex = 18;
+ this.RandomizeScaleCheckBox.Text = "Random";
+ this.RandomizeScaleCheckBox.UseVisualStyleBackColor = true;
+ //
+ // brushSettingsGroupBox
+ //
+ this.brushSettingsGroupBox.Controls.Add(this.DensityNumericUpDown);
+ this.brushSettingsGroupBox.Controls.Add(this.RadiusNumericUpDown);
+ this.brushSettingsGroupBox.Controls.Add(this.label5);
+ this.brushSettingsGroupBox.Controls.Add(this.radiusLabel);
+ this.brushSettingsGroupBox.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.brushSettingsGroupBox.Location = new System.Drawing.Point(8, 3);
+ this.brushSettingsGroupBox.Name = "brushSettingsGroupBox";
+ this.brushSettingsGroupBox.Size = new System.Drawing.Size(177, 146);
+ this.brushSettingsGroupBox.TabIndex = 38;
+ this.brushSettingsGroupBox.TabStop = false;
+ this.brushSettingsGroupBox.Text = "Brush Settings";
+ //
+ // DensityNumericUpDown
+ //
+ this.DensityNumericUpDown.Location = new System.Drawing.Point(76, 57);
+ this.DensityNumericUpDown.Maximum = new decimal(new int[] {
+ 128,
+ 0,
+ 0,
+ 0});
+ this.DensityNumericUpDown.Name = "DensityNumericUpDown";
+ this.DensityNumericUpDown.Size = new System.Drawing.Size(84, 20);
+ this.DensityNumericUpDown.TabIndex = 20;
+ this.DensityNumericUpDown.Value = new decimal(new int[] {
+ 28,
+ 0,
+ 0,
+ 0});
+ //
+ // RadiusNumericUpDown
+ //
+ this.RadiusNumericUpDown.DecimalPlaces = 2;
+ this.RadiusNumericUpDown.Increment = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 131072});
+ this.RadiusNumericUpDown.Location = new System.Drawing.Point(76, 31);
+ this.RadiusNumericUpDown.Name = "RadiusNumericUpDown";
+ this.RadiusNumericUpDown.Size = new System.Drawing.Size(84, 20);
+ this.RadiusNumericUpDown.TabIndex = 11;
+ this.RadiusNumericUpDown.Value = new decimal(new int[] {
+ 5,
+ 0,
+ 0,
+ 0});
+ this.RadiusNumericUpDown.ValueChanged += new System.EventHandler(this.RadiusNumericUpDown_ValueChanged);
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(21, 59);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(42, 13);
+ this.label5.TabIndex = 19;
+ this.label5.Text = "Density";
+ //
+ // radiusLabel
+ //
+ this.radiusLabel.AutoSize = true;
+ this.radiusLabel.Location = new System.Drawing.Point(21, 33);
+ this.radiusLabel.Name = "radiusLabel";
+ this.radiusLabel.Size = new System.Drawing.Size(40, 13);
+ this.radiusLabel.TabIndex = 10;
+ this.radiusLabel.Text = "Radius";
+ //
+ // OptimizeBatchButton
+ //
+ this.OptimizeBatchButton.Location = new System.Drawing.Point(16, 280);
+ this.OptimizeBatchButton.Name = "OptimizeBatchButton";
+ this.OptimizeBatchButton.Size = new System.Drawing.Size(108, 24);
+ this.OptimizeBatchButton.TabIndex = 70;
+ this.OptimizeBatchButton.Text = "Optimize Batch";
+ this.OptimizeBatchButtonTooltip.SetToolTip(this.OptimizeBatchButton, "Will split your batch into multiple different batches based on the threshold. If " +
+ "your threshold is 5.0 then each batch will have a size of 5.0 meters.");
+ this.OptimizeBatchButton.UseVisualStyleBackColor = true;
+ this.OptimizeBatchButton.Click += new System.EventHandler(this.OptimizeBatchButton_Click);
+ //
+ // ExtentsMinTextBox
+ //
+ this.ExtentsMinTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.ExtentsMinTextBox.Location = new System.Drawing.Point(84, 319);
+ this.ExtentsMinTextBox.Name = "ExtentsMinTextBox";
+ this.ExtentsMinTextBox.ReadOnly = true;
+ this.ExtentsMinTextBox.Size = new System.Drawing.Size(380, 20);
+ this.ExtentsMinTextBox.TabIndex = 55;
+ //
+ // label14
+ //
+ this.label14.AutoSize = true;
+ this.label14.Location = new System.Drawing.Point(13, 349);
+ this.label14.Name = "label14";
+ this.label14.Size = new System.Drawing.Size(68, 13);
+ this.label14.TabIndex = 54;
+ this.label14.Text = "Extents Max:";
+ //
+ // ExtentsMaxTextBox
+ //
+ this.ExtentsMaxTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.ExtentsMaxTextBox.Location = new System.Drawing.Point(84, 345);
+ this.ExtentsMaxTextBox.Name = "ExtentsMaxTextBox";
+ this.ExtentsMaxTextBox.ReadOnly = true;
+ this.ExtentsMaxTextBox.Size = new System.Drawing.Size(380, 20);
+ this.ExtentsMaxTextBox.TabIndex = 53;
+ //
+ // label13
+ //
+ this.label13.AutoSize = true;
+ this.label13.Location = new System.Drawing.Point(13, 322);
+ this.label13.Name = "label13";
+ this.label13.Size = new System.Drawing.Size(65, 13);
+ this.label13.TabIndex = 52;
+ this.label13.Text = "Extents Min:";
+ //
+ // GrassDeleteButton
+ //
+ this.GrassDeleteButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
+ this.GrassDeleteButton.Location = new System.Drawing.Point(257, 397);
+ this.GrassDeleteButton.Name = "GrassDeleteButton";
+ this.GrassDeleteButton.Size = new System.Drawing.Size(95, 23);
+ this.GrassDeleteButton.TabIndex = 51;
+ this.GrassDeleteButton.Text = "Delete Batch";
+ this.GrassDeleteButton.UseVisualStyleBackColor = true;
+ this.GrassDeleteButton.Click += new System.EventHandler(this.GrassDeleteButton_Click);
+ //
+ // GrassAddToProjectButton
+ //
+ this.GrassAddToProjectButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
+ this.GrassAddToProjectButton.Location = new System.Drawing.Point(159, 397);
+ this.GrassAddToProjectButton.Name = "GrassAddToProjectButton";
+ this.GrassAddToProjectButton.Size = new System.Drawing.Size(95, 23);
+ this.GrassAddToProjectButton.TabIndex = 50;
+ this.GrassAddToProjectButton.Text = "Add to Project";
+ this.GrassAddToProjectButton.UseVisualStyleBackColor = true;
+ this.GrassAddToProjectButton.Click += new System.EventHandler(this.GrassAddToProjectButton_Click);
+ //
+ // HashLabel
+ //
+ this.HashLabel.AutoSize = true;
+ this.HashLabel.Location = new System.Drawing.Point(254, 14);
+ this.HashLabel.Name = "HashLabel";
+ this.HashLabel.Size = new System.Drawing.Size(44, 13);
+ this.HashLabel.TabIndex = 61;
+ this.HashLabel.Text = "Hash: 0";
+ //
+ // ArchetypeNameTextBox
+ //
+ this.ArchetypeNameTextBox.Location = new System.Drawing.Point(66, 12);
+ this.ArchetypeNameTextBox.Name = "ArchetypeNameTextBox";
+ this.ArchetypeNameTextBox.Size = new System.Drawing.Size(144, 20);
+ this.ArchetypeNameTextBox.TabIndex = 60;
+ this.ArchetypeNameTextBox.TextChanged += new System.EventHandler(this.ArchetypeNameTextBox_TextChanged);
+ //
+ // label7
+ //
+ this.label7.AutoSize = true;
+ this.label7.Location = new System.Drawing.Point(16, 15);
+ this.label7.Name = "label7";
+ this.label7.Size = new System.Drawing.Size(35, 13);
+ this.label7.TabIndex = 59;
+ this.label7.Text = "Name";
+ //
+ // PositionTextBox
+ //
+ this.PositionTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.PositionTextBox.Location = new System.Drawing.Point(66, 39);
+ this.PositionTextBox.Name = "PositionTextBox";
+ this.PositionTextBox.ReadOnly = true;
+ this.PositionTextBox.Size = new System.Drawing.Size(275, 20);
+ this.PositionTextBox.TabIndex = 58;
+ //
// label1
//
this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(52, 52);
+ this.label1.Location = new System.Drawing.Point(16, 42);
this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(105, 13);
- this.label1.TabIndex = 0;
- this.label1.Text = "Grass editing TODO!";
+ this.label1.Size = new System.Drawing.Size(44, 13);
+ this.label1.TabIndex = 57;
+ this.label1.Text = "Position";
+ //
+ // GrassGoToButton
+ //
+ this.GrassGoToButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.GrassGoToButton.Location = new System.Drawing.Point(347, 36);
+ this.GrassGoToButton.Name = "GrassGoToButton";
+ this.GrassGoToButton.Size = new System.Drawing.Size(56, 23);
+ this.GrassGoToButton.TabIndex = 56;
+ this.GrassGoToButton.Text = "Go To";
+ this.GrassGoToButton.UseVisualStyleBackColor = true;
+ this.GrassGoToButton.Click += new System.EventHandler(this.GrassGoToButton_Click);
+ //
+ // label17
+ //
+ this.label17.AutoSize = true;
+ this.label17.Location = new System.Drawing.Point(130, 286);
+ this.label17.Name = "label17";
+ this.label17.Size = new System.Drawing.Size(54, 13);
+ this.label17.TabIndex = 71;
+ this.label17.Text = "Threshold";
+ //
+ // OptmizationThresholdNumericUpDown
+ //
+ this.OptmizationThresholdNumericUpDown.Location = new System.Drawing.Point(190, 284);
+ this.OptmizationThresholdNumericUpDown.Maximum = new decimal(new int[] {
+ 999999,
+ 0,
+ 0,
+ 0});
+ this.OptmizationThresholdNumericUpDown.Name = "OptmizationThresholdNumericUpDown";
+ this.OptmizationThresholdNumericUpDown.Size = new System.Drawing.Size(51, 20);
+ this.OptmizationThresholdNumericUpDown.TabIndex = 69;
+ this.OptmizationThresholdNumericUpDown.Value = new decimal(new int[] {
+ 5,
+ 0,
+ 0,
+ 0});
+ //
+ // BrushModeCheckBox
+ //
+ this.BrushModeCheckBox.AutoSize = true;
+ this.BrushModeCheckBox.Location = new System.Drawing.Point(16, 252);
+ this.BrushModeCheckBox.Name = "BrushModeCheckBox";
+ this.BrushModeCheckBox.Size = new System.Drawing.Size(83, 17);
+ this.BrushModeCheckBox.TabIndex = 68;
+ this.BrushModeCheckBox.Text = "Brush Mode";
+ this.BrushModeCheckBox.UseVisualStyleBackColor = true;
+ this.BrushModeCheckBox.CheckedChanged += new System.EventHandler(this.BrushModeCheckBox_CheckedChanged);
+ //
+ // label8
+ //
+ this.label8.AutoSize = true;
+ this.label8.Location = new System.Drawing.Point(211, 14);
+ this.label8.Name = "label8";
+ this.label8.Size = new System.Drawing.Size(24, 13);
+ this.label8.TabIndex = 72;
+ this.label8.Text = ".ydr";
+ this.label8.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// EditYmapGrassPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(554, 355);
+ this.ClientSize = new System.Drawing.Size(510, 443);
+ this.Controls.Add(this.label8);
+ this.Controls.Add(this.label17);
+ this.Controls.Add(this.OptmizationThresholdNumericUpDown);
+ this.Controls.Add(this.OptimizeBatchButton);
+ this.Controls.Add(this.BrushModeCheckBox);
+ this.Controls.Add(this.HashLabel);
+ this.Controls.Add(this.ExtentsMinTextBox);
+ this.Controls.Add(this.ArchetypeNameTextBox);
+ this.Controls.Add(this.ExtentsMaxTextBox);
+ this.Controls.Add(this.label7);
+ this.Controls.Add(this.PositionTextBox);
this.Controls.Add(this.label1);
+ this.Controls.Add(this.GrassGoToButton);
+ this.Controls.Add(this.label14);
+ this.Controls.Add(this.label13);
+ this.Controls.Add(this.GrassDeleteButton);
+ this.Controls.Add(this.tabControl1);
+ this.Controls.Add(this.GrassAddToProjectButton);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "EditYmapGrassPanel";
this.Text = "Grass Batch";
+ this.tabControl1.ResumeLayout(false);
+ this.GrassBatchTab.ResumeLayout(false);
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.OrientToTerrainNumericUpDown)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.LodFadeRangeNumericUpDown)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.LodFadeStartDistanceNumericUpDown)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.LodDistNumericUpDown)).EndInit();
+ this.BrushTab.ResumeLayout(false);
+ this.groupBox2.ResumeLayout(false);
+ this.groupBox2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.AoNumericUpDown)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.ScaleNumericUpDown)).EndInit();
+ this.brushSettingsGroupBox.ResumeLayout(false);
+ this.brushSettingsGroupBox.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.DensityNumericUpDown)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.RadiusNumericUpDown)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.OptmizationThresholdNumericUpDown)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@@ -57,6 +671,52 @@
#endregion
+ private System.Windows.Forms.TabControl tabControl1;
+ private System.Windows.Forms.TabPage GrassBatchTab;
+ private System.Windows.Forms.TabPage BrushTab;
+ private System.Windows.Forms.GroupBox brushSettingsGroupBox;
+ private System.Windows.Forms.NumericUpDown RadiusNumericUpDown;
+ private System.Windows.Forms.Label radiusLabel;
+ private System.Windows.Forms.NumericUpDown DensityNumericUpDown;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.NumericUpDown LodDistNumericUpDown;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.Label label9;
+ private System.Windows.Forms.NumericUpDown LodFadeStartDistanceNumericUpDown;
+ private System.Windows.Forms.Label label10;
+ private System.Windows.Forms.NumericUpDown LodFadeRangeNumericUpDown;
+ private System.Windows.Forms.Label label11;
+ private System.Windows.Forms.NumericUpDown OrientToTerrainNumericUpDown;
+ private System.Windows.Forms.Label label12;
+ private System.Windows.Forms.TextBox ScaleRangeTextBox;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.Label label15;
+ private System.Windows.Forms.TextBox PadTextBox;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label GrassColorLabel;
+ private System.Windows.Forms.CheckBox RandomizeScaleCheckBox;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.NumericUpDown ScaleNumericUpDown;
+ private System.Windows.Forms.NumericUpDown AoNumericUpDown;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.ToolTip OptimizeBatchButtonTooltip;
+ private System.Windows.Forms.TextBox ExtentsMinTextBox;
+ private System.Windows.Forms.Label label14;
+ private System.Windows.Forms.TextBox ExtentsMaxTextBox;
+ private System.Windows.Forms.Label label13;
+ private System.Windows.Forms.Button GrassDeleteButton;
+ private System.Windows.Forms.Button GrassAddToProjectButton;
+ private System.Windows.Forms.Label HashLabel;
+ private System.Windows.Forms.TextBox ArchetypeNameTextBox;
+ private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.TextBox PositionTextBox;
private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Button GrassGoToButton;
+ private System.Windows.Forms.Label label17;
+ private System.Windows.Forms.NumericUpDown OptmizationThresholdNumericUpDown;
+ private System.Windows.Forms.Button OptimizeBatchButton;
+ private System.Windows.Forms.CheckBox BrushModeCheckBox;
+ private System.Windows.Forms.Label label8;
}
}
\ No newline at end of file
diff --git a/Project/Panels/EditYmapGrassPanel.cs b/Project/Panels/EditYmapGrassPanel.cs
index 702ecb1..dedd9d1 100644
--- a/Project/Panels/EditYmapGrassPanel.cs
+++ b/Project/Panels/EditYmapGrassPanel.cs
@@ -1,22 +1,30 @@
-using CodeWalker.GameFiles;
-using System;
+using System;
using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.Windows.Forms;
+using CodeWalker.GameFiles;
+using CodeWalker.World;
+using SharpDX;
+
+// TODO
+// - COMPLETED -- Optimization feature.
+// - COMPLETED -- Remove grass instances using CTRL + SHIFT + LMB
+
+// - Better gizmo for grass brush (like a circle with a little line in the middle sticking upwards)
+// - Maybe some kind of auto coloring system? I've noticed that mostly all grass in GTA inherits it's color from the surface it's on.
+// - Grass area fill (generate grass on ydr based on colision materials?)
+// - Need to have a way to erase instances from other batches in the current batches ymap.
+// if we optimize our instances, we'd have to go through each batch to erase, this is very monotonous.
+
+// BUG
+// - I've added a "zoom" kind of feature when hitting the goto button, but when the bounds of the
+// grass batch are 0, the zoom of the camera is set to 0, which causes the end-user to have to scroll
+// out a lot in order to use any movement controls. I will need to clamp that to a minimum value.
namespace CodeWalker.Project.Panels
{
public partial class EditYmapGrassPanel : ProjectPanel
{
public ProjectForm ProjectForm;
- public YmapGrassInstanceBatch CurrentBatch { get; set; }
-
- //private bool populatingui = false;
public EditYmapGrassPanel(ProjectForm owner)
{
@@ -24,12 +32,44 @@ namespace CodeWalker.Project.Panels
InitializeComponent();
}
+ public YmapGrassInstanceBatch CurrentBatch { get; set; }
+
+ #region Form
+
public void SetBatch(YmapGrassInstanceBatch batch)
{
CurrentBatch = batch;
Tag = batch;
- LoadGrassBatch();
UpdateFormTitle();
+ UpdateControls();
+ }
+
+ private void UpdateControls()
+ {
+ if (ProjectForm?.CurrentProjectFile == null) return;
+ if (ProjectForm.GrassBatchExistsInProject(CurrentBatch))
+ {
+ GrassAddToProjectButton.Enabled = false;
+ GrassDeleteButton.Enabled = true;
+ }
+ else
+ {
+ GrassAddToProjectButton.Enabled = true;
+ GrassDeleteButton.Enabled = false;
+ }
+
+ ArchetypeNameTextBox.Text = CurrentBatch.Batch.archetypeName.ToString();
+ PositionTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.Position);
+ LodDistNumericUpDown.Value = CurrentBatch.Batch.lodDist;
+ LodFadeRangeNumericUpDown.Value = (decimal) CurrentBatch.Batch.LodInstFadeRange;
+ LodFadeStartDistanceNumericUpDown.Value = (decimal) CurrentBatch.Batch.LodFadeStartDist;
+ ScaleRangeTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.Batch.ScaleRange);
+ OrientToTerrainNumericUpDown.Value = (decimal)CurrentBatch.Batch.OrientToTerrain;
+ OptmizationThresholdNumericUpDown.Value = 15;
+ BrushModeCheckBox.Checked = CurrentBatch.BrushEnabled;
+ RadiusNumericUpDown.Value = (decimal)CurrentBatch.BrushRadius;
+ ExtentsMinTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.AABBMin);
+ ExtentsMaxTextBox.Text = FloatUtil.GetVector3String(CurrentBatch.AABBMax);
}
private void UpdateFormTitle()
@@ -37,11 +77,225 @@ namespace CodeWalker.Project.Panels
Text = CurrentBatch?.Batch.archetypeName.ToString() ?? "Grass Batch";
}
+ #endregion
+ #region Events
- private void LoadGrassBatch()
+ #region BrushSettings
+
+ private void GrassGoToButton_Click(object sender, EventArgs e)
{
+ if (CurrentBatch == null) return;
+ ProjectForm.WorldForm?.GoToPosition(CurrentBatch.Position, CurrentBatch.AABBMax - CurrentBatch.AABBMin);
}
+ private void GrassAddToProjectButton_Click(object sender, EventArgs e)
+ {
+ ProjectForm.SetProjectItem(CurrentBatch);
+ ProjectForm.AddGrassBatchToProject();
+ }
+
+ private void GrassDeleteButton_Click(object sender, EventArgs e)
+ {
+ ProjectForm.SetProjectItem(CurrentBatch);
+ var ymap = CurrentBatch?.Ymap;
+ if (!ProjectForm.DeleteGrassBatch()) return;
+
+ ymap?.CalcExtents(); // Recalculate the extents after deleting the grass batch.
+ ProjectForm.WorldForm.SelectItem();
+ }
+
+ private void GrassColorLabel_Click(object sender, EventArgs e)
+ {
+ var colDiag = new ColorDialog {Color = GrassColorLabel.BackColor};
+ if (colDiag.ShowDialog(this) == DialogResult.OK)
+ GrassColorLabel.BackColor = colDiag.Color;
+ }
+
+ private void BrushModeCheckBox_CheckedChanged(object sender, EventArgs e)
+ {
+ if (CurrentBatch == null) return;
+ CurrentBatch.BrushEnabled = BrushModeCheckBox.Checked;
+ }
+
+ private void RadiusNumericUpDown_ValueChanged(object sender, EventArgs e)
+ {
+ if (CurrentBatch == null) return;
+ CurrentBatch.BrushRadius = (float)RadiusNumericUpDown.Value;
+ }
+ #endregion
+
+ #region Batch Settings
+
+ private void ArchetypeNameTextBox_TextChanged(object sender, EventArgs e)
+ {
+ var archetypeHash = JenkHash.GenHash(ArchetypeNameTextBox.Text);
+ var archetype = ProjectForm.GameFileCache.GetArchetype(archetypeHash);
+ if (archetype == null)
+ {
+ HashLabel.Text = $@"Hash: {archetypeHash} (invalid)";
+ return;
+ }
+ CurrentBatch.Archetype = archetype;
+ var b = CurrentBatch.Batch;
+ b.archetypeName = archetypeHash;
+ CurrentBatch.Batch = b;
+ ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
+ HashLabel.Text = $@"Hash: {archetypeHash}";
+ UpdateFormTitle();
+ CurrentBatch.HasChanged = true;
+ ProjectForm.SetGrassBatchHasChanged(false);
+ ProjectForm.SetYmapHasChanged(true);
+ }
+
+ private void LodDistNumericUpDown_ValueChanged(object sender, EventArgs e)
+ {
+ var batch = CurrentBatch.Batch;
+ batch.lodDist = (uint) LodDistNumericUpDown.Value;
+ CurrentBatch.Batch = batch;
+ ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
+ ProjectForm.SetYmapHasChanged(true);
+ }
+
+ private void LodFadeStartDistanceNumericUpDown_ValueChanged(object sender, EventArgs e)
+ {
+ var batch = CurrentBatch.Batch;
+ batch.LodFadeStartDist = (float) LodFadeStartDistanceNumericUpDown.Value;
+ CurrentBatch.Batch = batch;
+ ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
+ ProjectForm.SetYmapHasChanged(true);
+ }
+
+ private void LodFadeRangeNumericUpDown_ValueChanged(object sender, EventArgs e)
+ {
+ var batch = CurrentBatch.Batch;
+ batch.LodInstFadeRange = (float) LodFadeRangeNumericUpDown.Value;
+ CurrentBatch.Batch = batch;
+ ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
+ ProjectForm.SetYmapHasChanged(true);
+ }
+
+ private void OrientToTerrainNumericUpDown_ValueChanged(object sender, EventArgs e)
+ {
+ var batch = CurrentBatch.Batch;
+ batch.OrientToTerrain = (float) OrientToTerrainNumericUpDown.Value;
+ CurrentBatch.Batch = batch;
+ ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
+ ProjectForm.SetYmapHasChanged(true);
+ }
+
+ private void ScaleRangeTextBox_TextChanged(object sender, EventArgs e)
+ {
+ var batch = CurrentBatch.Batch;
+ var v = FloatUtil.ParseVector3String(ScaleRangeTextBox.Text);
+ batch.ScaleRange = v;
+ CurrentBatch.Batch = batch;
+ ProjectForm.WorldForm.UpdateGrassBatchGraphics(CurrentBatch);
+ ProjectForm.SetYmapHasChanged(true);
+ }
+
+ private void OptimizeBatchButton_Click(object sender, EventArgs e)
+ {
+ if (CurrentBatch.Instances == null || CurrentBatch.Instances.Length <= 0) return;
+ lock (ProjectForm.WorldForm.RenderSyncRoot)
+ {
+ var newBatches = CurrentBatch?.OptimizeInstances(CurrentBatch, (float)OptmizationThresholdNumericUpDown.Value);
+ if (newBatches == null || newBatches.Length <= 0) return;
+
+ // Remove our batch from the ymap
+ CurrentBatch.Ymap.RemoveGrassBatch(CurrentBatch);
+ foreach (var batch in newBatches)
+ {
+ var b = batch.Batch;
+ b.lodDist = CurrentBatch.Batch.lodDist;
+ b.LodInstFadeRange = CurrentBatch.Batch.LodInstFadeRange;
+ b.LodFadeStartDist = CurrentBatch.Batch.LodFadeStartDist;
+ b.ScaleRange = CurrentBatch.Batch.ScaleRange;
+ b.OrientToTerrain = CurrentBatch.Batch.OrientToTerrain;
+ b.archetypeName = CurrentBatch.Batch.archetypeName;
+ batch.Batch = b;
+ batch.Archetype = CurrentBatch.Archetype;
+ batch.UpdateInstanceCount();
+ ProjectForm.NewGrassBatch(batch);
+ }
+ CurrentBatch.Ymap.CalcExtents();
+ CurrentBatch.Ymap.Save();
+
+ // TODO: Select the last grass batch in the new list on the project explorer.
+ ProjectForm.ProjectExplorer.TrySelectGrassBatchTreeNode(CurrentBatch.Ymap.GrassInstanceBatches[0]);
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Publics
+
+ public void CreateInstancesAtMouse(SpaceRayIntersectResult mouseRay)
+ {
+ var wf = ProjectForm.WorldForm;
+ if (wf == null) return;
+
+ lock (wf.RenderSyncRoot)
+ {
+ CurrentBatch.CreateInstancesAtMouse(
+ CurrentBatch,
+ mouseRay,
+ (float) RadiusNumericUpDown.Value,
+ (int) DensityNumericUpDown.Value,
+ SpawnRayFunc,
+ new Color(GrassColorLabel.BackColor.R, GrassColorLabel.BackColor.G, GrassColorLabel.BackColor.B),
+ (int) AoNumericUpDown.Value,
+ (int) ScaleNumericUpDown.Value,
+ FloatUtil.ParseVector3String(PadTextBox.Text),
+ RandomizeScaleCheckBox.Checked
+ );
+ wf.UpdateGrassBatchGraphics(CurrentBatch);
+ }
+
+ BatchChanged();
+ }
+
+ public void EraseInstancesAtMouse(SpaceRayIntersectResult mouseRay)
+ {
+ var wf = ProjectForm.WorldForm;
+ if (wf == null) return;
+ var changed = false;
+ lock (wf.RenderSyncRoot)
+ {
+ if (CurrentBatch.EraseInstancesAtMouse(
+ CurrentBatch,
+ mouseRay,
+ (float) RadiusNumericUpDown.Value
+ ))
+ {
+ wf.UpdateGrassBatchGraphics(CurrentBatch);
+ changed = true;
+ }
+ }
+
+ if (changed) BatchChanged();
+ }
+
+ #endregion
+
+ #region Privates
+
+ private SpaceRayIntersectResult SpawnRayFunc(Vector3 spawnPos)
+ {
+ var res = ProjectForm.WorldForm.Raycast(new Ray(spawnPos, -Vector3.UnitZ));
+ return res;
+ }
+
+ private void BatchChanged()
+ {
+ UpdateControls();
+ CurrentBatch.UpdateInstanceCount();
+ CurrentBatch.HasChanged = true;
+ ProjectForm.SetGrassBatchHasChanged(false);
+ }
+
+ #endregion
}
-}
+}
\ No newline at end of file
diff --git a/Project/Panels/EditYmapGrassPanel.resx b/Project/Panels/EditYmapGrassPanel.resx
index 1431f6b..6a9df94 100644
--- a/Project/Panels/EditYmapGrassPanel.resx
+++ b/Project/Panels/EditYmapGrassPanel.resx
@@ -117,6 +117,9 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 17, 17
+
diff --git a/Project/Panels/ProjectExplorerPanel.cs b/Project/Panels/ProjectExplorerPanel.cs
index f83fc13..027b2e4 100644
--- a/Project/Panels/ProjectExplorerPanel.cs
+++ b/Project/Panels/ProjectExplorerPanel.cs
@@ -641,6 +641,20 @@ namespace CodeWalker.Project.Panels
}
}
}
+ public void SetGrassBatchHasChanged(YmapGrassInstanceBatch batch, bool changed)
+ {
+ if (ProjectTreeView.Nodes.Count > 0)
+ {
+ var gbnode = FindGrassTreeNode(batch);
+ if (gbnode == null) return;
+ string changestr = changed ? "*" : "";
+ if (gbnode.Tag == batch)
+ {
+ string name = batch.ToString();
+ gbnode.Text = changestr + name;
+ }
+ }
+ }
@@ -698,6 +712,21 @@ namespace CodeWalker.Project.Panels
}
return null;
}
+ public TreeNode FindGrassTreeNode(YmapGrassInstanceBatch batch)
+ {
+ if (batch == null) return null;
+ TreeNode ymapnode = FindYmapTreeNode(batch.Ymap);
+ if (ymapnode == null) return null;
+ var batchnode = GetChildTreeNode(ymapnode, "GrassBatches");
+ if (batchnode == null) return null;
+ for (int i = 0; i < batchnode.Nodes.Count; i++)
+ {
+ TreeNode grassnode = batchnode.Nodes[i];
+ if (grassnode.Tag == batch) return grassnode;
+ }
+ return null;
+ }
+
public TreeNode FindYndTreeNode(YndFile ynd)
{
if (ProjectTreeView.Nodes.Count <= 0) return null;
@@ -930,6 +959,21 @@ namespace CodeWalker.Project.Panels
}
}
}
+ public void TrySelectGrassBatchTreeNode(YmapGrassInstanceBatch grassBatch)
+ {
+ TreeNode grassNode = FindGrassTreeNode(grassBatch);
+ if (grassNode != null)
+ {
+ if (ProjectTreeView.SelectedNode == grassNode)
+ {
+ OnItemSelected?.Invoke(grassNode);
+ }
+ else
+ {
+ ProjectTreeView.SelectedNode = grassNode;
+ }
+ }
+ }
public void TrySelectPathNodeTreeNode(YndNode node)
{
TreeNode tnode = FindPathNodeTreeNode(node);
@@ -1240,6 +1284,16 @@ namespace CodeWalker.Project.Panels
tn.Parent.Nodes.Remove(tn);
}
}
+
+ public void RemoveGrassBatchTreeNode(YmapGrassInstanceBatch batch)
+ {
+ var tn = FindGrassTreeNode(batch);
+ if ((tn != null) && (tn.Parent != null))
+ {
+ tn.Parent.Text = "Grass Batches (" + batch.Ymap.GrassInstanceBatches.Length.ToString() + ")";
+ tn.Parent.Nodes.Remove(tn);
+ }
+ }
public void RemovePathNodeTreeNode(YndNode node)
{
var tn = FindPathNodeTreeNode(node);
diff --git a/Project/ProjectForm.Designer.cs b/Project/ProjectForm.Designer.cs
index be220cc..00e8469 100644
--- a/Project/ProjectForm.Designer.cs
+++ b/Project/ProjectForm.Designer.cs
@@ -58,6 +58,14 @@
this.FileSaveItemMenu = new System.Windows.Forms.ToolStripMenuItem();
this.FileSaveItemAsMenu = new System.Windows.Forms.ToolStripMenuItem();
this.EditMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.EditUndoMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.EditRedoMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator();
+ this.EditCutMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.EditCopyMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.EditPasteMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.EditCloneMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.EditDeleteMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ViewMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ViewProjectExplorerMenu = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
@@ -65,6 +73,55 @@
this.ViewThemeBlueMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ViewThemeLightMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ViewThemeDarkMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YmapMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YmapNameMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
+ this.YmapNewEntityMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YmapNewCarGenMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YmapNewGrassBatchMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
+ this.YmapAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YmapRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YtypMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YtypNameMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator();
+ this.YtypNewArchetypeMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator();
+ this.YtypAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YtypRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YndMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YndNameMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator();
+ this.YndNewNodeMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator16 = new System.Windows.Forms.ToolStripSeparator();
+ this.YndAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YndRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YnvMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YnvNameMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator17 = new System.Windows.Forms.ToolStripSeparator();
+ this.YnvNewPolygonMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator18 = new System.Windows.Forms.ToolStripSeparator();
+ this.YnvAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.YnvRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.TrainsMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.TrainsNameMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator19 = new System.Windows.Forms.ToolStripSeparator();
+ this.TrainsNewNodeMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator20 = new System.Windows.Forms.ToolStripSeparator();
+ this.TrainsAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.TrainsRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioNameMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator21 = new System.Windows.Forms.ToolStripSeparator();
+ this.ScenarioNewPointMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioNewPointFromSelectedMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioNewEntityOverrideMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioNewChainMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioNewClusterMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioImportChainMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.toolStripSeparator22 = new System.Windows.Forms.ToolStripSeparator();
+ this.ScenarioAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this.ScenarioRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ToolsMenu = new System.Windows.Forms.ToolStripMenuItem();
this.ToolsManifestGeneratorMenu = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
@@ -98,62 +155,6 @@
this.ToolbarSaveButton = new System.Windows.Forms.ToolStripButton();
this.ToolbarSaveAllButton = new System.Windows.Forms.ToolStripButton();
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
- this.EditUndoMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.EditRedoMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator10 = new System.Windows.Forms.ToolStripSeparator();
- this.EditCutMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.EditCopyMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.EditPasteMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.EditDeleteMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.EditCloneMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YmapMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YtypMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YndMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YnvMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.TrainsMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YmapNameMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator11 = new System.Windows.Forms.ToolStripSeparator();
- this.YmapNewEntityMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YmapNewCarGenMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
- this.YmapAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YmapRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YtypNameMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator13 = new System.Windows.Forms.ToolStripSeparator();
- this.YtypNewArchetypeMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YndNameMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator();
- this.toolStripSeparator15 = new System.Windows.Forms.ToolStripSeparator();
- this.YtypAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YtypRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YndNewNodeMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator16 = new System.Windows.Forms.ToolStripSeparator();
- this.YndAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YndRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YnvNameMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator17 = new System.Windows.Forms.ToolStripSeparator();
- this.YnvNewPolygonMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator18 = new System.Windows.Forms.ToolStripSeparator();
- this.YnvAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.YnvRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.TrainsNameMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator19 = new System.Windows.Forms.ToolStripSeparator();
- this.TrainsNewNodeMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator20 = new System.Windows.Forms.ToolStripSeparator();
- this.TrainsAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.TrainsRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioNameMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator21 = new System.Windows.Forms.ToolStripSeparator();
- this.ScenarioNewPointMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioNewPointFromSelectedMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioNewEntityOverrideMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioNewChainMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioNewClusterMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioImportChainMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.toolStripSeparator22 = new System.Windows.Forms.ToolStripSeparator();
- this.ScenarioAddToProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
- this.ScenarioRemoveFromProjectMenu = new System.Windows.Forms.ToolStripMenuItem();
this.MainMenu.SuspendLayout();
this.MainToolbar.SuspendLayout();
this.SuspendLayout();
@@ -399,6 +400,66 @@
this.EditMenu.Size = new System.Drawing.Size(39, 20);
this.EditMenu.Text = "Edit";
//
+ // EditUndoMenu
+ //
+ this.EditUndoMenu.Enabled = false;
+ this.EditUndoMenu.Name = "EditUndoMenu";
+ this.EditUndoMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));
+ this.EditUndoMenu.Size = new System.Drawing.Size(190, 22);
+ this.EditUndoMenu.Text = "Undo";
+ //
+ // EditRedoMenu
+ //
+ this.EditRedoMenu.Enabled = false;
+ this.EditRedoMenu.Name = "EditRedoMenu";
+ this.EditRedoMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y)));
+ this.EditRedoMenu.Size = new System.Drawing.Size(190, 22);
+ this.EditRedoMenu.Text = "Redo";
+ //
+ // toolStripSeparator10
+ //
+ this.toolStripSeparator10.Name = "toolStripSeparator10";
+ this.toolStripSeparator10.Size = new System.Drawing.Size(187, 6);
+ //
+ // EditCutMenu
+ //
+ this.EditCutMenu.Enabled = false;
+ this.EditCutMenu.Name = "EditCutMenu";
+ this.EditCutMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
+ this.EditCutMenu.Size = new System.Drawing.Size(190, 22);
+ this.EditCutMenu.Text = "Cut Item";
+ //
+ // EditCopyMenu
+ //
+ this.EditCopyMenu.Enabled = false;
+ this.EditCopyMenu.Name = "EditCopyMenu";
+ this.EditCopyMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
+ this.EditCopyMenu.Size = new System.Drawing.Size(190, 22);
+ this.EditCopyMenu.Text = "Copy Item";
+ //
+ // EditPasteMenu
+ //
+ this.EditPasteMenu.Enabled = false;
+ this.EditPasteMenu.Name = "EditPasteMenu";
+ this.EditPasteMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
+ this.EditPasteMenu.Size = new System.Drawing.Size(190, 22);
+ this.EditPasteMenu.Text = "Paste Item";
+ //
+ // EditCloneMenu
+ //
+ this.EditCloneMenu.Enabled = false;
+ this.EditCloneMenu.Name = "EditCloneMenu";
+ this.EditCloneMenu.Size = new System.Drawing.Size(190, 22);
+ this.EditCloneMenu.Text = "Clone Item";
+ //
+ // EditDeleteMenu
+ //
+ this.EditDeleteMenu.Enabled = false;
+ this.EditDeleteMenu.Name = "EditDeleteMenu";
+ this.EditDeleteMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Delete)));
+ this.EditDeleteMenu.Size = new System.Drawing.Size(190, 22);
+ this.EditDeleteMenu.Text = "Delete Item";
+ //
// ViewMenu
//
this.ViewMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -454,6 +515,399 @@
this.ViewThemeDarkMenu.Text = "Dark";
this.ViewThemeDarkMenu.Click += new System.EventHandler(this.ViewThemeDarkMenu_Click);
//
+ // YmapMenu
+ //
+ this.YmapMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.YmapNameMenu,
+ this.toolStripSeparator11,
+ this.YmapNewEntityMenu,
+ this.YmapNewCarGenMenu,
+ this.YmapNewGrassBatchMenu,
+ this.toolStripSeparator12,
+ this.YmapAddToProjectMenu,
+ this.YmapRemoveFromProjectMenu});
+ this.YmapMenu.Name = "YmapMenu";
+ this.YmapMenu.Size = new System.Drawing.Size(49, 20);
+ this.YmapMenu.Text = "Ymap";
+ this.YmapMenu.Visible = false;
+ //
+ // YmapNameMenu
+ //
+ this.YmapNameMenu.Enabled = false;
+ this.YmapNameMenu.Name = "YmapNameMenu";
+ this.YmapNameMenu.Size = new System.Drawing.Size(199, 22);
+ this.YmapNameMenu.Text = "(No .ymap file selected)";
+ //
+ // toolStripSeparator11
+ //
+ this.toolStripSeparator11.Name = "toolStripSeparator11";
+ this.toolStripSeparator11.Size = new System.Drawing.Size(196, 6);
+ //
+ // YmapNewEntityMenu
+ //
+ this.YmapNewEntityMenu.Enabled = false;
+ this.YmapNewEntityMenu.Name = "YmapNewEntityMenu";
+ this.YmapNewEntityMenu.Size = new System.Drawing.Size(199, 22);
+ this.YmapNewEntityMenu.Text = "New Entity";
+ this.YmapNewEntityMenu.Click += new System.EventHandler(this.YmapNewEntityMenu_Click);
+ //
+ // YmapNewCarGenMenu
+ //
+ this.YmapNewCarGenMenu.Enabled = false;
+ this.YmapNewCarGenMenu.Name = "YmapNewCarGenMenu";
+ this.YmapNewCarGenMenu.Size = new System.Drawing.Size(199, 22);
+ this.YmapNewCarGenMenu.Text = "New Car Generator";
+ this.YmapNewCarGenMenu.Click += new System.EventHandler(this.YmapNewCarGenMenu_Click);
+ //
+ // YmapNewGrassBatchMenu
+ //
+ this.YmapNewGrassBatchMenu.Enabled = false;
+ this.YmapNewGrassBatchMenu.Name = "YmapNewGrassBatchMenu";
+ this.YmapNewGrassBatchMenu.Size = new System.Drawing.Size(199, 22);
+ this.YmapNewGrassBatchMenu.Text = "New Grass Batch";
+ this.YmapNewGrassBatchMenu.Click += new System.EventHandler(this.YmapNewGrassBatchMenu_Click);
+ //
+ // toolStripSeparator12
+ //
+ this.toolStripSeparator12.Name = "toolStripSeparator12";
+ this.toolStripSeparator12.Size = new System.Drawing.Size(196, 6);
+ //
+ // YmapAddToProjectMenu
+ //
+ this.YmapAddToProjectMenu.Enabled = false;
+ this.YmapAddToProjectMenu.Name = "YmapAddToProjectMenu";
+ this.YmapAddToProjectMenu.Size = new System.Drawing.Size(199, 22);
+ this.YmapAddToProjectMenu.Text = "Add to Project";
+ this.YmapAddToProjectMenu.Click += new System.EventHandler(this.YmapAddToProjectMenu_Click);
+ //
+ // YmapRemoveFromProjectMenu
+ //
+ this.YmapRemoveFromProjectMenu.Enabled = false;
+ this.YmapRemoveFromProjectMenu.Name = "YmapRemoveFromProjectMenu";
+ this.YmapRemoveFromProjectMenu.Size = new System.Drawing.Size(199, 22);
+ this.YmapRemoveFromProjectMenu.Text = "Remove from Project";
+ this.YmapRemoveFromProjectMenu.Click += new System.EventHandler(this.YmapRemoveFromProjectMenu_Click);
+ //
+ // YtypMenu
+ //
+ this.YtypMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.YtypNameMenu,
+ this.toolStripSeparator13,
+ this.YtypNewArchetypeMenu,
+ this.toolStripSeparator15,
+ this.YtypAddToProjectMenu,
+ this.YtypRemoveFromProjectMenu});
+ this.YtypMenu.Name = "YtypMenu";
+ this.YtypMenu.Size = new System.Drawing.Size(43, 20);
+ this.YtypMenu.Text = "Ytyp";
+ this.YtypMenu.Visible = false;
+ //
+ // YtypNameMenu
+ //
+ this.YtypNameMenu.Enabled = false;
+ this.YtypNameMenu.Name = "YtypNameMenu";
+ this.YtypNameMenu.Size = new System.Drawing.Size(192, 22);
+ this.YtypNameMenu.Text = "(No .ytyp file selected)";
+ //
+ // toolStripSeparator13
+ //
+ this.toolStripSeparator13.Name = "toolStripSeparator13";
+ this.toolStripSeparator13.Size = new System.Drawing.Size(189, 6);
+ //
+ // YtypNewArchetypeMenu
+ //
+ this.YtypNewArchetypeMenu.Enabled = false;
+ this.YtypNewArchetypeMenu.Name = "YtypNewArchetypeMenu";
+ this.YtypNewArchetypeMenu.Size = new System.Drawing.Size(192, 22);
+ this.YtypNewArchetypeMenu.Text = "New Archetype";
+ this.YtypNewArchetypeMenu.Click += new System.EventHandler(this.YtypNewArchetypeMenu_Click);
+ //
+ // toolStripSeparator15
+ //
+ this.toolStripSeparator15.Name = "toolStripSeparator15";
+ this.toolStripSeparator15.Size = new System.Drawing.Size(189, 6);
+ //
+ // YtypAddToProjectMenu
+ //
+ this.YtypAddToProjectMenu.Enabled = false;
+ this.YtypAddToProjectMenu.Name = "YtypAddToProjectMenu";
+ this.YtypAddToProjectMenu.Size = new System.Drawing.Size(192, 22);
+ this.YtypAddToProjectMenu.Text = "Add to Project";
+ this.YtypAddToProjectMenu.Click += new System.EventHandler(this.YtypAddToProjectMenu_Click);
+ //
+ // YtypRemoveFromProjectMenu
+ //
+ this.YtypRemoveFromProjectMenu.Enabled = false;
+ this.YtypRemoveFromProjectMenu.Name = "YtypRemoveFromProjectMenu";
+ this.YtypRemoveFromProjectMenu.Size = new System.Drawing.Size(192, 22);
+ this.YtypRemoveFromProjectMenu.Text = "Remove from Project";
+ this.YtypRemoveFromProjectMenu.Click += new System.EventHandler(this.YtypRemoveFromProjectMenu_Click);
+ //
+ // YndMenu
+ //
+ this.YndMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.YndNameMenu,
+ this.toolStripSeparator14,
+ this.YndNewNodeMenu,
+ this.toolStripSeparator16,
+ this.YndAddToProjectMenu,
+ this.YndRemoveFromProjectMenu});
+ this.YndMenu.Name = "YndMenu";
+ this.YndMenu.Size = new System.Drawing.Size(39, 20);
+ this.YndMenu.Text = "Ynd";
+ this.YndMenu.Visible = false;
+ //
+ // YndNameMenu
+ //
+ this.YndNameMenu.Enabled = false;
+ this.YndNameMenu.Name = "YndNameMenu";
+ this.YndNameMenu.Size = new System.Drawing.Size(189, 22);
+ this.YndNameMenu.Text = "(No .ynd file selected)";
+ //
+ // toolStripSeparator14
+ //
+ this.toolStripSeparator14.Name = "toolStripSeparator14";
+ this.toolStripSeparator14.Size = new System.Drawing.Size(186, 6);
+ //
+ // YndNewNodeMenu
+ //
+ this.YndNewNodeMenu.Enabled = false;
+ this.YndNewNodeMenu.Name = "YndNewNodeMenu";
+ this.YndNewNodeMenu.Size = new System.Drawing.Size(189, 22);
+ this.YndNewNodeMenu.Text = "New Node";
+ this.YndNewNodeMenu.Click += new System.EventHandler(this.YndNewNodeMenu_Click);
+ //
+ // toolStripSeparator16
+ //
+ this.toolStripSeparator16.Name = "toolStripSeparator16";
+ this.toolStripSeparator16.Size = new System.Drawing.Size(186, 6);
+ //
+ // YndAddToProjectMenu
+ //
+ this.YndAddToProjectMenu.Enabled = false;
+ this.YndAddToProjectMenu.Name = "YndAddToProjectMenu";
+ this.YndAddToProjectMenu.Size = new System.Drawing.Size(189, 22);
+ this.YndAddToProjectMenu.Text = "Add to Project";
+ this.YndAddToProjectMenu.Click += new System.EventHandler(this.YndAddToProjectMenu_Click);
+ //
+ // YndRemoveFromProjectMenu
+ //
+ this.YndRemoveFromProjectMenu.Enabled = false;
+ this.YndRemoveFromProjectMenu.Name = "YndRemoveFromProjectMenu";
+ this.YndRemoveFromProjectMenu.Size = new System.Drawing.Size(189, 22);
+ this.YndRemoveFromProjectMenu.Text = "Remove from Project";
+ this.YndRemoveFromProjectMenu.Click += new System.EventHandler(this.YndRemoveFromProjectMenu_Click);
+ //
+ // YnvMenu
+ //
+ this.YnvMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.YnvNameMenu,
+ this.toolStripSeparator17,
+ this.YnvNewPolygonMenu,
+ this.toolStripSeparator18,
+ this.YnvAddToProjectMenu,
+ this.YnvRemoveFromProjectMenu});
+ this.YnvMenu.Name = "YnvMenu";
+ this.YnvMenu.Size = new System.Drawing.Size(38, 20);
+ this.YnvMenu.Text = "Ynv";
+ this.YnvMenu.Visible = false;
+ //
+ // YnvNameMenu
+ //
+ this.YnvNameMenu.Enabled = false;
+ this.YnvNameMenu.Name = "YnvNameMenu";
+ this.YnvNameMenu.Size = new System.Drawing.Size(188, 22);
+ this.YnvNameMenu.Text = "(No .ynv file selected)";
+ //
+ // toolStripSeparator17
+ //
+ this.toolStripSeparator17.Name = "toolStripSeparator17";
+ this.toolStripSeparator17.Size = new System.Drawing.Size(185, 6);
+ //
+ // YnvNewPolygonMenu
+ //
+ this.YnvNewPolygonMenu.Enabled = false;
+ this.YnvNewPolygonMenu.Name = "YnvNewPolygonMenu";
+ this.YnvNewPolygonMenu.Size = new System.Drawing.Size(188, 22);
+ this.YnvNewPolygonMenu.Text = "New Polygon";
+ this.YnvNewPolygonMenu.Click += new System.EventHandler(this.YnvNewPolygonMenu_Click);
+ //
+ // toolStripSeparator18
+ //
+ this.toolStripSeparator18.Name = "toolStripSeparator18";
+ this.toolStripSeparator18.Size = new System.Drawing.Size(185, 6);
+ //
+ // YnvAddToProjectMenu
+ //
+ this.YnvAddToProjectMenu.Enabled = false;
+ this.YnvAddToProjectMenu.Name = "YnvAddToProjectMenu";
+ this.YnvAddToProjectMenu.Size = new System.Drawing.Size(188, 22);
+ this.YnvAddToProjectMenu.Text = "Add to Project";
+ this.YnvAddToProjectMenu.Click += new System.EventHandler(this.YnvAddToProjectMenu_Click);
+ //
+ // YnvRemoveFromProjectMenu
+ //
+ this.YnvRemoveFromProjectMenu.Enabled = false;
+ this.YnvRemoveFromProjectMenu.Name = "YnvRemoveFromProjectMenu";
+ this.YnvRemoveFromProjectMenu.Size = new System.Drawing.Size(188, 22);
+ this.YnvRemoveFromProjectMenu.Text = "Remove from Project";
+ this.YnvRemoveFromProjectMenu.Click += new System.EventHandler(this.YnvRemoveFromProjectMenu_Click);
+ //
+ // TrainsMenu
+ //
+ this.TrainsMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.TrainsNameMenu,
+ this.toolStripSeparator19,
+ this.TrainsNewNodeMenu,
+ this.toolStripSeparator20,
+ this.TrainsAddToProjectMenu,
+ this.TrainsRemoveFromProjectMenu});
+ this.TrainsMenu.Name = "TrainsMenu";
+ this.TrainsMenu.Size = new System.Drawing.Size(50, 20);
+ this.TrainsMenu.Text = "Trains";
+ this.TrainsMenu.Visible = false;
+ //
+ // TrainsNameMenu
+ //
+ this.TrainsNameMenu.Enabled = false;
+ this.TrainsNameMenu.Name = "TrainsNameMenu";
+ this.TrainsNameMenu.Size = new System.Drawing.Size(200, 22);
+ this.TrainsNameMenu.Text = "(No train track selected)";
+ //
+ // toolStripSeparator19
+ //
+ this.toolStripSeparator19.Name = "toolStripSeparator19";
+ this.toolStripSeparator19.Size = new System.Drawing.Size(197, 6);
+ //
+ // TrainsNewNodeMenu
+ //
+ this.TrainsNewNodeMenu.Enabled = false;
+ this.TrainsNewNodeMenu.Name = "TrainsNewNodeMenu";
+ this.TrainsNewNodeMenu.Size = new System.Drawing.Size(200, 22);
+ this.TrainsNewNodeMenu.Text = "New Node";
+ this.TrainsNewNodeMenu.Click += new System.EventHandler(this.TrainsNewNodeMenu_Click);
+ //
+ // toolStripSeparator20
+ //
+ this.toolStripSeparator20.Name = "toolStripSeparator20";
+ this.toolStripSeparator20.Size = new System.Drawing.Size(197, 6);
+ //
+ // TrainsAddToProjectMenu
+ //
+ this.TrainsAddToProjectMenu.Enabled = false;
+ this.TrainsAddToProjectMenu.Name = "TrainsAddToProjectMenu";
+ this.TrainsAddToProjectMenu.Size = new System.Drawing.Size(200, 22);
+ this.TrainsAddToProjectMenu.Text = "Add to Project";
+ this.TrainsAddToProjectMenu.Click += new System.EventHandler(this.TrainsAddToProjectMenu_Click);
+ //
+ // TrainsRemoveFromProjectMenu
+ //
+ this.TrainsRemoveFromProjectMenu.Enabled = false;
+ this.TrainsRemoveFromProjectMenu.Name = "TrainsRemoveFromProjectMenu";
+ this.TrainsRemoveFromProjectMenu.Size = new System.Drawing.Size(200, 22);
+ this.TrainsRemoveFromProjectMenu.Text = "Remove from Project";
+ this.TrainsRemoveFromProjectMenu.Click += new System.EventHandler(this.TrainsRemoveFromProjectMenu_Click);
+ //
+ // ScenarioMenu
+ //
+ this.ScenarioMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.ScenarioNameMenu,
+ this.toolStripSeparator21,
+ this.ScenarioNewPointMenu,
+ this.ScenarioNewPointFromSelectedMenu,
+ this.ScenarioNewEntityOverrideMenu,
+ this.ScenarioNewChainMenu,
+ this.ScenarioNewClusterMenu,
+ this.ScenarioImportChainMenu,
+ this.toolStripSeparator22,
+ this.ScenarioAddToProjectMenu,
+ this.ScenarioRemoveFromProjectMenu});
+ this.ScenarioMenu.Name = "ScenarioMenu";
+ this.ScenarioMenu.Size = new System.Drawing.Size(64, 20);
+ this.ScenarioMenu.Text = "Scenario";
+ this.ScenarioMenu.Visible = false;
+ //
+ // ScenarioNameMenu
+ //
+ this.ScenarioNameMenu.Enabled = false;
+ this.ScenarioNameMenu.Name = "ScenarioNameMenu";
+ this.ScenarioNameMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioNameMenu.Text = "(No scenario region selected)";
+ //
+ // toolStripSeparator21
+ //
+ this.toolStripSeparator21.Name = "toolStripSeparator21";
+ this.toolStripSeparator21.Size = new System.Drawing.Size(225, 6);
+ //
+ // ScenarioNewPointMenu
+ //
+ this.ScenarioNewPointMenu.Enabled = false;
+ this.ScenarioNewPointMenu.Name = "ScenarioNewPointMenu";
+ this.ScenarioNewPointMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioNewPointMenu.Text = "New Point (Blank)";
+ this.ScenarioNewPointMenu.Click += new System.EventHandler(this.ScenarioNewPointMenu_Click);
+ //
+ // ScenarioNewPointFromSelectedMenu
+ //
+ this.ScenarioNewPointFromSelectedMenu.Enabled = false;
+ this.ScenarioNewPointFromSelectedMenu.Name = "ScenarioNewPointFromSelectedMenu";
+ this.ScenarioNewPointFromSelectedMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioNewPointFromSelectedMenu.Text = "New Point (from Selected)";
+ this.ScenarioNewPointFromSelectedMenu.Click += new System.EventHandler(this.ScenarioNewPointFromSelectedMenu_Click);
+ //
+ // ScenarioNewEntityOverrideMenu
+ //
+ this.ScenarioNewEntityOverrideMenu.Enabled = false;
+ this.ScenarioNewEntityOverrideMenu.Name = "ScenarioNewEntityOverrideMenu";
+ this.ScenarioNewEntityOverrideMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioNewEntityOverrideMenu.Text = "New Entity Override";
+ this.ScenarioNewEntityOverrideMenu.Click += new System.EventHandler(this.ScenarioNewEntityOverrideMenu_Click);
+ //
+ // ScenarioNewChainMenu
+ //
+ this.ScenarioNewChainMenu.Enabled = false;
+ this.ScenarioNewChainMenu.Name = "ScenarioNewChainMenu";
+ this.ScenarioNewChainMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioNewChainMenu.Text = "New Chain";
+ this.ScenarioNewChainMenu.Click += new System.EventHandler(this.ScenarioNewChainMenu_Click);
+ //
+ // ScenarioNewClusterMenu
+ //
+ this.ScenarioNewClusterMenu.Enabled = false;
+ this.ScenarioNewClusterMenu.Name = "ScenarioNewClusterMenu";
+ this.ScenarioNewClusterMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioNewClusterMenu.Text = "New Cluster";
+ this.ScenarioNewClusterMenu.Click += new System.EventHandler(this.ScenarioNewClusterMenu_Click);
+ //
+ // ScenarioImportChainMenu
+ //
+ this.ScenarioImportChainMenu.Enabled = false;
+ this.ScenarioImportChainMenu.Name = "ScenarioImportChainMenu";
+ this.ScenarioImportChainMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioImportChainMenu.Text = "Import Chain...";
+ this.ScenarioImportChainMenu.Click += new System.EventHandler(this.ScenarioImportChainMenu_Click);
+ //
+ // toolStripSeparator22
+ //
+ this.toolStripSeparator22.Name = "toolStripSeparator22";
+ this.toolStripSeparator22.Size = new System.Drawing.Size(225, 6);
+ //
+ // ScenarioAddToProjectMenu
+ //
+ this.ScenarioAddToProjectMenu.Enabled = false;
+ this.ScenarioAddToProjectMenu.Name = "ScenarioAddToProjectMenu";
+ this.ScenarioAddToProjectMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioAddToProjectMenu.Text = "Add to Project";
+ this.ScenarioAddToProjectMenu.Click += new System.EventHandler(this.ScenarioAddToProjectMenu_Click);
+ //
+ // ScenarioRemoveFromProjectMenu
+ //
+ this.ScenarioRemoveFromProjectMenu.Enabled = false;
+ this.ScenarioRemoveFromProjectMenu.Name = "ScenarioRemoveFromProjectMenu";
+ this.ScenarioRemoveFromProjectMenu.Size = new System.Drawing.Size(228, 22);
+ this.ScenarioRemoveFromProjectMenu.Text = "Remove from Project";
+ this.ScenarioRemoveFromProjectMenu.Click += new System.EventHandler(this.ScenarioRemoveFromProjectMenu_Click);
+ //
// ToolsMenu
//
this.ToolsMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -720,451 +1174,7 @@
this.toolStripSeparator5.Name = "toolStripSeparator5";
this.toolStripSeparator5.Size = new System.Drawing.Size(6, 25);
//
- // EditUndoMenu
- //
- this.EditUndoMenu.Enabled = false;
- this.EditUndoMenu.Name = "EditUndoMenu";
- this.EditUndoMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));
- this.EditUndoMenu.Size = new System.Drawing.Size(190, 22);
- this.EditUndoMenu.Text = "Undo";
- //
- // EditRedoMenu
- //
- this.EditRedoMenu.Enabled = false;
- this.EditRedoMenu.Name = "EditRedoMenu";
- this.EditRedoMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y)));
- this.EditRedoMenu.Size = new System.Drawing.Size(190, 22);
- this.EditRedoMenu.Text = "Redo";
- //
- // toolStripSeparator10
- //
- this.toolStripSeparator10.Name = "toolStripSeparator10";
- this.toolStripSeparator10.Size = new System.Drawing.Size(187, 6);
- //
- // EditCutMenu
- //
- this.EditCutMenu.Enabled = false;
- this.EditCutMenu.Name = "EditCutMenu";
- this.EditCutMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X)));
- this.EditCutMenu.Size = new System.Drawing.Size(190, 22);
- this.EditCutMenu.Text = "Cut Item";
- //
- // EditCopyMenu
- //
- this.EditCopyMenu.Enabled = false;
- this.EditCopyMenu.Name = "EditCopyMenu";
- this.EditCopyMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C)));
- this.EditCopyMenu.Size = new System.Drawing.Size(190, 22);
- this.EditCopyMenu.Text = "Copy Item";
- //
- // EditPasteMenu
- //
- this.EditPasteMenu.Enabled = false;
- this.EditPasteMenu.Name = "EditPasteMenu";
- this.EditPasteMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V)));
- this.EditPasteMenu.Size = new System.Drawing.Size(190, 22);
- this.EditPasteMenu.Text = "Paste Item";
- //
- // EditDeleteMenu
- //
- this.EditDeleteMenu.Enabled = false;
- this.EditDeleteMenu.Name = "EditDeleteMenu";
- this.EditDeleteMenu.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Shift | System.Windows.Forms.Keys.Delete)));
- this.EditDeleteMenu.Size = new System.Drawing.Size(190, 22);
- this.EditDeleteMenu.Text = "Delete Item";
- //
- // EditCloneMenu
- //
- this.EditCloneMenu.Enabled = false;
- this.EditCloneMenu.Name = "EditCloneMenu";
- this.EditCloneMenu.Size = new System.Drawing.Size(190, 22);
- this.EditCloneMenu.Text = "Clone Item";
- //
- // YmapMenu
- //
- this.YmapMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.YmapNameMenu,
- this.toolStripSeparator11,
- this.YmapNewEntityMenu,
- this.YmapNewCarGenMenu,
- this.toolStripSeparator12,
- this.YmapAddToProjectMenu,
- this.YmapRemoveFromProjectMenu});
- this.YmapMenu.Name = "YmapMenu";
- this.YmapMenu.Size = new System.Drawing.Size(49, 20);
- this.YmapMenu.Text = "Ymap";
- this.YmapMenu.Visible = false;
- //
- // YtypMenu
- //
- this.YtypMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.YtypNameMenu,
- this.toolStripSeparator13,
- this.YtypNewArchetypeMenu,
- this.toolStripSeparator15,
- this.YtypAddToProjectMenu,
- this.YtypRemoveFromProjectMenu});
- this.YtypMenu.Name = "YtypMenu";
- this.YtypMenu.Size = new System.Drawing.Size(43, 20);
- this.YtypMenu.Text = "Ytyp";
- this.YtypMenu.Visible = false;
- //
- // YndMenu
- //
- this.YndMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.YndNameMenu,
- this.toolStripSeparator14,
- this.YndNewNodeMenu,
- this.toolStripSeparator16,
- this.YndAddToProjectMenu,
- this.YndRemoveFromProjectMenu});
- this.YndMenu.Name = "YndMenu";
- this.YndMenu.Size = new System.Drawing.Size(39, 20);
- this.YndMenu.Text = "Ynd";
- this.YndMenu.Visible = false;
- //
- // YnvMenu
- //
- this.YnvMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.YnvNameMenu,
- this.toolStripSeparator17,
- this.YnvNewPolygonMenu,
- this.toolStripSeparator18,
- this.YnvAddToProjectMenu,
- this.YnvRemoveFromProjectMenu});
- this.YnvMenu.Name = "YnvMenu";
- this.YnvMenu.Size = new System.Drawing.Size(38, 20);
- this.YnvMenu.Text = "Ynv";
- this.YnvMenu.Visible = false;
- //
- // TrainsMenu
- //
- this.TrainsMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.TrainsNameMenu,
- this.toolStripSeparator19,
- this.TrainsNewNodeMenu,
- this.toolStripSeparator20,
- this.TrainsAddToProjectMenu,
- this.TrainsRemoveFromProjectMenu});
- this.TrainsMenu.Name = "TrainsMenu";
- this.TrainsMenu.Size = new System.Drawing.Size(50, 20);
- this.TrainsMenu.Text = "Trains";
- this.TrainsMenu.Visible = false;
- //
- // ScenarioMenu
- //
- this.ScenarioMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.ScenarioNameMenu,
- this.toolStripSeparator21,
- this.ScenarioNewPointMenu,
- this.ScenarioNewPointFromSelectedMenu,
- this.ScenarioNewEntityOverrideMenu,
- this.ScenarioNewChainMenu,
- this.ScenarioNewClusterMenu,
- this.ScenarioImportChainMenu,
- this.toolStripSeparator22,
- this.ScenarioAddToProjectMenu,
- this.ScenarioRemoveFromProjectMenu});
- this.ScenarioMenu.Name = "ScenarioMenu";
- this.ScenarioMenu.Size = new System.Drawing.Size(64, 20);
- this.ScenarioMenu.Text = "Scenario";
- this.ScenarioMenu.Visible = false;
- //
- // YmapNameMenu
- //
- this.YmapNameMenu.Enabled = false;
- this.YmapNameMenu.Name = "YmapNameMenu";
- this.YmapNameMenu.Size = new System.Drawing.Size(199, 22);
- this.YmapNameMenu.Text = "(No .ymap file selected)";
- //
- // toolStripSeparator11
- //
- this.toolStripSeparator11.Name = "toolStripSeparator11";
- this.toolStripSeparator11.Size = new System.Drawing.Size(196, 6);
- //
- // YmapNewEntityMenu
- //
- this.YmapNewEntityMenu.Enabled = false;
- this.YmapNewEntityMenu.Name = "YmapNewEntityMenu";
- this.YmapNewEntityMenu.Size = new System.Drawing.Size(199, 22);
- this.YmapNewEntityMenu.Text = "New Entity";
- this.YmapNewEntityMenu.Click += new System.EventHandler(this.YmapNewEntityMenu_Click);
- //
- // YmapNewCarGenMenu
- //
- this.YmapNewCarGenMenu.Enabled = false;
- this.YmapNewCarGenMenu.Name = "YmapNewCarGenMenu";
- this.YmapNewCarGenMenu.Size = new System.Drawing.Size(199, 22);
- this.YmapNewCarGenMenu.Text = "New Car Generator";
- this.YmapNewCarGenMenu.Click += new System.EventHandler(this.YmapNewCarGenMenu_Click);
- //
- // toolStripSeparator12
- //
- this.toolStripSeparator12.Name = "toolStripSeparator12";
- this.toolStripSeparator12.Size = new System.Drawing.Size(196, 6);
- //
- // YmapAddToProjectMenu
- //
- this.YmapAddToProjectMenu.Enabled = false;
- this.YmapAddToProjectMenu.Name = "YmapAddToProjectMenu";
- this.YmapAddToProjectMenu.Size = new System.Drawing.Size(199, 22);
- this.YmapAddToProjectMenu.Text = "Add to Project";
- this.YmapAddToProjectMenu.Click += new System.EventHandler(this.YmapAddToProjectMenu_Click);
- //
- // YmapRemoveFromProjectMenu
- //
- this.YmapRemoveFromProjectMenu.Enabled = false;
- this.YmapRemoveFromProjectMenu.Name = "YmapRemoveFromProjectMenu";
- this.YmapRemoveFromProjectMenu.Size = new System.Drawing.Size(199, 22);
- this.YmapRemoveFromProjectMenu.Text = "Remove from Project";
- this.YmapRemoveFromProjectMenu.Click += new System.EventHandler(this.YmapRemoveFromProjectMenu_Click);
- //
- // YtypNameMenu
- //
- this.YtypNameMenu.Enabled = false;
- this.YtypNameMenu.Name = "YtypNameMenu";
- this.YtypNameMenu.Size = new System.Drawing.Size(192, 22);
- this.YtypNameMenu.Text = "(No .ytyp file selected)";
- //
- // toolStripSeparator13
- //
- this.toolStripSeparator13.Name = "toolStripSeparator13";
- this.toolStripSeparator13.Size = new System.Drawing.Size(189, 6);
- //
- // YtypNewArchetypeMenu
- //
- this.YtypNewArchetypeMenu.Enabled = false;
- this.YtypNewArchetypeMenu.Name = "YtypNewArchetypeMenu";
- this.YtypNewArchetypeMenu.Size = new System.Drawing.Size(192, 22);
- this.YtypNewArchetypeMenu.Text = "New Archetype";
- this.YtypNewArchetypeMenu.Click += new System.EventHandler(this.YtypNewArchetypeMenu_Click);
- //
- // YndNameMenu
- //
- this.YndNameMenu.Enabled = false;
- this.YndNameMenu.Name = "YndNameMenu";
- this.YndNameMenu.Size = new System.Drawing.Size(189, 22);
- this.YndNameMenu.Text = "(No .ynd file selected)";
- //
- // toolStripSeparator14
- //
- this.toolStripSeparator14.Name = "toolStripSeparator14";
- this.toolStripSeparator14.Size = new System.Drawing.Size(186, 6);
- //
- // toolStripSeparator15
- //
- this.toolStripSeparator15.Name = "toolStripSeparator15";
- this.toolStripSeparator15.Size = new System.Drawing.Size(189, 6);
- //
- // YtypAddToProjectMenu
- //
- this.YtypAddToProjectMenu.Enabled = false;
- this.YtypAddToProjectMenu.Name = "YtypAddToProjectMenu";
- this.YtypAddToProjectMenu.Size = new System.Drawing.Size(192, 22);
- this.YtypAddToProjectMenu.Text = "Add to Project";
- this.YtypAddToProjectMenu.Click += new System.EventHandler(this.YtypAddToProjectMenu_Click);
- //
- // YtypRemoveFromProjectMenu
- //
- this.YtypRemoveFromProjectMenu.Enabled = false;
- this.YtypRemoveFromProjectMenu.Name = "YtypRemoveFromProjectMenu";
- this.YtypRemoveFromProjectMenu.Size = new System.Drawing.Size(192, 22);
- this.YtypRemoveFromProjectMenu.Text = "Remove from Project";
- this.YtypRemoveFromProjectMenu.Click += new System.EventHandler(this.YtypRemoveFromProjectMenu_Click);
- //
- // YndNewNodeMenu
- //
- this.YndNewNodeMenu.Enabled = false;
- this.YndNewNodeMenu.Name = "YndNewNodeMenu";
- this.YndNewNodeMenu.Size = new System.Drawing.Size(189, 22);
- this.YndNewNodeMenu.Text = "New Node";
- this.YndNewNodeMenu.Click += new System.EventHandler(this.YndNewNodeMenu_Click);
- //
- // toolStripSeparator16
- //
- this.toolStripSeparator16.Name = "toolStripSeparator16";
- this.toolStripSeparator16.Size = new System.Drawing.Size(186, 6);
- //
- // YndAddToProjectMenu
- //
- this.YndAddToProjectMenu.Enabled = false;
- this.YndAddToProjectMenu.Name = "YndAddToProjectMenu";
- this.YndAddToProjectMenu.Size = new System.Drawing.Size(189, 22);
- this.YndAddToProjectMenu.Text = "Add to Project";
- this.YndAddToProjectMenu.Click += new System.EventHandler(this.YndAddToProjectMenu_Click);
- //
- // YndRemoveFromProjectMenu
- //
- this.YndRemoveFromProjectMenu.Enabled = false;
- this.YndRemoveFromProjectMenu.Name = "YndRemoveFromProjectMenu";
- this.YndRemoveFromProjectMenu.Size = new System.Drawing.Size(189, 22);
- this.YndRemoveFromProjectMenu.Text = "Remove from Project";
- this.YndRemoveFromProjectMenu.Click += new System.EventHandler(this.YndRemoveFromProjectMenu_Click);
- //
- // YnvNameMenu
- //
- this.YnvNameMenu.Enabled = false;
- this.YnvNameMenu.Name = "YnvNameMenu";
- this.YnvNameMenu.Size = new System.Drawing.Size(188, 22);
- this.YnvNameMenu.Text = "(No .ynv file selected)";
- //
- // toolStripSeparator17
- //
- this.toolStripSeparator17.Name = "toolStripSeparator17";
- this.toolStripSeparator17.Size = new System.Drawing.Size(185, 6);
- //
- // YnvNewPolygonMenu
- //
- this.YnvNewPolygonMenu.Enabled = false;
- this.YnvNewPolygonMenu.Name = "YnvNewPolygonMenu";
- this.YnvNewPolygonMenu.Size = new System.Drawing.Size(188, 22);
- this.YnvNewPolygonMenu.Text = "New Polygon";
- this.YnvNewPolygonMenu.Click += new System.EventHandler(this.YnvNewPolygonMenu_Click);
- //
- // toolStripSeparator18
- //
- this.toolStripSeparator18.Name = "toolStripSeparator18";
- this.toolStripSeparator18.Size = new System.Drawing.Size(185, 6);
- //
- // YnvAddToProjectMenu
- //
- this.YnvAddToProjectMenu.Enabled = false;
- this.YnvAddToProjectMenu.Name = "YnvAddToProjectMenu";
- this.YnvAddToProjectMenu.Size = new System.Drawing.Size(188, 22);
- this.YnvAddToProjectMenu.Text = "Add to Project";
- this.YnvAddToProjectMenu.Click += new System.EventHandler(this.YnvAddToProjectMenu_Click);
- //
- // YnvRemoveFromProjectMenu
- //
- this.YnvRemoveFromProjectMenu.Enabled = false;
- this.YnvRemoveFromProjectMenu.Name = "YnvRemoveFromProjectMenu";
- this.YnvRemoveFromProjectMenu.Size = new System.Drawing.Size(188, 22);
- this.YnvRemoveFromProjectMenu.Text = "Remove from Project";
- this.YnvRemoveFromProjectMenu.Click += new System.EventHandler(this.YnvRemoveFromProjectMenu_Click);
- //
- // TrainsNameMenu
- //
- this.TrainsNameMenu.Enabled = false;
- this.TrainsNameMenu.Name = "TrainsNameMenu";
- this.TrainsNameMenu.Size = new System.Drawing.Size(200, 22);
- this.TrainsNameMenu.Text = "(No train track selected)";
- //
- // toolStripSeparator19
- //
- this.toolStripSeparator19.Name = "toolStripSeparator19";
- this.toolStripSeparator19.Size = new System.Drawing.Size(197, 6);
- //
- // TrainsNewNodeMenu
- //
- this.TrainsNewNodeMenu.Enabled = false;
- this.TrainsNewNodeMenu.Name = "TrainsNewNodeMenu";
- this.TrainsNewNodeMenu.Size = new System.Drawing.Size(200, 22);
- this.TrainsNewNodeMenu.Text = "New Node";
- this.TrainsNewNodeMenu.Click += new System.EventHandler(this.TrainsNewNodeMenu_Click);
- //
- // toolStripSeparator20
- //
- this.toolStripSeparator20.Name = "toolStripSeparator20";
- this.toolStripSeparator20.Size = new System.Drawing.Size(197, 6);
- //
- // TrainsAddToProjectMenu
- //
- this.TrainsAddToProjectMenu.Enabled = false;
- this.TrainsAddToProjectMenu.Name = "TrainsAddToProjectMenu";
- this.TrainsAddToProjectMenu.Size = new System.Drawing.Size(200, 22);
- this.TrainsAddToProjectMenu.Text = "Add to Project";
- this.TrainsAddToProjectMenu.Click += new System.EventHandler(this.TrainsAddToProjectMenu_Click);
- //
- // TrainsRemoveFromProjectMenu
- //
- this.TrainsRemoveFromProjectMenu.Enabled = false;
- this.TrainsRemoveFromProjectMenu.Name = "TrainsRemoveFromProjectMenu";
- this.TrainsRemoveFromProjectMenu.Size = new System.Drawing.Size(200, 22);
- this.TrainsRemoveFromProjectMenu.Text = "Remove from Project";
- this.TrainsRemoveFromProjectMenu.Click += new System.EventHandler(this.TrainsRemoveFromProjectMenu_Click);
- //
- // ScenarioNameMenu
- //
- this.ScenarioNameMenu.Enabled = false;
- this.ScenarioNameMenu.Name = "ScenarioNameMenu";
- this.ScenarioNameMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioNameMenu.Text = "(No scenario region selected)";
- //
- // toolStripSeparator21
- //
- this.toolStripSeparator21.Name = "toolStripSeparator21";
- this.toolStripSeparator21.Size = new System.Drawing.Size(225, 6);
- //
- // ScenarioNewPointMenu
- //
- this.ScenarioNewPointMenu.Enabled = false;
- this.ScenarioNewPointMenu.Name = "ScenarioNewPointMenu";
- this.ScenarioNewPointMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioNewPointMenu.Text = "New Point (Blank)";
- this.ScenarioNewPointMenu.Click += new System.EventHandler(this.ScenarioNewPointMenu_Click);
- //
- // ScenarioNewPointFromSelectedMenu
- //
- this.ScenarioNewPointFromSelectedMenu.Enabled = false;
- this.ScenarioNewPointFromSelectedMenu.Name = "ScenarioNewPointFromSelectedMenu";
- this.ScenarioNewPointFromSelectedMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioNewPointFromSelectedMenu.Text = "New Point (from Selected)";
- this.ScenarioNewPointFromSelectedMenu.Click += new System.EventHandler(this.ScenarioNewPointFromSelectedMenu_Click);
- //
- // ScenarioNewEntityOverrideMenu
- //
- this.ScenarioNewEntityOverrideMenu.Enabled = false;
- this.ScenarioNewEntityOverrideMenu.Name = "ScenarioNewEntityOverrideMenu";
- this.ScenarioNewEntityOverrideMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioNewEntityOverrideMenu.Text = "New Entity Override";
- this.ScenarioNewEntityOverrideMenu.Click += new System.EventHandler(this.ScenarioNewEntityOverrideMenu_Click);
- //
- // ScenarioNewChainMenu
- //
- this.ScenarioNewChainMenu.Enabled = false;
- this.ScenarioNewChainMenu.Name = "ScenarioNewChainMenu";
- this.ScenarioNewChainMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioNewChainMenu.Text = "New Chain";
- this.ScenarioNewChainMenu.Click += new System.EventHandler(this.ScenarioNewChainMenu_Click);
- //
- // ScenarioNewClusterMenu
- //
- this.ScenarioNewClusterMenu.Enabled = false;
- this.ScenarioNewClusterMenu.Name = "ScenarioNewClusterMenu";
- this.ScenarioNewClusterMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioNewClusterMenu.Text = "New Cluster";
- this.ScenarioNewClusterMenu.Click += new System.EventHandler(this.ScenarioNewClusterMenu_Click);
- //
- // ScenarioImportChainMenu
- //
- this.ScenarioImportChainMenu.Enabled = false;
- this.ScenarioImportChainMenu.Name = "ScenarioImportChainMenu";
- this.ScenarioImportChainMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioImportChainMenu.Text = "Import Chain...";
- this.ScenarioImportChainMenu.Click += new System.EventHandler(this.ScenarioImportChainMenu_Click);
- //
- // toolStripSeparator22
- //
- this.toolStripSeparator22.Name = "toolStripSeparator22";
- this.toolStripSeparator22.Size = new System.Drawing.Size(225, 6);
- //
- // ScenarioAddToProjectMenu
- //
- this.ScenarioAddToProjectMenu.Enabled = false;
- this.ScenarioAddToProjectMenu.Name = "ScenarioAddToProjectMenu";
- this.ScenarioAddToProjectMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioAddToProjectMenu.Text = "Add to Project";
- this.ScenarioAddToProjectMenu.Click += new System.EventHandler(this.ScenarioAddToProjectMenu_Click);
- //
- // ScenarioRemoveFromProjectMenu
- //
- this.ScenarioRemoveFromProjectMenu.Enabled = false;
- this.ScenarioRemoveFromProjectMenu.Name = "ScenarioRemoveFromProjectMenu";
- this.ScenarioRemoveFromProjectMenu.Size = new System.Drawing.Size(228, 22);
- this.ScenarioRemoveFromProjectMenu.Text = "Remove from Project";
- this.ScenarioRemoveFromProjectMenu.Click += new System.EventHandler(this.ScenarioRemoveFromProjectMenu_Click);
- //
- // ProjectForm2
+ // ProjectForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
@@ -1175,7 +1185,7 @@
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.IsMdiContainer = true;
this.MainMenuStrip = this.MainMenu;
- this.Name = "ProjectForm2";
+ this.Name = "ProjectForm";
this.Text = "Project - CodeWalker by dexyfex";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ProjectForm_FormClosing);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ProjectForm_FormClosed);
@@ -1314,5 +1324,6 @@
private System.Windows.Forms.ToolStripSeparator toolStripSeparator22;
private System.Windows.Forms.ToolStripMenuItem ScenarioAddToProjectMenu;
private System.Windows.Forms.ToolStripMenuItem ScenarioRemoveFromProjectMenu;
+ private System.Windows.Forms.ToolStripMenuItem YmapNewGrassBatchMenu;
}
}
\ No newline at end of file
diff --git a/Project/ProjectForm.cs b/Project/ProjectForm.cs
index 24d7e59..3a9b906 100644
--- a/Project/ProjectForm.cs
+++ b/Project/ProjectForm.cs
@@ -104,7 +104,6 @@ namespace CodeWalker.Project
RpfMan = GameFileCache.RpfMan;
})).Start();
}
-
}
private void UpdateStatus(string text)
@@ -705,6 +704,25 @@ namespace CodeWalker.Project
//######## Public methods
+ // Possibly future proofing for procedural prop instances
+ public bool CanPaintInstances()
+ {
+ if (CurrentGrassBatch != null)
+ {
+ if (CurrentGrassBatch.BrushEnabled)
+ return true;
+ }
+
+ return false;
+ }
+ public float GetInstanceBrushRadius()
+ {
+ if (CurrentGrassBatch != null)
+ return CurrentGrassBatch.BrushRadius;
+
+ return 0f;
+ }
+
public void NewProject()
{
if (CurrentProjectFile != null)
@@ -1270,6 +1288,10 @@ namespace CodeWalker.Project
{
ProjectExplorer?.TrySelectCarGenTreeNode(CurrentCarGen);
}
+ else if (CurrentGrassBatch != null)
+ {
+ ProjectExplorer?.TrySelectGrassBatchTreeNode(CurrentGrassBatch);
+ }
}
public void RemoveYmapFromProject()
{
@@ -1435,6 +1457,155 @@ namespace CodeWalker.Project
return CurrentEntity == ent;
}
+ public void NewGrassBatch(YmapGrassInstanceBatch copy = null)
+ {
+ if (CurrentYmapFile == null) return;
+
+ rage__fwGrassInstanceListDef fwBatch = new rage__fwGrassInstanceListDef();
+ rage__fwGrassInstanceListDef__InstanceData[] instances = new rage__fwGrassInstanceListDef__InstanceData[0];
+
+ if (copy != null)
+ {
+ fwBatch = copy.Batch;
+ instances = copy.Instances;
+ }
+ else
+ {
+ fwBatch.archetypeName = new MetaHash(JenkHash.GenHash("proc_grasses01"));
+ fwBatch.lodDist = 120;
+ fwBatch.LodFadeStartDist = 15;
+ fwBatch.LodInstFadeRange = 0.75f;
+ fwBatch.OrientToTerrain = 1.0f;
+ fwBatch.ScaleRange = new Vector3(0.3f, 0.2f, 0.7f);
+ }
+
+ YmapGrassInstanceBatch batch = new YmapGrassInstanceBatch
+ {
+ AABBMin = fwBatch.BatchAABB.min.XYZ(),
+ AABBMax = fwBatch.BatchAABB.max.XYZ(),
+ Archetype = GameFileCache.GetArchetype(fwBatch.archetypeName),
+ Batch = fwBatch,
+ Instances = instances
+ };
+
+ batch.Position = (batch.AABBMin + batch.AABBMax) * 0.5f;
+ batch.Radius = (batch.AABBMax - batch.AABBMin).Length() * 0.5f;
+ batch.Ymap = CurrentYmapFile;
+
+ if (WorldForm != null)
+ {
+ lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
+ {
+ CurrentYmapFile.AddGrassBatch(batch);
+ }
+ }
+ else
+ {
+ CurrentYmapFile.AddGrassBatch(batch);
+ }
+
+ LoadProjectTree();
+
+ ProjectExplorer?.TrySelectGrassBatchTreeNode(batch);
+ CurrentGrassBatch = batch;
+ ShowEditYmapGrassBatchPanel(false);
+ }
+ public void AddGrassBatchToProject()
+ {
+ if (CurrentGrassBatch == null) return;
+
+ CurrentYmapFile = CurrentGrassBatch.Ymap;
+ if (!YmapExistsInProject(CurrentYmapFile))
+ {
+ var grassBatch = CurrentGrassBatch;
+ CurrentYmapFile.HasChanged = true;
+ AddYmapToProject(CurrentYmapFile);
+
+ CurrentGrassBatch = grassBatch; //bug fix for some reason the treeview selects the project node here.
+ CurrentYmapFile = grassBatch.Ymap;
+ ProjectExplorer?.TrySelectGrassBatchTreeNode(grassBatch);
+ }
+ }
+ public bool DeleteGrassBatch()
+ {
+ if (CurrentYmapFile == null) return false;
+ if (CurrentGrassBatch == null) return false;
+ if (CurrentGrassBatch.Ymap != CurrentYmapFile) return false;
+ if (CurrentYmapFile.GrassInstanceBatches == null) return false; //nothing to delete..
+
+ if (MessageBox.Show("Are you sure you want to delete this grass batch?\n" + CurrentGrassBatch.ToString() + "\n\nThis operation cannot be undone. Continue?", "Confirm delete", MessageBoxButtons.YesNo) != DialogResult.Yes)
+ {
+ return true;
+ }
+
+ bool res = false;
+ if (WorldForm != null)
+ {
+ lock (WorldForm.RenderSyncRoot) //don't try to do this while rendering...
+ {
+ res = CurrentYmapFile.RemoveGrassBatch(CurrentGrassBatch);
+ //WorldForm.SelectItem(null, null, null);
+ }
+ }
+ else
+ {
+ res = CurrentYmapFile.RemoveGrassBatch(CurrentGrassBatch);
+ }
+ if (!res)
+ {
+ MessageBox.Show("Unable to delete the grass batch. This shouldn't happen!");
+ }
+
+ var delbatch = CurrentGrassBatch;
+
+ ProjectExplorer?.RemoveGrassBatchTreeNode(CurrentGrassBatch);
+ ProjectExplorer?.SetYmapHasChanged(CurrentYmapFile, true);
+
+ ClosePanel((EditYmapGrassPanel p) => { return p.Tag == delbatch; });
+
+ CurrentGrassBatch = null;
+
+ return true;
+ }
+ public void PaintGrass(SpaceRayIntersectResult mouseRay, bool erase)
+ {
+ try
+ {
+ if (InvokeRequired)
+ {
+ Invoke(new Action(() => { PaintGrass(mouseRay, erase); }));
+ return;
+ }
+
+ if (!mouseRay.Hit || !mouseRay.TestComplete) return;
+ if (CurrentGrassBatch == null || (!CurrentGrassBatch.BrushEnabled)) return; // brush isn't enabled right now
+ EditYmapGrassPanel panel = FindPanel(x => x.CurrentBatch == CurrentGrassBatch);
+ if (panel == null) return; // no panels with this batch
+
+ // TODO: Maybe move these functions into the batch instead of the grass panel?
+ // although, the panel does have the brush settings.
+ if (!erase)
+ panel.CreateInstancesAtMouse(mouseRay);
+ else panel.EraseInstancesAtMouse(mouseRay);
+ }
+ catch { }
+ }
+ public bool GrassBatchExistsInProject(YmapGrassInstanceBatch batch)
+ {
+ if (CurrentProjectFile?.YmapFiles == null) return false;
+ if (CurrentProjectFile.YmapFiles.Count <= 0) return false;
+ foreach (var ymapFile in CurrentProjectFile.YmapFiles)
+ {
+ if (ymapFile.GrassInstanceBatches == null) continue;
+ foreach (var b in ymapFile.GrassInstanceBatches)
+ {
+ if (batch == b)
+ return true;
+ }
+ }
+ return false;
+ }
+
public void NewCarGen(YmapCarGen copy = null, bool copyPosition = false)
{
if (CurrentYmapFile == null) return;
@@ -3820,9 +3991,11 @@ namespace CodeWalker.Project
for (int i = 0; i < CurrentProjectFile.YmapFiles.Count; i++)
{
var ymap = CurrentProjectFile.YmapFiles[i];
+ // make sure we're not hiding ymaps that have been added by the end-user.
+ var isnew = ymap.RpfFileEntry.ShortNameHash == 0;
if (ymap.Loaded)
{
- ymaps[ymap._CMapData.name] = ymap;
+ ymaps[isnew ? JenkHash.GenHash(ymap.Name) : ymap.RpfFileEntry.ShortNameHash] = ymap;
}
}
}
@@ -4026,6 +4199,11 @@ namespace CodeWalker.Project
{
ProjectExplorer?.TrySelectCarGenTreeNode(cargen);
}
+ if (grassbatch != CurrentGrassBatch)
+ {
+ ProjectExplorer?.TrySelectGrassBatchTreeNode(grassbatch);
+ }
+
}
else if (YndExistsInProject(ynd))
{
@@ -4699,7 +4877,19 @@ namespace CodeWalker.Project
PromoteIfPreviewPanelActive();
}
+ public void SetGrassBatchHasChanged(bool changed)
+ {
+ if (CurrentGrassBatch == null) return;
+ bool changechange = changed != CurrentGrassBatch.HasChanged;
+ if (!changechange) return;
+
+ CurrentGrassBatch.HasChanged = true;
+
+ ProjectExplorer?.SetGrassBatchHasChanged(CurrentGrassBatch, changed);
+
+ PromoteIfPreviewPanelActive();
+ }
@@ -4877,6 +5067,7 @@ namespace CodeWalker.Project
YmapNewEntityMenu.Enabled = enable && inproj;
YmapNewCarGenMenu.Enabled = enable && inproj;
+ YmapNewGrassBatchMenu.Enabled = enable && inproj;
if (CurrentYmapFile != null)
{
@@ -5103,7 +5294,7 @@ namespace CodeWalker.Project
FileSaveItemAsMenu.Text = "Save As...";
ToolbarSaveButton.Text = "Save";
}
-
+
FileSaveItemMenu.Tag = filename;
FileSaveItemAsMenu.Tag = filename;
@@ -5312,6 +5503,10 @@ namespace CodeWalker.Project
{
NewCarGen();
}
+ private void YmapNewGrassBatchMenu_Click(object sender, EventArgs e)
+ {
+ NewGrassBatch();
+ }
private void YmapAddToProjectMenu_Click(object sender, EventArgs e)
{
AddYmapToProject(CurrentYmapFile);
diff --git a/Rendering/RenderableCache.cs b/Rendering/RenderableCache.cs
index 6add1c4..301e971 100644
--- a/Rendering/RenderableCache.cs
+++ b/Rendering/RenderableCache.cs
@@ -195,6 +195,14 @@ namespace CodeWalker.Rendering
}
}
+ public void Invalidate(YmapGrassInstanceBatch batch)
+ {
+ lock (updateSyncRoot)
+ {
+ instbatches.Invalidate(batch);
+ }
+ }
+
}
diff --git a/Rendering/Renderer.cs b/Rendering/Renderer.cs
index aa74391..e499331 100644
--- a/Rendering/Renderer.cs
+++ b/Rendering/Renderer.cs
@@ -380,6 +380,11 @@ namespace CodeWalker.Rendering
renderableCache.Invalidate(path);
}
+ public void Invalidate(YmapGrassInstanceBatch batch)
+ {
+ renderableCache.Invalidate(batch);
+ }
+
public void UpdateSelectionDrawFlags(DrawableModel model, DrawableGeometry geom, bool rem)
{
@@ -679,6 +684,33 @@ namespace CodeWalker.Rendering
}
+ public void RenderBrushRadiusOutline(Vector3 position, Vector3 dir, Vector3 up, float radius, uint col)
+ {
+ const int Reso = 36;
+ const float MaxDeg = 360f;
+ const float DegToRad = 0.0174533f;
+ const float Ang = MaxDeg / Reso;
+
+ var axis = Vector3.Cross(dir, up);
+ var c = new VertexTypePC[Reso];
+
+ for (var i = 0; i < Reso; i++)
+ {
+ var rDir = Quaternion.RotationAxis(dir, (i * Ang) * DegToRad).Multiply(axis);
+ c[i].Position = position + (rDir * radius);
+ c[i].Colour = col;
+ }
+
+ for (var i = 0; i < c.Length; i++)
+ {
+ SelectionLineVerts.Add(c[i]);
+ SelectionLineVerts.Add(c[(i + 1) % c.Length]);
+ }
+
+ SelectionLineVerts.Add(new VertexTypePC{Colour = col, Position = position});
+ SelectionLineVerts.Add(new VertexTypePC { Colour = col, Position = position + dir * 2f});
+ }
+
public void RenderSelectionArrowOutline(Vector3 pos, Vector3 dir, Vector3 up, Quaternion ori, float len, float rad, uint colour)
{
Vector3 ax = Vector3.Cross(dir, up);
diff --git a/Rendering/Shaders/BasicShader.cs b/Rendering/Shaders/BasicShader.cs
index ae1ea37..e7b85e8 100644
--- a/Rendering/Shaders/BasicShader.cs
+++ b/Rendering/Shaders/BasicShader.cs
@@ -695,6 +695,10 @@ namespace CodeWalker.Rendering
{
var gb = batch.Key;
+ // sanity check
+ if (batch.GrassInstanceBuffer == null)
+ return;
+
VSEntityVars.Vars.CamRel = new Vector4(gb.CamRel, 0.0f);
VSEntityVars.Vars.Orientation = Quaternion.Identity;
VSEntityVars.Vars.Scale = Vector3.One;
diff --git a/WorldForm.cs b/WorldForm.cs
index c39cf6f..d032479 100644
--- a/WorldForm.cs
+++ b/WorldForm.cs
@@ -75,6 +75,11 @@ namespace CodeWalker
bool ControlFireToggle = false;
+
+ int ControlBrushTimer = 0;
+ bool ControlBrushEnabled;
+ float ControlBrushRadius;
+
Entity camEntity = new Entity();
PedEntity pedEntity = new PedEntity();
@@ -98,7 +103,7 @@ namespace CodeWalker
-
+
@@ -486,7 +491,7 @@ namespace CodeWalker
}
- if (ControlMode == WorldControlMode.Free)
+ if (ControlMode == WorldControlMode.Free || ControlBrushEnabled)
{
if (Input.ShiftPressed)
{
@@ -1252,7 +1257,7 @@ namespace CodeWalker
if (MouseRayCollision.Hit)
{
var arup = GetPerpVec(MouseRayCollision.Normal);
- Renderer.RenderSelectionArrowOutline(MouseRayCollision.Position, MouseRayCollision.Normal, arup, Quaternion.Identity, 2.0f, 0.15f, cgrn);
+ Renderer.RenderBrushRadiusOutline(MouseRayCollision.Position, MouseRayCollision.Normal, arup, ProjectForm.GetInstanceBrushRadius(), cgrn);
}
}
@@ -1824,6 +1829,14 @@ namespace CodeWalker
}
}
+ public void UpdateGrassBatchGraphics(YmapGrassInstanceBatch grassBatch)
+ {
+ lock (Renderer.RenderSyncRoot)
+ {
+ Renderer.Invalidate(grassBatch);
+ }
+ }
+
public Vector3 GetCameraPosition()
{
@@ -2049,8 +2062,8 @@ namespace CodeWalker
if (mode == ControlMode) return;
- bool wasfree = (ControlMode == WorldControlMode.Free);
- bool isfree = (mode == WorldControlMode.Free);
+ bool wasfree = (ControlMode == WorldControlMode.Free || ControlBrushEnabled);
+ bool isfree = (mode == WorldControlMode.Free || ControlBrushEnabled);
if (isfree && !wasfree)
{
@@ -2104,17 +2117,17 @@ namespace CodeWalker
//reset variables for beginning the mouse hit test
CurMouseHit.Clear();
-
- MouseRayCollisionEnabled = Input.CtrlPressed; //temporary...!
- if (MouseRayCollisionEnabled)
+ // Get whether or not we can brush from the project form.
+ if (Input.CtrlPressed && ProjectForm != null && ProjectForm.CanPaintInstances())
{
- if (space.Inited && space.Grid != null)
- {
- Ray mray = new Ray();
- mray.Position = camera.MouseRay.Position + camera.Position;
- mray.Direction = camera.MouseRay.Direction;
- MouseRayCollision = space.RayIntersect(mray);
- }
+ ControlBrushEnabled = true;
+ MouseRayCollisionEnabled = true;
+ MouseRayCollision = GetSpaceMouseRay();
+ }
+ else if (MouseRayCollisionEnabled)
+ {
+ ControlBrushEnabled = false;
+ MouseRayCollisionEnabled = false;
}
@@ -2127,6 +2140,25 @@ namespace CodeWalker
}
+
+ public SpaceRayIntersectResult GetSpaceMouseRay()
+ {
+ SpaceRayIntersectResult ret = new SpaceRayIntersectResult();
+ if (space.Inited && space.Grid != null)
+ {
+ Ray mray = new Ray();
+ mray.Position = camera.MouseRay.Position + camera.Position;
+ mray.Direction = camera.MouseRay.Direction;
+ return space.RayIntersect(mray);
+ }
+ return ret;
+ }
+
+ public SpaceRayIntersectResult Raycast(Ray ray)
+ {
+ return space.RayIntersect(ray);
+ }
+
private void UpdateMouseHitsFromRenderer()
{
foreach (var rd in Renderer.RenderedDrawables)
@@ -4318,6 +4350,12 @@ namespace CodeWalker
{
camera.FollowEntity.Position = p;
}
+ public void GoToPosition(Vector3 p, Vector3 bound)
+ {
+ camera.FollowEntity.Position = p;
+ var bl = bound.Length();
+ camera.TargetDistance = bl > 1f ? bl : 1f;
+ }
private MapMarker AddMarker(Vector3 pos, string name, bool addtotxtbox = false)
{
@@ -5898,7 +5936,7 @@ namespace CodeWalker
MouseDownPoint = e.Location;
MouseLastPoint = MouseDownPoint;
- if (ControlMode == WorldControlMode.Free)
+ if (ControlMode == WorldControlMode.Free && !ControlBrushEnabled)
{
if (MouseLButtonDown)
{
@@ -5997,6 +6035,7 @@ namespace CodeWalker
SelectedMarker = null;
HideMarkerSelectionInfo();
}
+ ControlBrushTimer = 0;
}
}
@@ -6011,47 +6050,11 @@ namespace CodeWalker
dy = -dy;
}
- if (ControlMode == WorldControlMode.Free)
+ if (ControlMode == WorldControlMode.Free && !ControlBrushEnabled)
{
if (MouseLButtonDown)
{
- if (GrabbedMarker == null)
- {
- if (GrabbedWidget == null)
- {
- if (MapViewEnabled == false)
- {
- camera.MouseRotate(dx, dy);
- }
- else
- {
- //need to move the camera entity XY with mouse in mapview mode...
- MapViewDragX += dx;
- MapViewDragY += dy;
- }
- }
- else
- {
- //grabbed widget will move itself in Update() when IsDragging==true
- }
- }
- else
- {
- //move the grabbed marker...
- //float uptx = (CurrentMap != null) ? CurrentMap.UnitsPerTexelX : 1.0f;
- //float upty = (CurrentMap != null) ? CurrentMap.UnitsPerTexelY : 1.0f;
- //Vector3 wpos = GrabbedMarker.WorldPos;
- //wpos.X += dx * uptx;
- //wpos.Y += dy * upty;
- //GrabbedMarker.WorldPos = wpos;
- //UpdateMarkerTexturePos(GrabbedMarker);
- //if (GrabbedMarker == LocatorMarker)
- //{
- // LocateTextBox.Text = LocatorMarker.ToString();
- // WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
- // TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
- //}
- }
+ RotateCam(dx, dy);
}
if (MouseRButtonDown)
{
@@ -6075,11 +6078,31 @@ namespace CodeWalker
}
}
- MouseX = e.X;
- MouseY = e.Y;
- MouseLastPoint = e.Location;
+ UpdateMousePosition(e);
}
+ else if (ControlBrushEnabled)
+ {
+ if (MouseRButtonDown)
+ {
+ RotateCam(dx, dy);
+ }
+
+ UpdateMousePosition(e);
+
+ ControlBrushTimer++;
+ if (ControlBrushTimer > (Input.ShiftPressed ? 5 : 10))
+ {
+ lock (Renderer.RenderSyncRoot)
+ {
+ if (ProjectForm != null && MouseLButtonDown)
+ {
+ ProjectForm.PaintGrass(MouseRayCollision, Input.ShiftPressed);
+ }
+ ControlBrushTimer = 0;
+ }
+ }
+ }
else
{
lock (MouseControlSyncRoot)
@@ -6120,11 +6143,59 @@ namespace CodeWalker
}
}
+ private void UpdateMousePosition(MouseEventArgs e)
+ {
+ MouseX = e.X;
+ MouseY = e.Y;
+ MouseLastPoint = e.Location;
+ }
+
+ private void RotateCam(int dx, int dy)
+ {
+ if (GrabbedMarker == null)
+ {
+ if (GrabbedWidget == null)
+ {
+ if (MapViewEnabled == false)
+ {
+ camera.MouseRotate(dx, dy);
+ }
+ else
+ {
+ //need to move the camera entity XY with mouse in mapview mode...
+ MapViewDragX += dx;
+ MapViewDragY += dy;
+ }
+ }
+ else
+ {
+ //grabbed widget will move itself in Update() when IsDragging==true
+ }
+ }
+ else
+ {
+ //move the grabbed marker...
+ //float uptx = (CurrentMap != null) ? CurrentMap.UnitsPerTexelX : 1.0f;
+ //float upty = (CurrentMap != null) ? CurrentMap.UnitsPerTexelY : 1.0f;
+ //Vector3 wpos = GrabbedMarker.WorldPos;
+ //wpos.X += dx * uptx;
+ //wpos.Y += dy * upty;
+ //GrabbedMarker.WorldPos = wpos;
+ //UpdateMarkerTexturePos(GrabbedMarker);
+ //if (GrabbedMarker == LocatorMarker)
+ //{
+ // LocateTextBox.Text = LocatorMarker.ToString();
+ // WorldCoordTextBox.Text = LocatorMarker.Get2DWorldPosString();
+ // TextureCoordTextBox.Text = LocatorMarker.Get2DTexturePosString();
+ //}
+ }
+ }
+
private void WorldForm_MouseWheel(object sender, MouseEventArgs e)
{
if (e.Delta != 0)
{
- if (ControlMode == WorldControlMode.Free)
+ if (ControlMode == WorldControlMode.Free || ControlBrushEnabled)
{
camera.MouseZoom(e.Delta);
}
@@ -6254,7 +6325,7 @@ namespace CodeWalker
}
}
- if (ControlMode != WorldControlMode.Free)
+ if (ControlMode != WorldControlMode.Free || ControlBrushEnabled)
{
e.Handled = true;
}
@@ -7555,7 +7626,6 @@ namespace CodeWalker
}
}
-
public enum WorldControlMode
{
Free = 0,