Fix map viewer (#225)

This commit is contained in:
JelleInfinity 2022-09-10 19:37:53 +01:00 committed by GitHub
parent c7340bb785
commit 5c1fce310e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 147 additions and 76 deletions

View File

@ -71,11 +71,11 @@ public bool Contains(float x, float y, float z)
{
if (ShapeID == ShapeIdSphere)
{
if (!Parameters.Scale.IsDefault)
if (!Parameters.Scale.IsOne)
throw new NotImplementedException("Scaled spheres not yet supported!");
var radius = Math.Abs(SizeX);
var distance = Parameters.Coordinates.DistanceTo(x, y, z);
var distance = Parameters.Coordinates.DistanceTo(new(x, y, z));
return distance <= radius;
}
if (ShapeID == ShapeIdBox)
@ -116,11 +116,11 @@ public bool IntersectsSphere(float x, float y, float z, float sphereRadius)
if (ShapeID == ShapeIdSphere)
{
if (!Parameters.Scale.IsDefault)
if (!Parameters.Scale.IsOne)
throw new NotImplementedException("Scaled spheres not yet supported!");
var radius = Math.Abs(SizeX);
var distance = Parameters.Coordinates.DistanceTo(x, y, z);
var distance = Parameters.Coordinates.DistanceTo(new(x, y, z));
return distance <= radius + sphereRadius;
}
if (ShapeID == ShapeIdBox)

View File

@ -14,13 +14,36 @@ namespace pkNX.Structures.FlatBuffers;
[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]
public class PlacementV3f8a : IEquatable<PlacementV3f8a>
{
[FlatBufferItem(0)] public float X { get; set; }
[FlatBufferItem(1)] public float Y { get; set; }
[FlatBufferItem(2)] public float Z { get; set; }
public bool IsDefault => X is 1.0f && Y is 1.0f && Z is 1.0f;
[FlatBufferItem(0)] public float X { get; set; } = 0;
[FlatBufferItem(1)] public float Y { get; set; } = 0;
[FlatBufferItem(2)] public float Z { get; set; } = 0;
public double DistanceTo(PlacementV3f8a other) => DistanceTo(other.X, other.Y, other.Z);
public double DistanceTo(float x, float y, float z) => Math.Sqrt(Math.Pow(X - x, 2) + Math.Pow(Y - y, 2) + Math.Pow(Z - z, 2));
public PlacementV3f8a()
{
X = 0;
Y = 0;
Z = 0;
}
public PlacementV3f8a(float x = 0, float y = 0, float z = 0)
{
X = x;
Y = y;
Z = z;
}
public bool IsOne => X is 1 && Y is 1 && Z is 1;
public bool IsZero => X is 0 && Y is 0 && Z is 0;
public float Magnitude => (float)Math.Sqrt(MagnitudeSqr);
public float MagnitudeSqr => Dot(this);
public PlacementV3f8a Normalized => this * (1 / Magnitude);
public float Dot(PlacementV3f8a other) => X * other.X + Y * other.Y + Z * other.Z;
public PlacementV3f8a Cross(PlacementV3f8a other) => new(Y * other.Z - Z * other.Y, Z * other.X - X * other.Z, X * other.Y - Y * other.X);
public float DistanceTo(PlacementV3f8a other) => (this - other).Magnitude;
public float DistanceToSqr(PlacementV3f8a other) => (this - other).MagnitudeSqr;
public PlacementV3f8a Lerp(PlacementV3f8a other, float t) => this + (other - this) * t;
public PlacementV3f8a Clone() => new()
{
@ -58,6 +81,18 @@ public override int GetHashCode()
}
}
public static PlacementV3f8a operator -(PlacementV3f8a v) => new(-v.X, -v.Y, -v.Z);
public static PlacementV3f8a operator +(PlacementV3f8a l, PlacementV3f8a r) => new(l.X + r.X, l.Y + r.Y, l.Z + r.Z);
public static PlacementV3f8a operator -(PlacementV3f8a l, PlacementV3f8a r) => new(l.X - r.X, l.Y - r.Y, l.Z - r.Z);
public static PlacementV3f8a operator *(PlacementV3f8a l, PlacementV3f8a r) => new(l.X * r.X, l.Y * r.Y, l.Z * r.Z);
public static PlacementV3f8a operator /(PlacementV3f8a l, PlacementV3f8a r) => new(l.X / r.X, l.Y / r.Y, l.Z / r.Z);
public static PlacementV3f8a operator +(PlacementV3f8a l, float r) => new(l.X + r, l.Y + r, l.Z + r);
public static PlacementV3f8a operator -(PlacementV3f8a l, float r) => new(l.X - r, l.Y - r, l.Z - r);
public static PlacementV3f8a operator *(PlacementV3f8a l, float r) => new(l.X * r, l.Y * r, l.Z * r);
public static PlacementV3f8a operator /(PlacementV3f8a l, float r) => new(l.X / r, l.Y / r, l.Z / r);
public static bool operator ==(PlacementV3f8a? left, PlacementV3f8a? right) => Equals(left, right);
public static bool operator !=(PlacementV3f8a? left, PlacementV3f8a? right) => !Equals(left, right);
}

View File

@ -15,6 +15,8 @@ public sealed class AreaInstance8a
public IReadOnlyList<AreaInstance8a> SubAreas => Children;
public string AreaName => Area.AreaName;
public string FriendlyAreaName => Area.FriendlyAreaName;
// Encount
public EncounterTable8a[] Encounters => Area.Encounters;

View File

@ -81,6 +81,25 @@ public class AreaSettings8a
[FlatBufferItem(53)] public PlacementV3f8a Field_53 { get; set; } = new();
[FlatBufferItem(54)] public ulong VisibleFlagHash { get; set; } //A flag from system_works
[FlatBufferItem(55)] public bool Field_55 { get; set; }
// Get the in game name of the area
public string FriendlyAreaName
{
get
{
return Name switch
{
"ha_area00" => "Jubilife Village",
"ha_area01" => "Obsidian Fieldlands",
"ha_area02" => "Crimson Mirelands",
"ha_area03" => "Cobalt Coastlands",
"ha_area04" => "Cornet Highlands",
"ha_area05" => "Alabaster Icelands",
"ha_area06" => "Ancient Retreat",
_ => string.Format("Unknown Area ({0})", Name),
};
}
}
}
[FlatBufferTable, TypeConverter(typeof(ExpandableObjectConverter))]

