using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; namespace RimWorldAnimationStudio { public class Workspace : Singleton { public static AnimationDef animationDef; public static int stageID = 0; public static int keyframeID = 0; [SerializeField] private List workspaceHistory = new List(); [SerializeField] private int maxHistoryDepth = 100; public static ActorManipulationMode actorManipulationMode = ActorManipulationMode.Pan; public static ActorBodyPart selectedBodyPart; static int _actorID = 0; public static int actorID { get { return Mathf.Clamp(_actorID, 0, animationDef.actors.Count - 1); } set { _actorID = value; } } public static int StageWindowSize { get { if (animationDef == null) { return -1; } if (animationDef.animationStages[stageID].stageWindowSize < 0) { animationDef.animationStages[stageID].stageWindowSize = animationDef.animationStages[stageID].animationClips.Select(x => x.duration).Max(); } return animationDef.animationStages[stageID].stageWindowSize; } } public PawnKeyframe GetCurrentPawnKeyframe(bool makeKeyframe = false) { int stageTick = AnimationController.Instance.stageTick; PawnKeyframe keyframe = animationDef?.animationStages[stageID]?.animationClips[actorID]?.keyframes.FirstOrDefault(x => x.atTick == stageTick); if (keyframe != null || makeKeyframe == false) { return keyframe; } AnimationController.Instance.AddPawnKeyframe(); return animationDef?.animationStages[stageID]?.animationClips[actorID]?.keyframes.FirstOrDefault(x => x.atTick == stageTick); } public PawnAnimationClip GetCurrentPawnAnimationClip() { return animationDef.animationStages[stageID].animationClips[actorID]; } public PawnAnimationClip GetPawnAnimationClip(int actorID) { return animationDef.animationStages[stageID].animationClips[actorID]; } public PawnKeyframe GetPawnKeyframe(int actorID, int keyframeID) { return animationDef.animationStages[stageID].animationClips[actorID].keyframes.FirstOrDefault(x => x.keyframeID == keyframeID); } [SerializeField] public LinkedList pastSnapshots = new LinkedList(); public LinkedList futureSnapshots = new LinkedList(); public void MakeHistoricRecord(string eventDesc) { HistoricRecord record = new HistoricRecord(); record.recordID = pastSnapshots.Count; record.eventDesc = eventDesc; record.animationDef = animationDef.Copy(); record.stageID = stageID; futureSnapshots.Clear(); pastSnapshots.AddLast(record); if (pastSnapshots.Count > maxHistoryDepth) { pastSnapshots.RemoveFirst(); } } public void RestoreToHistoricRecord(HistoricRecord record) { animationDef = record.animationDef.Copy(); stageID = record.stageID; AnimationController.Instance.MakeTimelineDirty(); StageCardManager.Instance.Reset(); StageCardManager.Instance.Initialize(); } public void Undo() { HistoricRecord recordToRead = pastSnapshots.Last?.Previous?.Value; HistoricRecord recordToStore = pastSnapshots.Last?.Value; if (recordToRead == null || recordToStore == null) return; pastSnapshots.RemoveLast(); futureSnapshots.AddLast(recordToStore); RestoreToHistoricRecord(recordToRead); Debug.Log("Undoing : " + recordToStore.eventDesc); } public void Redo() { HistoricRecord recordToReadAndStore = futureSnapshots.Last?.Value; if (recordToReadAndStore == null) return; futureSnapshots.RemoveLast(); pastSnapshots.AddLast(recordToReadAndStore); RestoreToHistoricRecord(recordToReadAndStore); Debug.Log("Redoing : " + recordToReadAndStore.eventDesc); } public void ClearHistory() { pastSnapshots.Clear(); futureSnapshots.Clear(); } public void RecordEvent(string eventDesc) { //Debug.Log("Recording event: " + eventDesc + " (record ID: " + pastSnapshots.Count + ")"); MakeHistoricRecord(eventDesc); } } }