From 5cc94f049c873fa09bf7d45a6c057588bbdf8d41 Mon Sep 17 00:00:00 2001 From: PNWParksFan Date: Thu, 2 Dec 2021 00:15:12 -0800 Subject: [PATCH] Implemented water calming and wave quad selection --- CodeWalker.Core/World/Water.cs | 86 +++++++++++++++----------- CodeWalker/Project/ProjectForm.cs | 2 +- CodeWalker/Rendering/Renderable.cs | 8 +-- CodeWalker/Rendering/Renderer.cs | 4 ++ CodeWalker/World/MapSelection.cs | 20 ++++++ CodeWalker/World/WorldInfoForm.cs | 10 +++ CodeWalker/WorldForm.Designer.cs | 22 +++++++ CodeWalker/WorldForm.cs | 99 +++++++++++++++++++++++------- 8 files changed, 188 insertions(+), 63 deletions(-) diff --git a/CodeWalker.Core/World/Water.cs b/CodeWalker.Core/World/Water.cs index 954832c..9503eca 100644 --- a/CodeWalker.Core/World/Water.cs +++ b/CodeWalker.Core/World/Water.cs @@ -34,7 +34,7 @@ namespace CodeWalker.World for (int i = 0; i < waterquads.Count; i++) { var waterquad = new WaterQuad(); - waterquad.Init(waterquads[i]); + waterquad.Init(waterquads[i], i); WaterQuads.Add(waterquad); } @@ -43,7 +43,7 @@ namespace CodeWalker.World for (int i = 0; i < calmingquads.Count; i++) { var calmingquad = new WaterCalmingQuad(); - calmingquad.Init(calmingquads[i]); + calmingquad.Init(calmingquads[i], i); CalmingQuads.Add(calmingquad); } @@ -52,7 +52,7 @@ namespace CodeWalker.World for (int i = 0; i < wavequads.Count; i++) { var wavequad = new WaterWaveQuad(); - wavequad.Init(wavequads[i]); + wavequad.Init(wavequads[i], i); WaveQuads.Add(wavequad); } @@ -61,48 +61,68 @@ namespace CodeWalker.World - public void GetVisibleQuads(Camera camera, List quads) + public List GetVisibleQuads(Camera camera, IEnumerable allQuads) where T : BaseWaterQuad { - if (!Inited) return; + List quads = new List(); + + if (!Inited) return quads; var vf = camera.ViewFrustum; - for (int i = 0; i < WaterQuads.Count; i++) + foreach (var quad in allQuads) { - var quad = WaterQuads[i]; - Vector3 camrel = quad.BSCenter - camera.Position; if (vf.ContainsSphereNoClipNoOpt(ref camrel, quad.BSRadius)) { quads.Add(quad); } } + + return quads; } } - - public class WaterQuad + public abstract class BaseWaterQuad { + public int xmlNodeIndex { get; set; } public float minX { get; set; } public float maxX { get; set; } public float minY { get; set; } public float maxY { get; set; } + public float? z { get; set; } = null; + + public abstract void Init(XmlNode node, int index); + + public void CalcBS() + { + BSCenter = new Vector3((minX + maxX) * 0.5f, (minY + maxY) * 0.5f, z ?? 0); + BSRadius = new Vector2(maxX - minX, maxY - minY).Length() * 0.5f; + } + + public Vector3 BSCenter { get; private set; } + public float BSRadius { get; private set; } + + public override string ToString() + { + return string.Format("[{0}] X=({1} : {2}), Y=({3} : {4})", xmlNodeIndex, minX, maxX, minY, maxY); + } + } + + public class WaterQuad : BaseWaterQuad + { public int Type { get; set; } public bool IsInvisible { get; set; } public bool HasLimitedDepth { get; set; } - public float z { get; set; } public float a1 { get; set; } public float a2 { get; set; } public float a3 { get; set; } public float a4 { get; set; } public bool NoStencil { get; set; } - public Vector3 BSCenter; - public float BSRadius; - - public void Init(XmlNode node) + public override void Init(XmlNode node, int index) { + xmlNodeIndex = index; minX = Xml.GetChildFloatAttribute(node, "minX", "value"); maxX = Xml.GetChildFloatAttribute(node, "maxX", "value"); minY = Xml.GetChildFloatAttribute(node, "minY", "value"); @@ -133,29 +153,17 @@ namespace CodeWalker.World */ - - BSCenter = new Vector3((minX + maxX) * 0.5f, (minY + maxY) * 0.5f, z); - BSRadius = new Vector2(maxX - minX, maxY - minY).Length() * 0.5f; - + CalcBS(); } - - public override string ToString() - { - return string.Format("{0}, {1}, {2}", FloatUtil.ToString(minX), FloatUtil.ToString(minY), FloatUtil.ToString(z), FloatUtil.ToString(maxX), FloatUtil.ToString(maxY)); - } - } - public class WaterCalmingQuad + public class WaterCalmingQuad : BaseWaterQuad { - public float minX { get; set; } - public float maxX { get; set; } - public float minY { get; set; } - public float maxY { get; set; } public float fDampening { get; set; } - public void Init(XmlNode node) + public override void Init(XmlNode node, int index) { + xmlNodeIndex = index; minX = Xml.GetChildFloatAttribute(node, "minX", "value"); maxX = Xml.GetChildFloatAttribute(node, "maxX", "value"); minY = Xml.GetChildFloatAttribute(node, "minY", "value"); @@ -170,22 +178,22 @@ namespace CodeWalker.World */ + CalcBS(); } } - public class WaterWaveQuad + public class WaterWaveQuad : BaseWaterQuad { - public float minX { get; set; } - public float maxX { get; set; } - public float minY { get; set; } - public float maxY { get; set; } public float Amplitude { get; set; } public float XDirection { get; set; } public float YDirection { get; set; } + public Quaternion WaveOrientation { get; set; } - public void Init(XmlNode node) + + public override void Init(XmlNode node, int index) { + xmlNodeIndex = index; minX = Xml.GetChildFloatAttribute(node, "minX", "value"); maxX = Xml.GetChildFloatAttribute(node, "maxX", "value"); minY = Xml.GetChildFloatAttribute(node, "minY", "value"); @@ -194,6 +202,9 @@ namespace CodeWalker.World XDirection = Xml.GetChildFloatAttribute(node, "XDirection", "value"); YDirection = Xml.GetChildFloatAttribute(node, "YDirection", "value"); + float angl = (float)Math.Atan2(YDirection, XDirection); + WaveOrientation = Quaternion.RotationYawPitchRoll(0.0f, 0.0f, angl); + /* @@ -204,6 +215,7 @@ namespace CodeWalker.World */ + CalcBS(); } } diff --git a/CodeWalker/Project/ProjectForm.cs b/CodeWalker/Project/ProjectForm.cs index d2c108d..8db1766 100644 --- a/CodeWalker/Project/ProjectForm.cs +++ b/CodeWalker/Project/ProjectForm.cs @@ -7244,7 +7244,7 @@ namespace CodeWalker.Project } - public void GetVisibleWaterQuads(Camera camera, List quads) + public void GetVisibleWaterQuads(Camera camera, List quads) where T : BaseWaterQuad { if (hidegtavmap) { diff --git a/CodeWalker/Rendering/Renderable.cs b/CodeWalker/Rendering/Renderable.cs index 8a38126..e9c8c0d 100644 --- a/CodeWalker/Rendering/Renderable.cs +++ b/CodeWalker/Rendering/Renderable.cs @@ -1767,16 +1767,16 @@ namespace CodeWalker.Rendering VertexCount = 4; Vertices = new VertexTypePCT[4]; - Vertices[0].Position = new Vector3(key.minX, key.minY, key.z); + Vertices[0].Position = new Vector3(key.minX, key.minY, key.z.Value); Vertices[0].Texcoord = new Vector2(0.0f, 0.0f); Vertices[0].Colour = (uint)new Color4(key.a1 / 255.0f).ToRgba(); - Vertices[1].Position = new Vector3(key.maxX, key.minY, key.z); + Vertices[1].Position = new Vector3(key.maxX, key.minY, key.z.Value); Vertices[1].Texcoord = new Vector2(sx, 0.0f); Vertices[1].Colour = (uint)new Color4(key.a2 / 255.0f).ToRgba(); - Vertices[2].Position = new Vector3(key.minX, key.maxY, key.z); + Vertices[2].Position = new Vector3(key.minX, key.maxY, key.z.Value); Vertices[2].Texcoord = new Vector2(0.0f, sy); Vertices[2].Colour = (uint)new Color4(key.a3 / 255.0f).ToRgba(); - Vertices[3].Position = new Vector3(key.maxX, key.maxY, key.z); + Vertices[3].Position = new Vector3(key.maxX, key.maxY, key.z.Value); Vertices[3].Texcoord = new Vector2(sx, sy); Vertices[3].Colour = (uint)new Color4(key.a4 / 255.0f).ToRgba(); diff --git a/CodeWalker/Rendering/Renderer.cs b/CodeWalker/Rendering/Renderer.cs index 71b9f0a..68942a1 100644 --- a/CodeWalker/Rendering/Renderer.cs +++ b/CodeWalker/Rendering/Renderer.cs @@ -1242,6 +1242,8 @@ namespace CodeWalker.Rendering { case MapSelectionMode.NavMesh: case MapSelectionMode.WaterQuad: + case MapSelectionMode.CalmingQuad: + case MapSelectionMode.WaveQuad: case MapSelectionMode.MloInstance: clip = false; break; @@ -1326,6 +1328,8 @@ namespace CodeWalker.Rendering switch (mode) { case MapSelectionMode.WaterQuad: + case MapSelectionMode.CalmingQuad: + case MapSelectionMode.WaveQuad: case MapSelectionMode.MloInstance: clip = false; break; diff --git a/CodeWalker/World/MapSelection.cs b/CodeWalker/World/MapSelection.cs index 4493d0f..a040d9f 100644 --- a/CodeWalker/World/MapSelection.cs +++ b/CodeWalker/World/MapSelection.cs @@ -36,6 +36,8 @@ namespace CodeWalker Watermap = 17, Audio = 18, Occlusion = 19, + CalmingQuad = 20, + WaveQuad = 21, } @@ -58,6 +60,8 @@ namespace CodeWalker public YmapEntityDef MloEntityDef { get; set; } public MCMloRoomDef MloRoomDef { get; set; } public WaterQuad WaterQuad { get; set; } + public WaterCalmingQuad CalmingQuad { get; set; } + public WaterWaveQuad WaveQuad { get; set; } public Bounds CollisionBounds { get; set; } public BoundPolygon CollisionPoly { get; set; } public BoundVertex CollisionVertex { get; set; } @@ -100,6 +104,8 @@ namespace CodeWalker (CarGenerator != null) || (GrassBatch != null) || (WaterQuad != null) || + (CalmingQuad != null) || + (WaveQuad != null) || (CollisionBounds != null) || (CollisionPoly != null) || (CollisionVertex != null) || @@ -139,6 +145,8 @@ namespace CodeWalker || (BoxOccluder != mhit.BoxOccluder) || (OccludeModelTri != mhit.OccludeModelTri) || (WaterQuad != mhit.WaterQuad) + || (CalmingQuad != mhit.CalmingQuad) + || (WaveQuad != mhit.WaveQuad) || (CollisionBounds != mhit.CollisionBounds) || (CollisionPoly != mhit.CollisionPoly) || (CollisionVertex != mhit.CollisionVertex) @@ -166,6 +174,8 @@ namespace CodeWalker || (BoxOccluder != null) || (OccludeModelTri != null) || (WaterQuad != null) + || (CalmingQuad != null) + || (WaveQuad != null) || (CollisionBounds != null) || (CollisionPoly != null) || (CollisionVertex != null) @@ -195,6 +205,8 @@ namespace CodeWalker BoxOccluder = null; OccludeModelTri = null; WaterQuad = null; + CalmingQuad = null; + WaveQuad = null; CollisionBounds = null; CollisionPoly = null; CollisionVertex = null; @@ -277,6 +289,14 @@ namespace CodeWalker { name = "WaterQuad " + WaterQuad.ToString(); } + else if (CalmingQuad != null) + { + name = "WaterCalmingQuad " + CalmingQuad.ToString(); + } + else if (WaveQuad != null) + { + name = "WaterWaveQuad " + WaveQuad.ToString(); + } else if (NavPoly != null) { name = "NavPoly " + NavPoly.ToString(); diff --git a/CodeWalker/World/WorldInfoForm.cs b/CodeWalker/World/WorldInfoForm.cs index 1f84c0d..71c5af6 100644 --- a/CodeWalker/World/WorldInfoForm.cs +++ b/CodeWalker/World/WorldInfoForm.cs @@ -129,6 +129,16 @@ namespace CodeWalker.World SelectionEntityTabPage.Text = "Water Quad"; SelEntityPropertyGrid.SelectedObject = item.WaterQuad; } + else if (item.CalmingQuad != null) + { + SelectionEntityTabPage.Text = "Water Calming Quad"; + SelEntityPropertyGrid.SelectedObject = item.CalmingQuad; + } + else if (item.WaveQuad != null) + { + SelectionEntityTabPage.Text = "Water Wave Quad"; + SelEntityPropertyGrid.SelectedObject = item.WaveQuad; + } else if (item.NavPoly != null) { SelectionEntityTabPage.Text = "Nav Poly"; diff --git a/CodeWalker/WorldForm.Designer.cs b/CodeWalker/WorldForm.Designer.cs index 822a7ca..4db507f 100644 --- a/CodeWalker/WorldForm.Designer.cs +++ b/CodeWalker/WorldForm.Designer.cs @@ -312,6 +312,8 @@ namespace CodeWalker this.ToolbarPanel = new System.Windows.Forms.Panel(); this.SubtitleLabel = new System.Windows.Forms.Label(); this.SubtitleTimer = new System.Windows.Forms.Timer(this.components); + this.ToolbarSelectCalmingQuadButton = new System.Windows.Forms.ToolStripMenuItem(); + this.ToolbarSelectWaveQuadButton = new System.Windows.Forms.ToolStripMenuItem(); this.StatusStrip.SuspendLayout(); this.ToolsPanel.SuspendLayout(); this.ToolsTabControl.SuspendLayout(); @@ -1084,6 +1086,8 @@ namespace CodeWalker "Car Generator", "Grass", "Water Quad", + "Water Calming Quad", + "Water Wave Quad", "Collision", "Nav Mesh", "Path", @@ -3080,6 +3084,8 @@ namespace CodeWalker this.ToolbarSelectCarGeneratorButton, this.ToolbarSelectGrassButton, this.ToolbarSelectWaterQuadButton, + this.ToolbarSelectCalmingQuadButton, + this.ToolbarSelectWaveQuadButton, this.ToolbarSelectCollisionButton, this.ToolbarSelectNavMeshButton, this.ToolbarSelectPathButton, @@ -3604,6 +3610,20 @@ namespace CodeWalker // this.SubtitleTimer.Tick += new System.EventHandler(this.SubtitleTimer_Tick); // + // ToolbarSelectCalmingQuadButton + // + this.ToolbarSelectCalmingQuadButton.Name = "ToolbarSelectCalmingQuadButton"; + this.ToolbarSelectCalmingQuadButton.Size = new System.Drawing.Size(185, 22); + this.ToolbarSelectCalmingQuadButton.Text = "Water Calming Quad"; + this.ToolbarSelectCalmingQuadButton.Click += new System.EventHandler(this.ToolbarSelectCalmingQuadButton_Click); + // + // ToolbarSelectWaveQuadButton + // + this.ToolbarSelectWaveQuadButton.Name = "ToolbarSelectWaveQuadButton"; + this.ToolbarSelectWaveQuadButton.Size = new System.Drawing.Size(185, 22); + this.ToolbarSelectWaveQuadButton.Text = "Water Wave Quad"; + this.ToolbarSelectWaveQuadButton.Click += new System.EventHandler(this.ToolbarSelectWaveQuadButton_Click); + // // WorldForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -3975,5 +3995,7 @@ namespace CodeWalker private System.Windows.Forms.ToolStripMenuItem ToolbarRotationSnapping90Button; private System.Windows.Forms.ToolStripMenuItem ToolbarSnapGridSizeButton; private System.Windows.Forms.CheckBox HDLightsCheckBox; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectCalmingQuadButton; + private System.Windows.Forms.ToolStripMenuItem ToolbarSelectWaveQuadButton; } } \ No newline at end of file diff --git a/CodeWalker/WorldForm.cs b/CodeWalker/WorldForm.cs index 010716c..3e1ba15 100644 --- a/CodeWalker/WorldForm.cs +++ b/CodeWalker/WorldForm.cs @@ -127,7 +127,6 @@ namespace CodeWalker List renderpathynds = new List(); bool renderwaterquads = true; - List renderwaterquadlist = new List(); bool rendertraintracks = false; List rendertraintracklist = new List(); @@ -710,6 +709,14 @@ namespace CodeWalker { RenderWorldWaterQuads(); } + if (SelectionMode == MapSelectionMode.WaveQuad) + { + RenderWorldWaterWaveQuads(); + } + if (SelectionMode == MapSelectionMode.CalmingQuad) + { + RenderWorldWaterCalmingQuads(); + } if (rendercollisionmeshes || (SelectionMode == MapSelectionMode.Collision)) { RenderWorldCollisionMeshes(); @@ -804,19 +811,23 @@ namespace CodeWalker private void RenderWorldWaterQuads() { - renderwaterquadlist.Clear(); + var quads = RenderWorldBaseWaterQuads(water.WaterQuads, MapSelectionMode.WaterQuad); + Renderer.RenderWaterQuads(quads); + } - water.GetVisibleQuads(camera, renderwaterquadlist); + private void RenderWorldWaterCalmingQuads() => RenderWorldBaseWaterQuads(water.CalmingQuads, MapSelectionMode.CalmingQuad); - if (ProjectForm != null) - { - ProjectForm.GetVisibleWaterQuads(camera, renderwaterquadlist); - } + private void RenderWorldWaterWaveQuads() => RenderWorldBaseWaterQuads(water.WaveQuads, MapSelectionMode.WaveQuad); - Renderer.RenderWaterQuads(renderwaterquadlist); + private List RenderWorldBaseWaterQuads(IEnumerable quads, MapSelectionMode requiredMode) where T : BaseWaterQuad + { + List renderwaterquadlist = water.GetVisibleQuads(camera, quads); - UpdateMouseHits(renderwaterquadlist); + ProjectForm?.GetVisibleWaterQuads(camera, renderwaterquadlist); + if(SelectionMode == requiredMode) UpdateMouseHits(renderwaterquadlist); + + return renderwaterquadlist; } private void RenderWorldPaths() @@ -1379,6 +1390,15 @@ namespace CodeWalker Renderer.RenderCar(cg.Position, cgori, cg._CCarGen.carModel, cg._CCarGen.popGroup); } } + if (selectionItem.WaveQuad != null) + { + var quad = selectionItem.WaveQuad; + Vector3 quadArrowPos = new Vector3(quad.minX + (quad.maxX - quad.minX) * 0.5f, quad.minY + (quad.maxY - quad.minY) * 0.5f, 5); + Quaternion waveOri = quad.WaveOrientation; + float arrowlen = quad.Amplitude * 50; + float arrowrad = arrowlen * 0.066f; + Renderer.RenderSelectionArrowOutline(quadArrowPos, Vector3.UnitX, Vector3.UnitY, waveOri, arrowlen, arrowrad, cgrn); + } if (selectionItem.LodLight != null) { Renderer.RenderSelectionLodLight(selectionItem.LodLight); @@ -2900,35 +2920,42 @@ namespace CodeWalker } } - private void UpdateMouseHits(List waterquads) + private void UpdateMouseHits(List waterquads) where T : BaseWaterQuad { - if (SelectionMode != MapSelectionMode.WaterQuad) return; - BoundingBox bbox = new BoundingBox(); Ray mray = new Ray(); mray.Position = camera.MouseRay.Position + camera.Position; mray.Direction = camera.MouseRay.Direction; - float hitdist = float.MaxValue; + float hitdist; - foreach (var quad in waterquads) + foreach (T quad in waterquads) { MapBox mb = new MapBox(); mb.CamRelPos = -camera.Position; - mb.BBMin = new Vector3(quad.minX, quad.minY, quad.z); - mb.BBMax = new Vector3(quad.maxX, quad.maxY, quad.z); + mb.BBMin = new Vector3(quad.minX, quad.minY, quad.z ?? 0); + mb.BBMax = new Vector3(quad.maxX, quad.maxY, quad.z ?? 0); mb.Orientation = Quaternion.Identity; mb.Scale = Vector3.One; Renderer.BoundingBoxes.Add(mb); bbox.Minimum = mb.BBMin; bbox.Maximum = mb.BBMax; - if (mray.Intersects(ref bbox, out hitdist) && (hitdist < CurMouseHit.HitDist) && (hitdist > 0)) + + if(mray.Intersects(ref bbox, out hitdist) && hitdist > 0 && hitdist <= CurMouseHit.HitDist) { - CurMouseHit.WaterQuad = quad; - CurMouseHit.HitDist = hitdist; - CurMouseHit.CamRel = mb.CamRelPos; - CurMouseHit.AABB = bbox; + float curSize = CurMouseHit.AABB.Size.X * CurMouseHit.AABB.Size.Y; + float newSize = bbox.Size.X * bbox.Size.Y; + if ((curSize == 0) || (newSize < curSize)) + { + CurMouseHit.HitDist = hitdist; + CurMouseHit.CamRel = mb.CamRelPos; + CurMouseHit.AABB = bbox; + + CurMouseHit.WaterQuad = quad as WaterQuad; + CurMouseHit.WaveQuad = quad as WaterWaveQuad; + CurMouseHit.CalmingQuad = quad as WaterCalmingQuad; + } } } } @@ -3722,6 +3749,16 @@ namespace CodeWalker SelectionEntityTabPage.Text = "WaterQuad"; SelEntityPropertyGrid.SelectedObject = item.WaterQuad; } + else if (item.CalmingQuad != null) + { + SelectionEntityTabPage.Text = "CalmingQuad"; + SelEntityPropertyGrid.SelectedObject = item.CalmingQuad; + } + else if (item.WaveQuad != null) + { + SelectionEntityTabPage.Text = "WaveQuad"; + SelEntityPropertyGrid.SelectedObject = item.WaveQuad; + } else if (item.PathNode != null) { SelectionEntityTabPage.Text = "PathNode"; @@ -5551,6 +5588,14 @@ namespace CodeWalker mode = MapSelectionMode.WaterQuad; ToolbarSelectWaterQuadButton.Checked = true; break; + case "Water Calming Quad": + mode = MapSelectionMode.CalmingQuad; + ToolbarSelectCalmingQuadButton.Checked = true; + break; + case "Water Wave Quad": + mode = MapSelectionMode.WaveQuad; + ToolbarSelectWaveQuadButton.Checked = true; + break; case "Collision": mode = MapSelectionMode.Collision; ToolbarSelectCollisionButton.Checked = true; @@ -7309,6 +7354,18 @@ namespace CodeWalker SetMouseSelect(true); } + private void ToolbarSelectCalmingQuadButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Water Calming Quad"); + SetMouseSelect(true); + } + + private void ToolbarSelectWaveQuadButton_Click(object sender, EventArgs e) + { + SetSelectionMode("Water Wave Quad"); + SetMouseSelect(true); + } + private void ToolbarSelectCollisionButton_Click(object sender, EventArgs e) { SetSelectionMode("Collision");