Added editable stage lengths

This commit is contained in:
AbstractConcept 2022-09-18 00:01:12 -05:00
parent 8523abf957
commit d2ca61c61c
194 changed files with 820 additions and 269 deletions

View file

@ -13,8 +13,8 @@ namespace RimWorldAnimationStudio
public int playTimeTicksQuick = -1;
public bool isLooping = false;
[XmlArray("animationClips"), XmlArrayItem("li")]
public List<PawnAnimationClip> animationClips = new List<PawnAnimationClip>();
[XmlArray("animationClips"), XmlArrayItem("li")] public List<PawnAnimationClip> animationClips = new List<PawnAnimationClip>();
[XmlIgnore] public int stageWindowSize = -1;
public void Initialize()
{

View file

@ -54,5 +54,14 @@ namespace RimWorldAnimationStudio
KeyframeSlider keyframeSlider = GetComponentsInChildren<KeyframeSlider>().FirstOrDefault(x => x.keyframeID == keyframeID);
Destroy(keyframeSlider?.gameObject);
}
public void Update()
{
if (Workspace.actorID == actorID)
{ GetComponent<Image>().color = Constants.ColorGoldYellow; }
else
{ GetComponent<Image>().color = Constants.ColorGrey; }
}
}
}

View file

@ -32,7 +32,7 @@ namespace RimWorldAnimationStudio
this.keyframeID = keyframeID;
PawnKeyframe keyframe = Workspace.Instance.GetPawnKeyframe(actorID, keyframeID);
maxValue = Workspace.animationClipWindowSize;
maxValue = Workspace.StageWindowSize;
value = keyframe.atTick.Value;
OnValueChanged();
@ -61,7 +61,7 @@ namespace RimWorldAnimationStudio
for (int i = 0; i < Mathf.Max(nGhosts, ghostSliders.childCount); i++)
{
if ((i - 1) * clip.duration + keyframe.atTick <= Workspace.animationClipWindowSize)
if ((i - 1) * clip.duration + keyframe.atTick <= Workspace.StageWindowSize)
{
if (ghostSliders.childCount <= i)
{ Instantiate(ghostSliderPrefab, ghostSliders); }
@ -91,7 +91,7 @@ namespace RimWorldAnimationStudio
if (clip.duration <= 1)
{ return 0; }
return Math.Min(Mathf.CeilToInt((float)Workspace.animationClipWindowSize / clip.duration), maxGhosts);
return Math.Min(Mathf.CeilToInt((float)Workspace.StageWindowSize / clip.duration), maxGhosts);
}
public void OnPointerClick(PointerEventData eventData)

View file

@ -21,8 +21,8 @@ namespace RimWorldAnimationStudio
public Dropdown stageLoopDropdown;
public InputField cyclesNormalField;
public InputField cyclesFastField;
public Text stageTickText;
public Text stageLengthText;
public InputField animationClipTimeField;
public InputField animationClipLengthField;
public ActorCard actorCard;
public Transform animationTimelines;
@ -54,33 +54,38 @@ namespace RimWorldAnimationStudio
timeSinceLastUpdate -= 1f / 60f;
stageTick += 1;
if (stageTick > Workspace.animationClipWindowSize)
stageTimelineSlider.value = stageTick;
animationClipTimeField.text = stageTick.ToString();
if (stageTick > Workspace.StageWindowSize)
{
if (stageLoopDropdown.value == 1)
{ stageTick = 1; }
else if (stageLoopDropdown.value == 2 && Workspace.stageID < Workspace.animationDef.animationStages.Count - 1)
else if (stageLoopDropdown.value >= 2 && Workspace.stageID < Workspace.animationDef.animationStages.Count - 1)
{
++cycleIndex;
stageTick = 1;
if (cycleIndex > int.Parse(cyclesNormalField.text))
if ((stageLoopDropdown.value == 2 && cycleIndex > int.Parse(cyclesNormalField.text)) ||
(stageLoopDropdown.value == 3 && cycleIndex > int.Parse(cyclesFastField.text)))
{
++Workspace.stageID;
cycleIndex = 0;
ResetAnimationTimeline();
InitializeAnimationTimeline();
}
}
else
{ stageTick = Workspace.animationClipWindowSize; }
{ stageTick = Workspace.StageWindowSize; }
}
}
// Update stage timeline
stageTimelineSlider.maxValue = Workspace.animationClipWindowSize;
stageTimelineSlider.value = stageTick;
stageTickText.text = stageTick.ToString();
stageLengthText.text = Workspace.animationClipWindowSize.ToString();
animationClipTimeField.interactable = isAnimating == false;
animationClipLengthField.interactable = isAnimating == false;
// Update animation
UpdateAnimation();
@ -150,10 +155,8 @@ namespace RimWorldAnimationStudio
public void InitializeAnimationTimeline()
{
Workspace.animationClipWindowSize = Workspace.animationDef.animationStages[Workspace.stageID].animationClips.Select(x => x.duration).Max();
cyclesNormalField.text = Mathf.Max(Mathf.CeilToInt((float)Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicks / Workspace.animationClipWindowSize), 1).ToString();
cyclesFastField.text = Mathf.Max(Mathf.CeilToInt((float)Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicksQuick / Workspace.animationClipWindowSize), 1).ToString();
cyclesNormalField.text = Mathf.Max(Mathf.CeilToInt((float)Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicks / Workspace.StageWindowSize), 1).ToString();
cyclesFastField.text = Mathf.Max(Mathf.CeilToInt((float)Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicksQuick / Workspace.StageWindowSize), 1).ToString();
for (int actorID = 0; actorID < Workspace.animationDef.actors.Count; actorID++)
{
@ -164,7 +167,9 @@ namespace RimWorldAnimationStudio
animationTimeline.Initialize(actorID);
}
stageTimelineSlider.maxValue = Workspace.animationClipWindowSize;
animationClipLengthField.text = Workspace.StageWindowSize.ToString();
animationClipTimeField.text = "1";
stageTimelineSlider.maxValue = Workspace.StageWindowSize;
stageTimelineSlider.value = 1;
stageTick = 1;
}
@ -299,13 +304,21 @@ namespace RimWorldAnimationStudio
public void RemovePawnKeyframe()
{
PawnKeyframe keyframe = Workspace.Instance.GetCurrentPawnKeyframe(false);
RemovePawnKeyframe(Workspace.actorID, Workspace.keyframeID);
}
public void RemovePawnKeyframe(int actorID, int keyframeID)
{
PawnKeyframe keyframe = Workspace.Instance.GetPawnKeyframe(actorID, keyframeID);
if (keyframe.atTick == 1)
{ Debug.LogWarning("Cannot delete key frame - the first key frame of an animation cannot be deleted"); return; }
if (keyframe != null)
{
animationTimelines.GetChild(Workspace.actorID).GetComponent<AnimationTimeline>().RemovePawnKeyFrame(keyframe.keyframeID);
animationTimelines.GetChild(actorID).GetComponent<AnimationTimeline>().RemovePawnKeyFrame(keyframe.keyframeID);
PawnAnimationClip clip = Workspace.Instance.GetCurrentPawnAnimationClip();
PawnAnimationClip clip = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[actorID];
clip.keyframes.Remove(keyframe);
clip.BuildSimpleCurves();
}
@ -316,18 +329,78 @@ namespace RimWorldAnimationStudio
isAnimating = !isAnimating;
}
public void UpdateFromStageTimelineSlider()
{
if (Workspace.animationDef == null)
{ return; }
if (stageTick != (int)stageTimelineSlider.value)
{ stageTick = (int)stageTimelineSlider.value; }
}
public void ToggleActorManipulationMode(int mode)
{
Workspace.actorManipulationMode = (ActorManipulationMode)mode;
}
public void OnStageTimelineSliderChange()
{
if (Workspace.animationDef == null) return;
if (stageTick != (int)stageTimelineSlider.value)
{
stageTick = (int)stageTimelineSlider.value;
animationClipTimeField.text = stageTick.ToString();
}
}
public void OnAnimationClipTimeFieldChange()
{
if (Workspace.animationDef == null) return;
int.TryParse(animationClipTimeField.text, out int newStageTick);
stageTick = Mathf.Clamp(newStageTick, 1, Workspace.StageWindowSize);
stageTimelineSlider.value = stageTick;
}
public void OnAnimationClipLengthFieldChange()
{
if (Workspace.animationDef == null) return;
int.TryParse(animationClipLengthField.text, out int newstageWindowSize);
newstageWindowSize = Mathf.Clamp(newstageWindowSize, Constants.minAnimationClipLength, Constants.maxAnimationClipLength);
Debug.Log("Resizing animation clip length to " + newstageWindowSize.ToString() + " ticks.");
for (int i = 0; i < Workspace.animationDef.animationStages[Workspace.stageID].animationClips.Count; i++)
{
PawnAnimationClip clip = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[i];
List<PawnKeyframe> keyframes = clip.keyframes.Where(x => x.atTick > newstageWindowSize)?.ToList();
if (keyframes.NullOrEmpty())
{ continue; }
foreach (PawnKeyframe keyframe in keyframes)
{
RemovePawnKeyframe(i, keyframe.keyframeID);
if (Workspace.animationDef.animationStages[Workspace.stageID].animationClips[i].keyframes.Count <= 2)
{ break; }
}
}
animationClipLengthField.text = newstageWindowSize.ToString();
Workspace.animationDef.animationStages[Workspace.stageID].stageWindowSize = newstageWindowSize;
ResetAnimationTimeline();
InitializeAnimationTimeline();
}
public void OnCycleNormalFieldChange()
{
if (Workspace.animationDef == null) return;
if (int.TryParse(cyclesNormalField.text, out int cycles))
{ Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicks = cycles * Workspace.StageWindowSize; }
}
public void OnCycleFastFieldChange()
{
if (Workspace.animationDef == null) return;
if (int.TryParse(cyclesFastField.text, out int cycles))
{ Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicksQuick = cycles * Workspace.StageWindowSize; }
}
}
}

