- New AcreItemEditor control. Moves the acre item handling logic out of MainForm.cs

- Stalk Market editing support for City Folk (minus initial buy price)

- Moved selected item & selected building logic out of MainForm.cs and into their respective classes.

- New ListPriority class. Gives information about a Gen1 town's generic item list priorities.

- Worked on FurnitureShop.cs

- Fixed a minor bug in the GCN town generator.

- Moved Yaz0.cs to ACSE.Core.Compression

- Removed the need for MainForm to be a reference in many controls.

- Many other small updates.
This commit is contained in:
Cuyler36 2018-11-22 14:53:36 -05:00
parent 88b0bcc05e
commit a301ee516f
22 changed files with 898 additions and 721 deletions

View file

@ -3,7 +3,7 @@
using System.Text;
using ACSE.Core.Utilities;
namespace ACSE.Core
namespace ACSE.Core.Compression
{
public static class Yaz0
{

View file

@ -845,6 +845,11 @@ private int GetXYCoordinateForBlockType(byte[] Data, int BlockType, out int X, o
return Index;
}
/// <summary>
/// Returns a randomly generated float between 0.0f and 1.0f. The inclusivity is [0.0f - 1.0f).
/// </summary>
/// <param name="seed">The optional seed used to generate the random number.</param>
/// <returns>A random float [0.0f - 1.0f).</returns>
private float fqrand(int? seed = null) // NOTE: seed isn't a parameter in the actual function.
{
var startSeed = seed ?? _randomSeed;
@ -855,6 +860,12 @@ private float fqrand(int? seed = null) // NOTE: seed isn't a parameter in the ac
return BitConverter.ToSingle(BitConverter.GetBytes(startSeed), 0) - 1.0f;
}
/// <summary>
/// Returns a random integer between [0 - <param name="maxValue"/>).
/// </summary>
/// <param name="maxValue">The exclusive upper limit of the random number to be generated.</param>
/// <param name="seed">The optional seed parameter used to geenrate the random number.</param>
/// <returns></returns>
private int GetRandom(int maxValue, int? seed = null) // NOTE: seed isn't a parameter in the actual function.
=> (int)(fqrand(seed) * maxValue);
@ -864,7 +875,7 @@ private int GetRandom(int maxValue, int? seed = null) // NOTE: seed isn't a para
/// <returns>Step Mode</returns>
private int GetRandomStepMode()
{
int RNG = GetRandom(64);
int RNG = GetRandom(100);
int Temp = 0xF ^ RNG;
int ShiftedValue = Temp >> 1;
Temp &= 0xF;

View file

@ -1,11 +1,15 @@
using System;
using System.Drawing;
using ACSE.Core.Saves;
namespace ACSE.Core.Items
{
public class Item : IEquatable<Item>, IEquatable<ushort>
{
/// <summary>
/// The currently selected <see cref="Item"/>.
/// </summary>
public static Item SelectedItem;
public readonly ItemType Type;
public Inventory.AcItemFlag ItemFlag;

View file

@ -128,6 +128,7 @@ public static class SaveDataManager
HouseDataSize = 0x2128,
IslandAcreData = 0x13F60,
IslandWorldData = 0x1B450,
IslandHouse = 0x1B858,
IslandWorldSize = 0x400,
IslandBuriedData = 0x1C908,
IslandBuriedSize = 0x40,

View file

@ -27,6 +27,16 @@ public Acre(byte acreId, int position)
AcreId = acreId;
Index = position;
}
/// <summary>
/// Sets the acre's id number.
/// </summary>
/// <param name="acreId">The desired acre id.</param>
public void SetId(ushort acreId)
{
AcreId = acreId;
BaseAcreId = (ushort) (AcreId & 0xFFFC);
}
}
public class WorldAcre : Acre
@ -46,7 +56,6 @@ public WorldAcre(ushort acreId, int position, ushort[] items = null, uint[] nlIt
for (var i = 0; i < 256; i++)
{
Items[i] = new Item(items[i]);
//Items[i].Buried = IsItemBuried(Items[i], Save.SaveInstance.SaveGeneration);
}
}
else if (nlItems != null)
@ -63,14 +72,9 @@ public WorldAcre(ushort acreId, int position) : base(acreId, position) { }
public WorldAcre(ushort acreId, int position, uint[] items = null) : this(acreId, position, null, items)
{ }
public WorldAcre(ushort acreId, int position, Item[] items, int townPosition = -1) : base(acreId, position)
public WorldAcre(ushort acreId, int position, Item[] items) : base(acreId, position)
{
Items = items;
if (townPosition <= -1) return;
for (var i = 0; i < 256; i++)
{
//Items[i].Buried = IsItemBuried(Items[i], Save.SaveInstance.SaveGeneration);
}
}
public bool IsItemBuried(Item item, SaveGeneration generation)

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ACSE.Core.Saves;
namespace ACSE.Core.Town.Buildings
@ -9,6 +10,21 @@ namespace ACSE.Core.Town.Buildings
/// </summary>
public sealed class Building
{
/// <summary>
/// The currently selected <see cref="Building"/>.
/// </summary>
public static Building SelectedBuilding;
/// <summary>
/// The current list of buildings in town.
/// </summary>
public static Building[] Buildings { get; private set; }
/// <summary>
/// The current list of buildings in the island.
/// </summary>
public static Building[] IslandBuildings { get; private set; }
#region Building Names
public static readonly string[] CityFolkBuildingNames = {
@ -459,12 +475,20 @@ public Building(byte id, byte x, byte y, SaveType saveType)
}
}
public static Building[] GetBuildings(Save save, bool islandBuildings = false)
/// <summary>
/// Loads any buildings that exist in a specific <see cref="SaveGeneration"/>.
/// </summary>
/// <param name="save">The current <see cref="Save"/> file.</param>
/// <param name="islandBuildings">Load regular buildings or island buildings?</param>
/// <returns></returns>
public static Building[] LoadBuildings(Save save, bool islandBuildings = false)
{
var buildings = new List<Building>();
switch (save.SaveGeneration)
{
case SaveGeneration.Wii:
IslandBuildings = null;
for (var i = 0; i < 33; i++)
{
var dataOffset = save.SaveDataStartOffset + SaveDataManager.CityFolkOffsets.Buildings + i * 2;
@ -477,11 +501,13 @@ public static Building[] GetBuildings(Save save, bool islandBuildings = false)
var paveTable = new Building(0x21, save.ReadByte(paveOffset), save.ReadByte(paveOffset + 1),
SaveType.CityFolk);
buildings.Add(paveTable);
//Add Bus Stop
var busStopOffset = save.SaveDataStartOffset + 0x5EB8A;
var busStop = new Building(0x22, save.ReadByte(busStopOffset), save.ReadByte(busStopOffset + 1),
SaveType.CityFolk);
buildings.Add(busStop);
//Add Signs
for (var i = 0; i < 100; i++)
{
@ -495,6 +521,7 @@ public static Building[] GetBuildings(Save save, bool islandBuildings = false)
case SaveGeneration.N3DS:
if (islandBuildings == false)
{
for (var i = 0; i < 58; i++)
{
var dataOffset = save.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.Buildings +
@ -503,7 +530,9 @@ public static Building[] GetBuildings(Save save, bool islandBuildings = false)
save.ReadByte(dataOffset + 3), save.SaveType));
//Technically, Building IDs are shorts, but since they only use the lower byte, we'll just ignore that
}
}
else
{
for (var i = 0; i < 2; i++)
{
var dataOffset = save.SaveDataStartOffset +
@ -511,10 +540,33 @@ public static Building[] GetBuildings(Save save, bool islandBuildings = false)
buildings.Add(new Building(save.ReadByte(dataOffset), save.ReadByte(dataOffset + 2),
save.ReadByte(dataOffset + 3), save.SaveType));
}
}
break;
default:
IslandBuildings = null;
return Buildings = null;
}
return buildings.ToArray();
if (islandBuildings)
{
return IslandBuildings = buildings.ToArray();
}
return Buildings = buildings.ToArray();
}
/// <summary>
/// Queries whether or not a <see cref="Building"/> is at the specified acre and location.
/// </summary>
/// <param name="acre">The acre to check.</param>
/// <param name="x">The desired x-coordinate to check.</param>
/// <param name="y">The desired y-coordinate to check.</param>
/// <param name="islandAcre">Is the acre an island acre, or a regular town acre? Defaults to false.</param>
/// <returns>Building buildingFound (can be null)</returns>
public static Building IsBuildingHere(int acre, int x, int y, bool islandAcre = false) => islandAcre
? IslandBuildings?.FirstOrNull(b => b.Exists && b.AcreIndex == acre && b.XPos == x && b.YPos == y)
: Buildings?.FirstOrNull(b => b.Exists && b.AcreIndex == acre && b.XPos == x && b.YPos == y);
}
}

View file

@ -0,0 +1,65 @@
using ACSE.Core.Saves;
namespace ACSE.Core.Town
{
/// <summary>
/// Class for retrieving information about item list priorities.
/// </summary>
public static class ListPriority
{
/// <summary>
/// Generation 1 (N64, iQue, GCN) priority index titles.
/// </summary>
private static readonly string[] PriorityNames = {"Furniture", "Stationary", "Clothes", "Carpets", "Wallpaper"};
/// <summary>
/// Names for each level of priority.
/// </summary>
private static readonly string[] Priorities = {"Common", "Uncommon", "Rare"};
/// <summary>
/// Retrieves the priorities for the A, B, and C (generic) item lists.
/// </summary>
/// <param name="priorityIdx">The priority index to retrieve.</param>
/// <returns>(<see langword="int"/> priorityListA, <see langword="int"/> priorityListB, <see langword="int"/> priorityListC)</returns>
public static (int, int, int) GetABCListPriority(int priorityIdx)
{
var offset = -1;
switch (Save.SaveInstance?.SaveType)
{
case SaveType.DoubutsuNoMori:
case SaveType.DongwuSenlin:
break;
case SaveType.DoubutsuNoMoriPlus:
if (priorityIdx == 5)
{
priorityIdx = 0;
}
offset = 0x1963C;
break;
case SaveType.AnimalCrossing:
if (priorityIdx == 5)
{
priorityIdx = 0;
}
offset = 0x20340;
break;
case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus:
offset = 0x222EC;
break;
}
if (Save.SaveInstance == null || offset < 0) return (-1, -1, -1);
var listPriorityByte = Save.SaveInstance.ReadByte(offset + priorityIdx, true);
return ((listPriorityByte >> 6) & 3, (listPriorityByte >> 4) & 3, (listPriorityByte >> 2) & 3);
}
}
}

View file

@ -7,6 +7,7 @@ public sealed class FurnitureShop : Shop
{
public uint VisitorBellsSum;
public byte Size;
public Item[] LotteryItems;
public FurnitureShop(Save saveFile, int offset) : base(saveFile, offset)
{
@ -65,11 +66,44 @@ public FurnitureShop(Save saveFile, int offset) : base(saveFile, offset)
}
else
{
items[i] = new Item(SaveFile.ReadUInt16(Offset + ShopOffsets.FurnitureShop + i * 2, SaveFile.IsBigEndian));
items[i] = new Item(SaveFile.ReadUInt16(Offset + ShopOffsets.FurnitureShop + i * 2,
SaveFile.IsBigEndian));
}
}
Stock = items;
// Lottery
if (SaveFile.SaveGeneration != SaveGeneration.N64 && SaveFile.SaveGeneration != SaveGeneration.iQue &&
SaveFile.SaveGeneration != SaveGeneration.GCN) return;
LotteryItems = new Item[3];
var lotteryOffset = -1;
switch (SaveFile.SaveType)
{
case SaveType.DoubutsuNoMori:
case SaveType.DongwuSenlin:
break;
case SaveType.DoubutsuNoMoriPlus:
lotteryOffset = 0x19732;
break;
case SaveType.AnimalCrossing:
lotteryOffset = 0x2045E;
break;
case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus:
lotteryOffset = 0x223A0;
break;
}
for (var i = 0; i < 3; i++)
{
LotteryItems[i] = new Item(SaveFile.ReadByte(lotteryOffset + i, true));
}
}
public byte GetSize(SaveGeneration generation)

