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 actorID = 0; public static int keyframeID = 0; public static List defNames = new List() { "Human" }; public static List bodyParts = new List() { "Any appendage", "Any orifice", "Penis", "Vagina", "Anus", "Breasts", "Mouth" }; public static List bodyDefTypes = new List() { "Human", "Bird", "BeetleLike", "BeetleLikeWithClaw", "MechanicalCentipede", "MechanicalTermite", "Lancer", "Pikeman", "Monkey", "QuadrupedAnimalWithClawsTailAndJowl", "QuadrupedAnimalWithHooves", "QuadrupedAnimalWithHoovesAndHorn", "QuadrupedAnimalWithHoovesAndHump", "QuadrupedAnimalWithHoovesAndTusks", "QuadrupedAnimalWithHoovesTusksAndTrunk", "QuadrupedAnimalWithPaws", "QuadrupedAnimalWithPawsAndTail", "Scyther", "Snake", "TurtleLike" }; public static List sexTypes = new List() { "None", "Vaginal", "Anal", "Oral", "Masturbation", "DoublePenetration", "Boobjob", "Handjob", "Footjob", "Fingering", "Scissoring", "MutualMasturbation", "Fisting", "MechImplant", "Rimming", "Fellatio", "Cunnilingus", "Sixtynine" }; public static List interactionDefTypes = new List(); [SerializeField] private List workspaceHistory = new List(); [SerializeField] private int historyIndex = 0; [SerializeField] private int maxHistoryDepth = 100; private bool isDirty = false; public static ActorManipulationMode actorManipulationMode = ActorManipulationMode.Pan; public static int StageWindowSize { get { if (animationDef == null) { return -1; } if (animationDef.animationStages[stageID].stageWindowSize < 0) { return animationDef.animationStages[stageID].animationClips.Select(x => x.duration).Max(); } return animationDef.animationStages[stageID].stageWindowSize; } } public void Update() { if (isDirty) { TrackChanges(); } } public PawnKeyframe GetCurrentPawnKeyframe() { int stageTick = AnimationController.Instance.stageTick; PawnKeyframe keyframe = animationDef?.animationStages[stageID]?.animationClips[actorID]?.keyframes.FirstOrDefault(x => x.atTick == stageTick); if (keyframe != null) { 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); } public void TrackChanges() { if (historyIndex < workspaceHistory.Count - 1) { workspaceHistory.RemoveRange(historyIndex + 1, workspaceHistory.Count - historyIndex - 1); } if (workspaceHistory.Any() && workspaceHistory.Count >= maxHistoryDepth) { workspaceHistory.RemoveAt(0); } WorkspaceSnapShot workspaceSnapShot = new WorkspaceSnapShot(); workspaceSnapShot.animationDef = animationDef.Copy(); workspaceSnapShot.stageID = stageID; workspaceSnapShot.actorID = actorID; workspaceSnapShot.keyframeID = keyframeID; workspaceHistory.Add(workspaceSnapShot); historyIndex = workspaceHistory.Count - 1; isDirty = false; } public void Undo() { historyIndex = Mathf.Clamp(historyIndex - 1, 0, workspaceHistory.Count - 1); LoadHistoricState(); } public void Redo() { historyIndex = Mathf.Clamp(historyIndex + 1, 0, workspaceHistory.Count - 1); LoadHistoricState(); } public void LoadHistoricState() { if (workspaceHistory.NullOrEmpty()) { Debug.LogWarning("Cannot load historic state - workspace history is empty"); return; } animationDef = workspaceHistory[historyIndex].animationDef.Copy(); stageID = workspaceHistory[historyIndex].stageID; actorID = workspaceHistory[historyIndex].actorID; keyframeID = workspaceHistory[historyIndex].keyframeID; AnimationController.Instance.MakeTimelineDirty(); } public void ClearHistory() { workspaceHistory.Clear(); historyIndex = 0; } public void MakeDirty() { isDirty = true; } } }