From 8f903610bfdc20a6da555daccf7f1c6670a7ad63 Mon Sep 17 00:00:00 2001 From: dexy Date: Sun, 12 Jan 2020 22:53:57 +1100 Subject: [PATCH] Collisions editing progress --- CodeWalker.Core/GameFiles/Resources/Bounds.cs | 144 +++++++++++-- Project/Panels/EditYbnBoundPolyPanel.cs | 2 +- Project/ProjectForm.cs | 204 +++++++++++++++--- World/MapSelection.cs | 3 + 4 files changed, 305 insertions(+), 48 deletions(-) diff --git a/CodeWalker.Core/GameFiles/Resources/Bounds.cs b/CodeWalker.Core/GameFiles/Resources/Bounds.cs index f5f8e82..e54254e 100644 --- a/CodeWalker.Core/GameFiles/Resources/Bounds.cs +++ b/CodeWalker.Core/GameFiles/Resources/Bounds.cs @@ -981,30 +981,9 @@ namespace CodeWalker.GameFiles byte b0 = polygonData[offset]; polygonData[offset] = (byte)(b0 & 0xF8);//mask it off BoundPolygonType type = (BoundPolygonType)(b0 & 7); - BoundPolygon p = null; - switch (type) - { - case BoundPolygonType.Triangle: - p = new BoundPolygonTriangle(); - break; - case BoundPolygonType.Sphere: - p = new BoundPolygonSphere(); - break; - case BoundPolygonType.Capsule: - p = new BoundPolygonCapsule(); - break; - case BoundPolygonType.Box: - p = new BoundPolygonBox(); - break; - case BoundPolygonType.Cylinder: - p = new BoundPolygonCylinder(); - break; - default: - break; - } + BoundPolygon p = CreatePolygon(type); if (p != null) { - p.Owner = this; p.Index = i; p.Read(polygonData, offset); } @@ -1728,15 +1707,26 @@ namespace CodeWalker.GameFiles var verts = Vertices.ToList(); var verts2 = Vertices2?.ToList(); var vertcols = VertexColours?.ToList(); + var vertobjs = VertexObjects?.ToList(); verts.RemoveAt(index); verts2?.RemoveAt(index); vertcols?.RemoveAt(index); + vertobjs?.RemoveAt(index); Vertices = verts.ToArray(); Vertices2 = verts2?.ToArray(); VertexColours = vertcols?.ToArray(); + VertexObjects = vertobjs?.ToArray(); VerticesCount = (uint)verts.Count; Vertices2Count = VerticesCount; + if (VertexObjects != null) + { + for (int i = 0; i < VertexObjects.Length; i++) + { + if (VertexObjects[i] != null) VertexObjects[i].Index = i; + } + } + if (Polygons != null) { var delpolys = new List(); @@ -1777,6 +1767,87 @@ namespace CodeWalker.GameFiles return false; } + + public int AddVertex() + { + var verts = Vertices?.ToList() ?? new List(); + var verts2 = Vertices2?.ToList(); + var vertcols = VertexColours?.ToList(); + var vertobjs = VertexObjects?.ToList(); + var index = verts.Count; + + verts.Add(Vector3.Zero); + verts2?.Add(Vector3.Zero); + vertcols?.Add(new BoundMaterialColour()); + vertobjs?.Add(null); + + Vertices = verts.ToArray(); + Vertices2 = verts2?.ToArray(); + VertexColours = vertcols?.ToArray(); + VertexObjects = vertobjs?.ToArray(); + VerticesCount = (uint)verts.Count; + Vertices2Count = VerticesCount; + + return index; + } + + public BoundPolygon AddPolygon(BoundPolygonType type) + { + var p = CreatePolygon(type); + + var polys = Polygons?.ToList() ?? new List(); + var polymats = PolygonMaterialIndices?.ToList() ?? new List(); + + p.Index = polys.Count; + polys.Add(p); + polymats.Add(0); + + Polygons = polys.ToArray(); + PolygonMaterialIndices = polymats.ToArray(); + PolygonsCount = (uint)polys.Count; + + var vinds = p.VertexIndices; //just get the required array size + if (vinds != null) + { + for (int i = 0; i < vinds.Length; i++) + { + vinds[i] = AddVertex(); + } + p.VertexIndices = vinds; + } + + return p; + } + + private BoundPolygon CreatePolygon(BoundPolygonType type) + { + BoundPolygon p = null; + switch (type) + { + case BoundPolygonType.Triangle: + p = new BoundPolygonTriangle(); + break; + case BoundPolygonType.Sphere: + p = new BoundPolygonSphere(); + break; + case BoundPolygonType.Capsule: + p = new BoundPolygonCapsule(); + break; + case BoundPolygonType.Box: + p = new BoundPolygonBox(); + break; + case BoundPolygonType.Cylinder: + p = new BoundPolygonCylinder(); + break; + default: + break; + } + if (p != null) + { + p.Owner = this; + } + return p; + } } [TC(typeof(EXP))] public class BoundBVH : BoundGeometry { @@ -2519,6 +2590,35 @@ namespace CodeWalker.GameFiles } } public BoundMaterial_s? MaterialCustom; //for editing, when assigning a new material. + public Vector3[] VertexPositions + { + get + { + var inds = VertexIndices; + var va = new Vector3[inds.Length]; + if (Owner != null) + { + for (int i = 0; i < inds.Length; i++) + { + va[i] = Owner.GetVertexPos(inds[i]); + } + } + return va; + } + set + { + if (value == null) return; + var inds = VertexIndices; + if (Owner != null) + { + var imax = Math.Min(inds.Length, value.Length); + for (int i = 0; i < imax; i++) + { + Owner.SetVertexPos(inds[i], value[i]); + } + } + } + } public int Index { get; set; } //for editing convenience, not stored public abstract Vector3 BoxMin { get; } public abstract Vector3 BoxMax { get; } diff --git a/Project/Panels/EditYbnBoundPolyPanel.cs b/Project/Panels/EditYbnBoundPolyPanel.cs index e422a4a..b389138 100644 --- a/Project/Panels/EditYbnBoundPolyPanel.cs +++ b/Project/Panels/EditYbnBoundPolyPanel.cs @@ -176,7 +176,7 @@ namespace CodeWalker.Project.Panels if (CollisionCylinder != null) { CylVertex1TextBox.Text = FloatUtil.GetVector3String(CollisionCylinder.Vertex1); - CylVertex2TextBox.Text = FloatUtil.GetVector3String(CollisionCylinder.Vertex1); + CylVertex2TextBox.Text = FloatUtil.GetVector3String(CollisionCylinder.Vertex2); CylRadiusTextBox.Text = FloatUtil.ToString(CollisionCylinder.cylinderRadius); if (!PolyTabControl.TabPages.Contains(CylinderTabPage)) PolyTabControl.TabPages.Add(CylinderTabPage); } diff --git a/Project/ProjectForm.cs b/Project/ProjectForm.cs index 42d1e85..fabc75c 100644 --- a/Project/ProjectForm.cs +++ b/Project/ProjectForm.cs @@ -1496,7 +1496,7 @@ namespace CodeWalker.Project public object NewObject(MapSelection sel, bool copyPosition = false, bool selectNew = true) { //general method to add a new object, given a map selection - SelectObject(ref sel); + SetObject(ref sel); if (sel.MultipleSelectionItems != null) { var objs = new List(); @@ -1517,11 +1517,13 @@ namespace CodeWalker.Project else if (sel.ScenarioNode != null) return NewScenarioNode(sel.ScenarioNode, copyPosition, selectNew); else if (sel.Audio?.AudioZone != null) return NewAudioZone(sel.Audio, copyPosition, selectNew); else if (sel.Audio?.AudioEmitter != null) return NewAudioEmitter(sel.Audio, copyPosition, selectNew); + else if (sel.CollisionPoly != null) return NewCollisionPoly(sel.CollisionPoly.Type, sel.CollisionPoly, copyPosition, selectNew); + else if (sel.CollisionBounds != null) return NewCollisionBounds(sel.CollisionBounds.Type, sel.CollisionBounds, copyPosition, selectNew); return null; } public void DeleteObject(MapSelection sel) { - SelectObject(ref sel); + SetObject(ref sel); if (sel.MultipleSelectionItems != null) { for (int i = 0; i < sel.MultipleSelectionItems.Length; i++) @@ -1543,7 +1545,7 @@ namespace CodeWalker.Project else if (sel.CollisionPoly != null) DeleteCollisionPoly(); else if (sel.CollisionBounds != null) DeleteCollisionBounds(); } - public void SelectObject(ref MapSelection sel) + private void SetObject(ref MapSelection sel) { if (sel.MultipleSelectionItems != null) { } //todo... else if (sel.EntityDef != null) SetProjectItem(sel.EntityDef, false); @@ -1930,6 +1932,11 @@ namespace CodeWalker.Project CurrentEntity = null; + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } + return true; } public bool IsCurrentEntity(YmapEntityDef ent) @@ -2047,6 +2054,11 @@ namespace CodeWalker.Project CurrentGrassBatch = null; + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } + return true; } public void PaintGrass(SpaceRayIntersectResult mouseRay, bool erase) @@ -2197,6 +2209,11 @@ namespace CodeWalker.Project CurrentCarGen = null; + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } + return true; } public bool IsCurrentCarGen(YmapCarGen cargen) @@ -2844,6 +2861,11 @@ namespace CodeWalker.Project CurrentArchetype = null; + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } + return true; } public bool DeleteMloEntity() @@ -2902,7 +2924,11 @@ namespace CodeWalker.Project ClosePanel((EditYmapEntityPanel p) => { return p.Tag == delent; }); CurrentEntity = null; CurrentMloEntity = null; - WorldForm.SelectItem(null); + + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } return true; } @@ -2928,6 +2954,11 @@ namespace CodeWalker.Project ClosePanel((EditYtypMloRoomPanel p) => { return p.Tag == CurrentMloRoom; }); CurrentMloRoom = null; + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } + return true; } public bool DeleteMloPortal() @@ -2952,6 +2983,11 @@ namespace CodeWalker.Project ClosePanel((EditYtypMloPortalPanel p) => { return p.Tag == CurrentMloPortal; }); CurrentMloPortal = null; + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } + return true; } public bool DeleteMloEntitySet() @@ -2977,6 +3013,11 @@ namespace CodeWalker.Project ClosePanel((EditYtypMloEntSetPanel p) => { return p.Tag == CurrentMloEntitySet; }); CurrentMloEntitySet = null; + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } + return true; } @@ -3292,14 +3333,16 @@ namespace CodeWalker.Project CurrentCollisionBounds = null; - if (parent != null) + if (WorldForm != null) { - if (WorldForm != null) + if (parent != null) { WorldForm.UpdateCollisionBoundsGraphics(parent); } + WorldForm.SelectItem(null); } + return true; } public bool IsCurrentCollisionBounds(Bounds bounds) @@ -3309,11 +3352,118 @@ namespace CodeWalker.Project public BoundPolygon NewCollisionPoly(BoundPolygonType type, BoundPolygon copy = null, bool copyPosition = false, bool selectNew = true) { - if (CurrentYbnFile == null) return null; + var bgeom = CurrentCollisionBounds as BoundGeometry; + if (bgeom == null) return null; - //////// TODO!! - return null; + var poly = bgeom.AddPolygon(type); + var ptri = poly as BoundPolygonTriangle; + var psph = poly as BoundPolygonSphere; + var pcap = poly as BoundPolygonCapsule; + var pbox = poly as BoundPolygonBox; + var pcyl = poly as BoundPolygonCylinder; + var ctri = copy as BoundPolygonTriangle; + var csph = copy as BoundPolygonSphere; + var ccap = copy as BoundPolygonCapsule; + var cbox = copy as BoundPolygonBox; + var ccyl = copy as BoundPolygonCylinder; + + if (ptri != null) + { + ptri.edgeIndex1 = -1; + ptri.edgeIndex2 = -1; + ptri.edgeIndex3 = -1; + } + + if (copy != null) + { + poly.VertexPositions = copy.VertexPositions; + poly.Material = copy.Material; + switch (type) + { + case BoundPolygonType.Triangle: + if ((ptri != null) && (ctri != null)) + { + ptri.vertFlag1 = ctri.vertFlag1; + ptri.vertFlag2 = ctri.vertFlag2; + ptri.vertFlag3 = ctri.vertFlag3; + } + break; + case BoundPolygonType.Sphere: + if ((psph != null) && (csph != null)) + { + psph.sphereRadius = csph.sphereRadius; + } + break; + case BoundPolygonType.Capsule: + if ((pcap != null) && (ccap != null)) + { + pcap.capsuleRadius = ccap.capsuleRadius; + } + break; + case BoundPolygonType.Box: + if ((pbox != null) && (cbox != null)) + { + } + break; + case BoundPolygonType.Cylinder: + if ((pcyl != null) && (ccyl != null)) + { + pcyl.cylinderRadius = ccyl.cylinderRadius; + } + break; + default: + break; + } + } + else + { + var pos = GetSpawnPos(10.0f); + var x = Vector3.UnitX; + var y = Vector3.UnitY; + var z = Vector3.UnitZ; + + if (ptri != null) + { + ptri.VertexPositions = new[] { pos, pos + x, pos + y }; + } + if (psph != null) + { + psph.VertexPositions = new[] { pos }; + psph.sphereRadius = 1.0f; + } + if (pcap != null) + { + pcap.VertexPositions = new[] { pos - x, pos + x }; + pcap.capsuleRadius = 1.0f; + } + if (pbox != null) + { + pbox.VertexPositions = new[] { pos - x + y - z, pos - x - y + z, pos + x + y + z, pos + x - y - z }; + } + if (pcyl != null) + { + pcyl.VertexPositions = new[] { pos - x, pos + x }; + pcyl.cylinderRadius = 1.0f; + } + } + + if (selectNew) + { + //LoadProjectTree();//is this necessary? + ProjectExplorer?.TrySelectCollisionPolyTreeNode(poly); + CurrentCollisionPoly = poly; + //ShowEditYbnPanel(false);; + ShowEditYbnBoundPolyPanel(false); + } + + if (WorldForm != null) + { + WorldForm.UpdateCollisionBoundsGraphics(bgeom); + } + + + return poly; } public void AddCollisionPolyToProject() { @@ -3385,6 +3535,7 @@ namespace CodeWalker.Project if (WorldForm != null) { WorldForm.UpdateCollisionBoundsGraphics(CurrentCollisionBounds); + WorldForm.SelectItem(null); } return true; @@ -3461,6 +3612,12 @@ namespace CodeWalker.Project CurrentCollisionVertex = null; + if (WorldForm != null) + { + WorldForm.UpdateCollisionBoundsGraphics(CurrentCollisionBounds); + WorldForm.SelectItem(null); + } + return true; } public bool IsCurrentCollisionVertex(BoundVertex vertex) @@ -3764,6 +3921,7 @@ namespace CodeWalker.Project if (WorldForm != null) { WorldForm.UpdatePathYndGraphics(CurrentYndFile, false); + WorldForm.SelectItem(null); } return true; @@ -4247,6 +4405,7 @@ namespace CodeWalker.Project if (WorldForm != null) { WorldForm.UpdateTrainTrackGraphics(CurrentTrainTrack, false); + WorldForm.SelectItem(null); } return true; @@ -4526,9 +4685,9 @@ namespace CodeWalker.Project if (WorldForm != null) { WorldForm.UpdateScenarioGraphics(CurrentScenario, false); + WorldForm.SelectItem(null); } - return true; } public bool IsCurrentScenarioNode(ScenarioNode node) @@ -5705,13 +5864,10 @@ namespace CodeWalker.Project CurrentAudioZone = null; - //if (WorldForm != null) - //{ - // lock (WorldForm.RenderSyncRoot) - // { - // WorldForm.SelectItem(null); - // } - //} + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } return true; } @@ -5826,13 +5982,11 @@ namespace CodeWalker.Project ClosePanel((EditAudioEmitterPanel p) => { return p.CurrentEmitter.AudioEmitter == delem.AudioEmitter; }); - //if (WorldForm != null) - //{ - // lock (WorldForm.RenderSyncRoot) - // { - // WorldForm.SelectItem(null); - // } - //} + + if (WorldForm != null) + { + WorldForm.SelectItem(null); + } return true; } @@ -6439,7 +6593,7 @@ namespace CodeWalker.Project if (ybn.Bounds != null) { var hit = ybn.Bounds.RayIntersect(ref mray); //TODO: interior ybns! - if (hit.Hit) + if (hit.Hit && (hit.HitDist < curHit.HitDist)) { curHit.UpdateCollisionFromRayHit(ref hit, camera); } diff --git a/World/MapSelection.cs b/World/MapSelection.cs index 62a7a40..674fdc5 100644 --- a/World/MapSelection.cs +++ b/World/MapSelection.cs @@ -804,6 +804,9 @@ namespace CodeWalker else if (ScenarioNode != null) return true; else if (Audio?.AudioZone != null) return true; else if (Audio?.AudioEmitter != null) return true; + else if (CollisionVertex != null) return false;//can't copy just a vertex.. + else if (CollisionPoly != null) return true; + else if (CollisionBounds != null) return true; return false; } }