using System; using System.Collections.Generic; using System.Linq; using System.Xml; using System.Xml.Serialization; using UnityEngine; using UnityEngine.UI; namespace RimWorldAnimationStudio { public class PawnKeyframe { // Data to/from animationDef public float? bodyAngle; public float? headAngle; public float? headBob; public float? bodyOffsetX; public float? bodyOffsetZ; public int? headFacing; public int? bodyFacing; public float? genitalAngle; public bool? quiver; public int? tickDuration; public string soundEffect; public List tags; [XmlArray("addonKeyframes"), XmlArrayItem("li")] public List addonKeyframes; // Data serialization control public bool ShouldSerializebodyAngle() { return bodyAngle.HasValue && bodyAngle.Value != 0f; } public bool ShouldSerializeheadAngle() { return headAngle.HasValue && headAngle.Value != 0f; } public bool ShouldSerializeheadBob() { return headBob.HasValue && headBob.Value != 0f; } public bool ShouldSerializebodyOffsetX() { return bodyOffsetX.HasValue && bodyOffsetX.Value != 0f; } public bool ShouldSerializebodyOffsetZ() { return bodyOffsetZ.HasValue && bodyOffsetZ.Value != 0f; } public bool ShouldSerializegenitalAngle() { return genitalAngle.HasValue && genitalAngle.Value != 0f; } public bool ShouldSerializequiver() { return quiver == true; } public bool ShouldSerializetags() { return tags.NotNullOrEmpty(); } public bool ShouldSerializeaddonKeyframes() { return addonKeyframes.NotNullOrEmpty(); } // Data helper functions [XmlIgnore] public float BodyAngle { get { return bodyAngle.HasValue ? bodyAngle.Value : 0f; } set { bodyAngle = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public float HeadAngle { get { return headAngle.HasValue ? headAngle.Value : (float)(headAngle = 0f); } set { headAngle = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public float HeadBob { get { return headBob.HasValue ? headBob.Value : (float)(headBob = 0f); } set { headBob = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public float BodyOffsetX { get { return bodyOffsetX.HasValue ? bodyOffsetX.Value : (float)(bodyOffsetX = 0f); } set { bodyOffsetX = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public float BodyOffsetZ { get { return bodyOffsetZ.HasValue ? bodyOffsetZ.Value : (float)(bodyOffsetZ = 0f); } set { bodyOffsetZ = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public int HeadFacing { get { return headFacing.HasValue ? headFacing.Value : (int)(headFacing = 2); } set { headFacing = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public int BodyFacing { get { return bodyFacing.HasValue ? bodyFacing.Value : (int)(bodyFacing = 2); } set { bodyFacing = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public float GenitalAngle { get { return genitalAngle.HasValue ? genitalAngle.Value : (float)(genitalAngle = 0f); } set { genitalAngle = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public bool Quiver { get { return quiver == true; } set { quiver = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public int TickDuration { get { return tickDuration.HasValue ? tickDuration.Value : (int)(tickDuration = 0); } set { tickDuration = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public string SoundEffect { get { return soundEffect; } set { soundEffect = value; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public List Tags { get { return tags.NullOrEmpty() ? tags = new List() : tags; } set { tags = value.NotNullOrEmpty() ? value : null; EventsManager.OnPawnKeyframeChanged(this); } } [XmlIgnore] public List AddonKeyframes { get { return addonKeyframes.NullOrEmpty() ? addonKeyframes = new List() : addonKeyframes; } set { addonKeyframes = value.NotNullOrEmpty()? value : null; EventsManager.OnPawnKeyframeChanged(this); } } // Local data [XmlIgnore] public int keyframeID; [XmlIgnore] public int actorID = -1; [XmlIgnore] public int? atTick; // Methods public void GenerateKeyframeID(int actorID) { this.actorID = actorID; int _keyframeID = UnityEngine.Random.Range(100000, 1000000); if (Workspace.animationDef.AnimationStages.Any(x => x.AnimationClips.Any(y => y.Keyframes.Any(z => z.keyframeID == _keyframeID)))) { GenerateKeyframeID(actorID); return; } keyframeID = _keyframeID; } public bool HasValidKeyframeID() { return keyframeID >= 100000 && keyframeID < 1000000; } public KeyframeSlider GetKeyframeSlider() { return Selectable.allSelectablesArray.FirstOrDefault(x => x.GetComponent()?.keyframeID == keyframeID)?.GetComponent< KeyframeSlider>(); } public AddonKeyframe GetAddonKeyframe(string addonName) { return AddonKeyframes.FirstOrDefault(x => x.AddonName == addonName); } // Pre-save / post-load public void OnPreSave() { SoundEffect = DefaultTags.soundDefs.Concat(CustomTags.soundDefs).Contains(SoundEffect) ? SoundEffect : null; addonKeyframes.Clear(); foreach (AddonKeyframe addonKeyframe in AddonKeyframes) { ActorAddon addon = Workspace.GetAnimationClipThatOwnsKeyframe(keyframeID, out int clipID).GetActorAddon(addonKeyframe.AddonName); if (addon.Render) { addonKeyframes.Add(addonKeyframe.Copy()); } } } public void OnPostLoad() { AddonKeyframes.Clear(); foreach (AddonKeyframe addonKeyframe in addonKeyframes) { AddonKeyframes.Add(addonKeyframe.Copy()); } } } }