2018-07-15 00:53:37 +00:00
|
|
|
|
using System.Drawing;
|
|
|
|
|
using PKHeX.Core;
|
2019-09-29 16:47:06 +00:00
|
|
|
|
using PKHeX.Drawing.Properties;
|
2018-07-15 00:53:37 +00:00
|
|
|
|
|
2019-09-29 16:47:06 +00:00
|
|
|
|
namespace PKHeX.Drawing
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
|
public abstract class SpriteBuilder : ISpriteBuilder<Image>
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
2018-08-19 23:45:20 +00:00
|
|
|
|
public static bool ShowEggSpriteAsItem { get; set; } = true;
|
2021-08-24 21:21:35 +00:00
|
|
|
|
public static bool ShowEncounterColor { get; set; } = true;
|
|
|
|
|
public static bool ShowEncounterBall { get; set; } = true;
|
|
|
|
|
public static bool ShowEncounterColorPKM { get; set; }
|
2018-08-19 23:45:20 +00:00
|
|
|
|
|
2021-06-11 01:14:38 +00:00
|
|
|
|
/// <summary> Width of the generated Sprite image. </summary>
|
2019-11-16 01:34:18 +00:00
|
|
|
|
public abstract int Width { get; }
|
2021-06-11 01:14:38 +00:00
|
|
|
|
/// <summary> Height of the generated Sprite image. </summary>
|
2019-11-16 01:34:18 +00:00
|
|
|
|
public abstract int Height { get; }
|
|
|
|
|
|
2021-06-11 01:14:38 +00:00
|
|
|
|
/// <summary> Minimum amount of padding on the right side of the image when layering an item sprite. </summary>
|
2019-11-16 01:34:18 +00:00
|
|
|
|
protected abstract int ItemShiftX { get; }
|
2021-06-11 01:14:38 +00:00
|
|
|
|
/// <summary> Minimum amount of padding on the bottom side of the image when layering an item sprite. </summary>
|
2019-11-16 01:34:18 +00:00
|
|
|
|
protected abstract int ItemShiftY { get; }
|
2021-06-11 01:14:38 +00:00
|
|
|
|
/// <summary> Max width / height of an item image. </summary>
|
2019-11-16 01:34:18 +00:00
|
|
|
|
protected abstract int ItemMaxSize { get; }
|
2021-06-11 01:14:38 +00:00
|
|
|
|
|
2019-11-16 01:34:18 +00:00
|
|
|
|
protected abstract int EggItemShiftX { get; }
|
|
|
|
|
protected abstract int EggItemShiftY { get; }
|
|
|
|
|
|
|
|
|
|
public abstract Bitmap Hover { get; }
|
|
|
|
|
public abstract Bitmap View { get; }
|
|
|
|
|
public abstract Bitmap Set { get; }
|
|
|
|
|
public abstract Bitmap Delete { get; }
|
|
|
|
|
public abstract Bitmap Transparent { get; }
|
|
|
|
|
public abstract Bitmap Drag { get; }
|
2020-04-16 22:14:36 +00:00
|
|
|
|
public abstract Bitmap UnknownItem { get; }
|
2021-04-09 23:24:19 +00:00
|
|
|
|
public abstract Bitmap None { get; }
|
|
|
|
|
public abstract Bitmap ItemTM { get; }
|
|
|
|
|
public abstract Bitmap ItemTR { get; }
|
2019-11-16 01:34:18 +00:00
|
|
|
|
|
2019-04-23 05:24:29 +00:00
|
|
|
|
private const double UnknownFormTransparency = 0.5;
|
|
|
|
|
private const double ShinyTransparency = 0.7;
|
|
|
|
|
private const double EggUnderLayerTransparency = 0.33;
|
|
|
|
|
|
2021-04-09 23:24:19 +00:00
|
|
|
|
protected abstract string GetSpriteStringSpeciesOnly(int species);
|
|
|
|
|
|
|
|
|
|
protected abstract string GetSpriteAll(int species, int form, int gender, uint formarg, bool shiny, int generation);
|
|
|
|
|
protected abstract string GetItemResourceName(int item);
|
|
|
|
|
protected abstract Bitmap Unknown { get; }
|
|
|
|
|
protected abstract Bitmap GetEggSprite(int species);
|
2020-06-03 17:38:00 +00:00
|
|
|
|
public abstract Bitmap ShadowLugia { get; }
|
2019-11-16 01:34:18 +00:00
|
|
|
|
|
2018-07-15 00:53:37 +00:00
|
|
|
|
public void Initialize(SaveFile sav)
|
|
|
|
|
{
|
|
|
|
|
if (sav.Generation != 3)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Game = sav.Version;
|
|
|
|
|
if (Game == GameVersion.FRLG)
|
|
|
|
|
Game = sav.Personal == PersonalTable.FR ? GameVersion.FR : GameVersion.LG;
|
|
|
|
|
}
|
2018-07-22 02:20:11 +00:00
|
|
|
|
|
2018-07-15 00:53:37 +00:00
|
|
|
|
private GameVersion Game;
|
|
|
|
|
|
2021-01-02 01:08:49 +00:00
|
|
|
|
private static int GetDeoxysForm(GameVersion game) => game switch
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
2021-01-02 01:08:49 +00:00
|
|
|
|
GameVersion.FR => 1, // Attack
|
|
|
|
|
GameVersion.LG => 2, // Defense
|
|
|
|
|
GameVersion.E => 3, // Speed
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => 0,
|
2021-01-02 01:08:49 +00:00
|
|
|
|
};
|
2018-07-15 00:53:37 +00:00
|
|
|
|
|
2020-03-04 04:22:57 +00:00
|
|
|
|
public Image GetSprite(int species, int form, int gender, uint formarg, int heldItem, bool isEgg, bool isShiny, int generation = -1, bool isBoxBGRed = false, bool isAltShiny = false)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
|
|
|
|
if (species == 0)
|
2021-04-09 23:24:19 +00:00
|
|
|
|
return None;
|
2018-07-15 00:53:37 +00:00
|
|
|
|
|
2019-12-09 01:39:19 +00:00
|
|
|
|
if (generation == 3 && species == (int)Species.Deoxys) // Deoxys, special consideration for Gen3 save files
|
2018-07-15 00:53:37 +00:00
|
|
|
|
form = GetDeoxysForm(Game);
|
|
|
|
|
|
2020-03-04 04:22:57 +00:00
|
|
|
|
var baseImage = GetBaseImage(species, form, gender, formarg, isShiny, generation);
|
2019-11-25 17:27:42 +00:00
|
|
|
|
return GetSprite(baseImage, species, heldItem, isEgg, isShiny, generation, isBoxBGRed, isAltShiny);
|
2018-10-21 04:05:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-25 17:27:42 +00:00
|
|
|
|
public Image GetSprite(Image baseSprite, int species, int heldItem, bool isEgg, bool isShiny, int generation = -1, bool isBoxBGRed = false, bool isAltShiny = false)
|
2018-10-21 04:05:15 +00:00
|
|
|
|
{
|
2018-07-15 00:53:37 +00:00
|
|
|
|
if (isEgg)
|
2018-10-27 15:53:09 +00:00
|
|
|
|
baseSprite = LayerOverImageEgg(baseSprite, species, heldItem != 0);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
if (heldItem > 0)
|
2018-10-27 15:53:09 +00:00
|
|
|
|
baseSprite = LayerOverImageItem(baseSprite, heldItem, generation);
|
2019-11-16 01:34:18 +00:00
|
|
|
|
if (isShiny)
|
2019-11-25 17:31:41 +00:00
|
|
|
|
baseSprite = LayerOverImageShiny(baseSprite, isBoxBGRed, generation >= 8 && isAltShiny);
|
2018-10-27 15:53:09 +00:00
|
|
|
|
return baseSprite;
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 04:22:57 +00:00
|
|
|
|
private Image GetBaseImage(int species, int form, int gender, uint formarg, bool shiny, int generation)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
2020-12-11 04:42:30 +00:00
|
|
|
|
var img = FormInfo.IsTotemForm(species, form, generation)
|
2020-03-04 04:22:57 +00:00
|
|
|
|
? GetBaseImageTotem(species, form, gender, formarg, shiny, generation)
|
|
|
|
|
: GetBaseImageDefault(species, form, gender, formarg, shiny, generation);
|
|
|
|
|
return img ?? GetBaseImageFallback(species, form, gender, formarg, shiny, generation);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 04:22:57 +00:00
|
|
|
|
private Image? GetBaseImageTotem(int species, int form, int gender, uint formarg, bool shiny, int generation)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
2020-12-11 04:42:30 +00:00
|
|
|
|
var baseform = FormInfo.GetTotemBaseForm(species, form);
|
2020-03-04 04:22:57 +00:00
|
|
|
|
var baseImage = GetBaseImageDefault(species, baseform, gender, formarg, shiny, generation);
|
2019-10-08 02:10:38 +00:00
|
|
|
|
if (baseImage == null)
|
|
|
|
|
return null;
|
2018-07-15 00:53:37 +00:00
|
|
|
|
return ImageUtil.ToGrayscale(baseImage);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 04:22:57 +00:00
|
|
|
|
private Image? GetBaseImageDefault(int species, int form, int gender, uint formarg, bool shiny, int generation)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
2020-03-04 04:22:57 +00:00
|
|
|
|
var file = GetSpriteAll(species, form, gender, formarg, shiny, generation);
|
2019-10-08 02:10:38 +00:00
|
|
|
|
return (Image?)Resources.ResourceManager.GetObject(file);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-04 04:22:57 +00:00
|
|
|
|
private Image GetBaseImageFallback(int species, int form, int gender, uint formarg, bool shiny, int generation)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
|
|
|
|
if (shiny) // try again without shiny
|
|
|
|
|
{
|
2020-03-04 04:22:57 +00:00
|
|
|
|
var img = GetBaseImageDefault(species, form, gender, formarg, false, generation);
|
2019-04-23 05:24:29 +00:00
|
|
|
|
if (img != null)
|
|
|
|
|
return img;
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// try again without form
|
2019-11-16 01:34:18 +00:00
|
|
|
|
var baseImage = (Image?)Resources.ResourceManager.GetObject(GetSpriteStringSpeciesOnly(species));
|
2018-07-15 00:53:37 +00:00
|
|
|
|
if (baseImage == null) // failed again
|
2019-11-16 01:34:18 +00:00
|
|
|
|
return Unknown;
|
|
|
|
|
return ImageUtil.LayerImage(baseImage, Unknown, 0, 0, UnknownFormTransparency);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-16 01:34:18 +00:00
|
|
|
|
private Image LayerOverImageItem(Image baseImage, int item, int generation)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
2020-12-29 08:37:59 +00:00
|
|
|
|
Image itemimg = generation switch
|
|
|
|
|
{
|
2021-04-09 23:24:19 +00:00
|
|
|
|
<= 4 when item is >= 328 and <= 419 => ItemTM, // gen2/3/4 TM
|
|
|
|
|
>= 8 when item is >= 1130 and <= 1229 => ItemTR, // Gen8 TR
|
2020-12-29 08:37:59 +00:00
|
|
|
|
_ => (Image?)Resources.ResourceManager.GetObject(GetItemResourceName(item)) ?? UnknownItem,
|
|
|
|
|
};
|
2018-07-15 00:53:37 +00:00
|
|
|
|
|
2019-04-23 05:24:29 +00:00
|
|
|
|
// Redraw item in bottom right corner; since images are cropped, try to not have them at the edge
|
2021-06-11 01:07:26 +00:00
|
|
|
|
int x = baseImage.Width - itemimg.Width - ((ItemMaxSize - itemimg.Width) / 4) - ItemShiftX;
|
|
|
|
|
int y = baseImage.Height - itemimg.Height - ItemShiftY;
|
2018-07-15 01:43:46 +00:00
|
|
|
|
return ImageUtil.LayerImage(baseImage, itemimg, x, y);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-25 17:27:42 +00:00
|
|
|
|
private static Image LayerOverImageShiny(Image baseImage, bool isBoxBGRed, bool altShiny)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
|
|
|
|
// Add shiny star to top left of image.
|
|
|
|
|
var rare = isBoxBGRed ? Resources.rare_icon_alt : Resources.rare_icon;
|
2019-11-25 17:27:42 +00:00
|
|
|
|
if (altShiny)
|
|
|
|
|
rare = Resources.rare_icon_2;
|
2019-04-23 05:24:29 +00:00
|
|
|
|
return ImageUtil.LayerImage(baseImage, rare, 0, 0, ShinyTransparency);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-16 01:34:18 +00:00
|
|
|
|
private Image LayerOverImageEgg(Image baseImage, int species, bool hasItem)
|
2018-08-19 23:45:20 +00:00
|
|
|
|
{
|
2018-10-11 05:59:00 +00:00
|
|
|
|
if (ShowEggSpriteAsItem && !hasItem)
|
2018-08-19 23:45:20 +00:00
|
|
|
|
return LayerOverImageEggAsItem(baseImage, species);
|
|
|
|
|
return LayerOverImageEggTransparentSpecies(baseImage, species);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-16 01:34:18 +00:00
|
|
|
|
private Image LayerOverImageEggTransparentSpecies(Image baseImage, int species)
|
2018-07-15 00:53:37 +00:00
|
|
|
|
{
|
|
|
|
|
// Partially transparent species.
|
2018-08-19 23:45:20 +00:00
|
|
|
|
baseImage = ImageUtil.ChangeOpacity(baseImage, EggUnderLayerTransparency);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
// Add the egg layer over-top with full opacity.
|
2018-08-19 23:45:20 +00:00
|
|
|
|
var egg = GetEggSprite(species);
|
2018-07-15 01:43:46 +00:00
|
|
|
|
return ImageUtil.LayerImage(baseImage, egg, 0, 0);
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
2018-08-19 23:45:20 +00:00
|
|
|
|
|
2019-11-16 01:34:18 +00:00
|
|
|
|
private Image LayerOverImageEggAsItem(Image baseImage, int species)
|
2018-08-19 23:45:20 +00:00
|
|
|
|
{
|
|
|
|
|
var egg = GetEggSprite(species);
|
2019-04-23 05:24:29 +00:00
|
|
|
|
return ImageUtil.LayerImage(baseImage, egg, EggItemShiftX, EggItemShiftY); // similar to held item, since they can't have any
|
2018-08-19 23:45:20 +00:00
|
|
|
|
}
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|
2019-11-16 01:34:18 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 56 high, 68 wide sprite builder
|
|
|
|
|
/// </summary>
|
2020-09-07 20:51:13 +00:00
|
|
|
|
public sealed class SpriteBuilder5668 : SpriteBuilder
|
2019-11-16 01:34:18 +00:00
|
|
|
|
{
|
|
|
|
|
public override int Height => 56;
|
|
|
|
|
public override int Width => 68;
|
|
|
|
|
|
2021-06-11 01:07:26 +00:00
|
|
|
|
protected override int ItemShiftX => 2;
|
|
|
|
|
protected override int ItemShiftY => 2;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
protected override int ItemMaxSize => 32;
|
2020-08-14 20:56:37 +00:00
|
|
|
|
protected override int EggItemShiftX => 18;
|
|
|
|
|
protected override int EggItemShiftY => 1;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
|
|
|
|
|
protected override string GetSpriteStringSpeciesOnly(int species) => 'b' + $"_{species}";
|
2020-03-04 04:22:57 +00:00
|
|
|
|
protected override string GetSpriteAll(int species, int form, int gender, uint formarg, bool shiny, int generation) => 'b' + SpriteName.GetResourceStringSprite(species, form, gender, formarg, generation, shiny);
|
2019-11-16 01:34:18 +00:00
|
|
|
|
protected override string GetItemResourceName(int item) => 'b' + $"item_{item}";
|
2020-08-11 01:33:44 +00:00
|
|
|
|
protected override Bitmap Unknown => Resources.b_unknown;
|
|
|
|
|
protected override Bitmap GetEggSprite(int species) => species == (int)Species.Manaphy ? Resources.b_490_e : Resources.b_egg;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
|
|
|
|
|
public override Bitmap Hover => Resources.slotHover68;
|
|
|
|
|
public override Bitmap View => Resources.slotView68;
|
|
|
|
|
public override Bitmap Set => Resources.slotSet68;
|
|
|
|
|
public override Bitmap Delete => Resources.slotDel68;
|
|
|
|
|
public override Bitmap Transparent => Resources.slotTrans68;
|
|
|
|
|
public override Bitmap Drag => Resources.slotDrag68;
|
2020-04-16 22:14:36 +00:00
|
|
|
|
public override Bitmap UnknownItem => Resources.bitem_unk;
|
2021-04-09 23:24:19 +00:00
|
|
|
|
public override Bitmap None => Resources.b_0;
|
|
|
|
|
public override Bitmap ItemTM => Resources.bitem_tm;
|
|
|
|
|
public override Bitmap ItemTR => Resources.bitem_tr;
|
2020-06-03 17:38:00 +00:00
|
|
|
|
public override Bitmap ShadowLugia => Resources.b_249x;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
}
|
2018-07-15 00:53:37 +00:00
|
|
|
|
}
|