mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
119 lines
No EOL
3.9 KiB
C#
119 lines
No EOL
3.9 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Timers;
|
|
using System.Windows.Forms;
|
|
using PKHeX.Drawing;
|
|
using Timer = System.Timers.Timer;
|
|
|
|
namespace PKHeX.WinForms.Controls
|
|
{
|
|
public sealed class BitmapAnimator : Timer
|
|
{
|
|
public BitmapAnimator()
|
|
{
|
|
Elapsed += TimerElapsed;
|
|
}
|
|
|
|
private int imgWidth;
|
|
private int imgHeight;
|
|
private byte[]? GlowData;
|
|
private Image? ExtraLayer;
|
|
private Image?[]? GlowCache;
|
|
public Image? OriginalBackground;
|
|
private readonly object Lock = new();
|
|
|
|
private PictureBox? pb;
|
|
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;
|
|
|
|
public new static void Start() => throw new ArgumentException();
|
|
|
|
public new void Stop()
|
|
{
|
|
if (pb == null || !Enabled)
|
|
return;
|
|
|
|
lock (Lock)
|
|
{
|
|
Enabled = false;
|
|
pb.BackgroundImage = OriginalBackground;
|
|
}
|
|
|
|
// reset logic
|
|
if (GlowCache == null)
|
|
throw new ArgumentNullException(nameof(GlowCache));
|
|
GlowCounter = 0;
|
|
for (int i = 0; i < GlowCache.Length; i++)
|
|
GlowCache[i] = null;
|
|
}
|
|
|
|
public void Start(PictureBox pbox, Image baseImage, byte[] glowData, Image original, Image extra)
|
|
{
|
|
Enabled = false;
|
|
imgWidth = baseImage.Width;
|
|
imgHeight = baseImage.Height;
|
|
GlowData = glowData;
|
|
GlowCounter = 0;
|
|
GlowCache = new Image[GlowFps];
|
|
GlowInterval = 1000 / GlowFps;
|
|
Interval = GlowInterval;
|
|
lock (Lock)
|
|
{
|
|
pb = pbox;
|
|
ExtraLayer = extra;
|
|
OriginalBackground = original;
|
|
}
|
|
Enabled = true;
|
|
}
|
|
|
|
private void TimerElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
|
|
{
|
|
if (!Enabled)
|
|
return; // timer canceled, was waiting to proceed
|
|
GlowCounter = (GlowCounter + 1) % (GlowInterval * 2); // loop backwards
|
|
int frameIndex = GlowCounter >= GlowInterval ? (GlowInterval * 2) - GlowCounter : GlowCounter;
|
|
|
|
lock (Lock)
|
|
{
|
|
if (!Enabled)
|
|
return;
|
|
|
|
if (pb == null)
|
|
return;
|
|
try { pb.BackgroundImage = GetFrame(frameIndex); } // drawing GDI can be silly sometimes #2072
|
|
catch (AccessViolationException ex) { System.Diagnostics.Debug.WriteLine(ex.Message); }
|
|
}
|
|
}
|
|
|
|
private Image GetFrame(int frameIndex)
|
|
{
|
|
var cache = GlowCache;
|
|
if (cache == null)
|
|
throw new NullReferenceException(nameof(GlowCache));
|
|
var frame = cache[frameIndex];
|
|
if (frame != null)
|
|
return frame;
|
|
|
|
var elapsedFraction = (double)frameIndex / GlowInterval;
|
|
var frameColor = GetFrameColor(elapsedFraction);
|
|
|
|
if (GlowData == null)
|
|
throw new NullReferenceException(nameof(GlowData));
|
|
var frameData = (byte[])GlowData.Clone();
|
|
ImageUtil.ChangeAllColorTo(frameData, frameColor);
|
|
|
|
frame = ImageUtil.GetBitmap(frameData, imgWidth, imgHeight);
|
|
if (ExtraLayer != null)
|
|
frame = ImageUtil.LayerImage(frame, ExtraLayer, 0, 0);
|
|
if (OriginalBackground != null)
|
|
frame = ImageUtil.LayerImage(OriginalBackground, frame, 0, 0);
|
|
return cache[frameIndex] = frame;
|
|
}
|
|
|
|
private Color GetFrameColor(double elapsedFraction) => ImageUtil.Blend(GlowToColor, GlowFromColor, elapsedFraction);
|
|
}
|
|
} |