Stage and anim lengths display

This commit is contained in:
AbstractConcept 2022-10-14 14:00:57 -05:00
parent ab5a2a4c02
commit cc28ac4bd4
174 changed files with 604 additions and 245 deletions

View file

@ -16,7 +16,9 @@ namespace RimWorldAnimationStudio
[XmlArray("interactionDefTypes"), XmlArrayItem("li")] public List<string> interactionDefTypes = new List<string>();
[XmlArray("actors"), XmlArrayItem("li")] public List<Actor> actors = new List<Actor>();
[XmlArray("animationStages"), XmlArrayItem("li")] public List<AnimationStage> animationStages = new List<AnimationStage>();
[XmlIgnore] public int animationTimeTicks = 0;
[XmlIgnore] public int animationTimeTicks { get { return animationStages.Sum(x => x.playTimeTicks); } }
[XmlIgnore] public int animationTimeTicksQuick { get { return animationStages.Sum(x => x.playTimeTicksQuick); } }
public bool ShouldSerializesexTypes() { return sexTypes.NotNullOrEmpty(); }
public bool ShouldSerializeinteractionDefTypes() { return interactionDefTypes.NotNullOrEmpty(); }
@ -25,13 +27,8 @@ namespace RimWorldAnimationStudio
public void Initialize()
{
animationTimeTicks = 0;
foreach (AnimationStage stage in animationStages)
{
stage.Initialize();
animationTimeTicks += stage.playTimeTicks;
}
{ stage.Initialize(); }
}
public void ValidateData()

View file

@ -11,7 +11,7 @@ namespace RimWorldAnimationStudio
public string stageName = "NewStage";
public int stageIndex = 0;
public int playTimeTicks = 0;
public int playTimeTicksQuick = -1;
public int playTimeTicksQuick = 0;
public bool isLooping = false;
[XmlArray("animationClips"), XmlArrayItem("li")] public List<PawnAnimationClip> animationClips = new List<PawnAnimationClip>();
@ -50,7 +50,7 @@ namespace RimWorldAnimationStudio
}
Initialize();
playTimeTicksQuick = playTimeTicks;
Workspace.animationDef.animationStages.Add(this);
return true;

View file

@ -21,14 +21,10 @@ namespace RimWorldAnimationStudio
anchorTransform = transform.parent;
this.actorID = actorID;
Reset();
PawnAnimationClip clip = Workspace.Instance.GetPawnAnimationClip(actorID);
if (clip == null || clip.keyframes.NullOrEmpty())
{
//Debug.Log("Clip was empty");
clip = new PawnAnimationClip();
clip.keyframes.Add(new PawnKeyframe());
clip.BuildSimpleCurves();
@ -39,12 +35,27 @@ namespace RimWorldAnimationStudio
KeyframeSlider keyframeSlider = Instantiate(keyframeSliderPrefab, transform);
keyframeSlider.Initialize(this, actorID, keyframe.keyframeID);
}
}
public void Reset()
{
foreach(KeyframeSlider keyframeSlider in GetComponentsInChildren<KeyframeSlider>())
{ Destroy(keyframeSlider.gameObject); }
int keyframeCount = clip.keyframes.Count;
int childCount = GetComponentsInChildren<KeyframeSlider>().Count();
for (int i = 0; i < Mathf.Max(keyframeCount, childCount); i++)
{
// Add new keyframe sliders as required
if (i >= childCount)
{ Instantiate(keyframeSliderPrefab, transform); }
// Get objects to update
KeyframeSlider keyframeSlider = GetComponentsInChildren<KeyframeSlider>()[i];
// Update values
if (i < keyframeCount)
{ keyframeSlider.Initialize(this, actorID, clip.keyframes[i].keyframeID); }
// Remove excess objects as required
else
{ Destroy(keyframeSlider.gameObject); }
}
}
public void AddPawnKeyFrame(int keyframeID)
@ -70,6 +81,8 @@ namespace RimWorldAnimationStudio
public void InitiateUpdateOfGhostFrames()
{
if (AnimationController.Instance.IsTimelineDirty()) return;
BroadcastMessage("UpdateGhostFrames");
}
@ -79,12 +92,7 @@ namespace RimWorldAnimationStudio
int? siblingCount = anchorTransform.parent.GetComponentsInChildren<AnimationTimeline>()?.ToList()?.Count();
if (siblingIndex != null && siblingCount != null && MoveAnimationTimeline(siblingIndex.Value, delta))
{
//siblingIndex = Mathf.Clamp(siblingCount.Value + delta, 0, siblingCount.Value - 1);
//transform.SetSiblingIndex(transform.GetSiblingIndex() + delta);
AnimationController.Instance.ResetAnimationTimeline();
AnimationController.Instance.InitializeAnimationTimeline();
}
{ AnimationController.Instance.InitializeAnimationTimeline(); }
}
public bool MoveAnimationTimeline(int startIndex, int delta)

