using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; namespace RimWorldAnimationStudio { public class AnimationTimeline : MonoBehaviour, IPointerClickHandler { public int actorID = -1; public KeyframeSlider keyframeSliderPrefab; private Transform anchorTransform; private void Start() { EventsManager.onAnimationTimelinesChanged.AddListener(delegate { UpdateGUI(); }); EventsManager.onKeyframeCountChanged.AddListener(delegate { UpdateGUI(); }); EventsManager.onActorIDChanged.AddListener(delegate { UpdateTimelineSelection(); }); EventsManager.onStageWindowSizeChanged.AddListener(delegate { UpdateGUI(); }); EventsManager.onAnimationStageChanged.AddListener(delegate { UpdateGUI(); }); UpdateTimelineSelection(); UpdateGUI(); } public void Initialize(int actorID) { anchorTransform = transform.parent; this.actorID = actorID; UpdateGUI(); } public void ClearKeyframeSliders() { foreach (KeyframeSlider slider in GetComponentsInChildren()) { Destroy(slider.gameObject); } } public void UpdateGUI() { if (actorID < 0) return; PawnAnimationClip clip = Workspace.GetPawnAnimationClip(actorID); if (clip == null) return; clip.BuildSimpleCurves(); ClearKeyframeSliders(); foreach (PawnKeyframe keyframe in clip.Keyframes) { AddPawnKeyFrame(keyframe.keyframeID); } InitiateUpdateOfGhostFrames(); } public void UpdateTimelineSelection() { GetComponent().color = (Workspace.ActorID == actorID ? Constants.ColorGoldYellow : Constants.ColorMidGrey); } public void AddPawnKeyFrame(int keyframeID) { KeyframeSlider keyframeSlider = Instantiate(keyframeSliderPrefab, transform); keyframeSlider.Initialize(this, actorID, keyframeID); } public void RemovePawnKeyFrame(int keyframeID) { KeyframeSlider keyframeSlider = GetComponentsInChildren().FirstOrDefault(x => x.keyframeID == keyframeID); Destroy(keyframeSlider?.gameObject); } public void InitiateUpdateOfGhostFrames() { BroadcastMessage("UpdateGhostFrames"); } public void OnMoveTimeline(int delta) { int? siblingIndex = anchorTransform.parent.GetComponentsInChildren()?.ToList()?.IndexOf(this); int? siblingCount = anchorTransform.parent.GetComponentsInChildren()?.ToList()?.Count(); if (siblingIndex != null && siblingCount != null && MoveAnimationTimeline(siblingIndex.Value, delta)) { AnimationController.Instance.Initialize(); } } public bool MoveAnimationTimeline(int startIndex, int delta) { if (startIndex + delta < 0 || startIndex + delta >= Workspace.GetCurrentAnimationStage().AnimationClips.Count) { Debug.Log("Cannot move animation timeline - movement would exceed bounds"); return false; } Actor actor = Workspace.animationDef.Actors[startIndex]; Workspace.animationDef.Actors[startIndex] = Workspace.animationDef.Actors[startIndex + delta]; Workspace.animationDef.Actors[startIndex + delta] = actor; foreach (AnimationStage stage in Workspace.animationDef.animationStages) { int stageID = stage.GetStageID(); PawnAnimationClip clip = Workspace.GetPawnAnimationClip(stageID, startIndex); Workspace.GetAnimationStage(stageID).AnimationClips[startIndex] = Workspace.GetAnimationStage(stageID).AnimationClips[startIndex + delta]; Workspace.GetAnimationStage(stageID).AnimationClips[startIndex + delta] = clip; } Workspace.ActorID = startIndex + delta; Workspace.RecordEvent("Timeline move"); return true; } public void OnPointerClick(PointerEventData eventData) { Workspace.ActorID = actorID; Workspace.keyframeID.Clear(); } } }