From 922cbdf583a02edf25e5316be7498b722f9cffda Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 22 Jul 2018 20:04:28 -0700 Subject: [PATCH] Add glow animation to slothover --- .../Controls/SAV Editor/BitmapAnimator.cs | 92 +++++++++++++++++++ .../Controls/SAV Editor/SlotChangeManager.cs | 48 +++++++--- PKHeX.WinForms/PKHeX.WinForms.csproj | 3 + 3 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs diff --git a/PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs b/PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs new file mode 100644 index 000000000..6d963ea94 --- /dev/null +++ b/PKHeX.WinForms/Controls/SAV Editor/BitmapAnimator.cs @@ -0,0 +1,92 @@ +using System; +using System.Drawing; +using System.Timers; +using System.Windows.Forms; +using Timer = System.Timers.Timer; + +namespace PKHeX.WinForms.Controls +{ + public sealed class BitmapAnimator : Timer + { + public BitmapAnimator(Bitmap baseImage, Bitmap extraLayer = null) + { + GlowBase = baseImage; + ExtraLayer = extraLayer; + Elapsed += TimerElapsed; + } + + private readonly Bitmap GlowBase; + private readonly Bitmap ExtraLayer; + private Bitmap[] GlowCache; + private int GlowInterval; + private int GlowCounter; + + public int GlowFps { get; set; } = 60; + public Color GlowToColor { get; set; } = Color.LightSkyBlue; + public Color GlowFromColor { get; set; } = Color.White; + private readonly object Lock = new object(); + + public new void Start() => throw new ArgumentException(); + + public new void Stop() + { + lock (Lock) + StopTimer(); + } + + private void StopTimer() + { + Enabled = false; + pb.BackgroundImage = OriginalBackground; + GlowBase.Dispose(); + } + + private PictureBox pb; + public Image OriginalBackground; + public void Start(PictureBox pbox, Image original) + { + pb = pbox; + OriginalBackground = original; + GlowCache = new Bitmap[GlowFps]; + GlowInterval = 1000 / GlowFps; + Interval = GlowInterval; + Enabled = true; + } + + private void TimerElapsed(object sender, ElapsedEventArgs elapsedEventArgs) + { + lock (Lock) + { + if (!Enabled) + return; // timer canceled, was waiting to proceed + GlowCounter = (GlowCounter + 1) % (GlowInterval * 2); // loop backwards + int frameIndex = GlowCounter >= GlowInterval ? (GlowInterval * 2) - GlowCounter : GlowCounter; + try + { + var frame = GetFrame(frameIndex); + pb.BackgroundImage = ImageUtil.LayerImage(OriginalBackground, frame, 0, 0, 1); + } + catch + { + StopTimer(); + } + } + } + + private Bitmap GetFrame(int frameIndex) + { + var frame = GlowCache[frameIndex]; + if (frame != null) + return frame; + + var elapsedFraction = (double)frameIndex / GlowInterval; + var frameColor = GetFrameColor(elapsedFraction); + frame = ImageUtil.ChangeAllColorTo(GlowBase, frameColor); + if (ExtraLayer != null) + frame = ImageUtil.LayerImage(frame, ExtraLayer, 0, 0, 1); + return GlowCache[frameIndex] = frame; + } + + private Color GetFrameColor(double elapsedFraction) => ImageUtil.Blend(GlowToColor, GlowFromColor, elapsedFraction); + } +} \ No newline at end of file diff --git a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs index 2021aa02c..59dd13954 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SlotChangeManager.cs @@ -24,7 +24,11 @@ public sealed class SlotChangeManager : IDisposable public Image ColorizedColor { get; private set; } public int ColorizedBox { get; private set; } = -1; public int ColorizedSlot { get; private set; } = -1; + public bool GlowHover { get; set; } = true; + public Color GlowInitial { get; set; } = Color.White; + public Color GlowFinal { get; set; } = Color.LightSkyBlue; + private BitmapAnimator HoverWorker; private SaveFile SAV => SE.SAV; public SlotChangeInfo DragInfo; @@ -54,22 +58,15 @@ public void MouseEnter(object sender, EventArgs e) var pb = (PictureBox)sender; if (pb.Image == null) return; - OriginalBackground = pb.BackgroundImage; - var hover = GlowHover ? GetGlowSprite(pb) : Resources.slotHover; - pb.BackgroundImage = CurrentBackground = pb.BackgroundImage == null ? hover : ImageUtil.LayerImage(pb.BackgroundImage, hover, 0, 0); BeginHoverSlot(pb); } - private Bitmap GetGlowSprite(PictureBox pb) + private Bitmap GetGlowSprite(PictureBox pb, PKM pk) { - var view = WinFormsUtil.FindFirstControlOfType>(pb); - var data = view.GetSlotData(pb); - var pk = SAV.GetStoredSlot(data.Offset); var baseSprite = SpriteUtil.GetSprite(pk.Species, pk.AltForm, pk.Gender, 0, pk.IsEgg, false, pk.Format); var pixels = ImageUtil.GetPixelData((Bitmap)baseSprite); - ImageUtil.GlowEdges(pixels, new byte[] { 255, 255, 255 }, pb.Image.Width); - var hover = ImageUtil.GetBitmap(pixels, pb.Image.Width, pb.Image.Height); - return ImageUtil.LayerImage(Resources.slotHover, hover, 0, 0); + ImageUtil.GlowEdges(pixels, new[] {GlowInitial.B, GlowInitial.G, GlowInitial.R}, pb.Image.Width); + return ImageUtil.GetBitmap(pixels, pb.Image.Width, pb.Image.Height); } private void BeginHoverSlot(PictureBox pb) { @@ -78,6 +75,25 @@ private void BeginHoverSlot(PictureBox pb) var pk = SAV.GetStoredSlot(data.Offset); HoveredSlot = pb; + OriginalBackground = pb.BackgroundImage; + + Bitmap hover; + if (GlowHover) + { + HoverWorker?.Stop(); + + var GlowBase = GetGlowSprite(pb, pk); + hover = ImageUtil.LayerImage(GlowBase, Resources.slotHover, 0, 0); + HoverWorker = new BitmapAnimator(GlowBase, Resources.slotHover) { GlowFromColor = GlowInitial, GlowToColor = GlowFinal }; + HoverWorker.Start(pb, OriginalBackground); + } + else + { + hover = Resources.slotHover; + } + + pb.BackgroundImage = CurrentBackground = OriginalBackground == null ? hover : ImageUtil.LayerImage(OriginalBackground, hover, 0, 0); + if (Settings.Default.HoverSlotShowText) ShowSimulatorSetTooltip(pb, pk); if (Settings.Default.HoverSlotPlayCry) @@ -85,7 +101,13 @@ private void BeginHoverSlot(PictureBox pb) } private void EndHoverSlot() { - HoveredSlot = null; + if (HoveredSlot != null) + { + HoverWorker?.Stop(); + HoverWorker = null; + HoveredSlot.BackgroundImage = OriginalBackground; + HoveredSlot = null; + } ShowSet.RemoveAll(); Sounds.Stop(); } @@ -433,6 +455,10 @@ void updateView(ISlotViewer view) ColorizedBox = box; ColorizedSlot = slot; ColorizedColor = img; + + OriginalBackground = img; + if (HoverWorker != null) + HoverWorker.OriginalBackground = img; } // PKM Get Set diff --git a/PKHeX.WinForms/PKHeX.WinForms.csproj b/PKHeX.WinForms/PKHeX.WinForms.csproj index da6d9c2fd..9e2940034 100644 --- a/PKHeX.WinForms/PKHeX.WinForms.csproj +++ b/PKHeX.WinForms/PKHeX.WinForms.csproj @@ -178,6 +178,9 @@ TrainerID.cs + + Component + UserControl