rimworld-animations/1.5/Source/Comps/CompExtendedAnimator.cs

225 lines
6.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using rjw;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
namespace Rimworld_Animations {
public class CompExtendedAnimator : ThingComp
{
// CompExtendedAnimator
// Helps manage AnimationQueue, AbsolutePosition
//ticks of current animation
private int animationTicks;
private List<AnimationDef> animationQueue;
private BaseExtendedAnimatorAnchor anchor;
private Vector3? offset;
private bool isAnimating = false;
public bool IsAnimating
{
get
{
return isAnimating;
}
}
public bool IsAnchored
{
get
{
return anchor != null;
}
}
public Vector3? Offset
{
get
{
return offset;
}
set
{
this.offset = value;
}
}
public int AnimationLength
{
get
{
if (!IsAnimating) return 0;
int groupAnimLength = 0;
foreach(AnimationDef anim in animationQueue)
{
groupAnimLength += anim.durationTicks;
}
return groupAnimLength;
}
}
public Vector3 getAnchor()
{
return anchor.getDrawPos();
}
public override void CompTick()
{
if (isAnimating)
{
animationTicks++;
//if animationticks is equal to cur. anim duration,
if (animationTicks >= animationQueue[0].durationTicks)
{
//dequeue; returns false if more animations
if (!PopAnimationQueue())
{
//play next if more anims still
PlayNextAnimation();
}
else
{
StopAnimating();
}
}
}
base.CompTick();
}
//returns false if still more animations
public bool PopAnimationQueue()
{
if (!animationQueue.Empty())
{
//pop queue
animationQueue.RemoveAt(0);
}
return animationQueue.Empty();
}
public void PlayNextAnimation()
{
if (!animationQueue.Empty())
{
isAnimating = true;
animationTicks = 0;
pawn.Drawer.renderer.SetAnimation(animationQueue[0]);
}
}
public void StopAnimating()
{
isAnimating = false;
animationQueue = null;
anchor = null;
offset = null;
pawn.Drawer.renderer.SetAnimation(null);
}
public void PlayGroupAnimation(List<AnimationDef> groupAnimation, Vector3? offset)
{
this.Offset = offset;
animationQueue = groupAnimation;
PlayNextAnimation();
}
public void PlayGroupAnimation(List<AnimationDef> groupAnimation, Vector3? offset, BaseExtendedAnimatorAnchor anchor)
{
this.anchor = anchor;
PlayGroupAnimation(groupAnimation, offset);
}
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Values.Look<bool>(ref this.isAnimating, "animations_isAnimating", false);
Scribe_Values.Look<int>(ref this.animationTicks, "animations_ticks", 0);
Scribe_Collections.Look<AnimationDef>(ref animationQueue, "animations_queue");
Scribe_Deep.Look<BaseExtendedAnimatorAnchor>(ref this.anchor, "animations_anchor");
}
public override List<PawnRenderNode> CompRenderNodes()
{
//only if pawn is animating for performance
if (IsAnimating)
{
List<PawnRenderNode> animRenderNodes = new List<PawnRenderNode>();
// for all animationpropdefs,
foreach (AnimationPropDef animationProp in DefDatabase<AnimationPropDef>.AllDefsListForReading)
{
//if animation makes use of prop,
if (AnimationMakesUseOfProp(animationProp))
{
PawnRenderNodeProperties props = animationProp.animPropProperties;
if (props.texPath.NullOrEmpty())
{
props.texPath = "AnimationProps/Banana/Banana";
}
//create new render node
PawnRenderNode animRenderNode = (PawnRenderNode)Activator.CreateInstance(props.nodeClass, new object[] {
this.pawn,
props,
pawn.Drawer.renderer.renderTree
});
animRenderNodes.Add(animRenderNode);
}
}
//return list of rendernodes that should animate
return animRenderNodes;
}
else
{
return null;
}
}
public bool AnimationMakesUseOfProp(AnimationPropDef animationProp)
{
// never true if not animating; anim props shouldn't be attached
if (!IsAnimating) return false;
//for ONLY THE CURRENT animation,
foreach (PawnRenderNodeTagDef propTag in animationQueue[0].animationParts.Keys)
{
// if that proptag is the same as the one for animationProp,
if (propTag == animationProp.animPropProperties.tagDef)
{
//that prop is being used in the animation
return true;
}
}
return false;
}
private Pawn pawn => base.parent as Pawn;
}
}