View file

@ -28,6 +28,10 @@ public Updater()
SetCurrentVersionInfo();
}
/// <summary>
/// Gets the current version string.
/// </summary>
/// <returns>The current version string.</returns>
public string GetVersion() => $"{_versionMajor}.{_versionMinor}.{_versionRevision}";
private (bool, string) CheckForUpdate(string url)

View file

@ -71,19 +71,19 @@
</Compile>
<Compile Include="Backups\Backup.cs" />
<Compile Include="Controls\AcreItemEditor.cs">
<SubType>UserControl</SubType>
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\BadgeControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\FurnitureItemEditor.cs">
<SubType>UserControl</SubType>
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\HouseControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\ItemEditor.cs">
<SubType>UserControl</SubType>
<SubType>Component</SubType>
</Compile>
<Compile Include="Controls\OffsetablePictureBox.cs">
<SubType>Component</SubType>
@ -155,6 +155,7 @@
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities\DataUtility.cs" />
<Compile Include="Utilities\ToolTipManager.cs" />
<EmbeddedResource Include="AboutBox\AboutBox.resx">
<DependentUpon>AboutBox.cs</DependentUpon>
</EmbeddedResource>

View file

@ -1,29 +1,210 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using ACSE.Core.Items;
using ACSE.Core.Saves;
using ACSE.Core.Town.Acres;
using ACSE.Core.Town.Buildings;
using ACSE.WinForms.Imaging;
namespace ACSE.WinForms.Controls
{
/// <inheritdoc cref="ItemEditor" />
/// <summary>
/// All-in-one class for editing <see cref="Item" />s and <see cref="Building"/>s which belong to a <see cref="WorldAcre" />.
/// </summary>
public sealed class AcreItemEditor : ItemEditor
{
/// <summary>
/// The acre whose items are being edited.
/// Determines if the item that is modified is set as buried.
/// </summary>
public WorldAcre Acre { get; private set; }
public static bool BuryItem;
/// <summary>
/// The <see cref="WorldItem"/>s associated with the acre.
/// This event fires when a new item is selected.
/// </summary>
public new Item[] Items => Acre?.Items;
public new event ItemSelectedHandler ItemSelected;
/// <summary>
/// Signals when a building has changed location via the AcreItemEditor.
/// </summary>
public event BuildingChangedHandler BuildingChanged;
public AcreItemEditor(MainForm form, Item items, int itemsPerRow)
/// <summary>
/// Signals when a building is selected.
/// </summary>
public event BuildingSelectedHandler BuildingSelected;
/// <summary>
/// The <see cref="WorldAcre"/> whose items are being edited.
/// </summary>
public WorldAcre Acre { get; }
/// <summary>
/// The <see cref="Item"/>s associated with the acre.
/// </summary>
public new Item[] Items
{
get => Acre?.Items;
set
{
if (value == null || value.Length != 256)
throw new ArgumentException($"{nameof(value)} cannot be null and must contain 256 items.");
Acre.Items = value;
SetItemPicture();
}
}
/// <summary>
/// This handler is used when a <see cref="Building"/> has changed some property.
/// </summary>
/// <param name="previousAcre">The previous acre index the building was in.</param>
/// <param name="newAcre">The current acre index the building is now in.</param>
/// <param name="building">The <see cref="Building"/> that was modified in some way.</param>
public delegate void BuildingChangedHandler(int previousAcre, int newAcre, Building building);
/// <summary>
/// This handler is used when a <see cref="Building"/> is selected.
/// </summary>
/// <param name="building"></param>
public delegate void BuildingSelectedHandler(Building building);
/// <summary>
/// Initializes a new AcreItemEditor control.
/// </summary>
/// <param name="acre">The <see cref="WorldAcre"/> whose items will be edited.</param>
/// <param name="itemsPerRow">The number of items per row. Defaults to 16.</param>
/// <param name="cellSize">The pixel size of each item cell.</param>
public AcreItemEditor(WorldAcre acre, int itemsPerRow = 16, int cellSize = 8)
: base(acre?.Items, itemsPerRow, cellSize)
{
InterpolationMode = (InterpolationMode) Properties.Settings.Default.ImageResizeMode;
DrawBaseImage = false;
Acre = acre;
SetItemPicture();
}
protected override void SetItemPicture()
{
if (Items == null) return;
Size = new Size(ItemCellSize * ItemsPerRow + 3,
ItemCellSize * (int) Math.Ceiling((decimal) Items.Length / ItemsPerRow) + 3);
Image?.Dispose();
CurrentItemImage = Inventory.GetItemPic(ItemCellSize, ItemsPerRow, Items, MainForm.SaveFile.SaveType,
Size);
ImageGeneration.DrawBuildings((Bitmap) CurrentItemImage, Building.Buildings, Acre.Index, ItemCellSize); // TODO: How do we draw island buildings?
ImageGeneration.DrawBuriedIcons((Bitmap) CurrentItemImage, Acre, ItemCellSize);
Image = (Image) CurrentItemImage.Clone();
base.Refresh();
}
protected override void OnEditorMouseDown(object sender, MouseEventArgs e)
{
if (!GetXyPosition(e, out var x, out var y, out var index)) return;
var selectedItem = Items[index];
var selectedBuilding = Building.IsBuildingHere(Acre.Index, x, y);
switch (e.Button)
{
case MouseButtons.Left:
if (Building.SelectedBuilding != null)
{
if (selectedBuilding == null)
{
var previousAcre = Building.SelectedBuilding.AcreIndex;
Building.SelectedBuilding.AcreIndex = (byte) Acre.Index;
Building.SelectedBuilding.XPos = (byte) x;
Building.SelectedBuilding.YPos = (byte) y;
// TODO: Update the selected building's X & Y acre positions.
// It is the responsibility of the user to hook into the BuildingChanged event.
BuildingChanged?.Invoke(previousAcre, Acre.Index, Building.SelectedBuilding);
Refresh();
}
Building.SelectedBuilding = null;
BuildingSelected?.Invoke(null); // Clear the selected building even if there was a building at the selected location.
return;
}
break;
case MouseButtons.Right:
if (Building.Buildings != null && selectedBuilding != null)
{
Building.SelectedBuilding = selectedBuilding;
BuildingSelected?.Invoke(selectedBuilding);
return; // End execution immediately. We don't need to update the image or any item info when a building was selected.
}
BuildingSelected?.Invoke(null); // Clear selected building.
break;
}
// Execute base logic.
base.OnEditorMouseDown(sender, e);
switch (e.Button)
{
case MouseButtons.Left:
// Set the buried state of the new item.
Acre.SetItemBuried(Items[index], BuryItem, Save.SaveInstance.SaveGeneration);
SetItemPicture();
// Set the updated image since the one set before is inaccurate.
this.SetNewImage((Image) CurrentItemImage.Clone());
break;
case MouseButtons.Right:
ItemSelected?.Invoke(selectedItem, Acre.IsItemBuried(selectedItem));
break;
}
}
protected override string GetToolTipString(int x, int y, params object[] parameters)
{
var item = (Item) parameters[0];
var b = Building.IsBuildingHere(Acre.Index, x, y); // TODO: How do we determine if this is an island acre?
if (b != null)
{
return $"{b.Name} - [0x{b.Id:X2} - Building]";
}
var buried = Acre.IsItemBuried(item);
var watered = (item.Flag1 & 0x40) != 0;
var hasPerfectFruit = item.Type == ItemType.Tree && item.Flag1 == 1;
var statusString = buried ? " (Buried)" : "";
if (watered)
{
statusString += "(Watered)";
}
if (hasPerfectFruit)
{
statusString += " (Perfect Fruit)";
}
return $"{item.Name}{statusString} - [0x{item.ItemId:X4}]";
}
/// <summary>
/// Manually refreshes the editor's item image.
/// </summary>
public new void Refresh()
{
SetItemPicture();
base.Refresh();
}
}
}

