mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
2989d9a72c
- Insert adds a new keyframe to the selected timeline - New stages have frames cloned from the last frame of current stage - Existing key are now replaced when another key is dropped on them - Fixed bug where starting a new animation could result in errors
136 lines
5.9 KiB
C#
136 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
using System.Xml.Serialization;
|
|
using UnityEngine;
|
|
|
|
namespace RimWorldAnimationStudio
|
|
{
|
|
public class PawnAnimationClip : AnimationClip
|
|
{
|
|
[XmlAttribute("Class")] public string className = "Rimworld_Animations.PawnAnimationClip";
|
|
[XmlArray("keyframes"), XmlArrayItem("li")] public List<PawnKeyframe> keyframes = new List<PawnKeyframe>();
|
|
|
|
[XmlIgnore] public Dictionary<int, bool> quiver = new Dictionary<int, bool>();
|
|
[XmlIgnore] public SimpleCurve GenitalAngle = new SimpleCurve();
|
|
[XmlIgnore] public SimpleCurve BodyAngle = new SimpleCurve();
|
|
[XmlIgnore] public SimpleCurve HeadAngle = new SimpleCurve();
|
|
[XmlIgnore] public SimpleCurve HeadBob = new SimpleCurve();
|
|
[XmlIgnore] public SimpleCurve BodyOffsetX = new SimpleCurve();
|
|
[XmlIgnore] public SimpleCurve BodyOffsetZ = new SimpleCurve();
|
|
[XmlIgnore] public SimpleCurve HeadFacing = new SimpleCurve();
|
|
[XmlIgnore] public SimpleCurve BodyFacing = new SimpleCurve();
|
|
|
|
public override int duration { get { return keyframes.Max(x => x.atTick.Value); } }
|
|
|
|
public override void BuildSimpleCurves()
|
|
{
|
|
BodyAngle.Clear();
|
|
HeadAngle.Clear();
|
|
BodyOffsetX.Clear();
|
|
BodyOffsetZ.Clear();
|
|
HeadFacing.Clear();
|
|
BodyFacing.Clear();
|
|
HeadBob.Clear();
|
|
GenitalAngle.Clear();
|
|
|
|
int keyframePosition = 0;
|
|
int duration = 0;
|
|
|
|
keyframes[keyframes.Count - 1].tickDuration = 1;
|
|
|
|
foreach (PawnKeyframe frame in keyframes)
|
|
{ duration += frame.tickDuration; }
|
|
|
|
for (int i = 0; i < keyframes.Count; i++)
|
|
{
|
|
PawnKeyframe keyframe = keyframes[i];
|
|
|
|
if (keyframe.atTick.HasValue)
|
|
{
|
|
if (keyframe.HasValidKeyframeID() == false)
|
|
{ keyframe.GenerateKeyframeID(Workspace.animationDef.animationStages[Workspace.stageID].animationClips.IndexOf(this)); }
|
|
|
|
BodyAngle.Add((float)keyframe.atTick / (float)duration, keyframe.bodyAngle, true);
|
|
HeadAngle.Add((float)keyframe.atTick / (float)duration, keyframe.headAngle, true);
|
|
BodyOffsetX.Add((float)keyframe.atTick / (float)duration, keyframe.bodyOffsetX, true);
|
|
BodyOffsetZ.Add((float)keyframe.atTick / (float)duration, keyframe.bodyOffsetZ, true);
|
|
HeadFacing.Add((float)keyframe.atTick / (float)duration, keyframe.headFacing, true);
|
|
BodyFacing.Add((float)keyframe.atTick / (float)duration, keyframe.bodyFacing, true);
|
|
HeadBob.Add((float)keyframe.atTick / (float)duration, keyframe.headBob, true);
|
|
GenitalAngle.Add((float)keyframe.atTick / (float)duration, keyframe.genitalAngle, true);
|
|
|
|
if (i + 1 < keyframes.Count)
|
|
{ keyframes[i].tickDuration = keyframes[i + 1].atTick.Value - keyframes[i].atTick.Value; }
|
|
}
|
|
|
|
else
|
|
{
|
|
BodyAngle.Add((float)keyframePosition / (float)duration, keyframe.bodyAngle, true);
|
|
HeadAngle.Add((float)keyframePosition / (float)duration, keyframe.headAngle, true);
|
|
BodyOffsetX.Add((float)keyframePosition / (float)duration, keyframe.bodyOffsetX, true);
|
|
BodyOffsetZ.Add((float)keyframePosition / (float)duration, keyframe.bodyOffsetZ, true);
|
|
HeadFacing.Add((float)keyframePosition / (float)duration, keyframe.headFacing, true);
|
|
BodyFacing.Add((float)keyframePosition / (float)duration, keyframe.bodyFacing, true);
|
|
HeadBob.Add((float)keyframePosition / (float)duration, keyframe.headBob, true);
|
|
GenitalAngle.Add((float)keyframePosition / (float)duration, keyframe.genitalAngle, true);
|
|
|
|
if (keyframe.tickDuration != 1 && keyframe.quiver.HasValue)
|
|
{
|
|
quiver.Add(keyframePosition, true);
|
|
quiver.Add(keyframePosition + keyframe.tickDuration - 1, false);
|
|
}
|
|
|
|
keyframe.atTick = keyframePosition + Constants.minTick;
|
|
keyframePosition += keyframe.tickDuration;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void ValidateData() { }
|
|
|
|
public int GetOwningActorID()
|
|
{
|
|
if (Workspace.animationDef == null) return -1;
|
|
|
|
return Workspace.animationDef.animationStages[Workspace.stageID].animationClips.IndexOf(this);
|
|
}
|
|
|
|
public bool MakeNew(int actorID = -1)
|
|
{
|
|
PawnKeyframe lastkeyframe = null;
|
|
|
|
if (actorID >= 0)
|
|
{ lastkeyframe = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[actorID]?.keyframes?.Last(); }
|
|
|
|
if (lastkeyframe != null)
|
|
{
|
|
PawnKeyframe keyframeA = lastkeyframe.Copy();
|
|
keyframeA.atTick = null;
|
|
keyframeA.tickDuration = Constants.defaultAnimationClipLength - 1;
|
|
keyframeA.GenerateKeyframeID(actorID);
|
|
keyframes.Add(keyframeA);
|
|
|
|
PawnKeyframe keyframeB = lastkeyframe.Copy();
|
|
keyframeB.atTick = null;
|
|
keyframeB.tickDuration = 1;
|
|
keyframeB.GenerateKeyframeID(actorID);
|
|
keyframes.Add(keyframeB);
|
|
}
|
|
|
|
else
|
|
{
|
|
PawnKeyframe keyframeA = new PawnKeyframe();
|
|
keyframeA.tickDuration = Constants.defaultAnimationClipLength - 1;
|
|
keyframes.Add(keyframeA);
|
|
|
|
PawnKeyframe keyframeB = new PawnKeyframe();
|
|
keyframes.Add(keyframeB);
|
|
}
|
|
|
|
BuildSimpleCurves();
|
|
return true;
|
|
}
|
|
}
|
|
}
|