View file

@ -187,11 +187,7 @@ namespace RimWorldAnimationStudio
{ linkedSlider = null; }
else if (AnimationController.Instance.stretchKeyframesToggle.isOn && linkedSlider != null && linkedSlider.IsPivotKeyframe(keyframe) == false)
{
//int minTick = linkedSlider.pivotKeyframe.atTick.Value + GetIndexAmongstSelectedKeyframes();
//value = Mathf.Clamp(Mathf.CeilToInt(linkedSlider.keyframe.atTick.Value + linkedOffset * linkedSlider.ScaledOffsetFromPivot()), minTick, Workspace.StageWindowSize);
value = Mathf.CeilToInt(linkedSlider.keyframe.atTick.Value + linkedOffset * linkedSlider.ScaledOffsetFromPivot());
}
{ value = Mathf.CeilToInt(linkedSlider.keyframe.atTick.Value + linkedOffset * linkedSlider.ScaledOffsetFromPivot()); }
else if (AnimationController.Instance.stretchKeyframesToggle.isOn == false && linkedSlider != null)
{ value = Mathf.Clamp(linkedSlider.keyframe.atTick.Value + linkedOffset, Constants.minTick + 1, Workspace.StageWindowSize); }
@ -219,7 +215,6 @@ namespace RimWorldAnimationStudio
public float ScaledOffsetFromPivot()
{
//if (IsPivotKeyframe(keyframe)) return 1f;
if (dragTickStart == pivotKeyframe.atTick.Value) return 0f;
return (float)(keyframe.atTick.Value - pivotKeyframe.atTick.Value) / (dragTickStart - pivotKeyframe.atTick.Value);
@ -229,13 +224,5 @@ namespace RimWorldAnimationStudio
{
return pivotKeyframe == otherKeyframe;
}
public int GetIndexAmongstSelectedKeyframes()
{
List<PawnKeyframe> selectedKeyframes = Workspace.Instance.GetPawnKeyframes(Workspace.keyframeID).OrderBy(x => x.atTick)?.ToList();
if (selectedKeyframes.NullOrEmpty() || selectedKeyframes.Contains(keyframe) == false) return -1;
return selectedKeyframes.IndexOf(keyframe);
}
}
}

View file