View file

@ -10,8 +10,8 @@ namespace ACSE.WinForms.Controls
{
internal sealed class FurnitureItemEditor : ItemEditor
{
public FurnitureItemEditor(MainForm mainForm, Furniture[] furniture, int itemsPerRow, int itemCellSize = 8) :
base(mainForm, furniture, itemsPerRow, itemCellSize) { }
public FurnitureItemEditor(Furniture[] furniture, int itemsPerRow, int itemCellSize = 8) :
base(furniture, itemsPerRow, itemCellSize) { }
protected override void SetItemPicture()
{
@ -21,11 +21,11 @@ protected override void SetItemPicture()
CurrentItemImage?.Dispose();
CurrentItemImage = ImageGeneration.DrawFurnitureArrows((Bitmap) Inventory.GetItemPic(ItemCellSize,
ItemsPerRow, Items, MainForm.SaveFile.SaveType, EditorPictureBox.Size), (Furniture[]) Items,
ItemsPerRow, Items, MainForm.SaveFile.SaveType, Size), (Furniture[]) Items,
ItemsPerRow);
EditorPictureBox.Image?.Dispose();
EditorPictureBox.Image = (Image) CurrentItemImage.Clone();
Image?.Dispose();
Image = (Image) CurrentItemImage.Clone();
}
protected override void OnEditorMouseDown(object sender, MouseEventArgs e)
@ -35,7 +35,7 @@ protected override void OnEditorMouseDown(object sender, MouseEventArgs e)
switch (e.Button)
{
case MouseButtons.Left:
var newItem = new Furniture(MainFormReference.GetCurrentItem());
var newItem = new Furniture(Item.SelectedItem);
if (selectedItem != newItem)
{
@ -52,13 +52,13 @@ protected override void OnEditorMouseDown(object sender, MouseEventArgs e)
CurrentItemImage?.Dispose();
CurrentItemImage = ImageGeneration.DrawFurnitureArrows((Bitmap) Inventory.GetItemPic(
ItemCellSize,
ItemsPerRow, Items, MainForm.SaveFile.SaveType, EditorPictureBox.Size),
ItemsPerRow, Items, MainForm.SaveFile.SaveType, Size),
(Furniture[]) Items,
ItemsPerRow);
EditorPictureBox.Image?.Dispose();
EditorPictureBox.Image = (Image)CurrentItemImage.Clone();
ImageGeneration.OverlayItemBoxGlow((Bitmap) EditorPictureBox.Image, ItemCellSize, x, y);
Image?.Dispose();
Image = (Image)CurrentItemImage.Clone();
ImageGeneration.OverlayItemBoxGlow((Bitmap) Image, ItemCellSize, x, y);
// Update ToolTip
ItemToolTip.Show(
@ -74,12 +74,12 @@ protected override void OnEditorMouseDown(object sender, MouseEventArgs e)
break;
case MouseButtons.Right:
MainFormReference.SetCurrentItem(selectedItem);
base.OnEditorMouseDown(sender, e); // Just invoke the default bevavior here.
break;
case MouseButtons.Middle:
var tempItems = (Furniture[]) Items;
Utility.FloodFillFurnitureArray(ref tempItems, ItemsPerRow, index,
(Furniture) Items[index], new Furniture(MainFormReference.GetCurrentItem()));
(Furniture) Items[index], new Furniture(Item.SelectedItem));
Items = tempItems;
break;
}
@ -98,9 +98,9 @@ public override void Undo()
// Undo
Items[previousItemChange.Index] = (Furniture)previousItemChange.Item;
var img = EditorPictureBox.Image;
EditorPictureBox.Image = ImageGeneration.DrawFurnitureArrows((Bitmap)Inventory.GetItemPic(ItemCellSize,
ItemsPerRow, Items, MainForm.SaveFile.SaveType, EditorPictureBox.Size), (Furniture[])Items, ItemsPerRow);
var img = Image;
Image = ImageGeneration.DrawFurnitureArrows((Bitmap)Inventory.GetItemPic(ItemCellSize,
ItemsPerRow, Items, MainForm.SaveFile.SaveType, Size), (Furniture[])Items, ItemsPerRow);
img?.Dispose();
OnItemChanged(selectedItem, Items[previousItemChange.Index], previousItemChange.Index);
@ -119,9 +119,9 @@ public override void Redo()
// Redo
Items[previousItemChange.Index] = (Furniture)previousItemChange.Item;
var img = EditorPictureBox.Image;
EditorPictureBox.Image = ImageGeneration.DrawFurnitureArrows((Bitmap)Inventory.GetItemPic(ItemCellSize,
ItemsPerRow, Items, MainForm.SaveFile.SaveType, EditorPictureBox.Size), (Furniture[])Items, ItemsPerRow);
var img = Image;
Image = ImageGeneration.DrawFurnitureArrows((Bitmap)Inventory.GetItemPic(ItemCellSize,
ItemsPerRow, Items, MainForm.SaveFile.SaveType, Size), (Furniture[])Items, ItemsPerRow);
img?.Dispose();
OnItemChanged(selectedItem, Items[previousItemChange.Index], previousItemChange.Index);

View file

@ -83,7 +83,7 @@ public HouseControl(MainForm mainFormReference, Save saveFile, House house)
layerSize = editors.Count == 0 ? 10 : 8;
}
var editor = new FurnitureItemEditor(mainFormReference, layer.Items, layerSize, 16);
var editor = new FurnitureItemEditor(layer.Items, layerSize, 16);
roomPanel.Controls.Add(editor);
if (roomPanel.MaximumSize.Height == 0)
@ -101,7 +101,7 @@ public HouseControl(MainForm mainFormReference, Save saveFile, House house)
roomEditors.Add(editors.ToArray());
// Add the wallpaper, carpet, & song editors
var wallpaperEditor = new SingleItemEditor(mainFormReference, room.Wallpaper, 16);
var wallpaperEditor = new SingleItemEditor(room.Wallpaper, 16);
infoFlowPanel.Controls.Add(wallpaperEditor);
wallpaperEditor.SetCenterMargins(5, 5);
wallpaperEditors.Add(wallpaperEditor);
@ -110,7 +110,7 @@ public HouseControl(MainForm mainFormReference, Save saveFile, House house)
room.Wallpaper = e.NewItem;
};
var carpetEditor = new SingleItemEditor(mainFormReference, room.Carpet, 16);
var carpetEditor = new SingleItemEditor(room.Carpet, 16);
infoFlowPanel.Controls.Add(carpetEditor);
carpetEditor.SetCenterMargins(5, 5);
carpetEditors.Add(carpetEditor);
@ -120,7 +120,7 @@ public HouseControl(MainForm mainFormReference, Save saveFile, House house)
};
if (saveFile.SaveGeneration != SaveGeneration.N3DS) continue;
var songEditor = new SingleItemEditor(mainFormReference, room.Song, 16);
var songEditor = new SingleItemEditor(room.Song, 16);
infoFlowPanel.Controls.Add(songEditor);
songEditor.SetCenterMargins(5, 5);
songEditors.Add(songEditor);