View file

@ -0,0 +1,17 @@
using UnityEngine;
namespace RimWorldAnimationStudio
{
public static class Constants
{
public static int defaultAnimationClipLength = 600;
public static int minAnimationClipLength = 2;
public static int maxAnimationClipLength = 9999;
public static Color ColorWhite = new Color(1f, 1f, 1f);
public static Color ColorGreen = new Color(0f, 1f, 0f);
public static Color ColorGoldYellow = new Color(1f, 0.85f, 0f);
public static Color ColorGrey = new Color(0.5f, 0.5f, 0.5f);
public static Color ColorDarkGrey = new Color(0.2f, 0.2f, 0.2f);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5736ef91f32211942abe6c2f765da6c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -26,7 +26,20 @@ namespace RimWorldAnimationStudio
private static int historyIndex = 0;
public static ActorManipulationMode actorManipulationMode = ActorManipulationMode.Pan;
public static int animationClipWindowSize = 600;
public static int StageWindowSize
{
get
{
if (animationDef == null)
{ return -1; }
if (animationDef.animationStages[stageID].stageWindowSize < 0)
{ return animationDef.animationStages[stageID].animationClips.Select(x => x.duration).Max(); }
return animationDef.animationStages[stageID].stageWindowSize;
}
}
public PawnKeyframe GetCurrentPawnKeyframe(bool makeNewIfNull = true)
{