mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-05-22 01:26:31 +00:00
AnimationPictureBox - Update animation system as a whole
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using AnimatedGif;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PckStudio.Internal;
|
||||
|
||||
@@ -11,6 +13,17 @@ namespace PckStudio.Extensions
|
||||
{
|
||||
internal static class AnimationExtensions
|
||||
{
|
||||
internal static Image CreateAnimationImage(this Animation animation)
|
||||
{
|
||||
var ms = new System.IO.MemoryStream();
|
||||
var generateor = new AnimatedGifCreator(ms, Animation.GameTickInMilliseconds, 0);
|
||||
foreach (var frame in animation.GetInterpolatedFrames())
|
||||
{
|
||||
generateor.AddFrame(frame.Texture, frame.Ticks * Animation.GameTickInMilliseconds, GifQuality.Bit8);
|
||||
}
|
||||
ms.Position = 0;
|
||||
return Image.FromStream(ms);
|
||||
}
|
||||
|
||||
internal static JObject ConvertToJavaAnimation(this Animation animation)
|
||||
{
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace PckStudio.Forms.Editor
|
||||
|
||||
private Animation _animation;
|
||||
private bool _isSpecialTile;
|
||||
|
||||
private AnimationEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -56,6 +57,7 @@ namespace PckStudio.Forms.Editor
|
||||
_animation = animation;
|
||||
tileLabel.Text = displayName;
|
||||
_isSpecialTile = isSpecialTile;
|
||||
animationPictureBox.Image = animation.CreateAnimationImage();
|
||||
}
|
||||
|
||||
internal AnimationEditor(Animation animation, string displayName, Color blendColor)
|
||||
@@ -63,7 +65,7 @@ namespace PckStudio.Forms.Editor
|
||||
{
|
||||
animationPictureBox.UseBlendColor = true;
|
||||
animationPictureBox.BlendColor = blendColor;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateToolStrip()
|
||||
{
|
||||
@@ -90,12 +92,11 @@ namespace PckStudio.Forms.Editor
|
||||
InterpolationCheckbox.Checked = _animation.Interpolate;
|
||||
TextureIcons.Images.Clear();
|
||||
TextureIcons.Images.AddRange(_animation.GetTextures().ToArray());
|
||||
|
||||
UpdateTreeView();
|
||||
|
||||
if (_animation.FrameCount > 0)
|
||||
{
|
||||
animationPictureBox.SelectFrame(_animation, 0);
|
||||
animationPictureBox.Image.SelectActiveFrame(FrameDimension.Page, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,13 +112,15 @@ namespace PckStudio.Forms.Editor
|
||||
})
|
||||
.ToArray()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void frameTreeView_AfterSelect(object sender, TreeViewEventArgs e)
|
||||
{
|
||||
if (animationPictureBox.IsPlaying)
|
||||
AnimationStartStopBtn.Text = "Play Animation";
|
||||
animationPictureBox.SelectFrame(_animation, frameTreeView.SelectedNode.Index);
|
||||
{
|
||||
StopAnimation();
|
||||
}
|
||||
animationPictureBox.Image = _animation.GetFrame(frameTreeView.SelectedNode.Index).Texture;
|
||||
}
|
||||
|
||||
private void StopAnimation()
|
||||
@@ -133,9 +136,11 @@ namespace PckStudio.Forms.Editor
|
||||
StopAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_animation.FrameCount > 1)
|
||||
{
|
||||
animationPictureBox.Start(_animation);
|
||||
animationPictureBox.Image = _animation.CreateAnimationImage();
|
||||
animationPictureBox.Start();
|
||||
AnimationStartStopBtn.Text = "Stop Animation";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,8 @@ namespace PckStudio.Forms.Editor
|
||||
animationFile.Size > 0)
|
||||
{
|
||||
var animation = animationFile.GetDeserializedData(AnimationDeserializer.DefaultDeserializer);
|
||||
selectTilePictureBox.Start(animation);
|
||||
selectTilePictureBox.Image = animation.CreateAnimationImage();
|
||||
selectTilePictureBox.Start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,142 +16,61 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading.Tasks;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using PckStudio.Extensions;
|
||||
using PckStudio.Internal;
|
||||
using System.Drawing;
|
||||
using AnimatedGif;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace PckStudio.ToolboxItems
|
||||
{
|
||||
internal class AnimationPictureBox : BlendPictureBox
|
||||
{
|
||||
public bool IsPlaying
|
||||
{
|
||||
get
|
||||
{
|
||||
lock(l_playing)
|
||||
{
|
||||
return _isPlaying;
|
||||
}
|
||||
}
|
||||
private set
|
||||
{
|
||||
lock (l_playing)
|
||||
{
|
||||
_isPlaying = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool IsPlaying => _isPlaying;
|
||||
|
||||
private bool _isPlaying;
|
||||
|
||||
private bool _isPlaying = false;
|
||||
private int currentAnimationFrameIndex = 0;
|
||||
private Animation.Frame currentFrame;
|
||||
private Animation _animation;
|
||||
private CancellationTokenSource cts = new CancellationTokenSource();
|
||||
private object l_dispose = new object();
|
||||
private object l_playing = new object();
|
||||
|
||||
public void Start(Animation animation)
|
||||
{
|
||||
_animation = animation;
|
||||
cts = new CancellationTokenSource();
|
||||
IsPlaying = true;
|
||||
Task.Run(DoAnimate, cts.Token);
|
||||
}
|
||||
|
||||
public void Stop([CallerMemberName] string callerName = default!)
|
||||
{
|
||||
Debug.WriteLine($"{nameof(AnimationPictureBox.Stop)} called from {callerName}!");
|
||||
IsPlaying = false;
|
||||
cts.Cancel();
|
||||
cts.Token.WaitHandle.WaitOne(500);
|
||||
}
|
||||
|
||||
public void SelectFrame(Animation animation, int index)
|
||||
{
|
||||
if (IsPlaying)
|
||||
Stop();
|
||||
_animation = animation;
|
||||
currentAnimationFrameIndex = index;
|
||||
currentFrame = SetAnimationFrame(index);
|
||||
}
|
||||
|
||||
private void DoAnimate()
|
||||
{
|
||||
_ = _animation ?? throw new ArgumentNullException(nameof(_animation));
|
||||
Animation.Frame nextFrame;
|
||||
while (!cts.IsCancellationRequested && IsPlaying)
|
||||
{
|
||||
if (currentAnimationFrameIndex >= _animation.FrameCount)
|
||||
{
|
||||
currentAnimationFrameIndex = 0;
|
||||
}
|
||||
|
||||
if (currentAnimationFrameIndex + 1 >= _animation.FrameCount)
|
||||
{
|
||||
nextFrame = _animation.GetFrame(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextFrame = _animation.GetFrame(currentAnimationFrameIndex + 1);
|
||||
}
|
||||
|
||||
currentFrame = _animation.GetFrame(currentAnimationFrameIndex++);
|
||||
if (_animation.Interpolate)
|
||||
{
|
||||
InterpolateFrame(currentFrame, nextFrame);
|
||||
continue;
|
||||
}
|
||||
SetAnimationFrame(currentFrame);
|
||||
if (cts.Token.WaitHandle.WaitOne(Animation.GameTickInMilliseconds * currentFrame.Ticks))
|
||||
{
|
||||
IsPlaying = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InterpolateFrame(Animation.Frame currentFrame, Animation.Frame nextFrame)
|
||||
private void PictureBox_Internal_Animate(PictureBox pictureBox, bool animate)
|
||||
{
|
||||
for (int tick = 0; tick < currentFrame.Ticks && !cts.IsCancellationRequested; tick++)
|
||||
var animateMethod = typeof(PictureBox).GetMethod("Animate",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance,
|
||||
null, new Type[] { typeof(bool) }, null);
|
||||
animateMethod.Invoke(pictureBox, new object[] { animate });
|
||||
}
|
||||
|
||||
public new Image Image
|
||||
{
|
||||
get => base.Image;
|
||||
set
|
||||
{
|
||||
double delta = 1.0f - tick / (double)currentFrame.Ticks;
|
||||
SetTexture(currentFrame.Texture.Interpolate(nextFrame.Texture, delta));
|
||||
if (cts.Token.WaitHandle.WaitOne(Animation.GameTickInMilliseconds))
|
||||
break;
|
||||
base.Image = value;
|
||||
PictureBox_Internal_Animate(this, false);
|
||||
if (value is null)
|
||||
return;
|
||||
value.SelectActiveFrame(new FrameDimension(value.FrameDimensionsList[0]), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private Animation.Frame SetAnimationFrame(int frameIndex)
|
||||
public void Start()
|
||||
{
|
||||
var frame = _animation.GetFrame(frameIndex);
|
||||
SetAnimationFrame(frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
private void SetTexture(Image texture)
|
||||
{
|
||||
if (!IsHandleCreated || Disposing)
|
||||
return;
|
||||
Invoke(() => Image = texture);
|
||||
}
|
||||
|
||||
private void SetAnimationFrame(Animation.Frame frame)
|
||||
{
|
||||
SetTexture(frame.Texture);
|
||||
_isPlaying = true;
|
||||
PictureBox_Internal_Animate(this, _isPlaying);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
public void Stop()
|
||||
{
|
||||
_isPlaying = false;
|
||||
PictureBox_Internal_Animate(this, _isPlaying);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
Stop();
|
||||
cts.Token.WaitHandle.WaitOne(500);
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user