Switch-Toolbox/Switch_Toolbox_Library/GUI/AnimationPanel.cs
2018-11-11 19:48:33 -05:00

285 lines
9.1 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using WeifenLuo.WinFormsUI.Docking;
namespace Switch_Toolbox.Library
{
//Thanks to forge! Based on
// https://github.com/jam1garner/Smash-Forge/blob/52844da94c7bed830d841e0d7e5d49c3f2c69471/Smash%20Forge/GUI/ModelViewport.cs
public partial class AnimationPanel : UserControl
{
private static AnimationPanel _instance;
public static AnimationPanel Instance { get { return _instance == null ? _instance = new AnimationPanel() : _instance; } }
//Animation Functions
public int AnimationSpeed = 60;
public float Frame = 0;
public bool isPlaying;
private bool isOpen = true;
private Thread renderThread;
private GL_Core.GL_ControlModern gL_ControlModern1;
private bool renderThreadIsUpdating = false;
private Animation currentAnimation;
public Animation CurrentAnimation
{
get
{
return currentAnimation;
}
set
{
ResetModels();
/* currentAnimation = value;
totalFrame.Value = value.FrameCount;
animationTrackBar.TickFrequency = 1;
animationTrackBar.SetRange(0, (int)value.FrameCount);
currentFrameUpDown.Value = 1;
currentFrameUpDown.Value = 0;*/
}
}
public void ResetModels()
{
foreach (var drawable in Runtime.abstractGlDrawables)
{
if (drawable is STSkeleton)
{
((STSkeleton)drawable).reset();
}
}
}
public AnimationPanel()
{
InitializeComponent();
}
public static Stopwatch directUVTimeStopWatch = new Stopwatch();
private void animationPlayBtn_Click(object sender, EventArgs e)
{
isPlaying = !isPlaying;
animationPlayBtn.Text = isPlaying ? "Pause" : "Play";
if (isPlaying)
directUVTimeStopWatch.Start();
else
directUVTimeStopWatch.Stop();
}
private void totalFrame_ValueChanged(object sender, EventArgs e)
{
if (currentAnimation == null) return;
if (totalFrame.Value < 1)
{
totalFrame.Value = 1;
}
else
{
if (currentAnimation.Tag is Animation)
((Animation)currentAnimation.Tag).FrameCount = (int)totalFrame.Value;
currentAnimation.FrameCount = (int)totalFrame.Value;
animationTrackBar.Value = 0;
animationTrackBar.SetRange(0, currentAnimation.FrameCount);
}
}
private GL_Core.GL_ControlModern GetViewport()
{
Form form1 = Application.OpenForms[0];
foreach (Control control in form1.Controls)
{
if (control is DockPanel)
{
foreach (DockContent ctrl in ((DockPanel)control).Contents)
{
foreach (Control controls in ctrl.Controls)
{
if (controls is GL_Core.GL_ControlModern)
{
return (GL_Core.GL_ControlModern)controls;
}
}
}
}
}
return null;
}
private void UpdateViewport()
{
if (Viewport.Instance.gL_ControlModern1.InvokeRequired)
{
Viewport.Instance.gL_ControlModern1.Invoke((MethodInvoker)delegate {
// Running on the UI thread
Viewport.Instance.gL_ControlModern1.Invalidate();
});
}
else
{
Viewport.Instance.gL_ControlModern1.Invalidate();
}
}
private void RenderAndAnimationLoop()
{
if (IsDisposed)
return;
// TODO: We don't really need two timers.
Stopwatch renderStopwatch = Stopwatch.StartNew();
Stopwatch animationStopwatch = Stopwatch.StartNew();
// Wait for UI to load before triggering paint events.
int waitTimeMs = 500;
Thread.Sleep(waitTimeMs);
UpdateViewport();
int frameUpdateInterval = 5;
int animationUpdateInterval = 16;
while (isOpen)
{
// Always refresh the viewport when animations are playing.
if (renderThreadIsUpdating || isPlaying)
{
if (renderStopwatch.ElapsedMilliseconds > frameUpdateInterval)
{
UpdateViewport();
renderStopwatch.Restart();
}
if (animationStopwatch.ElapsedMilliseconds > animationUpdateInterval)
{
UpdateAnimationFrame();
animationStopwatch.Restart();
}
}
else
{
// Avoid wasting the CPU if we don't need to render anything.
Thread.Sleep(1);
}
}
}
private void UpdateAnimationFrame()
{
if (isPlaying)
{
if (currentFrameUpDown.InvokeRequired)
{
this.currentFrameUpDown.Invoke((MethodInvoker)delegate {
// Running on the UI thread
if (currentFrameUpDown.Value == totalFrame.Value)
currentFrameUpDown.Value = 0;
else
currentFrameUpDown.Value++;
});
}
else
{
if (currentFrameUpDown.Value == totalFrame.Value)
currentFrameUpDown.Value = 0;
else
currentFrameUpDown.Value++;
}
}
}
private void nextButton_Click(object sender, EventArgs e)
{
// Loop the animation.
if (currentFrameUpDown.Value == totalFrame.Value)
currentFrameUpDown.Value = 0;
else
currentFrameUpDown.Value++;
}
private void prevButton_Click(object sender, EventArgs e)
{
if (currentFrameUpDown.Value != 0)
currentFrameUpDown.Value--;
}
private void animationTrackBar_Scroll(object sender, EventArgs e)
{
}
private void animationTrackBar_ValueChanged(object sender, EventArgs e)
{
if (animationTrackBar.Value > (int)totalFrame.Value)
animationTrackBar.Value = 0;
if (animationTrackBar.Value < 0)
animationTrackBar.Value = (int)totalFrame.Value;
currentFrameUpDown.Value = animationTrackBar.Value;
int currentFrame = animationTrackBar.Value;
SetAnimationsToFrame(currentFrame);
UpdateViewport();
}
private void SetAnimationsToFrame(int frameNum)
{
if (currentAnimation == null)
return;
float animFrameNum = frameNum;
foreach (var drawable in Runtime.abstractGlDrawables)
{
if (drawable is STSkeleton)
{
currentAnimation.SetFrame(animFrameNum);
currentAnimation.NextFrame((STSkeleton)drawable);
}
}
}
private void currentFrameUpDown_ValueChanged(object sender, EventArgs e)
{
if (currentFrameUpDown.Value > totalFrame.Value)
currentFrameUpDown.Value = totalFrame.Value;
animationTrackBar.Value = (int)currentFrameUpDown.Value;
}
private void AnimationPanel_FormClosed(object sender, FormClosedEventArgs e)
{
isOpen = false;
Dispose();
}
private void AnimationPanel_Shown(object sender, EventArgs e)
{
// if (Viewport.Instance.gL_ControlModern1 != null)
// Viewport.Instance.gL_ControlModern1.VSync = Runtime.enableVSync;
// renderThread = new Thread(new ThreadStart(RenderAndAnimationLoop));
// renderThread.Start();
}
private void AnimationPanel_Enter(object sender, EventArgs e)
{
}
private void AnimationPanel_Click(object sender, EventArgs e)
{
renderThreadIsUpdating = true;
}
private void AnimationPanel_Leave(object sender, EventArgs e)
{
renderThreadIsUpdating = false;
}
}
}