diff --git a/1.4/Source/Animations/AnimationStage.cs b/1.4/Source/Animations/AnimationStage.cs index 7a1304e..6f0f709 100644 --- a/1.4/Source/Animations/AnimationStage.cs +++ b/1.4/Source/Animations/AnimationStage.cs @@ -15,14 +15,17 @@ namespace Rimworld_Animations { public List animationClips; public List tags = new List(); - public void initialize() { - foreach (BaseAnimationClip clip in animationClips) { - clip.buildSimpleCurves(); + public int Initialize(List isGenitalAngleMandatory) { + var brokenClips = 0; + for (var i = 0; i < animationClips.Count; ++i) { + var clip = animationClips[i]; + if (clip.BuildSimpleCurves(isGenitalAngleMandatory[i])) + ++brokenClips; //select playTimeTicks as longest playtime of all the animations - if(clip.duration > playTimeTicks) { - playTimeTicks = clip.duration; - } + if (clip.duration > playTimeTicks) + playTimeTicks = clip.duration; } + return brokenClips; } } } diff --git a/1.4/Source/Animations/Clips/BaseAnimationClip.cs b/1.4/Source/Animations/Clips/BaseAnimationClip.cs index aa35b31..119fbf3 100644 --- a/1.4/Source/Animations/Clips/BaseAnimationClip.cs +++ b/1.4/Source/Animations/Clips/BaseAnimationClip.cs @@ -12,9 +12,18 @@ namespace Rimworld_Animations { public Dictionary SoundEffects = new Dictionary(); public List types; //types of participants public int duration; - public abstract void buildSimpleCurves(); + /** failure - if 'true', this clip should not be used */ + public abstract bool BuildSimpleCurves(bool isGenitalAngleMandatory = false); public string soundDef = null; //for playing sounds public int actor; public List tags = new List(); + + protected bool EmitMandatoryCurveEmptyError(SimpleCurve curve, string name) { + if (curve.PointsCount <= 0) { + Log.Error($"Mandatory curve '{name}' is empty in an animation clip!"); + return true; + } + return false; + } } } diff --git a/1.4/Source/Animations/Clips/PawnAnimationClip.cs b/1.4/Source/Animations/Clips/PawnAnimationClip.cs index e9d2489..e4e2f67 100644 --- a/1.4/Source/Animations/Clips/PawnAnimationClip.cs +++ b/1.4/Source/Animations/Clips/PawnAnimationClip.cs @@ -21,9 +21,9 @@ namespace Rimworld_Animations { public SimpleCurve BodyOffsetZ = new SimpleCurve(); public SimpleCurve HeadFacing = new SimpleCurve(); public SimpleCurve BodyFacing = new SimpleCurve(); - - public override void buildSimpleCurves() { + + public override bool BuildSimpleCurves(bool isGenitalAngleMandatory) { int duration = 0; @@ -109,7 +109,18 @@ namespace Rimworld_Animations { } + // check whether all mandatory curves have been filled + bool invalid = false; + invalid |= this.EmitMandatoryCurveEmptyError(this.BodyOffsetX, "BodyOffsetX"); + invalid |= this.EmitMandatoryCurveEmptyError(this.BodyOffsetZ, "BodyOffsetZ"); + invalid |= this.EmitMandatoryCurveEmptyError(this.BodyAngle, "BodyAngle"); + invalid |= this.EmitMandatoryCurveEmptyError(this.HeadAngle, "HeadAngle"); + if (isGenitalAngleMandatory) + invalid |= this.EmitMandatoryCurveEmptyError(this.GenitalAngle, "GenitalAngle"); + invalid |= this.EmitMandatoryCurveEmptyError(this.BodyFacing, "BodyFacing"); + invalid |= this.EmitMandatoryCurveEmptyError(this.HeadFacing, "HeadFacing"); + invalid |= this.EmitMandatoryCurveEmptyError(this.HeadBob, "HeadBob"); + return invalid; } - } } diff --git a/1.4/Source/Animations/Clips/ThingAnimationClip.cs b/1.4/Source/Animations/Clips/ThingAnimationClip.cs index 26f4d4c..c3661de 100644 --- a/1.4/Source/Animations/Clips/ThingAnimationClip.cs +++ b/1.4/Source/Animations/Clips/ThingAnimationClip.cs @@ -16,7 +16,7 @@ namespace Rimworld_Animations { public SimpleCurve Rotation = new SimpleCurve(); - public override void buildSimpleCurves() { + public override bool BuildSimpleCurves(bool unused = false) { int duration = 0; //getting the length of the whole clip foreach (ThingKeyframe frame in keyframes) @@ -69,6 +69,13 @@ namespace Rimworld_Animations { } } + + // check whether all mandatory curves have been filled + bool invalid = false; + invalid |= this.EmitMandatoryCurveEmptyError(this.PositionX, "PositionX"); + invalid |= this.EmitMandatoryCurveEmptyError(this.PositionZ, "PositionZ"); + invalid |= this.EmitMandatoryCurveEmptyError(this.Rotation, "Rotation"); + return invalid; } } } diff --git a/1.4/Source/Defs/AnimationDef.cs b/1.4/Source/Defs/AnimationDef.cs index 395ff83..2b13680 100644 --- a/1.4/Source/Defs/AnimationDef.cs +++ b/1.4/Source/Defs/AnimationDef.cs @@ -19,8 +19,12 @@ namespace Rimworld_Animations { public override void PostLoad() { base.PostLoad(); + // FIXME: I could not figure out how to map between controlGenitalAngle and PawnAnimationClip. This is brittle AF! -Zsar 2023-04-16 + var controlGenitalAngle = this.actors.ConvertAll(actor => actor.controlGenitalAngle); foreach(AnimationStage stage in animationStages) { - stage.initialize(); + var brokenClips = stage.Initialize(controlGenitalAngle); + if (brokenClips > 0) + throw new Exception($"AnimationDef '{this.defName}', stage '{stage.stageName}' contained {brokenClips} broken Clips. The animation has been dropped."); animationTimeTicks += stage.playTimeTicks; } }