Show item sprites in item editor

put a folder named "items" with the english named item sprites (tbd if we change to a more sane filename format)

bring your own files, it's like 45 MB so not distributing with the EXE.
This commit is contained in:
Kurt 2020-05-05 22:13:29 -07:00
parent 478b8e29c5
commit bf841b8ecf
15 changed files with 177 additions and 146 deletions

View File

@ -0,0 +1,23 @@
using System;
using System.Drawing;
using System.Linq;
using NHSE.Core;
namespace NHSE.Sprites
{
public static class ItemColor
{
private static readonly Color[] Colors = ((KnownColor[])Enum.GetValues(typeof(KnownColor)))
.Select(Color.FromKnownColor).Select(z => ColorUtil.Blend(Color.White, z, 0.5d)).ToArray();
public static Color GetItemColor(IHeldItem item)
{
if (item.ItemId == Item.NONE)
return Color.Transparent;
var kind = ItemInfo.GetItemKind(item);
if (kind == ItemKind.Unknown)
return Color.LimeGreen;
return Colors[(int)kind];
}
}
}

View File

@ -1,118 +1,110 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.IO;
using NHSE.Core;
using NHSE.Sprites.Properties;
namespace NHSE.Sprites
{
public static class ItemSprite
{
public static Bitmap GetImage(Item item, Font font, int width, int height)
{
if (item.ItemId == Item.NONE)
return GetNone(font, width, height);
private static readonly Dictionary<string, string> FileLookup = new Dictionary<string, string>();
private static string[] ItemNames = Array.Empty<string>();
return CreateFake(item, font, width, height);
public static void Initialize(string path, string[] itemNames)
{
if (FileLookup.Count > 0)
return;
ItemNames = itemNames;
var files = Directory.EnumerateFiles(path, "*.png", SearchOption.AllDirectories);
foreach (var f in files)
{
var fn = Path.GetFileNameWithoutExtension(f);
FileLookup.Add(fn, f);
}
}
public static Bitmap GetImage(Item item, int width, int height)
public static Bitmap GetItemMarkup(IHeldItem item, Font font, int width, int height, Bitmap backing)
{
return CreateFake(item, font, width, height, backing);
}
public static Image? GetItemSprite(IHeldItem item)
{
var id = item.ItemId;
if (id == Item.NONE)
return null;
if (!GetItemImageSprite(id, out var path))
return Resources.leaf;
try
{
return Image.FromFile(path);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Console.WriteLine(ex.Message);
return Resources.leaf;
}
}
private static bool GetItemImageSprite(ushort id, out string? path)
{
path = string.Empty;
var str = ItemNames;
if (id >= str.Length)
return false;
var name = str[id];
return FileLookup.TryGetValue(name, out path);
}
public static Bitmap? GetImage(IHeldItem item, Font font, int width, int height)
{
if (item.ItemId == Item.NONE)
return GetNone(width, height);
return null;
return CreateFake(item, width, height);
return CreateFake(item, font, width, height);
}
private static readonly StringFormat Center = new StringFormat
{ Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
private static Bitmap GetNone(int w, int h) => new Bitmap(w, h);
private static Bitmap GetNone(Font font, int w, int h)
{
var bmp = GetNone(w, h);
using var gfx = Graphics.FromImage(bmp);
gfx.DrawString("None", font, Brushes.Black, w / 2f, h / 2f, Center);
return bmp;
}
public static Bitmap CreateFake(Item item, int width, int height, bool slash = false)
public static Bitmap CreateFake(IHeldItem item, Font font, int width, int height)
{
var bmp = new Bitmap(width, height);
return CreateFake(item, font, width, height, bmp);
}
const int x1 = 0;
const int y1 = 0;
int x2 = width - 1;
int y2 = height - 1;
private static Bitmap CreateFake(IHeldItem item, Font font, int width, int height, Bitmap bmp)
{
using var gfx = Graphics.FromImage(bmp);
DrawItemAt(gfx, item, x1, y1, x2, y2, slash);
DrawItemAt(gfx, item, font, width, height);
return bmp;
}
public static Bitmap CreateFake(Item item, Font font, int width, int height, bool slash = false)
public static void DrawItemAt(Graphics gfx, IHeldItem item, Font font, int width, int height)
{
var bmp = new Bitmap(width, height);
const int x1 = 0;
const int y1 = 0;
int x2 = width - 1;
int y2 = height - 1;
using var gfx = Graphics.FromImage(bmp);
DrawItemAt(gfx, item, font, x1, y1, x2, y2, slash);
return bmp;
DrawInfo(gfx, font, item, width, height, Brushes.Black);
}
public static void DrawItemAt(Graphics gfx, Item item, Font font, int x1, int y1, int x2, int y2, bool slash = false)
{
DrawItemAt(gfx, item, x1, y1, x2, y2, slash);
DrawInfo(gfx, font, item, x1, y1, Brushes.Black);
}
public static void DrawItemAt(Graphics gfx, Item item, int x1, int y1, int x2, int y2, bool slash = false)
{
var color = GetItemColor(item);
using var brush = new SolidBrush(color);
DrawItem(gfx, x1, y1, x2, y2, brush);
if (slash)
DrawX(gfx, x1, y1, x2, y2, color);
}
private static void DrawX(Graphics gfx, int x1, int y1, int x2, int y2, Color color)
{
var icolor = Color.FromArgb(color.R ^ 0xFF, color.G ^ 0xFF, color.B ^ 0xFF);
using var ipen = new Pen(icolor);
DrawForwardSlash(gfx, x1, y1, x2, y2, ipen);
DrawBackwardSlash(gfx, x1, y1, x2, y2, ipen);
}
private static void DrawItem(Graphics gfx, int x1, int y1, int x2, int y2, Brush brush) => gfx.FillRectangle(brush, x1, y1, x2 + 1, y2 + 1);
private static void DrawForwardSlash(Graphics gfx, int x1, int y1, int x2, int y2, Pen ipen) => gfx.DrawLine(ipen, x2, y1, x1, y2);
private static void DrawBackwardSlash(Graphics gfx, int x1, int y1, int x2, int y2, Pen ipen) => gfx.DrawLine(ipen, x1, y1, x2, y2);
private static void DrawInfo(Graphics gfx, Font font, Item item, int x1, int y1, Brush brush)
private static void DrawInfo(Graphics gfx, Font font, IHeldItem item, int width, int height, Brush brush)
{
if (item.Count != 0)
gfx.DrawString(item.Count.ToString(), font, brush, x1, y1);
gfx.DrawString(item.Count.ToString(), font, brush, 0, 0);
if (item.UseCount != 0)
gfx.DrawString(item.UseCount.ToString(), font, brush, x1 + 16, y1 + 16, Center);
gfx.DrawString(item.UseCount.ToString(), font, brush, width >> 1, height >> 1, Center);
if (item.Flags0 != 0)
gfx.DrawString(item.Flags0.ToString(), font, brush, x1 + 20, y1 + 0);
gfx.DrawString(item.Flags0.ToString(), font, brush, width - 12, 0);
if (item.Flags1 != 0)
gfx.DrawString(item.Flags1.ToString(), font, brush, x1 + 0, y1 + 20);
gfx.DrawString(item.Flags1.ToString(), font, brush, 0, height - 12);
}
private static Color GetItemColor(Item item)
{
var kind = ItemInfo.GetItemKind(item);
if (kind == ItemKind.Unknown)
return Color.LimeGreen;
return Colors[(int)kind];
}
private static readonly Color[] Colors = ((KnownColor[])Enum.GetValues(typeof(KnownColor)))
.Select(Color.FromKnownColor).Select(z => ColorUtil.Blend(Color.White, z, 0.5d)).ToArray();
}
}

View File

@ -1,17 +0,0 @@
using System.Drawing;
using NHSE.Core;
using NHSE.Sprites.Properties;
namespace NHSE.Sprites
{
public class ItemSpriteDrawer : IGridItem
{
public int Width { get; set; } = 32;
public int Height { get; set; } = 32;
public readonly Image HoverBackground = Resources.itemHover;
public Bitmap GetImage(Item item, Font font) => ItemSprite.GetImage(item, font, Width, Height);
public Bitmap GetImage(Item item) => ItemSprite.GetImage(item, Width, Height);
}
}

View File

@ -2280,16 +2280,6 @@ internal class Resources {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap itemHover {
get {
object obj = ResourceManager.GetObject("itemHover", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@ -2460,6 +2450,16 @@ internal class Resources {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap leaf {
get {
object obj = ResourceManager.GetObject("leaf", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@ -784,9 +784,6 @@
<data name="hrs16" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Villagers\hrs16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="itemHover" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Misc\itemHover.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="kal00" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Villagers\kal00.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -838,6 +835,9 @@
<data name="kgr10" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Villagers\kgr10.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="leaf" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Misc\leaf.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="lon00" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Villagers\lon00.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -120,10 +120,22 @@ public static void ScalePixelImage(int[] data, int[] scaled, int fW, int fH, int
/// <summary>
/// Sets a bitwise and of the requested transparency; this is assuming the pixel value is 0xFF_xx_xx_xx. Single operation laziness!
/// </summary>
public static void SetAllTransparencyTo(int[] data, int trans)
public static void ClampAllTransparencyTo(int[] data, int trans)
{
for (int i = 0; i < data.Length; i++)
data[i] &= trans;
}
/// <summary>
/// Sets a bitwise and of the requested transparency; this is assuming the pixel value is 0xFF_xx_xx_xx. Single operation laziness!
/// </summary>
public static void SetAllTransparencyTo(int[] data, int color)
{
for (int i = 0; i < data.Length; i++)
{
if ((data[i] & 0xFF000000) == 0)
data[i] = color;
}
}
}
}

View File

@ -1,7 +0,0 @@
namespace NHSE.Sprites
{
public static class SpriteUtil
{
public static readonly ItemSpriteDrawer Items = new ItemSpriteDrawer();
}
}

View File

@ -64,7 +64,8 @@ public static PictureBox GetControl(int width, int height)
return new PictureBox
{
AutoSize = false,
SizeMode = PictureBoxSizeMode.CenterImage,
SizeMode = PictureBoxSizeMode.Zoom,
BackgroundImageLayout = ImageLayout.Zoom,
BackColor = Color.Transparent,
Width = width + (2 * 1),
Height = height + (2 * 1),

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using NHSE.Core;
using NHSE.Sprites;
@ -8,7 +9,7 @@ namespace NHSE.WinForms
{
public partial class ItemGridEditor : UserControl
{
private static readonly ItemSpriteDrawer Sprites = SpriteUtil.Items;
private static readonly GridSize Sprites = new GridSize();
private readonly ItemEditor Editor;
private readonly IReadOnlyList<Item> Items;
@ -28,8 +29,10 @@ public ItemGridEditor(ItemEditor editor, IReadOnlyList<Item> items)
L_ItemName.Text = string.Empty;
}
public void InitializeGrid(int width, int height)
public void InitializeGrid(int width, int height, int itemWidth, int itemHeight)
{
Sprites.Width = itemWidth;
Sprites.Height = itemHeight;
ItemsPerPage = width * height;
ItemGrid.InitializeGrid(width, height, Sprites);
InitializeSlots();
@ -69,14 +72,12 @@ public void Slot_MouseEnter(object? sender, EventArgs e)
var text = GetItemText(item);
HoverTip.SetToolTip(pb, text);
L_ItemName.Text = text;
pb.Image = Sprites.HoverBackground;
}
public void Slot_MouseLeave(object? sender, EventArgs e)
{
if (!(sender is PictureBox pb))
if (!(sender is PictureBox))
return;
pb.Image = null;
L_ItemName.Text = string.Empty;
HoverTip.RemoveAll();
}
@ -123,7 +124,7 @@ private void ClickSet(object sender, EventArgs e)
return;
var index = SlotPictureBoxes.IndexOf(pb);
var item = SetItem(index);
pb.BackgroundImage = Sprites.GetImage(item, L_ItemName.Font);
SetItemSprite(item, pb);
ItemUpdated();
}
@ -135,7 +136,7 @@ private void ClickDelete(object sender, EventArgs e)
var index = SlotPictureBoxes.IndexOf(pb);
var item = GetItem(index);
item.Delete();
pb.BackgroundImage = Sprites.GetImage(item, L_ItemName.Font);
SetItemSprite(item, pb);
ItemUpdated();
}
@ -152,12 +153,23 @@ private void ClickClone(object sender, EventArgs e)
continue;
var dest = GetItem(i);
dest.CopyFrom(item);
SlotPictureBoxes[i].BackgroundImage = Sprites.GetImage(item, L_ItemName.Font);
SetItemSprite(item, SlotPictureBoxes[i]);
ItemUpdated();
}
System.Media.SystemSounds.Asterisk.Play();
}
private void SetItemSprite(IHeldItem item, PictureBox pb)
{
var dw = Sprites.Width;
var dh = Sprites.Height;
var font = L_ItemName.Font;
pb.BackColor = ItemColor.GetItemColor(item);
pb.BackgroundImage = ItemSprite.GetItemSprite(item);
var backing = new Bitmap(dw, dh);
pb.Image = ItemSprite.GetItemMarkup(item, font, dw, dh, backing);
}
private int GetPageJump()
{
return ModifierKeys switch
@ -203,7 +215,7 @@ public void LoadItems()
for (int i = 0; i < SlotPictureBoxes.Count; i++)
{
var item = GetItem(i);
SlotPictureBoxes[i].BackgroundImage = Sprites.GetImage(item, L_ItemName.Font);
SetItemSprite(item, SlotPictureBoxes[i]);
}
ItemUpdated();
}
@ -218,5 +230,11 @@ private void B_Clear_Click(object sender, EventArgs e)
LoadItems();
System.Media.SystemSounds.Asterisk.Play();
}
private class GridSize : IGridItem
{
public int Width { get; set; } = 64;
public int Height { get; set; } = 64;
}
}
}

View File

@ -7,6 +7,7 @@
using System.Windows.Forms;
using NHSE.Core;
using NHSE.Injection;
using NHSE.Sprites;
using NHSE.WinForms.Properties;
namespace NHSE.WinForms
@ -53,6 +54,7 @@ private void Menu_Language_SelectedIndexChanged(object sender, EventArgs e)
Task.Run(() =>
{
ItemSprite.Initialize(Main.ItemPath, GameInfo.GetStrings("en").itemlist);
TranslationUtil.SetLocalization(typeof(MessageStrings), lang);
TranslationUtil.SetLocalization(GameInfo.Strings.InternalNameTranslation, lang);
});

View File

@ -13,8 +13,10 @@ namespace NHSE.WinForms
public partial class Main : Form
{
public const string BackupFolderName = "bak";
public const string ItemFolderName = "items";
public static readonly string WorkingDirectory = Application.StartupPath;
public static readonly string BackupPath = Path.Combine(WorkingDirectory, BackupFolderName);
public static readonly string ItemPath = Path.Combine(WorkingDirectory, ItemFolderName);
public Main()
{

View File

@ -33,15 +33,15 @@ private void InitializeComponent()
this.B_Save = new System.Windows.Forms.Button();
this.B_Dump = new System.Windows.Forms.Button();
this.B_Load = new System.Windows.Forms.Button();
this.ItemEditor = new NHSE.WinForms.ItemEditor();
this.PAN_Items = new System.Windows.Forms.Panel();
this.B_Inject = new System.Windows.Forms.Button();
this.ItemEditor = new NHSE.WinForms.ItemEditor();
this.SuspendLayout();
//
// B_Cancel
//
this.B_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.B_Cancel.Location = new System.Drawing.Point(422, 228);
this.B_Cancel.Location = new System.Drawing.Point(742, 378);
this.B_Cancel.Name = "B_Cancel";
this.B_Cancel.Size = new System.Drawing.Size(72, 23);
this.B_Cancel.TabIndex = 5;
@ -52,7 +52,7 @@ private void InitializeComponent()
// B_Save
//
this.B_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.B_Save.Location = new System.Drawing.Point(500, 228);
this.B_Save.Location = new System.Drawing.Point(820, 378);
this.B_Save.Name = "B_Save";
this.B_Save.Size = new System.Drawing.Size(72, 23);
this.B_Save.TabIndex = 4;
@ -62,7 +62,8 @@ private void InitializeComponent()
//
// B_Dump
//
this.B_Dump.Location = new System.Drawing.Point(9, 228);
this.B_Dump.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.B_Dump.Location = new System.Drawing.Point(9, 378);
this.B_Dump.Name = "B_Dump";
this.B_Dump.Size = new System.Drawing.Size(90, 23);
this.B_Dump.TabIndex = 7;
@ -72,7 +73,8 @@ private void InitializeComponent()
//
// B_Load
//
this.B_Load.Location = new System.Drawing.Point(105, 228);
this.B_Load.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.B_Load.Location = new System.Drawing.Point(105, 378);
this.B_Load.Name = "B_Load";
this.B_Load.Size = new System.Drawing.Size(90, 23);
this.B_Load.TabIndex = 8;
@ -80,14 +82,6 @@ private void InitializeComponent()
this.B_Load.UseVisualStyleBackColor = true;
this.B_Load.Click += new System.EventHandler(this.B_Load_Click);
//
// ItemEditor
//
this.ItemEditor.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.ItemEditor.Location = new System.Drawing.Point(422, 12);
this.ItemEditor.Name = "ItemEditor";
this.ItemEditor.Size = new System.Drawing.Size(150, 210);
this.ItemEditor.TabIndex = 6;
//
// PAN_Items
//
this.PAN_Items.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -95,12 +89,13 @@ private void InitializeComponent()
| System.Windows.Forms.AnchorStyles.Right)));
this.PAN_Items.Location = new System.Drawing.Point(9, 12);
this.PAN_Items.Name = "PAN_Items";
this.PAN_Items.Size = new System.Drawing.Size(407, 210);
this.PAN_Items.Size = new System.Drawing.Size(727, 360);
this.PAN_Items.TabIndex = 9;
//
// B_Inject
//
this.B_Inject.Location = new System.Drawing.Point(273, 228);
this.B_Inject.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.B_Inject.Location = new System.Drawing.Point(273, 378);
this.B_Inject.Name = "B_Inject";
this.B_Inject.Size = new System.Drawing.Size(90, 23);
this.B_Inject.TabIndex = 10;
@ -108,11 +103,21 @@ private void InitializeComponent()
this.B_Inject.UseVisualStyleBackColor = true;
this.B_Inject.Click += new System.EventHandler(this.B_Inject_Click);
//
// ItemEditor
//
this.ItemEditor.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.ItemEditor.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.ItemEditor.Location = new System.Drawing.Point(742, 12);
this.ItemEditor.Name = "ItemEditor";
this.ItemEditor.Size = new System.Drawing.Size(150, 360);
this.ItemEditor.TabIndex = 6;
//
// PlayerItemEditor
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(584, 261);
this.ClientSize = new System.Drawing.Size(904, 411);
this.Controls.Add(this.B_Inject);
this.Controls.Add(this.PAN_Items);
this.Controls.Add(this.B_Load);

View File

@ -21,7 +21,7 @@ public PlayerItemEditor(IReadOnlyList<T> array, int width, int height, bool sysb
ItemArray = new ItemArrayEditor<T>(array);
var Editor = ItemGrid = new ItemGridEditor(ItemEditor, array) {Dock = DockStyle.Fill};
Editor.InitializeGrid(width, height);
Editor.InitializeGrid(width, height, 64, 64);
PAN_Items.Controls.Add(Editor);
ItemEditor.Initialize(GameInfo.Strings.ItemDataSource);