2018-07-23 03:04:28 +00:00
|
|
|
using System;
|
|
|
|
using System.Drawing;
|
|
|
|
using System.Timers;
|
|
|
|
using System.Windows.Forms;
|
2019-09-29 16:47:06 +00:00
|
|
|
using PKHeX.Drawing;
|
2018-07-23 03:04:28 +00:00
|
|
|
using Timer = System.Timers.Timer;
|
|
|
|
|
|
|
|
namespace PKHeX.WinForms.Controls
|
|
|
|
{
|
|
|
|
public sealed class BitmapAnimator : Timer
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
public BitmapAnimator()
|
2018-07-23 03:04:28 +00:00
|
|
|
{
|
|
|
|
Elapsed += TimerElapsed;
|
|
|
|
}
|
|
|
|
|
2018-08-28 23:40:27 +00:00
|
|
|
private int imgWidth;
|
|
|
|
private int imgHeight;
|
2020-10-18 18:02:39 +00:00
|
|
|
private byte[]? GlowData;
|
|
|
|
private Image? ExtraLayer;
|
|
|
|
private Image?[]? GlowCache;
|
|
|
|
public Image? OriginalBackground;
|
2020-12-22 07:37:07 +00:00
|
|
|
private readonly object Lock = new();
|
2018-07-24 01:31:01 +00:00
|
|
|
|
2020-10-18 18:02:39 +00:00
|
|
|
private PictureBox? pb;
|
2018-07-23 03:04:28 +00:00
|
|
|
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;
|
|
|
|
|
2019-10-08 01:40:09 +00:00
|
|
|
public new static void Start() => throw new ArgumentException();
|
2018-07-23 03:04:28 +00:00
|
|
|
|
|
|
|
public new void Stop()
|
|
|
|
{
|
2018-07-28 16:56:13 +00:00
|
|
|
if (pb == null || !Enabled)
|
2018-07-28 02:59:14 +00:00
|
|
|
return;
|
2018-07-29 18:05:48 +00:00
|
|
|
|
|
|
|
lock (Lock)
|
|
|
|
{
|
|
|
|
Enabled = false;
|
|
|
|
pb.BackgroundImage = OriginalBackground;
|
|
|
|
}
|
2018-07-28 02:59:14 +00:00
|
|
|
|
|
|
|
// reset logic
|
2020-10-18 18:02:39 +00:00
|
|
|
if (GlowCache == null)
|
|
|
|
throw new ArgumentNullException(nameof(GlowCache));
|
2018-07-28 02:59:14 +00:00
|
|
|
GlowCounter = 0;
|
|
|
|
for (int i = 0; i < GlowCache.Length; i++)
|
|
|
|
GlowCache[i] = null;
|
2018-07-23 03:04:28 +00:00
|
|
|
}
|
|
|
|
|
2019-11-16 01:34:18 +00:00
|
|
|
public void Start(PictureBox pbox, Image baseImage, byte[] glowData, Image original, Image extra)
|
2018-07-23 03:04:28 +00:00
|
|
|
{
|
2018-08-28 23:40:27 +00:00
|
|
|
Enabled = false;
|
|
|
|
imgWidth = baseImage.Width;
|
|
|
|
imgHeight = baseImage.Height;
|
2018-07-28 02:59:14 +00:00
|
|
|
GlowData = glowData;
|
2018-08-28 23:40:27 +00:00
|
|
|
GlowCounter = 0;
|
2018-07-28 02:59:14 +00:00
|
|
|
GlowCache = new Image[GlowFps];
|
2018-07-23 03:04:28 +00:00
|
|
|
GlowInterval = 1000 / GlowFps;
|
|
|
|
Interval = GlowInterval;
|
2019-09-11 05:07:50 +00:00
|
|
|
lock (Lock)
|
|
|
|
{
|
|
|
|
pb = pbox;
|
2019-11-16 01:34:18 +00:00
|
|
|
ExtraLayer = extra;
|
2019-09-11 05:07:50 +00:00
|
|
|
OriginalBackground = original;
|
|
|
|
}
|
2018-07-23 03:04:28 +00:00
|
|
|
Enabled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void TimerElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
|
|
|
|
{
|
2018-07-28 02:59:14 +00:00
|
|
|
if (!Enabled)
|
|
|
|
return; // timer canceled, was waiting to proceed
|
|
|
|
GlowCounter = (GlowCounter + 1) % (GlowInterval * 2); // loop backwards
|
|
|
|
int frameIndex = GlowCounter >= GlowInterval ? (GlowInterval * 2) - GlowCounter : GlowCounter;
|
2018-07-29 18:05:48 +00:00
|
|
|
|
|
|
|
lock (Lock)
|
|
|
|
{
|
2018-08-29 01:21:46 +00:00
|
|
|
if (!Enabled)
|
|
|
|
return;
|
2020-10-18 18:02:39 +00:00
|
|
|
|
|
|
|
if (pb == null)
|
|
|
|
return;
|
2018-08-29 01:21:46 +00:00
|
|
|
try { pb.BackgroundImage = GetFrame(frameIndex); } // drawing GDI can be silly sometimes #2072
|
|
|
|
catch (AccessViolationException ex) { System.Diagnostics.Debug.WriteLine(ex.Message); }
|
2018-07-29 18:05:48 +00:00
|
|
|
}
|
2018-07-23 03:04:28 +00:00
|
|
|
}
|
|
|
|
|
2018-07-28 02:59:14 +00:00
|
|
|
private Image GetFrame(int frameIndex)
|
2018-07-23 03:04:28 +00:00
|
|
|
{
|
2021-05-18 20:29:55 +00:00
|
|
|
var cache = GlowCache;
|
|
|
|
if (cache == null)
|
2020-11-14 16:20:48 +00:00
|
|
|
throw new NullReferenceException(nameof(GlowCache));
|
2021-05-18 20:29:55 +00:00
|
|
|
var frame = cache[frameIndex];
|
2018-07-23 03:04:28 +00:00
|
|
|
if (frame != null)
|
|
|
|
return frame;
|
|
|
|
|
|
|
|
var elapsedFraction = (double)frameIndex / GlowInterval;
|
|
|
|
var frameColor = GetFrameColor(elapsedFraction);
|
2020-10-18 18:02:39 +00:00
|
|
|
|
|
|
|
if (GlowData == null)
|
2020-11-14 16:20:48 +00:00
|
|
|
throw new NullReferenceException(nameof(GlowData));
|
2018-07-28 02:59:14 +00:00
|
|
|
var frameData = (byte[])GlowData.Clone();
|
|
|
|
ImageUtil.ChangeAllColorTo(frameData, frameColor);
|
|
|
|
|
2018-08-29 01:21:46 +00:00
|
|
|
frame = ImageUtil.GetBitmap(frameData, imgWidth, imgHeight);
|
2018-07-23 03:04:28 +00:00
|
|
|
if (ExtraLayer != null)
|
2018-08-28 23:40:27 +00:00
|
|
|
frame = ImageUtil.LayerImage(frame, ExtraLayer, 0, 0);
|
2020-10-31 02:56:16 +00:00
|
|
|
if (OriginalBackground != null)
|
|
|
|
frame = ImageUtil.LayerImage(OriginalBackground, frame, 0, 0);
|
2021-05-18 20:29:55 +00:00
|
|
|
return cache[frameIndex] = frame;
|
2018-07-23 03:04:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private Color GetFrameColor(double elapsedFraction) => ImageUtil.Blend(GlowToColor, GlowFromColor, elapsedFraction);
|
|
|
|
}
|
|
|
|
}
|