168 lines
5.5 KiB
C#
168 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
using System.Xml.Serialization;
|
|
using UnityEngine;
|
|
|
|
namespace RimWorldAnimationStudio
|
|
{
|
|
public class AnimationStage
|
|
{
|
|
// Data to/from animationDef
|
|
public string stageName;
|
|
public int? playTimeTicks;
|
|
public int? playTimeTicksQuick;
|
|
public bool? isLooping;
|
|
[XmlArray("animationClips"), XmlArrayItem("li")] public List<PawnAnimationClip> animationClips;
|
|
|
|
// Data serialization control
|
|
public bool ShouldSerializeanimationClips() { return animationClips.NotNullOrEmpty(); }
|
|
|
|
// Data helper functions
|
|
[XmlIgnore] public string StageName
|
|
{
|
|
get { return string.IsNullOrEmpty(stageName) ? stageName = "NewStage" : stageName; }
|
|
set { stageName = value; }
|
|
}
|
|
|
|
[XmlIgnore] public int PlayTimeTicks
|
|
{
|
|
get { return playTimeTicks.HasValue ? playTimeTicks.Value : 0; }
|
|
set { playTimeTicks = value; }
|
|
}
|
|
|
|
[XmlIgnore] public int PlayTimeTicksQuick
|
|
{
|
|
get { return playTimeTicksQuick.HasValue ? playTimeTicksQuick.Value : 0; }
|
|
set { playTimeTicksQuick = value; }
|
|
}
|
|
|
|
[XmlIgnore] public bool IsLooping
|
|
{
|
|
get { return isLooping == true; }
|
|
set { isLooping = value; }
|
|
}
|
|
|
|
[XmlIgnore] public List<PawnAnimationClip> AnimationClips
|
|
{
|
|
get { return animationClips.NullOrEmpty() ? animationClips = new List<PawnAnimationClip>() : animationClips; }
|
|
set { animationClips = value.NotNullOrEmpty() ? value : null; }
|
|
}
|
|
|
|
[XmlIgnore] public int StageLoopsNormal
|
|
{
|
|
get { return Mathf.CeilToInt(PlayTimeTicks / Workspace.StageWindowSize); }
|
|
set { value = Math.Max(1, value); PlayTimeTicks = value * Workspace.StageWindowSize; IsLooping = value > 1; }
|
|
}
|
|
|
|
[XmlIgnore] public int StageLoopsQuick
|
|
{
|
|
get { return Mathf.CeilToInt(PlayTimeTicksQuick / Workspace.StageWindowSize); }
|
|
set { value = Math.Max(0, Math.Min(value, StageLoopsNormal)); PlayTimeTicksQuick = value * Workspace.StageWindowSize; IsLooping = value > 1; }
|
|
}
|
|
|
|
// Local data
|
|
[XmlIgnore] public int stageWindowSize = -1;
|
|
|
|
// Methods
|
|
public void Initialize()
|
|
{
|
|
foreach (PawnAnimationClip clip in AnimationClips)
|
|
{
|
|
clip.BuildSimpleCurves();
|
|
|
|
if (clip.duration > PlayTimeTicks)
|
|
{ PlayTimeTicks = clip.duration; }
|
|
}
|
|
}
|
|
|
|
public int GetStageID()
|
|
{
|
|
if (Workspace.animationDef == null) return -1;
|
|
|
|
return Workspace.animationDef.AnimationStages.IndexOf(this);
|
|
}
|
|
|
|
public void StretchStageWindow(int newStageWindowSize)
|
|
{
|
|
float scale = (float)newStageWindowSize / Workspace.StageWindowSize;
|
|
|
|
foreach (PawnAnimationClip clip in AnimationClips)
|
|
{
|
|
foreach (PawnKeyframe keyframe in clip.Keyframes)
|
|
{
|
|
keyframe.TickDuration = Mathf.RoundToInt(keyframe.TickDuration * scale);
|
|
keyframe.atTick = null;
|
|
}
|
|
|
|
clip.BuildSimpleCurves();
|
|
}
|
|
|
|
EventsManager.OnStageWindowSizeChanged(this);
|
|
}
|
|
|
|
public void ResizeStageWindow(int newStageWindowSize)
|
|
{
|
|
Workspace.GetCurrentAnimationStage().stageWindowSize = newStageWindowSize;
|
|
Workspace.GetCurrentAnimationStage().PlayTimeTicks = newStageWindowSize * StageLoopsNormal;
|
|
Workspace.GetCurrentAnimationStage().PlayTimeTicksQuick = newStageWindowSize * StageLoopsQuick;
|
|
|
|
EventsManager.OnStageWindowSizeChanged(this);
|
|
}
|
|
|
|
public void AddAnimationClip(int actorID = -1)
|
|
{
|
|
PawnAnimationClip clip = new PawnAnimationClip();
|
|
PawnKeyframe lastkeyframe = null;
|
|
|
|
if (actorID >= 0)
|
|
{ lastkeyframe = Workspace.GetPawnAnimationClip(actorID)?.Keyframes?.Last(); }
|
|
|
|
if (lastkeyframe != null)
|
|
{
|
|
PawnKeyframe keyframeA = lastkeyframe.Copy();
|
|
keyframeA.atTick = null;
|
|
keyframeA.TickDuration = Constants.defaultAnimationClipLength - 1;
|
|
keyframeA.GenerateKeyframeID(actorID);
|
|
|
|
clip.Keyframes.Add(keyframeA);
|
|
|
|
PawnKeyframe keyframeB = lastkeyframe.Copy();
|
|
keyframeB.atTick = null;
|
|
keyframeB.TickDuration = 1;
|
|
keyframeB.GenerateKeyframeID(actorID);
|
|
|
|
clip.Keyframes.Add(keyframeB);
|
|
}
|
|
|
|
else
|
|
{
|
|
PawnKeyframe keyframeA = new PawnKeyframe();
|
|
keyframeA.TickDuration = Constants.defaultAnimationClipLength - 1;
|
|
|
|
clip.Keyframes.Add(keyframeA);
|
|
|
|
PawnKeyframe keyframeB = new PawnKeyframe();
|
|
|
|
clip.Keyframes.Add(keyframeB);
|
|
}
|
|
|
|
animationClips.Add(clip);
|
|
}
|
|
|
|
// Pre-save / post-load
|
|
public void OnPreSave()
|
|
{
|
|
foreach (PawnAnimationClip clip in AnimationClips)
|
|
{ clip.Keyframes = clip.Keyframes.OrderBy(x => x.atTick).ToList(); }
|
|
}
|
|
|
|
public void OnPostLoad()
|
|
{
|
|
foreach (PawnAnimationClip clip in AnimationClips)
|
|
{ clip.OnPostLoad(); }
|
|
}
|
|
}
|
|
}
|