@ -28,6 +28,8 @@ namespace RimWorldAnimationStudio
public Toggle stretchKeyframesToggle;
public InputField playBackSpeedField;
public Button playToggleButton;
public Text stageLengthText;
public Text animationLengthText;
[Header("Prefabs")]
public ActorBody actorBodyPrefab;
@ -47,6 +49,12 @@ namespace RimWorldAnimationStudio
public void MakeTimelineDirty()
{ isTimelineDirty = true; }
public bool IsDirty()
{ return isDirty; }
public bool IsTimelineDirty()
{ return isTimelineDirty; }
public void Update()
{
// No animation, exit
@ -56,6 +64,25 @@ namespace RimWorldAnimationStudio
if (Workspace.animationDef != null && isDirty)
{ Initialize(); }
// Update animation lengths
if (stageLoopDropdown.value == 3)
{
stageLengthText.text = "Stage length (quickie): " + Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicksQuick + " (" + Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicksQuick / 60f + " s)";
animationLengthText.text = "Animation length (quickie): " + Workspace.animationDef.animationTimeTicksQuick + " (" + Workspace.animationDef.animationTimeTicksQuick / 60f + " s)";
LayoutRebuilder.ForceRebuildLayoutImmediate(stageLengthText.GetComponent<RectTransform>());
LayoutRebuilder.ForceRebuildLayoutImmediate(animationLengthText.GetComponent<RectTransform>());
}
else
{
stageLengthText.text = "Stage length (normal): " + Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicks + " (" + Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicks / 60f + " s)";
animationLengthText.text = "Animation length (normal): " + Workspace.animationDef.animationTimeTicks + " (" + Workspace.animationDef.animationTimeTicks / 60f + " s)";
LayoutRebuilder.ForceRebuildLayoutImmediate(stageLengthText.GetComponent<RectTransform>());
LayoutRebuilder.ForceRebuildLayoutImmediate(animationLengthText.GetComponent<RectTransform>());
}
// Update tick if animating
stageTick = Mathf.Clamp(stageTick, Constants.minTick, Workspace.StageWindowSize);
@ -123,10 +150,7 @@ namespace RimWorldAnimationStudio
public void UpdateAnimation()
{
if (AnimationTimelinesNeedUpdate())
{
ResetAnimationTimeline();
InitializeAnimationTimeline();
}
{ InitializeAnimationTimeline(); }
List<ActorBody> _actorBodies = actorBodies.GetComponentsInChildren<ActorBody>().ToList();
@ -217,59 +241,73 @@ namespace RimWorldAnimationStudio
public void Initialize()
{
isDirty = true;
Debug.Log("Initializing animation preview");
foreach (Transform child in transform)
{ child.gameObject.SetActive(true); }
Reset();
InitializeAnimationTimeline();
StageCardManager.Instance.Initialize();
isDirty = false;
}
public void Reset()
{
Workspace.stageID = 0;
isAnimating = false;
timeSinceLastUpdate = 0;
cycleIndex = 0;
}
public void InitializeAnimationTimeline()
{
isTimelineDirty = true;
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), 0).ToString();
Workspace.animationDef.animationStages[Workspace.stageID].isLooping = int.Parse(cyclesNormalField.text) > 1 ? true : false;
for (int actorID = 0; actorID < Workspace.animationDef.actors.Count; actorID++)
{
ActorBody actorBody = Instantiate(actorBodyPrefab, actorBodies.transform);
actorBody.Initialize(actorID);
int actorCount = Workspace.animationDef.actors.Count;
int childCount = animationTimelines.GetComponentsInChildren<AnimationTimeline>().Count();
AnimationTimeline animationTimeline = Instantiate(animationTimelinePrefab, animationTimelines).GetComponentInChildren<AnimationTimeline>();
animationTimeline.Initialize(actorID);
for (int actorID = 0; actorID < Mathf.Max(actorCount, childCount); actorID++)
{
// Add new actors as required
if (actorID >= childCount)
{
Instantiate(animationTimelinePrefab, animationTimelines);
Instantiate(actorBodyPrefab, actorBodies.transform);
}
// Get objects to update
AnimationTimeline animationTimeline = animationTimelines.GetComponentsInChildren<AnimationTimeline>()[actorID];
ActorBody actorBody = actorBodies.GetComponentsInChildren<ActorBody>()[actorID];
// Update values
if (actorID < actorCount)
{
animationTimeline.Initialize(actorID);
actorBody.Initialize(actorID);
}
// Remove excess objects as required
else
{
Destroy(animationTimeline.transform.parent.gameObject);
Destroy(actorBody.gameObject);
}
}
animationClipLengthField.text = Workspace.StageWindowSize.ToString();
stageTimelineSlider.maxValue = Workspace.StageWindowSize;
isTimelineDirty = false;
}
public void Reset()
{
Workspace.stageID = 0;
isAnimating = false;
ResetAnimationTimeline();
StageCardManager.Instance.Reset();
}
public void ResetAnimationTimeline()
{
timeSinceLastUpdate = 0;
cycleIndex = 0;
foreach (ActorBody actorBody in actorBodies.GetComponentsInChildren<ActorBody>())
{ Destroy(actorBody.gameObject); }
foreach (AnimationTimeline animationTimeline in animationTimelines.GetComponentsInChildren<AnimationTimeline>())
{ Destroy(animationTimeline.transform.parent.gameObject); }
foreach (AnimationTimeline timeline in animationTimelines.GetComponentsInChildren<AnimationTimeline>())
{ timeline.InitiateUpdateOfGhostFrames(); }
}
public void AddActor()
@ -436,41 +474,6 @@ namespace RimWorldAnimationStudio
Workspace.Instance.RecordEvent("Keyframe pasted");
}
/*public void PastePawnKeyframes()
{
foreach (PawnKeyframe keyframe in Workspace.copiedKeyframes)
{
PawnAnimationClip clip = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[keyframe.actorID];
if (Workspace.Instance.DoesPawnKeyframeExistAtTick(Workspace.stageID, keyframe.actorID, stageTick))
{
PawnKeyframe oldKeyframe = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[keyframe.actorID].keyframes.First(x => x.atTick == stageTick);
RemovePawnKeyframe(keyframe.actorID, oldKeyframe.keyframeID, true);
}
keyframe.GenerateKeyframeID(keyframe.actorID);
keyframe.atTick = stageTick;
PawnKeyframe nextKeyframe = clip.keyframes.FirstOrDefault(x => x.atTick > stageTick);
if (nextKeyframe != null)
{ clip.keyframes.Insert(clip.keyframes.IndexOf(nextKeyframe), keyframe); }
else
{ clip.keyframes.Add(keyframe); }
clip.BuildSimpleCurves();
animationTimelines.GetComponentsInChildren<AnimationTimeline>()[keyframe.actorID].AddPawnKeyFrame(keyframe.keyframeID);
clip.BuildSimpleCurves();
}
Workspace.Instance.RecordEvent("Keyframe pasted");
}*/
public void RemovePawnKeyframe()
{
foreach (int keyframeID in Workspace.keyframeID)
@ -541,10 +544,7 @@ namespace RimWorldAnimationStudio
Debug.Log("Resizing animation clip length to " + newStageWindowSize.ToString() + " ticks.");
if (stretchKeyframesToggle.isOn)
{
List<PawnKeyframe> keyframes = Workspace.animationDef.animationStages[Workspace.stageID].animationClips.SelectMany(x => x.keyframes)?.ToList();
StretchKeyframes(keyframes, Workspace.StageWindowSize, newStageWindowSize);
}
{ StretchKeyframes(newStageWindowSize); }
else
{
@ -569,7 +569,7 @@ namespace RimWorldAnimationStudio
ResizeStageWindowSize(newStageWindowSize);
}
/*public void StretchKeyframes(int newStageWindowSize)
public void StretchKeyframes(int newStageWindowSize)
{
float scale = (float)newStageWindowSize / Workspace.StageWindowSize;
@ -583,39 +583,6 @@ namespace RimWorldAnimationStudio
clip.BuildSimpleCurves();
}
}*/
public void StretchKeyframes(List<PawnKeyframe> keyframesToStretch, int v1, int v2)
{
int v0 = keyframesToStretch.Min(x => x.atTick.Value);
if (v1 == v0)
{ OffsetKeyframes(keyframesToStretch, v1, v2); return; }
float scaleFactor = (float)(v2 - v0) / (v1 - v0);
foreach (PawnKeyframe keyframe in keyframesToStretch)
{
keyframe.atTick = Mathf.RoundToInt(scaleFactor * (keyframe.atTick.Value - v0) + v0);
}
foreach(PawnAnimationClip clip in Workspace.animationDef.animationStages[Workspace.stageID].animationClips)
{ clip.BuildSimpleCurves(); }
}
public void OffsetKeyframes(List<PawnKeyframe> keyframesToOffset, int v1, int v2)
{
float offset = v2 - v1;
foreach (PawnKeyframe keyframe in keyframesToOffset)
{
keyframe.atTick = Mathf.RoundToInt(keyframe.atTick.Value + offset);
Debug.Log(keyframe.atTick);
Workspace.Instance.GetAnimationClipThatOwnsKeyframe(keyframe.keyframeID, out int clipID).BuildSimpleCurves();
}
foreach (PawnAnimationClip clip in Workspace.animationDef.animationStages[Workspace.stageID].animationClips)
{ clip.BuildSimpleCurves(); }
}
public void ResizeStageWindowSize(int newStageWindowSize)

View file

@ -78,7 +78,20 @@ namespace RimWorldAnimationStudio
public void RunPostLoadOperations(AnimationDef animationDef)
{
if (animationDef.animationTimeTicksQuick <= 0)
{
if (animationDef.animationStages.Count > 1)
{
for (int i = 0; i < animationDef.animationStages.Count; i++)
{
if (i == 0) continue;
animationDef.animationStages[i].playTimeTicksQuick = animationDef.animationStages[i].playTimeTicks;
}
}
else if (animationDef.animationStages.Count == 0)
{ animationDef.animationStages[0].playTimeTicksQuick = animationDef.animationStages[0].playTimeTicks; }
}
}
public void TryToSaveAnimation()

View file

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
@ -14,6 +15,27 @@ namespace RimWorldAnimationStudio
{
foreach(AnimationStage stage in Workspace.animationDef.animationStages)
{ MakeStageCard(stage.stageName); }
int stageCount = Workspace.animationDef.animationStages.Count;
int childCount = GetComponentsInChildren<StageCard>().Count();
for (int i = 0; i < Mathf.Max(stageCount, childCount); i++)
{
// Add new stage cards as required
if (i >= childCount)
{ Instantiate(stageCardPrefab, transform); }
// Get objects to update
StageCard stageCard = GetComponentsInChildren<StageCard>()[i];
// Update values
if (i < stageCount)
{ stageCard.Initialize(Workspace.animationDef.animationStages[i].stageName); }
// Remove excess objects as required
else
{ Destroy(stageCard.gameObject); }
}
}
public void Reset()
@ -41,7 +63,6 @@ namespace RimWorldAnimationStudio
public bool AddAnimationStage()
{
AnimationStage stage = new AnimationStage();
Workspace.Instance.RecordEvent("Stage addition");
return stage.MakeNew();

View file

@ -37,9 +37,6 @@ namespace RimWorldAnimationStudio
if (animationDef.animationStages[stageID].stageWindowSize < 0)
{ animationDef.animationStages[stageID].stageWindowSize = animationDef.animationStages[stageID].animationClips.Select(x => x.duration).Max(); }
Debug.Log(animationDef.animationStages[stageID].stageWindowSize);
return animationDef.animationStages[stageID].stageWindowSize;
}
}
@ -230,7 +227,6 @@ namespace RimWorldAnimationStudio
stageID = record.stageID;
AnimationController.Instance.MakeTimelineDirty();
StageCardManager.Instance.Reset();
StageCardManager.Instance.Initialize();
}