View file

@ -5,8 +5,10 @@
using System.Windows.Forms;
using ACSE.Core.Items;
using ACSE.Core.Modifiable;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
using ACSE.WinForms.Imaging;
using ACSE.WinForms.Utilities;
namespace ACSE.WinForms.Controls
{
@ -14,14 +16,23 @@ namespace ACSE.WinForms.Controls
/// <summary>
/// An all-in-one control for editing items.
/// </summary>
public class ItemEditor : UserControl, IModifiable
public class ItemEditor : PictureBoxWithInterpolationMode, IModifiable
{
/// <summary>
/// This event fires when an item is set or changed. PreviousItem will be null if it is the first time setting the item.
/// </summary>
public event EventHandler<IndexedItemChangedEventArgs> ItemChanged;
public readonly PictureBox EditorPictureBox;
/// <summary>
/// This event fires when a new item is selected.
/// </summary>
public event ItemSelectedHandler ItemSelected;
// Delegates
public delegate void ItemSelectedHandler(Item selectedItem, bool buried);
public readonly ToolTip ItemToolTip;
public readonly Stack<ItemChange> UndoStack = new Stack<ItemChange>();
public readonly Stack<ItemChange> RedoStack = new Stack<ItemChange>();
@ -29,7 +40,18 @@ public class ItemEditor : UserControl, IModifiable
public string HoverText = "{0} - [0x{1}]";
public bool ShowHoveredItemCellHighlight = true;
protected Image CurrentItemImage;
protected bool DrawBaseImage = true;
private Image _currentItemImage;
protected Image CurrentItemImage
{
get => _currentItemImage;
set
{
_currentItemImage?.Dispose();
_currentItemImage = value;
}
}
private int _itemsPerRow;
public int ItemsPerRow
@ -38,10 +60,7 @@ public int ItemsPerRow
set
{
_itemsPerRow = value;
if (EditorPictureBox != null)
{
SetItemPicture();
}
SetItemPicture();
}
}
@ -52,10 +71,7 @@ public int ItemCellSize
set
{
_itemCellSize = value;
if (EditorPictureBox != null)
{
SetItemPicture();
}
SetItemPicture();
}
}
@ -75,51 +91,39 @@ protected virtual void SetItemPicture()
Size = new Size(_itemCellSize * _itemsPerRow + 3,
_itemCellSize * (int) (Math.Ceiling((decimal) _items.Length / _itemsPerRow)) + 3);
CurrentItemImage?.Dispose();
EditorPictureBox.Image?.Dispose();
Image?.Dispose();
CurrentItemImage = Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items, MainForm.SaveFile.SaveType,
EditorPictureBox.Size);
EditorPictureBox.Image = (Image) CurrentItemImage.Clone();
EditorPictureBox.Refresh();
CurrentItemImage =
Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items, Save.SaveInstance.SaveType, Size);
Image = (Image) CurrentItemImage.Clone();
Refresh();
}
protected readonly MainForm MainFormReference;
protected int LastX = -1, LastY = -1;
protected ItemEditor()
{
ItemToolTip = new ToolTip
{
ShowAlways = true
};
EditorPictureBox = new PictureBox
{
Dock = DockStyle.Fill
};
ItemToolTip = ToolTipManager.GetSharedToolTip();
BorderStyle = BorderStyle.FixedSingle;
Controls.Add(EditorPictureBox);
BackgroundImageLayout = ImageLayout.Stretch;
}
public ItemEditor(MainForm mainForm, Item[] items, int itemsPerRow, int itemCellSize = 8) : this()
public ItemEditor(Item[] items, int itemsPerRow, int itemCellSize = 8) : this()
{
MainFormReference = mainForm;
_items = items;
_itemsPerRow = itemsPerRow;
ItemCellSize = itemCellSize;
EditorPictureBox.MouseMove += OnEditorMouseMove;
EditorPictureBox.MouseLeave += delegate
MouseMove += OnEditorMouseMove;
MouseLeave += delegate
{
ItemToolTip.Hide(this);
EditorPictureBox.Image?.Dispose();
EditorPictureBox.Image = (Image) CurrentItemImage.Clone();
EditorPictureBox.Refresh();
Image.Dispose();
Image = (Image) CurrentItemImage.Clone();
Refresh();
};
EditorPictureBox.MouseDown += OnEditorMouseDown;
MouseDown += OnEditorMouseDown;
}
protected virtual void OnItemChanged(Item previousItem, Item newItem, int index)
@ -145,7 +149,7 @@ protected virtual bool GetXyPosition(MouseEventArgs e, out int x, out int y, out
protected virtual void OnEditorMouseMove(object sender, MouseEventArgs e)
{
if (_items == null || !GetXyPosition(e, out var x, out var y, out var index) ||
(e.X == LastX && e.Y == LastY)) return;
(e.X == LastX && e.Y == LastY) || x < 0 || x > 15 || y < 0 || y > 15) return;
// Update Last Hover Position
LastX = e.X;
@ -154,18 +158,16 @@ protected virtual void OnEditorMouseMove(object sender, MouseEventArgs e)
// Draw the item highlight if necessary.
if (ShowHoveredItemCellHighlight)
{
EditorPictureBox.Image?.Dispose();
EditorPictureBox.Image = (Bitmap) CurrentItemImage.Clone();
ImageGeneration.OverlayItemBoxGlow((Bitmap) EditorPictureBox.Image, _itemCellSize, x, y);
EditorPictureBox.Refresh();
Image?.Dispose();
Image = (Bitmap) CurrentItemImage.Clone();
ImageGeneration.OverlayItemBoxGlow((Bitmap) Image, _itemCellSize, x, y);
Refresh();
}
var hoveredItem = _items[index];
// Refresh ToolTip
ItemToolTip.Show(
string.Format(HoverText, hoveredItem.Name, hoveredItem.ItemId.ToString("X4"),
hoveredItem.ItemFlag.ToString()), this, e.X + 10, e.Y + 10, 100000);
ShowToolTip(GetToolTipString(x, y, hoveredItem), e.X, e.Y);
// Check for MouseDown
if (e.Button != MouseButtons.None)
@ -175,11 +177,12 @@ protected virtual void OnEditorMouseMove(object sender, MouseEventArgs e)
protected virtual void OnEditorMouseDown(object sender, MouseEventArgs e)
{
if (!GetXyPosition(e, out var x, out var y, out var index)) return;
var selectedItem = _items[index];
switch (e.Button)
{
case MouseButtons.Left:
var newItem = MainFormReference.GetCurrentItem();
var newItem = Item.SelectedItem;
if (selectedItem != newItem)
{
@ -190,41 +193,54 @@ protected virtual void OnEditorMouseDown(object sender, MouseEventArgs e)
NewChange(null);
// Set New Item
_items[index] = newItem;
_items[index] = new Item(newItem); // Ensure we create a copy of the item.
// Redraw Item Image
CurrentItemImage?.Dispose();
EditorPictureBox.Image?.Dispose();
if (DrawBaseImage)
{
Image?.Dispose();
CurrentItemImage = Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items, MainForm.SaveFile.SaveType,
EditorPictureBox.Size);
EditorPictureBox.Image = (Image)CurrentItemImage.Clone();
ImageGeneration.OverlayItemBoxGlow((Bitmap) EditorPictureBox.Image, _itemCellSize, x, y);
EditorPictureBox.Refresh();
CurrentItemImage = Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items,
Save.SaveInstance.SaveType, Size);
Image = (Image) CurrentItemImage.Clone();
ImageGeneration.OverlayItemBoxGlow((Bitmap) Image, _itemCellSize, x, y);
Refresh();
}
// Update ToolTip
ItemToolTip.Show(
string.Format(HoverText, newItem.Name, newItem.ItemId.ToString("X4"),
newItem.ItemFlag.ToString()), this, e.X + 10, e.Y + 10, 100000);
ShowToolTip(GetToolTipString(x, y, newItem), e.X, e.Y);
// Fire ItemChanged Event
OnItemChanged(selectedItem, newItem, index);
MainForm.SaveFile.ChangesMade = true;
Save.SaveInstance.ChangesMade = true;
Modified = true;
}
break;
case MouseButtons.Right:
MainFormReference.SetCurrentItem(selectedItem);
ItemSelected?.Invoke(selectedItem, false);
break;
case MouseButtons.Middle:
Utility.FloodFillItemArray(ref _items, ItemsPerRow, index, _items[index],
MainFormReference.GetCurrentItem());
Utility.FloodFillItemArray(ref _items, ItemsPerRow, index, _items[index], Item.SelectedItem);
SetItemPicture();
break;
}
}
protected virtual string GetToolTipString(int x, int y, params object[] parameters)
{
var item = (Item) parameters[0];
return $"{item.Name} - [0x{item.ItemId:X4}]";
}
public virtual void ShowToolTip(string text, int x, int y)
{
if (!string.IsNullOrWhiteSpace(text))
{
ItemToolTip.Show(text, this, x + 10, y + 10, 100000);
}
}
public virtual void Undo()
{
if (!UndoStack.Any()) return;
@ -238,9 +254,9 @@ public virtual void Undo()
// Undo
_items[previousItemChange.Index] = previousItemChange.Item;
var img = EditorPictureBox.Image;
EditorPictureBox.Image = Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items,
MainForm.SaveFile.SaveType, EditorPictureBox.Size);
var img = Image;
Image = Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items,
Save.SaveInstance.SaveType, Size);
img?.Dispose();
OnItemChanged(selectedItem, Items[previousItemChange.Index], previousItemChange.Index);
@ -259,9 +275,9 @@ public virtual void Redo()
// Redo
_items[previousItemChange.Index] = previousItemChange.Item;
var img = EditorPictureBox.Image;
EditorPictureBox.Image = Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items,
MainForm.SaveFile.SaveType, EditorPictureBox.Size);
var img = Image;
Image = Inventory.GetItemPic(_itemCellSize, _itemsPerRow, _items,
Save.SaveInstance.SaveType, Size);
img?.Dispose();
OnItemChanged(selectedItem, Items[previousItemChange.Index], previousItemChange.Index);
@ -276,9 +292,7 @@ public virtual void NewChange(object change)
protected new virtual void Dispose()
{
ItemToolTip.Dispose();
EditorPictureBox.Image?.Dispose();
EditorPictureBox.Dispose();
Image?.Dispose();
base.Dispose();
}
}

