From 6c51f65906c5b64e871b5674b3b26d6acd552b48 Mon Sep 17 00:00:00 2001 From: burninrubber0 Date: Wed, 12 Jul 2023 14:55:48 -0400 Subject: [PATCH] Add PVS editor --- PVSFormat/AddZone.Designer.cs | 101 ++++++ PVSFormat/AddZone.cs | 32 ++ PVSFormat/AddZone.resx | 120 +++++++ PVSFormat/PVS.cs | 353 +++++++++++--------- PVSFormat/PVSEditControl.cs | 127 +++++-- PVSFormat/PVSEditControl.resx | 120 +++++++ PVSFormat/PVSEditor.Designer.cs | 493 ++++++++++++++++++++++++---- PVSFormat/PVSEditor.cs | 282 +++++++++++++++- PVSFormat/PVSEditor.resx | 58 ++-- PVSFormat/Util/GeneralExtensions.cs | 69 ---- 10 files changed, 1399 insertions(+), 356 deletions(-) create mode 100644 PVSFormat/AddZone.Designer.cs create mode 100644 PVSFormat/AddZone.cs create mode 100644 PVSFormat/AddZone.resx create mode 100644 PVSFormat/PVSEditControl.resx delete mode 100644 PVSFormat/Util/GeneralExtensions.cs diff --git a/PVSFormat/AddZone.Designer.cs b/PVSFormat/AddZone.Designer.cs new file mode 100644 index 0000000..e0f2199 --- /dev/null +++ b/PVSFormat/AddZone.Designer.cs @@ -0,0 +1,101 @@ +namespace PVSFormat +{ + partial class AddZone + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + okButton = new System.Windows.Forms.Button(); + cancelButton = new System.Windows.Forms.Button(); + zoneIdNumericUpDown = new System.Windows.Forms.NumericUpDown(); + label1 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)zoneIdNumericUpDown).BeginInit(); + SuspendLayout(); + // + // okButton + // + okButton.Location = new System.Drawing.Point(12, 65); + okButton.Name = "okButton"; + okButton.Size = new System.Drawing.Size(75, 23); + okButton.TabIndex = 0; + okButton.Text = "OK"; + okButton.UseVisualStyleBackColor = true; + okButton.Click += okButton_Click; + // + // cancelButton + // + cancelButton.Location = new System.Drawing.Point(93, 65); + cancelButton.Name = "cancelButton"; + cancelButton.Size = new System.Drawing.Size(75, 23); + cancelButton.TabIndex = 1; + cancelButton.Text = "Cancel"; + cancelButton.UseVisualStyleBackColor = true; + cancelButton.Click += cancelButton_Click; + // + // zoneIdNumericUpDown + // + zoneIdNumericUpDown.Location = new System.Drawing.Point(42, 32); + zoneIdNumericUpDown.Maximum = new decimal(new int[] { 1024, 0, 0, 0 }); + zoneIdNumericUpDown.Name = "zoneIdNumericUpDown"; + zoneIdNumericUpDown.Size = new System.Drawing.Size(100, 23); + zoneIdNumericUpDown.TabIndex = 2; + // + // label1 + // + label1.AutoSize = true; + label1.Location = new System.Drawing.Point(41, 9); + label1.Name = "label1"; + label1.Size = new System.Drawing.Size(104, 15); + label1.TabIndex = 3; + label1.Text = "Enter new zone ID:"; + // + // AddZone + // + AcceptButton = okButton; + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + CancelButton = cancelButton; + ClientSize = new System.Drawing.Size(184, 101); + Controls.Add(label1); + Controls.Add(zoneIdNumericUpDown); + Controls.Add(cancelButton); + Controls.Add(okButton); + FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + Name = "AddZone"; + Text = "Add Zone"; + ((System.ComponentModel.ISupportInitialize)zoneIdNumericUpDown).EndInit(); + ResumeLayout(false); + PerformLayout(); + } + + #endregion + + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Button cancelButton; + private System.Windows.Forms.NumericUpDown zoneIdNumericUpDown; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/PVSFormat/AddZone.cs b/PVSFormat/AddZone.cs new file mode 100644 index 0000000..9cbc77a --- /dev/null +++ b/PVSFormat/AddZone.cs @@ -0,0 +1,32 @@ +using System; +using System.Windows.Forms; + +namespace PVSFormat +{ + public partial class AddZone : Form + { + ulong zone; + + public AddZone() + { + InitializeComponent(); + } + + public ulong GetNewZoneId() + { + ShowDialog(); + return zone; + } + + private void okButton_Click(object sender, EventArgs e) + { + zone = (ulong)zoneIdNumericUpDown.Value; + Close(); + } + + private void cancelButton_Click(object sender, EventArgs e) + { + Close(); + } + } +} diff --git a/PVSFormat/AddZone.resx b/PVSFormat/AddZone.resx new file mode 100644 index 0000000..a395bff --- /dev/null +++ b/PVSFormat/AddZone.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/PVSFormat/PVS.cs b/PVSFormat/PVS.cs index f5e7e4d..ae3eca3 100644 --- a/PVSFormat/PVS.cs +++ b/PVSFormat/PVS.cs @@ -1,6 +1,8 @@ +using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Numerics; using BundleFormat; using BundleUtilities; using BurnoutImage; @@ -8,204 +10,233 @@ namespace PVSFormat { - public struct ZonePoint + public struct ZoneList { - public float X; - public float Y; - public int Padding1; // Padding??? - public int Padding2; // Padding??? + //public List Points; // Redundant; use Zones[zoneIndex].Points + public List Zones; + //public List ZonePointStarts; // Per-zone start point index. Unnecessary as they are always sequential multiples of 4 + //public List ZonePointCounts; // Per-zone point count. Unnecessary as there are always 4 points + public uint TotalZones; + //public uint TotalPoints; // Unnecessary, calculated during writing - public override string ToString() + public ZoneList() { - return "X: " + X + ", Y: " + Y + ", Padding1: " + Padding1 + ", Padding2: " + Padding2; + Zones = new(); + //ZonePointStarts = new(); + //ZonePointCounts = new(); } } - public enum NeighbourFlags + public struct Zone { - E_RENDERFLAG_NONE = 0x0, - E_NEIGHBOURFLAG_RENDER = 0x1, - E_NEIGHBOURFLAG_IMMEDIATE = 0x2, - E_NEIGHBOURFLAG_RENDER_IMMEDIATE = 0x3, - } - - public struct ZoneNeighbour - { - public int NeighborIndex; - public uint NeighborPtr; - public NeighbourFlags Flags; - public int Padding1; // Padding??? - public int Padding2; // Padding??? + public List Points; + //public List SafeNeighbours; // Unnecessary, always empty + public List UnsafeNeighbours; + public ulong ZoneId; + //public short ZoneType; // Unnecessary, always 0 + //public short NumPoints; // Unnecessary, always 4 + //public short NumSafeNeighbours; // Unnecessary, always 0 + public short NumUnsafeNeighbours; + //public ulong Flags; // Unnecessary, always 0 - public override string ToString() + public Zone() { - return "NeighborIndex: " + NeighborIndex + ", Type: " + Flags + ", Unk1: " + Padding1 + ", Unk2: " + Padding2; + Points = new(); + for (int i = 0; i < 400; i += 100) + Points.Add(new(i % 200, i > 100 ? 0 : 100)); // 0x0,100x0,0x100,100x100 + //SafeNeighbours = new(); + UnsafeNeighbours = new(); } } - public struct PVSZone + public struct Neighbour { - public uint Address; - public uint PointsPtr; - public uint SafeNeighboursPtr; - public uint UnsafeNeighboursPtr; - public uint Unknown; - public long ZoneID; - public short ZoneType; - public short NumPoints; - public short NumSafeNeighbours; - public short NumUnsafeNeighbours; - public int Flags; - public int Padding1; // Padding??? - public int Padding2; // Padding??? - public int Padding3; // Padding??? - - public List Points; - public List UnsafeNeighbours; + //Zone Zone; // Redundant, replaced by ZoneId + public ulong ZoneId; + public NeighbourFlags Flags; + } - public override string ToString() - { - return "ZoneID: " + ZoneID; - } + [Flags] + public enum NeighbourFlags + { + E_RENDERFLAG_NONE = 0x0, + E_NEIGHBOURFLAG_RENDER = 0x1, + E_NEIGHBOURFLAG_IMMEDIATE = 0x2 } public class PVS : IEntryData { - private Image _gameMap; + public ZoneList data; - public uint PointsPtr; - public uint ZonePtr; - public uint ZonePointStart1; - public uint ZonePointStart2; - public uint ZonePointCount; - public uint TotalZones; - public uint TotalPoints; - public uint Padding; // Padding??? - public List Zones; - - public PVS() - { - Zones = new List(); - } - - private void Clear() - { - PointsPtr = default; - ZonePtr = default; - ZonePointStart1 = default; - ZonePointStart2 = default; - ZonePointCount = default; - TotalZones = default; - TotalPoints = default; - - Zones.Clear(); - } + private Image _gameMap; + internal ulong selectedZoneId = ulong.MaxValue; - public bool Read(BundleEntry entry, ILoader loader) + public bool Read(BundleEntry entry, ILoader loader = null) { - Clear(); + data = new(); - Stream s = entry.MakeStream(); - BinaryReader2 br = new BinaryReader2(s); + BinaryReader2 br = new(entry.MakeStream()); br.BigEndian = entry.Console; - PointsPtr = br.ReadUInt32(); - ZonePtr = br.ReadUInt32(); - - ZonePointStart1 = br.ReadUInt32(); - ZonePointStart2 = br.ReadUInt32(); - - ZonePointCount = br.ReadUInt32(); - TotalZones = br.ReadUInt32(); - TotalPoints = br.ReadUInt32(); - Padding = br.ReadUInt32(); - - for (uint i = 0; i < ZonePointCount; i++) + // Get zone count + br.BaseStream.Position = 0x10; + data.TotalZones = br.ReadUInt32(); + + // Get zones + br.BaseStream.Position = 0x4; + br.BaseStream.Position = br.ReadUInt32(); + long zonePos; + long unsafeNeighboursPos; + long unsafeNeighbourZonePos; + for (int i = 0; i < data.TotalZones; ++i) { - PVSZone pvsEntry = new PVSZone(); - - pvsEntry.Address = (uint)br.BaseStream.Position; - pvsEntry.PointsPtr = br.ReadUInt32(); - pvsEntry.SafeNeighboursPtr = br.ReadUInt32(); - pvsEntry.UnsafeNeighboursPtr = br.ReadUInt32(); - pvsEntry.Unknown = br.ReadUInt32(); - pvsEntry.ZoneID = br.ReadInt64(); - pvsEntry.ZoneType = br.ReadInt16(); - pvsEntry.NumPoints = br.ReadInt16(); - pvsEntry.NumSafeNeighbours = br.ReadInt16(); - pvsEntry.NumUnsafeNeighbours = br.ReadInt16(); - pvsEntry.Flags = br.ReadInt32(); - pvsEntry.Padding1 = br.ReadInt32(); - pvsEntry.Padding2 = br.ReadInt32(); - pvsEntry.Padding3 = br.ReadInt32(); - - long pos = br.BaseStream.Position; - - br.BaseStream.Position = (long)pvsEntry.PointsPtr; - - pvsEntry.Points = new List(); - for (int j = 0; j < pvsEntry.NumPoints; j++) - { - ZonePoint data = new ZonePoint(); - - data.X = br.ReadSingle(); - data.Y = br.ReadSingle(); - data.Padding1 = br.ReadInt32(); - data.Padding2 = br.ReadInt32(); + Zone zone = new(); + zonePos = br.BaseStream.Position; - pvsEntry.Points.Add(data); + // Get points + br.BaseStream.Position = br.ReadUInt32(); + for (int j = 0; j < 4; ++j) + { + zone.Points[j] = new(br.ReadSingle(), br.ReadSingle()); + br.SkipUniquePadding(8); } - br.BaseStream.Position = (long) pvsEntry.UnsafeNeighboursPtr; - - pvsEntry.UnsafeNeighbours = new List(); - for (int j = 0; j < pvsEntry.NumUnsafeNeighbours; j++) + // Get unsafe neighbours + br.BaseStream.Position = zonePos + 0x1E; + zone.NumUnsafeNeighbours = br.ReadInt16(); + br.BaseStream.Position = zonePos + 8; + unsafeNeighboursPos = br.ReadUInt32(); + for (int j = 0; j < zone.NumUnsafeNeighbours; ++j) { - ZoneNeighbour data = new ZoneNeighbour(); + Neighbour neighbour = new(); + br.BaseStream.Position = unsafeNeighboursPos + 0x10 * j; + unsafeNeighbourZonePos = br.ReadUInt32(); + neighbour.Flags = (NeighbourFlags)br.ReadUInt32(); + br.BaseStream.Position = unsafeNeighbourZonePos + 0x10; + neighbour.ZoneId = br.ReadUInt64(); + zone.UnsafeNeighbours.Add(neighbour); + } - data.NeighborIndex = -1; + // Get zone ID + br.BaseStream.Position = zonePos + 0x10; + zone.ZoneId = br.ReadUInt64(); + br.BaseStream.Position += 0x18; // Seek to next zone - data.NeighborPtr = br.ReadUInt32(); - data.Flags = (NeighbourFlags)br.ReadInt32(); - data.Padding1 = br.ReadInt32(); - data.Padding2 = br.ReadInt32(); + data.Zones.Add(zone); + } - pvsEntry.UnsafeNeighbours.Add(data); - } + br.Close(); - br.BaseStream.Position = pos; + _gameMap = GetGameMap(entry.Archive); - Zones.Add(pvsEntry); - } + return true; + } - for (int i = 0; i < Zones.Count; i++) + public bool Write(BundleEntry entry) + { + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + + // Update neighbours in case of zone deletion + for (int i = 0; i < data.TotalZones; ++i) { - for (int k = 0; k < Zones[i].UnsafeNeighbours.Count; k++) + for (int j = 0; j < data.Zones[i].NumUnsafeNeighbours; ++j) { - ZoneNeighbour data = Zones[i].UnsafeNeighbours[k]; - uint ptr = data.NeighborPtr; - for (int j = 0; j < Zones.Count; j++) + if (data.Zones.FindIndex(z => z.ZoneId == data.Zones[i].UnsafeNeighbours[j].ZoneId) == -1) { - if (Zones[j].Address == ptr) - { - data.NeighborIndex = j; - Zones[i].UnsafeNeighbours[k] = data; - break; - } + Zone zone = data.Zones[i]; + zone.UnsafeNeighbours.RemoveAt(j); + zone.NumUnsafeNeighbours--; + data.Zones[i] = zone; } } } - br.Close(); - s.Close(); + // Get necessary information before writing + uint zonesPtr = 0x20; + uint zonesLength = data.TotalZones * 0x30; + uint neighboursPtr = zonesPtr + zonesLength; + uint neighborsLength = 0; + for (int i = 0; i < data.Zones.Count; ++i) + neighborsLength += (uint)data.Zones[i].NumUnsafeNeighbours * 0x10; + uint pointsPtr = neighboursPtr + neighborsLength; + uint pointsLength = (uint)(data.Zones.Count * 0x4 * 0x10); + uint zoneStartsPtr = pointsPtr + pointsLength; + uint zoneStartsLength = data.TotalZones * 0x4; + uint zoneCountsPtr = zoneStartsPtr + zoneStartsLength; + if (zoneCountsPtr % 0x10 != 0) // Align + zoneCountsPtr = (zoneCountsPtr & 0xFFFFFFF0) + 0x10; + + // Write ZoneList + bw.Write(pointsPtr); + bw.Write(zonesPtr); + bw.Write(zoneStartsPtr); + bw.Write(zoneCountsPtr); + bw.Write(data.TotalZones); + bw.Write(data.TotalZones * 0x4); + + // Write zones + uint neighboursPosition = 0; + for (int i = 0; i < data.TotalZones; ++i) + { + bw.BaseStream.Position = zonesPtr + i * 0x30; + bw.Write((uint)(pointsPtr + i * 0x4 * 0x10)); // Points + bw.Write(0); // Safe neighbours + if (data.Zones[i].NumUnsafeNeighbours == 0) // Unsafe neighbours + bw.Write(0); + else + bw.Write(neighboursPtr + neighboursPosition); + bw.Write(0); // Padding + bw.Write(data.Zones[i].ZoneId); + bw.Write((short)0); // Zone type + bw.Write((short)4); // Point count + bw.Write((short)0); // Safe neighbour count + bw.Write(data.Zones[i].NumUnsafeNeighbours); // Unsafe neighbour count + bw.Write(0); // Flags + + // Write points + bw.BaseStream.Position = pointsPtr + i * 0x4 * 0x10; + for (int j = 0; j < 4; ++j) + { + bw.Write(data.Zones[i].Points[j].X); + bw.Write(data.Zones[i].Points[j].Y); + bw.BaseStream.Position += 0x8; + } - _gameMap = GetGameMap(entry.Archive); + // Write neighbours + bw.BaseStream.Position = neighboursPtr + neighboursPosition; + for (int j = 0; j < data.Zones[i].NumUnsafeNeighbours; ++j) + { + ulong zoneId = data.Zones[i].UnsafeNeighbours[j].ZoneId; + int neighbourZoneIndex = data.Zones.FindIndex(z => z.ZoneId == zoneId); + uint neighbourZonePtr = (uint)(zonesPtr + neighbourZoneIndex * 0x30); + bw.Write(neighbourZonePtr); + bw.Write((uint)data.Zones[i].UnsafeNeighbours[j].Flags); + bw.BaseStream.Position += 0x8; + neighboursPosition += 0x10; + } + } - return true; - } + // Write zone start point indices + bw.BaseStream.Position = zoneStartsPtr; + for (int i = 0; i < data.TotalZones * 4; i += 4) + bw.Write(i); + + // Write zone point counts + bw.BaseStream.Position = zoneCountsPtr; + for (int i = 0; i < data.TotalZones; ++i) + bw.Write((short)4); + + bw.Align(16); + + bw.Flush(); + byte[] rawData = ms.ToArray(); + bw.Close(); + ms.Close(); + + entry.EntryBlocks[0].Data = rawData; + entry.Dirty = true; - public bool Write(BundleEntry entry) - { return true; } @@ -216,10 +247,15 @@ public EntryType GetEntryType(BundleEntry entry) public IEntryEditor GetEditor(BundleEntry entry) { - PVSEditor pvsForm = new PVSEditor(); + PVSEditor pvsForm = new(); pvsForm.GameMap = _gameMap; pvsForm.Open(this); + pvsForm.Edit += () => + { + Write(entry); + }; + return pvsForm; } @@ -241,9 +277,12 @@ private Image GetGameMap(BundleArchive archive) if (descEntry1 == null) { string path = Path.GetDirectoryName(archive.Path) + Path.DirectorySeparatorChar + "GUITEXTURES.BIN"; - BundleArchive archive2 = BundleArchive.Read(path); - if (archive2 != null) - descEntry1 = archive2.GetEntryByID(id); + if (Path.Exists(path)) + { + BundleArchive archive2 = BundleArchive.Read(path); + if (archive2 != null) + descEntry1 = archive2.GetEntryByID(id); + } } Image image = null; diff --git a/PVSFormat/PVSEditControl.cs b/PVSFormat/PVSEditControl.cs index 1c48678..1b5d6a7 100644 --- a/PVSFormat/PVSEditControl.cs +++ b/PVSFormat/PVSEditControl.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Drawing; +using System.Numerics; using System.Windows.Forms; namespace PVSFormat @@ -26,11 +28,17 @@ public PVS PVS protected PointF CameraPosition; protected PointF RenderOffset => new PointF(-CameraPosition.X + ClientRectangle.Width / 2.0f, -CameraPosition.Y + ClientRectangle.Height / 2.0f); protected float MapSize => (RenderScale * 32); - protected bool isHand; protected bool isDragging; protected Point lastMouse; protected Point mousePos; + protected enum MapSectionType + { + Unloaded, + Current, + Neighbour + } + protected PointF MousePosOnMap { get @@ -61,42 +69,58 @@ public PVSEditControl() CameraPosition = new Point(0, 0); } - protected override void OnKeyDown(KeyEventArgs e) + // Get zone ID for UI update + public ulong GetZoneId() { - if (e.KeyData == Keys.Space) - { - isHand = true; - UpdateCursor(); - } - if (e.KeyData == Keys.Oemplus) + ulong id = ulong.MaxValue; + foreach (Zone zone in PVS.data.Zones) { - CameraPosition.X = 0; - CameraPosition.Y = 0; - Invalidate(); + List points = new(); + foreach (Vector2 point in zone.Points) + points.Add(new PointF(point.X, point.Y)); + Polygon polygon = new Polygon(points); + if (MousePosOnMap.X >= polygon.MinX && MousePosOnMap.X < polygon.MaxX + && MousePosOnMap.Y >= polygon.MinY && MousePosOnMap.Y < polygon.MaxY) + { + id = zone.ZoneId; + break; + } } + return id; } - protected override void OnKeyUp(KeyEventArgs e) + // Get zone index for UI update + public int GetZoneIndex(ulong zoneId) { - if (e.KeyData == Keys.Space) - { - isHand = false; - lastMouse = new Point(0, 0); - } + return PVS.data.Zones.FindIndex(z => z.ZoneId == zoneId); + } - UpdateCursor(); + // Get zone info for UI update + public List GetZonePoints(ulong zoneId) + { + List points = new(); + foreach (Vector2 point in PVS.data.Zones[GetZoneIndex(zoneId)].Points) + points.Add(new Vector2(point.X, point.Y)); + return points; + } + + // Get zone neighbours for UI update + public List GetZoneNeighbours(ulong zoneId) + { + List neighbours = new(); + foreach (Neighbour neighbour in PVS.data.Zones[GetZoneIndex(zoneId)].UnsafeNeighbours) + neighbours.Add(neighbour); + return neighbours; } protected override void OnMouseDown(MouseEventArgs e) { + // Move the camera if (e.Button == MouseButtons.Left) { lastMouse = e.Location; - if (isHand) - { - isDragging = true; - } + isDragging = true; } } @@ -109,11 +133,29 @@ protected override void OnMouseUp(MouseEventArgs e) } } + protected override void OnKeyDown(KeyEventArgs e) + { + // Reset the camera + if (e.KeyData == Keys.R) + { + RenderScale = 1; + CameraPosition.X = 0; + CameraPosition.Y = 0; + Invalidate(); + } + } + + protected override void OnKeyUp(KeyEventArgs e) + { + lastMouse = new Point(0, 0); + } + + // Move the camera protected override void OnMouseMove(MouseEventArgs e) { mousePos = e.Location; Invalidate(); - if (isHand && isDragging) + if (isDragging) { Size difference = new Size(e.X - lastMouse.X, e.Y - lastMouse.Y); lastMouse = new Point(e.X, e.Y); @@ -123,6 +165,7 @@ protected override void OnMouseMove(MouseEventArgs e) } } + // Zoom protected override void OnMouseWheel(MouseEventArgs e) { int wheelDelta = 120; @@ -133,7 +176,7 @@ protected override void OnMouseWheel(MouseEventArgs e) if (RenderScale < 1) { - RenderScale = oldScale; + RenderScale = 1; } else if (RenderScale > 500) { @@ -149,11 +192,6 @@ protected override void OnMouseWheel(MouseEventArgs e) Invalidate(); } - protected void UpdateCursor() - { - Cursor = isHand ? Cursors.SizeAll : Cursors.Arrow; - } - protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; @@ -194,20 +232,35 @@ protected void DrawPVS(Graphics g) return; // Draw all plates - for (int i = 0; i < PVS.Zones.Count; i++) + int selectedZoneIndex = PVS.data.Zones.FindIndex(z => z.ZoneId == PVS.selectedZoneId); + for (int i = 0; i < PVS.data.Zones.Count; i++) { - PVSZone plate = PVS.Zones[i]; + Zone plate = PVS.data.Zones[i]; + if (selectedZoneIndex != -1) + { + if (i == selectedZoneIndex) + { + DrawMapSection(g, plate, MapSectionType.Current); + continue; + } + if (PVS.data.Zones[selectedZoneIndex].UnsafeNeighbours.FindIndex(n => n.ZoneId == plate.ZoneId) != -1) + { + DrawMapSection(g, plate, MapSectionType.Neighbour); + continue; + } + } + DrawMapSection(g, plate); } } - protected void DrawMapSection(Graphics g, PVSZone entry) + protected void DrawMapSection(Graphics g, Zone entry, MapSectionType type = MapSectionType.Unloaded) { PointF[] points = new PointF[entry.Points.Count]; for (int i = 0; i < entry.Points.Count; i++) { - ZonePoint data = entry.Points[i]; + Vector2 data = entry.Points[i]; points[i] = new PointF(data.X * Multiplier * RenderScale + RenderOffset.X, data.Y * Multiplier * RenderScale + RenderOffset.Y); } @@ -216,8 +269,10 @@ protected void DrawMapSection(Graphics g, PVSZone entry) if (bounds.IntersectsWith(ClientRectangle)) { - - //g.FillPolygon(new SolidBrush(Color.IndianRed), points); + if (type == MapSectionType.Current) + g.FillPolygon(new SolidBrush(Color.FromArgb(127, 255, 0, 0)), points); // Red + else if (type == MapSectionType.Neighbour) + g.FillPolygon(new SolidBrush(Color.FromArgb(127, 255, 255, 0)), points); // Yellow g.DrawPolygon(new Pen(Color.Cyan), points); Font font; @@ -241,7 +296,7 @@ protected void DrawMapSection(Graphics g, PVSZone entry) } float textScale = RenderScale / (Multiplier * 2) - times; font = new Font(Font.FontFamily, textScale); - infoText = entry.ZoneID.ToString(); + infoText = entry.ZoneId.ToString(); textSize = g.MeasureString(infoText, font); times++; diff --git a/PVSFormat/PVSEditControl.resx b/PVSFormat/PVSEditControl.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/PVSFormat/PVSEditControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/PVSFormat/PVSEditor.Designer.cs b/PVSFormat/PVSEditor.Designer.cs index 0fd3f3a..7bcef33 100644 --- a/PVSFormat/PVSEditor.Designer.cs +++ b/PVSFormat/PVSEditor.Designer.cs @@ -1,4 +1,4 @@ -namespace PVSFormat +namespace PVSFormat { partial class PVSEditor { @@ -28,73 +28,446 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.stsMain = new System.Windows.Forms.StatusStrip(); - this.mnuMain = new System.Windows.Forms.MenuStrip(); - this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.pvsMain = new PVSFormat.PVSEditControl(); - this.mnuMain.SuspendLayout(); - this.SuspendLayout(); - // - // stsMain - // - this.stsMain.Location = new System.Drawing.Point(0, 339); - this.stsMain.Name = "stsMain"; - this.stsMain.Size = new System.Drawing.Size(524, 22); - this.stsMain.TabIndex = 1; - this.stsMain.Text = "statusStrip1"; - // - // mnuMain - // - this.mnuMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.debugToolStripMenuItem}); - this.mnuMain.Location = new System.Drawing.Point(0, 0); - this.mnuMain.Name = "mnuMain"; - this.mnuMain.Size = new System.Drawing.Size(524, 24); - this.mnuMain.TabIndex = 2; - this.mnuMain.Text = "menuStrip1"; - // - // debugToolStripMenuItem - // - this.debugToolStripMenuItem.Name = "debugToolStripMenuItem"; - this.debugToolStripMenuItem.Size = new System.Drawing.Size(54, 20); - this.debugToolStripMenuItem.Text = "Debug"; - this.debugToolStripMenuItem.Click += new System.EventHandler(this.DebugToolStripMenuItem_Click); + pvsSplitContainer = new System.Windows.Forms.SplitContainer(); + pvsMain = new PVSEditControl(); + deleteZoneButton = new System.Windows.Forms.Button(); + addZoneButton = new System.Windows.Forms.Button(); + zonesListBox = new System.Windows.Forms.ListBox(); + deleteNeighbourButton = new System.Windows.Forms.Button(); + addNeighbourButton = new System.Windows.Forms.Button(); + yLabel2 = new System.Windows.Forms.Label(); + yLabel3 = new System.Windows.Forms.Label(); + yLabel4 = new System.Windows.Forms.Label(); + yLabel1 = new System.Windows.Forms.Label(); + immediateCheckBox = new System.Windows.Forms.CheckBox(); + renderCheckBox = new System.Windows.Forms.CheckBox(); + zonesLabel = new System.Windows.Forms.Label(); + neighboursListBox = new System.Windows.Forms.ListBox(); + neighboursLabel = new System.Windows.Forms.Label(); + xLabel2 = new System.Windows.Forms.Label(); + point2YNumericUpDown = new System.Windows.Forms.NumericUpDown(); + point2XNumericUpDown = new System.Windows.Forms.NumericUpDown(); + xLabel3 = new System.Windows.Forms.Label(); + point3YNumericUpDown = new System.Windows.Forms.NumericUpDown(); + point3XNumericUpDown = new System.Windows.Forms.NumericUpDown(); + xLabel4 = new System.Windows.Forms.Label(); + point4YNumericUpDown = new System.Windows.Forms.NumericUpDown(); + point4XNumericUpDown = new System.Windows.Forms.NumericUpDown(); + xLabel1 = new System.Windows.Forms.Label(); + point1YNumericUpDown = new System.Windows.Forms.NumericUpDown(); + point1XNumericUpDown = new System.Windows.Forms.NumericUpDown(); + pointsLabel = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)pvsSplitContainer).BeginInit(); + pvsSplitContainer.Panel1.SuspendLayout(); + pvsSplitContainer.Panel2.SuspendLayout(); + pvsSplitContainer.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)point2YNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)point2XNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)point3YNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)point3XNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)point4YNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)point4XNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)point1YNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)point1XNumericUpDown).BeginInit(); + SuspendLayout(); + // + // pvsSplitContainer + // + pvsSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; + pvsSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + pvsSplitContainer.Location = new System.Drawing.Point(0, 0); + pvsSplitContainer.Name = "pvsSplitContainer"; + // + // pvsSplitContainer.Panel1 + // + pvsSplitContainer.Panel1.Controls.Add(pvsMain); + // + // pvsSplitContainer.Panel2 + // + pvsSplitContainer.Panel2.Controls.Add(deleteZoneButton); + pvsSplitContainer.Panel2.Controls.Add(addZoneButton); + pvsSplitContainer.Panel2.Controls.Add(zonesListBox); + pvsSplitContainer.Panel2.Controls.Add(deleteNeighbourButton); + pvsSplitContainer.Panel2.Controls.Add(addNeighbourButton); + pvsSplitContainer.Panel2.Controls.Add(yLabel2); + pvsSplitContainer.Panel2.Controls.Add(yLabel3); + pvsSplitContainer.Panel2.Controls.Add(yLabel4); + pvsSplitContainer.Panel2.Controls.Add(yLabel1); + pvsSplitContainer.Panel2.Controls.Add(immediateCheckBox); + pvsSplitContainer.Panel2.Controls.Add(renderCheckBox); + pvsSplitContainer.Panel2.Controls.Add(zonesLabel); + pvsSplitContainer.Panel2.Controls.Add(neighboursListBox); + pvsSplitContainer.Panel2.Controls.Add(neighboursLabel); + pvsSplitContainer.Panel2.Controls.Add(xLabel2); + pvsSplitContainer.Panel2.Controls.Add(point2YNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(point2XNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(xLabel3); + pvsSplitContainer.Panel2.Controls.Add(point3YNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(point3XNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(xLabel4); + pvsSplitContainer.Panel2.Controls.Add(point4YNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(point4XNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(xLabel1); + pvsSplitContainer.Panel2.Controls.Add(point1YNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(point1XNumericUpDown); + pvsSplitContainer.Panel2.Controls.Add(pointsLabel); + pvsSplitContainer.Size = new System.Drawing.Size(784, 561); + pvsSplitContainer.SplitterDistance = 580; + pvsSplitContainer.TabIndex = 0; // // pvsMain // - this.pvsMain.BackColor = System.Drawing.Color.Black; - this.pvsMain.Dock = System.Windows.Forms.DockStyle.Fill; - this.pvsMain.Font = new System.Drawing.Font("Courier New", 10F); - this.pvsMain.ForeColor = System.Drawing.Color.White; - this.pvsMain.Location = new System.Drawing.Point(0, 24); - this.pvsMain.Name = "pvsMain"; - this.pvsMain.PVS = null; - this.pvsMain.Size = new System.Drawing.Size(524, 315); - this.pvsMain.TabIndex = 3; - this.pvsMain.Text = "pvsEditControl1"; + pvsMain.BackColor = System.Drawing.Color.Black; + pvsMain.Dock = System.Windows.Forms.DockStyle.Fill; + pvsMain.Font = new System.Drawing.Font("Courier New", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + pvsMain.ForeColor = System.Drawing.Color.White; + pvsMain.Location = new System.Drawing.Point(0, 0); + pvsMain.Name = "pvsMain"; + pvsMain.PVS = null; + pvsMain.Size = new System.Drawing.Size(580, 561); + pvsMain.TabIndex = 0; + pvsMain.DoubleClick += pvsMain_DoubleClick; + // + // deleteZoneButton + // + deleteZoneButton.Enabled = false; + deleteZoneButton.Location = new System.Drawing.Point(136, 8); + deleteZoneButton.Name = "deleteZoneButton"; + deleteZoneButton.Size = new System.Drawing.Size(48, 23); + deleteZoneButton.TabIndex = 28; + deleteZoneButton.Text = "Delete"; + deleteZoneButton.UseVisualStyleBackColor = true; + deleteZoneButton.Click += deleteZoneButton_Click; + // + // addZoneButton + // + addZoneButton.Location = new System.Drawing.Point(16, 8); + addZoneButton.Name = "addZoneButton"; + addZoneButton.Size = new System.Drawing.Size(48, 23); + addZoneButton.TabIndex = 27; + addZoneButton.Text = "Add"; + addZoneButton.UseVisualStyleBackColor = true; + addZoneButton.Click += addZoneButton_Click; + // + // zonesListBox + // + zonesListBox.FormattingEnabled = true; + zonesListBox.ItemHeight = 15; + zonesListBox.Location = new System.Drawing.Point(12, 32); + zonesListBox.Name = "zonesListBox"; + zonesListBox.Size = new System.Drawing.Size(177, 184); + zonesListBox.Sorted = true; + zonesListBox.TabIndex = 26; + zonesListBox.SelectedIndexChanged += zonesListBox_SelectedIndexChanged; + // + // deleteNeighbourButton + // + deleteNeighbourButton.Enabled = false; + deleteNeighbourButton.Location = new System.Drawing.Point(135, 353); + deleteNeighbourButton.Name = "deleteNeighbourButton"; + deleteNeighbourButton.Size = new System.Drawing.Size(48, 23); + deleteNeighbourButton.TabIndex = 24; + deleteNeighbourButton.Text = "Delete"; + deleteNeighbourButton.UseVisualStyleBackColor = true; + deleteNeighbourButton.Click += deleteNeighbourButton_Click; + // + // addNeighbourButton + // + addNeighbourButton.Enabled = false; + addNeighbourButton.Location = new System.Drawing.Point(15, 353); + addNeighbourButton.Name = "addNeighbourButton"; + addNeighbourButton.Size = new System.Drawing.Size(48, 23); + addNeighbourButton.TabIndex = 23; + addNeighbourButton.Text = "Add"; + addNeighbourButton.UseVisualStyleBackColor = true; + addNeighbourButton.Click += addNeighbourButton_Click; + // + // yLabel2 + // + yLabel2.AutoSize = true; + yLabel2.Location = new System.Drawing.Point(100, 269); + yLabel2.Name = "yLabel2"; + yLabel2.Size = new System.Drawing.Size(13, 15); + yLabel2.TabIndex = 22; + yLabel2.Text = "y"; + // + // yLabel3 + // + yLabel3.AutoSize = true; + yLabel3.Location = new System.Drawing.Point(100, 298); + yLabel3.Name = "yLabel3"; + yLabel3.Size = new System.Drawing.Size(13, 15); + yLabel3.TabIndex = 21; + yLabel3.Text = "y"; + // + // yLabel4 + // + yLabel4.AutoSize = true; + yLabel4.Location = new System.Drawing.Point(100, 327); + yLabel4.Name = "yLabel4"; + yLabel4.Size = new System.Drawing.Size(13, 15); + yLabel4.TabIndex = 20; + yLabel4.Text = "y"; + // + // yLabel1 + // + yLabel1.AutoSize = true; + yLabel1.Location = new System.Drawing.Point(100, 240); + yLabel1.Name = "yLabel1"; + yLabel1.Size = new System.Drawing.Size(13, 15); + yLabel1.TabIndex = 19; + yLabel1.Text = "y"; + // + // immediateCheckBox + // + immediateCheckBox.AutoSize = true; + immediateCheckBox.Enabled = false; + immediateCheckBox.Location = new System.Drawing.Point(97, 538); + immediateCheckBox.Name = "immediateCheckBox"; + immediateCheckBox.Size = new System.Drawing.Size(83, 19); + immediateCheckBox.TabIndex = 18; + immediateCheckBox.Text = "Immediate"; + immediateCheckBox.UseVisualStyleBackColor = true; + immediateCheckBox.CheckedChanged += immediateCheckBox_CheckedChanged; + // + // renderCheckBox + // + renderCheckBox.AutoSize = true; + renderCheckBox.Enabled = false; + renderCheckBox.Location = new System.Drawing.Point(23, 538); + renderCheckBox.Name = "renderCheckBox"; + renderCheckBox.Size = new System.Drawing.Size(63, 19); + renderCheckBox.TabIndex = 17; + renderCheckBox.Text = "Render"; + renderCheckBox.UseVisualStyleBackColor = true; + renderCheckBox.CheckedChanged += renderCheckBox_CheckedChanged; + // + // zonesLabel + // + zonesLabel.AutoSize = true; + zonesLabel.Location = new System.Drawing.Point(79, 12); + zonesLabel.Name = "zonesLabel"; + zonesLabel.Size = new System.Drawing.Size(39, 15); + zonesLabel.TabIndex = 15; + zonesLabel.Text = "Zones"; + // + // neighboursListBox + // + neighboursListBox.Enabled = false; + neighboursListBox.FormattingEnabled = true; + neighboursListBox.ItemHeight = 15; + neighboursListBox.Location = new System.Drawing.Point(11, 378); + neighboursListBox.Name = "neighboursListBox"; + neighboursListBox.Size = new System.Drawing.Size(177, 154); + neighboursListBox.Sorted = true; + neighboursListBox.TabIndex = 14; + neighboursListBox.SelectedIndexChanged += neighboursListBox_SelectedIndexChanged; + // + // neighboursLabel + // + neighboursLabel.AutoSize = true; + neighboursLabel.Location = new System.Drawing.Point(64, 357); + neighboursLabel.Name = "neighboursLabel"; + neighboursLabel.Size = new System.Drawing.Size(69, 15); + neighboursLabel.TabIndex = 13; + neighboursLabel.Text = "Neighbours"; + // + // xLabel2 + // + xLabel2.AutoSize = true; + xLabel2.Location = new System.Drawing.Point(10, 269); + xLabel2.Name = "xLabel2"; + xLabel2.Size = new System.Drawing.Size(13, 15); + xLabel2.TabIndex = 12; + xLabel2.Text = "x"; + // + // point2YNumericUpDown + // + point2YNumericUpDown.DecimalPlaces = 3; + point2YNumericUpDown.Enabled = false; + point2YNumericUpDown.Location = new System.Drawing.Point(115, 265); + point2YNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point2YNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point2YNumericUpDown.Name = "point2YNumericUpDown"; + point2YNumericUpDown.Size = new System.Drawing.Size(70, 23); + point2YNumericUpDown.TabIndex = 11; + point2YNumericUpDown.ValueChanged += point2YNumericUpDown_ValueChanged; + // + // point2XNumericUpDown + // + point2XNumericUpDown.DecimalPlaces = 3; + point2XNumericUpDown.Enabled = false; + point2XNumericUpDown.Location = new System.Drawing.Point(24, 265); + point2XNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point2XNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point2XNumericUpDown.Name = "point2XNumericUpDown"; + point2XNumericUpDown.Size = new System.Drawing.Size(70, 23); + point2XNumericUpDown.TabIndex = 10; + point2XNumericUpDown.ValueChanged += point2XNumericUpDown_ValueChanged; + // + // xLabel3 + // + xLabel3.AutoSize = true; + xLabel3.Location = new System.Drawing.Point(10, 298); + xLabel3.Name = "xLabel3"; + xLabel3.Size = new System.Drawing.Size(13, 15); + xLabel3.TabIndex = 9; + xLabel3.Text = "x"; + // + // point3YNumericUpDown + // + point3YNumericUpDown.DecimalPlaces = 3; + point3YNumericUpDown.Enabled = false; + point3YNumericUpDown.Location = new System.Drawing.Point(115, 294); + point3YNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point3YNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point3YNumericUpDown.Name = "point3YNumericUpDown"; + point3YNumericUpDown.Size = new System.Drawing.Size(70, 23); + point3YNumericUpDown.TabIndex = 8; + point3YNumericUpDown.ValueChanged += point3YNumericUpDown_ValueChanged; + // + // point3XNumericUpDown + // + point3XNumericUpDown.DecimalPlaces = 3; + point3XNumericUpDown.Enabled = false; + point3XNumericUpDown.Location = new System.Drawing.Point(24, 294); + point3XNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point3XNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point3XNumericUpDown.Name = "point3XNumericUpDown"; + point3XNumericUpDown.Size = new System.Drawing.Size(70, 23); + point3XNumericUpDown.TabIndex = 7; + point3XNumericUpDown.ValueChanged += point3XNumericUpDown_ValueChanged; + // + // xLabel4 + // + xLabel4.AutoSize = true; + xLabel4.Location = new System.Drawing.Point(10, 327); + xLabel4.Name = "xLabel4"; + xLabel4.Size = new System.Drawing.Size(13, 15); + xLabel4.TabIndex = 6; + xLabel4.Text = "x"; + // + // point4YNumericUpDown + // + point4YNumericUpDown.DecimalPlaces = 3; + point4YNumericUpDown.Enabled = false; + point4YNumericUpDown.Location = new System.Drawing.Point(115, 323); + point4YNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point4YNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point4YNumericUpDown.Name = "point4YNumericUpDown"; + point4YNumericUpDown.Size = new System.Drawing.Size(70, 23); + point4YNumericUpDown.TabIndex = 5; + point4YNumericUpDown.ValueChanged += point4YNumericUpDown_ValueChanged; + // + // point4XNumericUpDown + // + point4XNumericUpDown.DecimalPlaces = 3; + point4XNumericUpDown.Enabled = false; + point4XNumericUpDown.Location = new System.Drawing.Point(24, 323); + point4XNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point4XNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point4XNumericUpDown.Name = "point4XNumericUpDown"; + point4XNumericUpDown.Size = new System.Drawing.Size(70, 23); + point4XNumericUpDown.TabIndex = 4; + point4XNumericUpDown.ValueChanged += point4XNumericUpDown_ValueChanged; + // + // xLabel1 + // + xLabel1.AutoSize = true; + xLabel1.Location = new System.Drawing.Point(10, 240); + xLabel1.Name = "xLabel1"; + xLabel1.Size = new System.Drawing.Size(13, 15); + xLabel1.TabIndex = 3; + xLabel1.Text = "x"; + // + // point1YNumericUpDown + // + point1YNumericUpDown.DecimalPlaces = 3; + point1YNumericUpDown.Enabled = false; + point1YNumericUpDown.Location = new System.Drawing.Point(115, 236); + point1YNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point1YNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point1YNumericUpDown.Name = "point1YNumericUpDown"; + point1YNumericUpDown.Size = new System.Drawing.Size(70, 23); + point1YNumericUpDown.TabIndex = 2; + point1YNumericUpDown.ValueChanged += point1YNumericUpDown_ValueChanged; + // + // point1XNumericUpDown + // + point1XNumericUpDown.DecimalPlaces = 3; + point1XNumericUpDown.Enabled = false; + point1XNumericUpDown.Location = new System.Drawing.Point(24, 236); + point1XNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); + point1XNumericUpDown.Minimum = new decimal(new int[] { 10000, 0, 0, int.MinValue }); + point1XNumericUpDown.Name = "point1XNumericUpDown"; + point1XNumericUpDown.Size = new System.Drawing.Size(70, 23); + point1XNumericUpDown.TabIndex = 1; + point1XNumericUpDown.ValueChanged += point1XNumericUpDown_ValueChanged; + // + // pointsLabel + // + pointsLabel.AutoSize = true; + pointsLabel.Location = new System.Drawing.Point(78, 218); + pointsLabel.Name = "pointsLabel"; + pointsLabel.Size = new System.Drawing.Size(40, 15); + pointsLabel.TabIndex = 0; + pointsLabel.Text = "Points"; // // PVSEditor // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(524, 361); - this.Controls.Add(this.pvsMain); - this.Controls.Add(this.stsMain); - this.Controls.Add(this.mnuMain); - this.MainMenuStrip = this.mnuMain; - this.Name = "PVSEditor"; - this.Text = "PVSEditor"; - this.mnuMain.ResumeLayout(false); - this.mnuMain.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - + FormClosing += PVSEditor_FormClosing; + AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + ClientSize = new System.Drawing.Size(784, 561); + Controls.Add(pvsSplitContainer); + Name = "PVSEditor"; + Text = "PVS Editor"; + pvsSplitContainer.Panel1.ResumeLayout(false); + pvsSplitContainer.Panel2.ResumeLayout(false); + pvsSplitContainer.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)pvsSplitContainer).EndInit(); + pvsSplitContainer.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)point2YNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)point2XNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)point3YNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)point3XNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)point4YNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)point4XNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)point1YNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)point1XNumericUpDown).EndInit(); + ResumeLayout(false); } #endregion - private System.Windows.Forms.StatusStrip stsMain; - private System.Windows.Forms.MenuStrip mnuMain; - private System.Windows.Forms.ToolStripMenuItem debugToolStripMenuItem; + + private System.Windows.Forms.SplitContainer pvsSplitContainer; + private System.Windows.Forms.Label pointsLabel; private PVSEditControl pvsMain; + private System.Windows.Forms.Label xLabel2; + private System.Windows.Forms.Label xLabel3; + private System.Windows.Forms.Label xLabel4; + private System.Windows.Forms.Label xLabel1; + private System.Windows.Forms.Label neighboursLabel; + private System.Windows.Forms.Label zonesLabel; + private System.Windows.Forms.NumericUpDown point1XNumericUpDown; + private System.Windows.Forms.NumericUpDown point1YNumericUpDown; + private System.Windows.Forms.NumericUpDown point2YNumericUpDown; + private System.Windows.Forms.NumericUpDown point2XNumericUpDown; + private System.Windows.Forms.NumericUpDown point3YNumericUpDown; + private System.Windows.Forms.NumericUpDown point3XNumericUpDown; + private System.Windows.Forms.NumericUpDown point4YNumericUpDown; + private System.Windows.Forms.NumericUpDown point4XNumericUpDown; + private System.Windows.Forms.ListBox neighboursListBox; + private System.Windows.Forms.CheckBox immediateCheckBox; + private System.Windows.Forms.CheckBox renderCheckBox; + private System.Windows.Forms.Label yLabel2; + private System.Windows.Forms.Label yLabel3; + private System.Windows.Forms.Label yLabel4; + private System.Windows.Forms.Label yLabel1; + private System.Windows.Forms.Button deleteNeighbourButton; + private System.Windows.Forms.Button addNeighbourButton; + private System.Windows.Forms.Button deleteZoneButton; + private System.Windows.Forms.Button addZoneButton; + private System.Windows.Forms.ListBox zonesListBox; } -} \ No newline at end of file +} diff --git a/PVSFormat/PVSEditor.cs b/PVSFormat/PVSEditor.cs index a5c0591..637eab5 100644 --- a/PVSFormat/PVSEditor.cs +++ b/PVSFormat/PVSEditor.cs @@ -1,4 +1,8 @@ +using System; +using System.Collections.Generic; using System.Drawing; +using System.Linq; +using System.Numerics; using System.Windows.Forms; using DebugHelper; using PluginAPI; @@ -7,6 +11,9 @@ namespace PVSFormat { public partial class PVSEditor : Form, IEntryEditor { + public delegate void OnEdit(); + public event OnEdit Edit; + private PVS _currentPVS; public Image GameMap @@ -24,6 +31,9 @@ public void UpdateDisplay() { //dbgMain.SelectedObject = _currentPVS; pvsMain.PVS = _currentPVS; + + foreach (Zone zone in pvsMain.PVS.data.Zones) + zonesListBox.Items.Add(zone.ZoneId.ToString("000")); } public void Open(PVS pvs) @@ -33,9 +43,277 @@ public void Open(PVS pvs) UpdateDisplay(); } - private void DebugToolStripMenuItem_Click(object sender, System.EventArgs e) + private List GetZones() + { + return pvsMain.PVS.data.Zones; + } + + private List GetPoints() + { + return pvsMain.PVS.data.Zones[pvsMain.GetZoneIndex(ulong.Parse(zonesListBox.SelectedItem.ToString()))].Points; + } + + private List GetUnsafeNeighbours() + { + return pvsMain.PVS.data.Zones[pvsMain.GetZoneIndex(ulong.Parse(zonesListBox.SelectedItem.ToString()))].UnsafeNeighbours; + } + + private void SelectZone(ulong zoneId) + { + neighboursListBox.Items.Clear(); + renderCheckBox.Checked = false; + immediateCheckBox.Checked = false; + + pvsMain.PVS.selectedZoneId = zoneId; + + List points = pvsMain.GetZonePoints(zoneId); + List neighbours = pvsMain.GetZoneNeighbours(zoneId); + + point1XNumericUpDown.Value = (decimal)points[0].X; + point1YNumericUpDown.Value = (decimal)points[0].Y; + point2XNumericUpDown.Value = (decimal)points[1].X; + point2YNumericUpDown.Value = (decimal)points[1].Y; + point3XNumericUpDown.Value = (decimal)points[2].X; + point3YNumericUpDown.Value = (decimal)points[2].Y; + point4XNumericUpDown.Value = (decimal)points[3].X; + point4YNumericUpDown.Value = (decimal)points[3].Y; + + foreach (Neighbour neighbour in neighbours) + neighboursListBox.Items.Add(neighbour.ZoneId.ToString("000")); + + point1XNumericUpDown.Enabled = true; + point1YNumericUpDown.Enabled = true; + point2XNumericUpDown.Enabled = true; + point2YNumericUpDown.Enabled = true; + point3XNumericUpDown.Enabled = true; + point3YNumericUpDown.Enabled = true; + point4XNumericUpDown.Enabled = true; + point4YNumericUpDown.Enabled = true; + neighboursListBox.Enabled = true; + addNeighbourButton.Enabled = true; + deleteNeighbourButton.Enabled = false; + renderCheckBox.Enabled = false; + immediateCheckBox.Enabled = false; + } + + private void PVSEditor_FormClosing(object sender, FormClosingEventArgs e) + { + pvsMain.PVS.selectedZoneId = ulong.MaxValue; + Edit?.Invoke(); + } + + private void pvsMain_DoubleClick(object sender, System.EventArgs e) + { + ulong zoneId = pvsMain.GetZoneId(); + if (zoneId == ulong.MaxValue) + return; + + zonesListBox.SelectedIndex = zonesListBox.FindStringExact(zoneId.ToString("000")); + } + + private void zonesListBox_SelectedIndexChanged(object sender, System.EventArgs e) + { + if (zonesListBox.SelectedIndex == -1) + return; + ulong zoneId = ulong.Parse(zonesListBox.SelectedItem.ToString()); + SelectZone(zoneId); + + deleteZoneButton.Enabled = true; + } + + private void addZoneButton_Click(object sender, System.EventArgs e) + { + var zones = GetZones(); + ulong newZoneId; + while (true) + { + newZoneId = new AddZone().GetNewZoneId(); + if (zones.FindIndex(z => z.ZoneId == newZoneId) != -1) + { + MessageBox.Show("A zone with ID " + newZoneId + " already exists."); + continue; + } + break; + } + Zone newZone = new(); + newZone.ZoneId = newZoneId; + zones.Add(newZone); + pvsMain.PVS.data.TotalZones++; + + zonesListBox.Items.Add(newZoneId.ToString("000")); + zonesListBox.SelectedIndex = zonesListBox.FindStringExact(newZoneId.ToString("000")); + if (zonesListBox.Items.Count == 1) + deleteZoneButton.Enabled = true; + } + + private void deleteZoneButton_Click(object sender, System.EventArgs e) + { + int index = zonesListBox.SelectedIndex; + ulong zoneId = ulong.Parse(zonesListBox.Items[index].ToString()); + GetZones().Remove(GetZones().Find(z => z.ZoneId == zoneId)); + pvsMain.PVS.data.TotalZones--; + + zonesListBox.Items.RemoveAt(index); + if (zonesListBox.Items.Count == 0) + { + deleteZoneButton.Enabled = false; + return; + } + if (index == zonesListBox.Items.Count) + zonesListBox.SelectedIndex = zonesListBox.Items.Count - 1; + else + zonesListBox.SelectedIndex = index; + } + + private void point1XNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[0]; + point.X = (float)point1XNumericUpDown.Value; + GetPoints()[0] = point; + pvsMain.Invalidate(); + } + + private void point1YNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[0]; + point.Y = (float)point1YNumericUpDown.Value; + GetPoints()[0] = point; + pvsMain.Invalidate(); + } + + private void point2XNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[1]; + point.X = (float)point2XNumericUpDown.Value; + GetPoints()[1] = point; + pvsMain.Invalidate(); + } + + private void point2YNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[1]; + point.Y = (float)point2YNumericUpDown.Value; + GetPoints()[1] = point; + pvsMain.Invalidate(); + } + + private void point3XNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[2]; + point.X = (float)point3XNumericUpDown.Value; + GetPoints()[2] = point; + pvsMain.Invalidate(); + } + + private void point3YNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[2]; + point.Y = (float)point3YNumericUpDown.Value; + GetPoints()[2] = point; + pvsMain.Invalidate(); + } + + private void point4XNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[3]; + point.X = (float)point4XNumericUpDown.Value; + GetPoints()[3] = point; + pvsMain.Invalidate(); + } + + private void point4YNumericUpDown_ValueChanged(object sender, System.EventArgs e) + { + Vector2 point = GetPoints()[3]; + point.Y = (float)point4YNumericUpDown.Value; + GetPoints()[3] = point; + pvsMain.Invalidate(); + } + + private void neighboursListBox_SelectedIndexChanged(object sender, System.EventArgs e) + { + if (neighboursListBox.SelectedIndex == -1) + return; + int neighbourIndex = GetUnsafeNeighbours().FindIndex(n => n.ZoneId == ulong.Parse(neighboursListBox.SelectedItem.ToString())); + Neighbour neighbour = GetUnsafeNeighbours()[neighbourIndex]; + renderCheckBox.Checked = neighbour.Flags.HasFlag(NeighbourFlags.E_NEIGHBOURFLAG_RENDER); + immediateCheckBox.Checked = neighbour.Flags.HasFlag(NeighbourFlags.E_NEIGHBOURFLAG_IMMEDIATE); + + if (neighboursListBox.Items.Count != 0) + deleteNeighbourButton.Enabled = true; + renderCheckBox.Enabled = true; + immediateCheckBox.Enabled = true; + } + + private void addNeighbourButton_Click(object sender, System.EventArgs e) + { + ulong newZoneId = new AddZone().GetNewZoneId(); + var neighbours = GetUnsafeNeighbours(); + Neighbour newNeighbour = new(); + newNeighbour.ZoneId = newZoneId; + neighbours.Add(newNeighbour); + int parentIndex = GetZones().FindIndex(z => z.ZoneId == ulong.Parse(zonesListBox.SelectedItem.ToString())); + Zone parent = GetZones()[parentIndex]; + parent.NumUnsafeNeighbours++; + GetZones()[parentIndex] = parent; + + neighboursListBox.Items.Add(newZoneId.ToString("000")); + neighboursListBox.SelectedIndex = neighboursListBox.FindStringExact(newZoneId.ToString("000")); + pvsMain.Invalidate(); + if (neighboursListBox.Items.Count == 1) + deleteNeighbourButton.Enabled = true; + } + + private void deleteNeighbourButton_Click(object sender, System.EventArgs e) + { + int index = neighboursListBox.SelectedIndex; + ulong zoneId = ulong.Parse(neighboursListBox.Items[index].ToString()); + GetUnsafeNeighbours().Remove(GetUnsafeNeighbours().Find(n => n.ZoneId == zoneId)); + int parentIndex = GetZones().FindIndex(z => z.ZoneId == ulong.Parse(zonesListBox.SelectedItem.ToString())); + Zone parent = GetZones()[parentIndex]; + parent.NumUnsafeNeighbours--; + GetZones()[parentIndex] = parent; + + neighboursListBox.Items.RemoveAt(index); + pvsMain.Invalidate(); + if (neighboursListBox.Items.Count == 0) + { + deleteNeighbourButton.Enabled = false; + renderCheckBox.Enabled = false; + immediateCheckBox.Enabled = false; + renderCheckBox.Checked = false; + immediateCheckBox.Checked = false; + return; + } + if (index == neighboursListBox.Items.Count) + neighboursListBox.SelectedIndex = neighboursListBox.Items.Count - 1; + else + neighboursListBox.SelectedIndex = index; + } + + private void renderCheckBox_CheckedChanged(object sender, System.EventArgs e) + { + if (neighboursListBox.SelectedIndex == -1) + return; + int neighbourIndex = GetUnsafeNeighbours().FindIndex(n => n.ZoneId == ulong.Parse(neighboursListBox.SelectedItem.ToString())); + Neighbour neighbour = GetUnsafeNeighbours()[neighbourIndex]; + if (renderCheckBox.Checked) + neighbour.Flags |= NeighbourFlags.E_NEIGHBOURFLAG_RENDER; + else + neighbour.Flags &= ~NeighbourFlags.E_NEIGHBOURFLAG_RENDER; + GetUnsafeNeighbours()[neighbourIndex] = neighbour; + } + + private void immediateCheckBox_CheckedChanged(object sender, System.EventArgs e) { - DebugUtil.ShowDebug(_currentPVS); + if (neighboursListBox.SelectedIndex == -1) + return; + int neighbourIndex = GetUnsafeNeighbours().FindIndex(n => n.ZoneId == ulong.Parse(neighboursListBox.SelectedItem.ToString())); + Neighbour neighbour = GetUnsafeNeighbours()[neighbourIndex]; + if (immediateCheckBox.Checked) + neighbour.Flags |= NeighbourFlags.E_NEIGHBOURFLAG_IMMEDIATE; + else + neighbour.Flags &= ~NeighbourFlags.E_NEIGHBOURFLAG_IMMEDIATE; + GetUnsafeNeighbours()[neighbourIndex] = neighbour; } } } diff --git a/PVSFormat/PVSEditor.resx b/PVSFormat/PVSEditor.resx index 411bc26..a395bff 100644 --- a/PVSFormat/PVSEditor.resx +++ b/PVSFormat/PVSEditor.resx @@ -1,24 +1,24 @@  - @@ -117,10 +117,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 17, 17 - - - 111, 17 - \ No newline at end of file diff --git a/PVSFormat/Util/GeneralExtensions.cs b/PVSFormat/Util/GeneralExtensions.cs deleted file mode 100644 index c2d99e5..0000000 --- a/PVSFormat/Util/GeneralExtensions.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System.IO; -using System.Text; - -namespace PVSFormat.Util -{ - public static class GeneralExtensions - { - public static bool Matches(this string[] self, string[] other) - { - if (self.Length != other.Length) - return false; - - for (int i = 0; i < self.Length; i++) - { - if (self[i] != other[i]) - return false; - } - - return true; - } - - public static string[] Rebuild(this string[] self, int size) - { - string[] result = new string[size]; - for (int i = 0; i < result.Length; i++) - { - if (i >= self.Length) - { - result[i] = ""; - continue; - } - result[i] = self[i]; - } - return result; - } - - public static string BuildString(this string[] self) - { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < self.Length; i++) - { - sb.Append(self[i] + "\r\n"); - } - - return sb.ToString(); - } - - public static string AsArrayIndexString(this int[] self) - { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < self.Length; i++) - { - sb.Append(self[i].ToString()); - - if (i < self.Length - 1) - sb.Append(", "); - } - - return sb.ToString(); - } - - public static bool EOF(this BinaryReader self) - { - return self.BaseStream.Position >= self.BaseStream.Length; - } - } -}