View File

@ -16,6 +16,7 @@ public ResidentArea8a(GFPack resident, AreaSettings8a settings)
}
public string AreaName => Settings.Name;
public string FriendlyAreaName => Settings.FriendlyAreaName;
// Encount
public EncounterTable8a[] Encounters { get; private set; } = Array.Empty<EncounterTable8a>();

View File

@ -327,7 +327,7 @@ public void EditMiscSpeciesInfo()
PopFlat<PokeMiscTable8a, PokeMisc8a>(GameFile.PokeMisc, "Misc Species Info Editor", z => $"{names[z.Species]}{(z.Form == 0 ? "" : $"-{z.Form}")} ~ {z.Value}");
}
public void EditSpawns()
public void EditMap_viewer()
{
var resident = (GFPack)ROM.GetFile(GameFile.Resident);
using var form = new MapViewer8a((GameManagerPLA)ROM, resident);

View File

@ -32,18 +32,17 @@ private void InitializeComponent()
this.CB_Map = new System.Windows.Forms.ComboBox();
this.CB_Species = new System.Windows.Forms.ComboBox();
this.L_CoordinateMouse = new System.Windows.Forms.Label();
this.NUD_Tolerance = new System.Windows.Forms.NumericUpDown();
this.L_SpawnDump = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_Tolerance)).BeginInit();
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.pictureBox1.Location = new System.Drawing.Point(12, 12);
this.pictureBox1.Location = new System.Drawing.Point(20, 23);
this.pictureBox1.Margin = new System.Windows.Forms.Padding(5, 6, 5, 6);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(512, 512);
this.pictureBox1.Size = new System.Drawing.Size(853, 985);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
this.pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MapViewer8a_MouseMove);
@ -52,9 +51,10 @@ private void InitializeComponent()
//
this.CB_Map.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.CB_Map.FormattingEnabled = true;
this.CB_Map.Location = new System.Drawing.Point(530, 12);
this.CB_Map.Location = new System.Drawing.Point(883, 23);
this.CB_Map.Margin = new System.Windows.Forms.Padding(5, 6, 5, 6);
this.CB_Map.Name = "CB_Map";
this.CB_Map.Size = new System.Drawing.Size(121, 21);
this.CB_Map.Size = new System.Drawing.Size(199, 33);
this.CB_Map.TabIndex = 1;
this.CB_Map.SelectedIndexChanged += new System.EventHandler(this.CB_Map_SelectedIndexChanged);
//
@ -63,57 +63,47 @@ private void InitializeComponent()
this.CB_Species.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.CB_Species.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.CB_Species.FormattingEnabled = true;
this.CB_Species.Location = new System.Drawing.Point(530, 138);
this.CB_Species.Location = new System.Drawing.Point(883, 265);
this.CB_Species.Margin = new System.Windows.Forms.Padding(5, 6, 5, 6);
this.CB_Species.Name = "CB_Species";
this.CB_Species.Size = new System.Drawing.Size(121, 21);
this.CB_Species.Size = new System.Drawing.Size(199, 33);
this.CB_Species.TabIndex = 2;
this.CB_Species.SelectedIndexChanged += new System.EventHandler(this.CB_Species_SelectedIndexChanged);
//
// L_CoordinateMouse
//
this.L_CoordinateMouse.AutoSize = true;
this.L_CoordinateMouse.Location = new System.Drawing.Point(527, 510);
this.L_CoordinateMouse.Location = new System.Drawing.Point(878, 981);
this.L_CoordinateMouse.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
this.L_CoordinateMouse.Name = "L_CoordinateMouse";
this.L_CoordinateMouse.Size = new System.Drawing.Size(153, 13);
this.L_CoordinateMouse.Size = new System.Drawing.Size(265, 25);
this.L_CoordinateMouse.TabIndex = 3;
this.L_CoordinateMouse.Text = "Hover over img for Coordinates";
//
// NUD_Tolerance
//
this.NUD_Tolerance.Location = new System.Drawing.Point(530, 487);
this.NUD_Tolerance.Name = "NUD_Tolerance";
this.NUD_Tolerance.Size = new System.Drawing.Size(57, 20);
this.NUD_Tolerance.TabIndex = 4;
this.NUD_Tolerance.Value = new decimal(new int[] {
5,
0,
0,
0});
//
// L_SpawnDump
//
this.L_SpawnDump.Location = new System.Drawing.Point(530, 162);
this.L_SpawnDump.Location = new System.Drawing.Point(883, 312);
this.L_SpawnDump.Margin = new System.Windows.Forms.Padding(5, 0, 5, 0);
this.L_SpawnDump.Name = "L_SpawnDump";
this.L_SpawnDump.Size = new System.Drawing.Size(176, 322);
this.L_SpawnDump.Size = new System.Drawing.Size(293, 669);
this.L_SpawnDump.TabIndex = 5;
this.L_SpawnDump.Text = "~";
this.L_SpawnDump.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
//
// MapViewer8a
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 25F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(709, 532);
this.ClientSize = new System.Drawing.Size(1182, 1023);
this.Controls.Add(this.L_SpawnDump);
this.Controls.Add(this.NUD_Tolerance);
this.Controls.Add(this.L_CoordinateMouse);
this.Controls.Add(this.CB_Species);
this.Controls.Add(this.CB_Map);
this.Controls.Add(this.pictureBox1);
this.Margin = new System.Windows.Forms.Padding(5, 6, 5, 6);
this.Name = "MapViewer8a";
this.Text = "MapViewer8a";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.NUD_Tolerance)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@ -125,7 +115,6 @@ private void InitializeComponent()
private System.Windows.Forms.ComboBox CB_Map;
private System.Windows.Forms.ComboBox CB_Species;
private System.Windows.Forms.Label L_CoordinateMouse;
private System.Windows.Forms.NumericUpDown NUD_Tolerance;
private System.Windows.Forms.Label L_SpawnDump;
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
using pkNX.Containers;
@ -29,9 +30,9 @@ public MapViewer8a(GameManagerPLA rom, GFPack resident)
InitializeComponent();
Areas = ResidentAreaSet.AreaNames.Select(z => AreaInstance8a.Create(Resident, z, Settings)).ToArray();
var speciesNames = ROM.GetStrings(TextName.SpeciesNames);
CB_Map.Items.AddRange(Areas.Select(z => z.ParentArea?.AreaName ?? z.AreaName).ToArray());
CB_Map.Items.AddRange(Areas.Select(z => z.ParentArea?.FriendlyAreaName ?? z.FriendlyAreaName).ToArray());
var speciesNames = ROM.GetStrings(TextName.SpeciesNames);
var pt = rom.Data.PersonalData;
var nameList = new List<ComboItem>();
foreach (var e in pt.Table.OfType<PersonalInfoLA>())
@ -44,16 +45,16 @@ public MapViewer8a(GameManagerPLA rom, GFPack resident)
nameList.Add(new(speciesNames[species], species));
}
nameList.Insert(0, new("(Any)", -1));
nameList.Insert(0, new("(All)", -1));
nameList.Sort((x, y) => string.Compare(x.Text, y.Text, StringComparison.InvariantCulture));
CB_Species.DisplayMember = nameof(ComboItem.Text);
CB_Species.ValueMember = nameof(ComboItem.Value);
CB_Species.DataSource = new BindingSource(nameList, null);
CB_Species.SelectedValue = 399;
CB_Species.SelectedValue = -1;
Loading = false;
CB_Map.SelectedIndex = 0;
CB_Map.SelectedIndex = 1;
}
private class ComboItem
@ -80,23 +81,41 @@ private void CB_Species_SelectedIndexChanged(object sender, EventArgs e)
private List<AreaDef> Defs = new();
private string GetMapImagePath(AreaInstance8a area)
{
string mapName = area.AreaName switch
{
"ha_area00" => "map_lmap_pic_05_05",
"ha_area01" => "map_lmap_pic_00",
"ha_area02" => "map_lmap_pic_01",
"ha_area03" => "map_lmap_pic_02",
"ha_area04" => "map_lmap_pic_03",
"ha_area05" => "map_lmap_pic_04",
"ha_area06" => "map_lmap_pic_06",
_ => area.AreaName,
};
return $"map_pla\\{mapName}.png";
}
private void UpdateMap(int map, int species)
{
if (Loading)
return;
var mapfile = $"map_pla\\map_lmap_pic_l_{map-1:00}.png";
if (!System.IO.File.Exists(mapfile))
var area = Areas[map];
var mapImagePath = System.IO.Path.GetFullPath(GetMapImagePath(area));
if (System.IO.File.Exists(mapImagePath))
{
pictureBox1.BackgroundImage = null;
return;
pictureBox1.BackgroundImage = Image.FromFile(mapImagePath);
}
else
{
WinFormsUtil.Error(string.Format("Unable to find map image at path: {0}", mapImagePath), "Automatic extraction of the map images is not yet supported.\nYou will have to extract them manually and place them at the location above. (You can use Switch-Toolbox for this.)");
pictureBox1.BackgroundImage = new Bitmap(1024, 1024);
}
var area = Areas[map];
var coordinates = Defs = GetSpawnerInfo(species, area);
var img = Image.FromFile(mapfile);
using var gr = Graphics.FromImage(img);
using var gr = Graphics.FromImage(pictureBox1.BackgroundImage);
var r = new SolidBrush(Color.FromArgb(100, 255, 0, 0));
var g = new SolidBrush(Color.FromArgb(100, 20, 255, 10));
var b = new SolidBrush(Color.FromArgb(100, 10, 0, 255));
@ -106,9 +125,11 @@ private void UpdateMap(int map, int species)
var gs = new Pen(Color.FromArgb(255, 20, 255, 10)) { Width = 3 };
var bs = new Pen(Color.FromArgb(255, 10, 0, 255)) { Width = 3 };
var cs = new Pen(Color.FromArgb(255, 10, 255, 255)) { Width = 3 };
var coordinates = Defs = GetSpawnerInfo(species, area);
foreach (var o in coordinates)
{
var pen = o.Type switch
var brush = o.Type switch
{
SpawnerType.Spawner => r,
SpawnerType.Wormhole => g,
@ -124,15 +145,16 @@ private void UpdateMap(int map, int species)
SpawnerType.Unown => cs,
_ => throw new ArgumentOutOfRangeException(nameof(o.Type)),
};
var p = o.Position;
var s = o.Scale;
var x = (p.X * 2) - (s / 2);
var y = (p.Z * 2) - (s / 2);
gr.FillEllipse(pen, x, y, s, s);
gr.DrawEllipse(penS, x, y, s, s);
}
pictureBox1.BackgroundImage = img;
var center = o.Position;
var radius = o.Radius;
var x = center.X - radius;
var y = center.Z - radius;
var d = radius * 2;
gr.FillEllipse(brush, x, y, d, d);
gr.DrawEllipse(penS, x, y, d, d);
}
}
private static List<AreaDef> GetSpawnerInfo(int species, AreaInstance8a area)
@ -149,7 +171,7 @@ private static List<AreaDef> GetSpawnerInfo(int species, AreaInstance8a area)
if (species != -1 && slots.Table.All(z => z.Species != species))
continue;
result.Add(new(slots.TableName, s.MinSpawnCount, s.MaxSpawnCount, s.Parameters.Coordinates, SpawnerType.Spawner, slots.Table, s.Scalar * 4));
result.Add(new(slots.TableName, s.MinSpawnCount, s.MaxSpawnCount, s.Parameters.Coordinates, SpawnerType.Spawner, slots.Table, s.Scalar));
}
foreach (var s in area.Wormholes.Concat(area.SubAreas.SelectMany(z => z.Wormholes)))
@ -162,7 +184,7 @@ private static List<AreaDef> GetSpawnerInfo(int species, AreaInstance8a area)
if (species != -1 && slots.Table.All(z => z.Species != species))
continue;
result.Add(new(slots.TableName, s.MinSpawnCount, s.MaxSpawnCount, s.Parameters.Coordinates, SpawnerType.Wormhole, slots.Table, Math.Max(s.Scalar * 4, 50)));
result.Add(new(slots.TableName, s.MinSpawnCount, s.MaxSpawnCount, s.Parameters.Coordinates, SpawnerType.Wormhole, slots.Table, s.Scalar));
}
foreach (var a in area.LandMarks.Concat(area.SubAreas.SelectMany(z => z.LandMarks)))
@ -200,15 +222,20 @@ private static List<AreaDef> GetSpawnerInfo(int species, AreaInstance8a area)
private void MapViewer8a_MouseMove(object sender, MouseEventArgs e)
{
LatestCoordinates = (e.X * 2, e.Y * 2);
L_CoordinateMouse.Text = $"{LatestCoordinates.X}, {LatestCoordinates.Y}";
SizeF imageSize = pictureBox1.BackgroundImage.Size;
SizeF controlSize = pictureBox1.Size;
float scaleX = imageSize.Width / controlSize.Width;
float scaleY = imageSize.Height / controlSize.Height;
var (x, z) = (e.X * scaleX, e.Y * scaleY);
L_CoordinateMouse.Text = $"{x}, {z}";
var dist = NUD_Tolerance.Value;
var (x, z) = (LatestCoordinates.X, LatestCoordinates.Y);
var spawners = Defs
.Select(s => (Spawner: s, Distance: s.Position.DistanceTo(x, s.Position.Y, z)))
.Where(s=> s.Distance <= (float)dist)
.Select(s => (Spawner: s, Distance: s.Position.DistanceTo(new(x, s.Position.Y, z))))
.Where(s => s.Distance <= s.Spawner.Radius)
.OrderByDescending(s => s.Distance).ToArray();
if (spawners.Length == 0)
{
L_SpawnDump.Text = "";
@ -217,8 +244,6 @@ private void MapViewer8a_MouseMove(object sender, MouseEventArgs e)
L_SpawnDump.Text = string.Join(Environment.NewLine, spawners.Select(s => s.Spawner.GetLine()));
}
private (int X, int Y) LatestCoordinates;
}
public class AreaDef
@ -229,9 +254,9 @@ public class AreaDef
public readonly PlacementV3f8a Position;
public readonly SpawnerType Type;
public readonly EncounterSlot8a[] Slots;
public readonly float Scale;
public readonly float Radius;
public AreaDef(string NameSummary, int min, int max, PlacementV3f8a position, SpawnerType type, EncounterSlot8a[] slots, float scale)
public AreaDef(string NameSummary, int min, int max, PlacementV3f8a position, SpawnerType type, EncounterSlot8a[] slots, float radius)
{
this.NameSummary = NameSummary;
Min = min;
@ -239,7 +264,7 @@ public AreaDef(string NameSummary, int min, int max, PlacementV3f8a position, Sp
Position = position;
Type = type;
Slots = slots;
Scale = scale;
Radius = radius;
}
public string GetLine()