286 lines
9.1 KiB
C#
286 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;
|
|
}
|
|
}
|
|
}
|