View file

@ -54,7 +54,7 @@ public ShopEditorControl(MainForm mainWindow, Shop shop, int itemsPerRow, bool h
Controls.Add(BellsSumTextBox);
}
ShopEditor = new ItemEditor(mainWindow, shop.Stock, itemsPerRow, 16);
ShopEditor = new ItemEditor(shop.Stock, itemsPerRow, 16);
var width = ShopLabel.Size.Width > ShopEditor.Size.Width ? ShopLabel.Size.Width : ShopEditor.Size.Width;
Size = new System.Drawing.Size(width, ShopLabel.Size.Height + ShopEditor.Size.Height);

View file

@ -5,6 +5,7 @@
using System.Windows.Forms;
using ACSE.Core.Items;
using ACSE.Core.Modifiable;
using ACSE.WinForms.Utilities;
using ItemChangedEventArgs = ACSE.Core.Items.ItemChangedEventArgs;
namespace ACSE.WinForms.Controls
@ -20,6 +21,15 @@ public partial class SingleItemEditor : UserControl, IModifiable
/// </summary>
public event EventHandler<ItemChangedEventArgs> ItemChanged;
/// <summary>
/// This event fires when a new item is selected.
/// </summary>
public event ItemSelectedHandler ItemSelected;
// Delegates
public delegate void ItemSelectedHandler(Item selectedItem, bool buried);
public readonly PictureBox EditorPictureBox;
public readonly ToolTip ItemToolTip;
public readonly Stack<ItemChange> UndoStack = new Stack<ItemChange>();
@ -84,16 +94,12 @@ private void SetItemPicture()
img?.Dispose();
}
private readonly MainForm _mainFormReference;
private int _lastX = -1, _lastY = -1;
private bool _isMouseDown;
protected SingleItemEditor()
{
ItemToolTip = new ToolTip
{
ShowAlways = true
};
ItemToolTip = ToolTipManager.GetSharedToolTip();
EditorPictureBox = new PictureBox
{
@ -105,9 +111,8 @@ protected SingleItemEditor()
Controls.Add(EditorPictureBox);
}
public SingleItemEditor(MainForm mainForm, Item item, int itemCellSize = 8) : this()
public SingleItemEditor(Item item, int itemCellSize = 8) : this()
{
_mainFormReference = mainForm;
_item = item;
ItemCellSize = itemCellSize;
@ -151,7 +156,7 @@ protected virtual void OnEditorMouseDown(object sender, MouseEventArgs e)
{
case MouseButtons.Left:
case MouseButtons.Middle:
var newItem = _mainFormReference.GetCurrentItem();
var newItem = Item.SelectedItem;
var previousItem = _item;
if (previousItem != newItem)
@ -171,7 +176,7 @@ protected virtual void OnEditorMouseDown(object sender, MouseEventArgs e)
break;
case MouseButtons.Right:
_mainFormReference.SetCurrentItem(_item);
ItemSelected?.Invoke(_item, false);
break;
}
}
@ -215,7 +220,6 @@ public virtual void NewChange(object change)
protected virtual void Dipose()
{
ItemToolTip.Dispose();
EditorPictureBox.Image?.Dispose();
EditorPictureBox.Dispose();
Dispose();

View file

@ -14,6 +14,11 @@ internal enum GameCubeStalkMarketTrend
Spike, Random, Falling
}
internal enum CityFolkStalkMarketTrend
{
Trend0, Trend1, Trend2, Trend3
}
public int Days = 7;
public int[] Prices;
public int Trend;
@ -47,15 +52,23 @@ public StalkMarketEditor(Save saveData)
_offset = saveData.SaveDataStartOffset + 0x20480;
_trendOffset = _offset + 0xE;
break;
case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus:
_offset = saveData.SaveDataStartOffset + 0x223C8;
_trendOffset = _offset + 0xE;
break;
case SaveType.CityFolk:
_offset = saveData.SaveDataStartOffset + 0x63200;
_trendOffset = _offset + 0x3C;
break;
case SaveType.NewLeaf:
Days = 6;
_offset = saveData.SaveDataStartOffset + 0x6535C;
break;
case SaveType.WelcomeAmiibo:
Days = 6;
_offset = saveData.SaveDataStartOffset + 0x6AD60;
@ -93,17 +106,35 @@ public StalkMarketEditor(Save saveData)
};
trendPanel.Controls.Add(trendLabel);
Trend = saveData.ReadUInt16(_trendOffset, saveData.IsBigEndian);
_trendComboBox = new ComboBox
{
AutoSize = false,
Size = new Size(60, 20)
};
foreach (var trend in Enum.GetNames(typeof(GameCubeStalkMarketTrend)))
switch (saveData.SaveGeneration)
{
_trendComboBox.Items.Add(trend);
case SaveGeneration.N64:
case SaveGeneration.GCN:
case SaveGeneration.iQue:
Trend = saveData.ReadUInt16(_trendOffset, saveData.IsBigEndian);
foreach (var trend in Enum.GetNames(typeof(GameCubeStalkMarketTrend)))
{
_trendComboBox.Items.Add(trend);
}
break;
case SaveGeneration.Wii:
Trend = (int) saveData.ReadUInt32(_trendOffset, saveData.IsBigEndian);
foreach (var trend in Enum.GetNames(typeof(CityFolkStalkMarketTrend)))
{
_trendComboBox.Items.Add(trend);
}
break;
}
_trendComboBox.SelectedIndex = Trend;
@ -116,6 +147,15 @@ public StalkMarketEditor(Save saveData)
// Prices
var offset = _offset;
// City Folk has a Sunday buy price that differs from the Sunday AM/PM prices.
if (saveData.SaveGeneration == SaveGeneration.Wii)
{
// TODO: Do we want to offer a way to change the buy price?
var buyPriceFromJoan = saveData.ReadUInt32(offset, true);
offset += 4;
}
for (var day = 0; day < Days; day++)
{
switch (_saveData.SaveGeneration)
@ -159,6 +199,50 @@ public StalkMarketEditor(Save saveData)
Controls.Add(pricePanel);
break;
}
case SaveGeneration.Wii:
{
var amPrice = saveData.ReadUInt32(offset, true);
var pmPrice = saveData.ReadUInt32(offset + 4, true);
offset += 8;
for (var i = 0; i < 2; i++)
{
var pricePanel = new FlowLayoutPanel
{
AutoSize = true,
FlowDirection = FlowDirection.LeftToRight
};
var priceLabel = new Label
{
AutoSize = false,
Size = new Size(130, 22),
TextAlign = ContentAlignment.MiddleRight,
Text = $"{DayNames[day]}'s Price [{(i == 0 ? "AM" : "PM")}]:"
};
pricePanel.Controls.Add(priceLabel);
var priceBox = new NumericTextBox
{
AutoSize = false,
Size = new Size(60, 20),
Location = new Point(5, day * 24),
Text = (i == 0 ? amPrice : pmPrice).ToString(),
MaxLength = 9
};
var currentDay = day;
priceBox.TextChanged += (s, e) =>
PriceChanged(currentDay, int.Parse(priceBox.Text));
pricePanel.Controls.Add(priceBox);
_panels.Add(pricePanel);
Controls.Add(pricePanel);
}
break;
}
case SaveGeneration.N3DS:
{
var amPrice = new NewLeafInt32(saveData.ReadUInt32(offset), saveData.ReadUInt32(offset + 4)).Value;

View file

@ -3,7 +3,7 @@
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using ACSE.Core;
using ACSE.Core.Compression;
using ACSE.Core.Items;
using ACSE.Core.Saves;
using ACSE.Core.Utilities;
@ -127,7 +127,7 @@ public VillagerControl(MainForm mainFormReference, int index, Save saveFile, Vil
_catchphraseBox.Margin = new Padding(0, margin, 10, margin);
_catchphraseBox.TextChanged += (s, e) => CatchphraseChanged();
_shirtEditor = new SingleItemEditor(mainFormReference, _villager.Data.Shirt, 16);
_shirtEditor = new SingleItemEditor(_villager.Data.Shirt, 16);
margin = CalculateControlVerticalMargin(_shirtEditor);
_shirtEditor.Margin = new Padding(0, margin, 10, margin);
_shirtEditor.ItemChanged += delegate(object sender, ItemChangedEventArgs e)
@ -137,7 +137,7 @@ public VillagerControl(MainForm mainFormReference, int index, Save saveFile, Vil
if (_villager.Data.Umbrella != null)
{
_umbrellaEditor = new SingleItemEditor(mainFormReference, _villager.Data.Umbrella, 16);
_umbrellaEditor = new SingleItemEditor(_villager.Data.Umbrella, 16);
margin = CalculateControlVerticalMargin(_umbrellaEditor);
_umbrellaEditor.Margin = new Padding(0, margin, 10, margin);
}
@ -199,16 +199,16 @@ public VillagerControl(MainForm mainFormReference, int index, Save saveFile, Vil
case SaveGeneration.NDS:
case SaveGeneration.Wii:
case SaveGeneration.N3DS:
_carpetWallpaperEditor = new ItemEditor(mainFormReference,
new[] {_villager.Data.Carpet, _villager.Data.Wallpaper}, 2, 16);
_carpetWallpaperEditor =
new ItemEditor(new[] {_villager.Data.Carpet, _villager.Data.Wallpaper}, 2, 16);
margin = CalculateControlVerticalMargin(_carpetWallpaperEditor);
_carpetWallpaperEditor.Margin = new Padding(0, margin, 10, margin);
_musicEditor = new SingleItemEditor(mainFormReference, _villager.Data.Song, 16);
_musicEditor = new SingleItemEditor(_villager.Data.Song, 16);
margin = CalculateControlVerticalMargin(_musicEditor);
_musicEditor.Margin = new Padding(0, margin, 10, margin);
_furnitureEditor = new ItemEditor(mainFormReference, _villager.Data.Furniture,
_furnitureEditor = new ItemEditor(_villager.Data.Furniture,
_villager.Data.Furniture.Length, 16);
margin = CalculateControlVerticalMargin(_furnitureEditor);
_furnitureEditor.Margin = new Padding(0, margin, 10, margin);

View file

@ -33,11 +33,13 @@ private void InitializeComponent()
this.components = new System.ComponentModel.Container();
System.Windows.Forms.TabPage patternsTab;
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.patternNameTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.paletteColorSelectedPictureBox = new System.Windows.Forms.PictureBox();
this.paletteIndexLabel = new System.Windows.Forms.Label();
this.palettePreviousButton = new System.Windows.Forms.Button();
this.paletteNextButton = new System.Windows.Forms.Button();
this.patternEditorPanel = new System.Windows.Forms.Panel();
this.patternEditorPictureBox = new ACSE.WinForms.Controls.PictureBoxWithInterpolationMode();
this.patternEditorPreviewPanel = new System.Windows.Forms.Panel();
this.patternGroupTabControl = new System.Windows.Forms.TabControl();
this.player1Tab = new System.Windows.Forms.TabPage();
@ -269,15 +271,14 @@ private void InitializeComponent()
this.loadingPanel = new System.Windows.Forms.Panel();
this.label45 = new System.Windows.Forms.Label();
this.infoTip = new System.Windows.Forms.ToolTip(this.components);
this.itemIdTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.itemIdLabel = new System.Windows.Forms.Label();
this.StatusLabel = new System.Windows.Forms.TextBox();
this.itemIdTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.patternNameTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.patternEditorPictureBox = new ACSE.WinForms.Controls.PictureBoxWithInterpolationMode();
patternsTab = new System.Windows.Forms.TabPage();
patternsTab.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.paletteColorSelectedPictureBox)).BeginInit();
this.patternEditorPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).BeginInit();
this.patternGroupTabControl.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.paletteSelectionPictureBox)).BeginInit();
this.menuStrip1.SuspendLayout();
@ -314,7 +315,6 @@ private void InitializeComponent()
this.pictureContextMenu.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.acreHeightTrackBar)).BeginInit();
this.loadingPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).BeginInit();
this.SuspendLayout();
//
// patternsTab
@ -335,6 +335,18 @@ private void InitializeComponent()
patternsTab.Text = "Patterns";
patternsTab.UseVisualStyleBackColor = true;
//
// patternNameTextBox
//
this.patternNameTextBox.Anchor = System.Windows.Forms.AnchorStyles.None;
this.patternNameTextBox.Location = new System.Drawing.Point(415, 538);
this.patternNameTextBox.MaxLength = 16;
this.patternNameTextBox.Name = "patternNameTextBox";
this.patternNameTextBox.PlaceholderText = "Pattern Name";
this.patternNameTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.patternNameTextBox.Size = new System.Drawing.Size(100, 20);
this.patternNameTextBox.TabIndex = 0;
this.patternNameTextBox.TextChanged += new System.EventHandler(this.PatternEditorNameBox_TextChanged);
//
// paletteColorSelectedPictureBox
//
this.paletteColorSelectedPictureBox.Anchor = System.Windows.Forms.AnchorStyles.None;
@ -387,6 +399,23 @@ private void InitializeComponent()
this.patternEditorPanel.Size = new System.Drawing.Size(513, 513);
this.patternEditorPanel.TabIndex = 16;
//
// patternEditorPictureBox
//
this.patternEditorPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.patternEditorPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.patternEditorPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.patternEditorPictureBox.Location = new System.Drawing.Point(0, 0);
this.patternEditorPictureBox.Name = "patternEditorPictureBox";
this.patternEditorPictureBox.Size = new System.Drawing.Size(513, 513);
this.patternEditorPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.patternEditorPictureBox.TabIndex = 0;
this.patternEditorPictureBox.TabStop = false;
this.patternEditorPictureBox.UseInternalInterpolationSetting = false;
this.patternEditorPictureBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseDown);
this.patternEditorPictureBox.MouseLeave += new System.EventHandler(this.PatternEditorBoxMouseLeave);
this.patternEditorPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseMove);
this.patternEditorPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseUp);
//
// patternEditorPreviewPanel
//
this.patternEditorPreviewPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -1831,6 +1860,7 @@ private void InitializeComponent()
this.buriedCheckbox.TabIndex = 8;
this.buriedCheckbox.Text = "Buried";
this.buriedCheckbox.UseVisualStyleBackColor = true;
this.buriedCheckbox.CheckedChanged += new System.EventHandler(this.buriedCheckbox_CheckedChanged);
//
// townMisc
//
@ -2768,6 +2798,21 @@ private void InitializeComponent()
this.label45.TabIndex = 15;
this.label45.Text = "Loading...";
//
// itemIdTextBox
//
this.itemIdTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.itemIdTextBox.Enabled = false;
this.itemIdTextBox.Location = new System.Drawing.Point(132, 620);
this.itemIdTextBox.Name = "itemIdTextBox";
this.itemIdTextBox.PlaceholderText = "Item ID";
this.itemIdTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.itemIdTextBox.Size = new System.Drawing.Size(46, 20);
this.itemIdTextBox.TabIndex = 78;
this.itemIdTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.infoTip.SetToolTip(this.itemIdTextBox, "The hexadecimal Item ID. Example: A31C");
this.itemIdTextBox.TextChanged += new System.EventHandler(this.CurrentItemIdTextChanged);
this.itemIdTextBox.Leave += new System.EventHandler(this.CurrentItemIdLostFocus);
//
// itemIdLabel
//
this.itemIdLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@ -2790,50 +2835,6 @@ private void InitializeComponent()
this.StatusLabel.TabIndex = 16;
this.StatusLabel.TabStop = false;
//
// itemIdTextBox
//
this.itemIdTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.itemIdTextBox.Enabled = false;
this.itemIdTextBox.Location = new System.Drawing.Point(132, 620);
this.itemIdTextBox.Name = "itemIdTextBox";
this.itemIdTextBox.PlaceholderText = "Item ID";
this.itemIdTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.itemIdTextBox.Size = new System.Drawing.Size(46, 20);
this.itemIdTextBox.TabIndex = 78;
this.itemIdTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.infoTip.SetToolTip(this.itemIdTextBox, "The hexadecimal Item ID. Example: A31C");
this.itemIdTextBox.TextChanged += new System.EventHandler(this.CurrentItemIdTextChanged);
this.itemIdTextBox.Leave += new System.EventHandler(this.CurrentItemIdLostFocus);
//
// patternNameTextBox
//
this.patternNameTextBox.Anchor = System.Windows.Forms.AnchorStyles.None;
this.patternNameTextBox.Location = new System.Drawing.Point(415, 538);
this.patternNameTextBox.MaxLength = 16;
this.patternNameTextBox.Name = "patternNameTextBox";
this.patternNameTextBox.PlaceholderText = "Pattern Name";
this.patternNameTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.patternNameTextBox.Size = new System.Drawing.Size(100, 20);
this.patternNameTextBox.TabIndex = 0;
this.patternNameTextBox.TextChanged += new System.EventHandler(this.PatternEditorNameBox_TextChanged);
//
// patternEditorPictureBox
//
this.patternEditorPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.patternEditorPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.patternEditorPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.patternEditorPictureBox.Location = new System.Drawing.Point(0, 0);
this.patternEditorPictureBox.Name = "patternEditorPictureBox";
this.patternEditorPictureBox.Size = new System.Drawing.Size(513, 513);
this.patternEditorPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.patternEditorPictureBox.TabIndex = 0;
this.patternEditorPictureBox.TabStop = false;
this.patternEditorPictureBox.UseInternalInterpolationSetting = false;
this.patternEditorPictureBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseDown);
this.patternEditorPictureBox.MouseLeave += new System.EventHandler(this.PatternEditorBoxMouseLeave);
this.patternEditorPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseMove);
this.patternEditorPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseUp);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -2865,6 +2866,7 @@ private void InitializeComponent()
patternsTab.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.paletteColorSelectedPictureBox)).EndInit();
this.patternEditorPanel.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).EndInit();
this.patternGroupTabControl.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.paletteSelectionPictureBox)).EndInit();
this.menuStrip1.ResumeLayout(false);
@ -2912,7 +2914,6 @@ private void InitializeComponent()
((System.ComponentModel.ISupportInitialize)(this.acreHeightTrackBar)).EndInit();
this.loadingPanel.ResumeLayout(false);
this.loadingPanel.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();

File diff suppressed because it is too large Load diff

View file

@ -137,7 +137,7 @@ public static Image FetchAcMapIcon(byte index)
}
public static void CheckReferencesAndDispose(Image referencedImage,
PictureBoxWithInterpolationMode[] pictureBoxes, PictureBoxWithInterpolationMode selectedAcreBox)
IList<PictureBoxWithInterpolationMode> pictureBoxes, PictureBoxWithInterpolationMode selectedAcreBox)
{
if (referencedImage == null || selectedAcreBox.Image == referencedImage
|| pictureBoxes.Any(

View file

@ -0,0 +1,18 @@
using System.Windows.Forms;
namespace ACSE.WinForms.Utilities
{
public static class ToolTipManager
{
/// <summary>
/// The shared <see cref="ToolTip"/> instance.
/// </summary>
private static readonly ToolTip ToolTip = new ToolTip {ShowAlways = true};
/// <summary>
/// Gets the shared <see cref="ToolTip"/> instance.
/// </summary>
/// <returns><see cref="ToolTip"/> SharedToolTip</returns>
public static ToolTip GetSharedToolTip() => ToolTip;
}
}