mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
v 1.0.0
This commit is contained in:
parent
0828ecd037
commit
2998865184
9821 changed files with 90 additions and 90 deletions
19
Source/Assets/Scripts/Workspace/HistoricRecord.cs
Normal file
19
Source/Assets/Scripts/Workspace/HistoricRecord.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RimWorldAnimationStudio
|
||||
{
|
||||
[Serializable]
|
||||
public class WorkspaceRecord
|
||||
{
|
||||
public int recordID = 0;
|
||||
public string eventDesc;
|
||||
public AnimationDef animationDef;
|
||||
public int stageID = 0;
|
||||
public int actorID = 0;
|
||||
public int keyframeID = 0;
|
||||
}
|
||||
}
|
11
Source/Assets/Scripts/Workspace/HistoricRecord.cs.meta
Normal file
11
Source/Assets/Scripts/Workspace/HistoricRecord.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d877470affbfa194db9947e8bdd1bcb9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
363
Source/Assets/Scripts/Workspace/Workspace.cs
Normal file
363
Source/Assets/Scripts/Workspace/Workspace.cs
Normal file
|
@ -0,0 +1,363 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace RimWorldAnimationStudio
|
||||
{
|
||||
public static class Workspace
|
||||
{
|
||||
// Animation def
|
||||
public static AnimationDef animationDef;
|
||||
|
||||
// Animation indices set / get
|
||||
public static int StageID
|
||||
{
|
||||
get { return Mathf.Clamp(stageID, 0, animationDef.AnimationStages.Count - 1); }
|
||||
set
|
||||
{
|
||||
bool triggerEvent = stageID != value;
|
||||
stageID = value;
|
||||
|
||||
if (triggerEvent) { StageTick = Constants.minTick; EventsManager.OnStageIDChanged(); }
|
||||
}
|
||||
}
|
||||
|
||||
public static int ActorID
|
||||
{
|
||||
get { return Mathf.Clamp(actorID, 0, animationDef.Actors.Count - 1); }
|
||||
set
|
||||
{
|
||||
bool triggerEvent = actorID != value;
|
||||
actorID = value;
|
||||
|
||||
if (triggerEvent) { EventsManager.OnActorIDChanged(); }
|
||||
}
|
||||
}
|
||||
|
||||
public static int StageTick
|
||||
{
|
||||
get { return Mathf.Clamp(stageTick, Constants.minTick, StageWindowSize); }
|
||||
set
|
||||
{
|
||||
bool triggerEvent = stageTick != value;
|
||||
stageTick = value;
|
||||
|
||||
if (triggerEvent) { EventsManager.OnStageTickChanged(); }
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Selected keyframes and copied keyframe data
|
||||
public static List<int> keyframeID = new List<int>();
|
||||
public static List<PawnKeyframe> copiedKeyframes = new List<PawnKeyframe>();
|
||||
|
||||
// Actor manipulation
|
||||
public static ActorManipulationMode actorManipulationMode = ActorManipulationMode.Pan;
|
||||
public static ActorBodyPart selectedBodyPart;
|
||||
|
||||
// Current save path
|
||||
public static string animationSavePath;
|
||||
|
||||
// Stage controls
|
||||
private static float playBackSpeed = 1f;
|
||||
private static bool isAnimating;
|
||||
public static bool stretchKeyframes;
|
||||
|
||||
// Stage controls set / get
|
||||
public static float PlayBackSpeed
|
||||
{
|
||||
get { return playBackSpeed; }
|
||||
set { Mathf.Clamp(Workspace.playBackSpeed, 0.01f, 10f); }
|
||||
}
|
||||
|
||||
public static bool IsAnimating
|
||||
{
|
||||
get { return isAnimating; }
|
||||
set { isAnimating = value; EventsManager.OnAnimationToggled(); }
|
||||
}
|
||||
|
||||
// Animation indices
|
||||
private static int stageID = 0;
|
||||
private static int actorID = 0;
|
||||
private static int stageTick = Constants.minTick;
|
||||
|
||||
// Workspace history
|
||||
private static LinkedList<WorkspaceRecord> pastSnapshots = new LinkedList<WorkspaceRecord>();
|
||||
private static LinkedList<WorkspaceRecord> futureSnapshots = new LinkedList<WorkspaceRecord>();
|
||||
private static int maxHistoryDepth = 100;
|
||||
|
||||
public static Actor GetCurrentActor()
|
||||
{
|
||||
return GetActor(ActorID);
|
||||
}
|
||||
|
||||
public static AnimationStage GetCurrentAnimationStage()
|
||||
{
|
||||
return GetAnimationStage(StageID);
|
||||
}
|
||||
|
||||
public static PawnAnimationClip GetCurrentPawnAnimationClip()
|
||||
{
|
||||
return GetPawnAnimationClip(ActorID);
|
||||
}
|
||||
|
||||
public static PawnKeyframe GetCurrentPawnKeyframe(bool makeKeyframe = false)
|
||||
{
|
||||
PawnKeyframe keyframe = animationDef?.AnimationStages[StageID]?.AnimationClips[ActorID]?.Keyframes.FirstOrDefault(x => x.atTick == StageTick);
|
||||
|
||||
if (keyframe != null || makeKeyframe == false)
|
||||
{ return keyframe; }
|
||||
|
||||
GetCurrentPawnAnimationClip().AddPawnKeyframe();
|
||||
return animationDef?.AnimationStages[StageID]?.AnimationClips[ActorID]?.Keyframes.FirstOrDefault(x => x.atTick == StageTick);
|
||||
}
|
||||
|
||||
public static Actor GetActor(int actorID)
|
||||
{
|
||||
return animationDef?.Actors.ElementAtOrDefault(actorID);
|
||||
}
|
||||
|
||||
public static AnimationStage GetAnimationStage(int stageID)
|
||||
{
|
||||
return animationDef?.AnimationStages.ElementAtOrDefault(stageID);
|
||||
}
|
||||
|
||||
public static PawnAnimationClip GetPawnAnimationClip(int actorID)
|
||||
{
|
||||
return GetCurrentAnimationStage()?.AnimationClips.ElementAtOrDefault(actorID);
|
||||
}
|
||||
|
||||
public static PawnKeyframe GetPawnKeyframe(int keyframeID)
|
||||
{
|
||||
foreach (AnimationStage stage in animationDef?.AnimationStages)
|
||||
{
|
||||
foreach (PawnAnimationClip clip in stage.animationClips)
|
||||
{
|
||||
PawnKeyframe keyframe = clip.Keyframes.FirstOrDefault(x => x.keyframeID == keyframeID);
|
||||
|
||||
if (keyframe != null) return keyframe;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PawnAnimationClip GetAnimationClipThatOwnsKeyframe(int keyframeID)
|
||||
{
|
||||
foreach (AnimationStage stage in animationDef?.AnimationStages)
|
||||
{
|
||||
foreach (PawnAnimationClip clip in stage.animationClips)
|
||||
{
|
||||
PawnKeyframe keyframe = clip.Keyframes.FirstOrDefault(x => x.keyframeID == keyframeID);
|
||||
|
||||
if (keyframe != null) return clip;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<PawnKeyframe> GetAllPawnKeyframesAtTick(int actorID, int atTick)
|
||||
{
|
||||
return animationDef?.AnimationStages[StageID]?.AnimationClips[actorID]?.Keyframes.Where(x => x.atTick == atTick)?.ToList();
|
||||
}
|
||||
|
||||
public static List<PawnKeyframe> GetPawnKeyframesByID(List<int> keyframeIDs)
|
||||
{
|
||||
List<PawnKeyframe> pawnKeyframes = new List<PawnKeyframe>();
|
||||
|
||||
foreach (PawnAnimationClip clip in animationDef.AnimationStages[StageID].AnimationClips)
|
||||
{
|
||||
foreach (PawnKeyframe keyframe in clip.Keyframes)
|
||||
{
|
||||
if (keyframeIDs.Contains(keyframe.keyframeID))
|
||||
{ pawnKeyframes.Add(keyframe); }
|
||||
}
|
||||
}
|
||||
|
||||
return pawnKeyframes;
|
||||
}
|
||||
|
||||
public static bool DoesPawnKeyframeExistAtTick(int stageID, int actorID, int atTick)
|
||||
{
|
||||
return animationDef.AnimationStages[stageID].AnimationClips[actorID].Keyframes.Any(x => x.atTick == atTick);
|
||||
}
|
||||
|
||||
public static PawnKeyframe GetNextKeyframe(int actorID)
|
||||
{
|
||||
PawnKeyframe pawnKeyframe = null;
|
||||
PawnAnimationClip clip = GetPawnAnimationClip(actorID);
|
||||
|
||||
foreach (PawnKeyframe keyframe in clip.Keyframes)
|
||||
{
|
||||
if (keyframe.atTick > StageTick)
|
||||
{ pawnKeyframe = keyframe; break; }
|
||||
}
|
||||
|
||||
return pawnKeyframe;
|
||||
}
|
||||
|
||||
public static PawnKeyframe GetPreviousKeyframe(int actorID)
|
||||
{
|
||||
PawnKeyframe pawnKeyframe = null;
|
||||
PawnAnimationClip clip = GetPawnAnimationClip(actorID);
|
||||
|
||||
foreach (PawnKeyframe keyframe in clip.Keyframes)
|
||||
{
|
||||
if (keyframe.atTick < StageTick)
|
||||
{ pawnKeyframe = keyframe; }
|
||||
}
|
||||
|
||||
return pawnKeyframe;
|
||||
}
|
||||
|
||||
public static PawnKeyframe GetCurrentOrPreviousKeyframe(int actorID)
|
||||
{
|
||||
PawnKeyframe pawnKeyframe = null;
|
||||
PawnAnimationClip clip = GetPawnAnimationClip(actorID);
|
||||
|
||||
foreach (PawnKeyframe keyframe in clip.Keyframes)
|
||||
{
|
||||
if (keyframe.atTick <= StageTick)
|
||||
{ pawnKeyframe = keyframe; }
|
||||
}
|
||||
|
||||
return pawnKeyframe;
|
||||
}
|
||||
|
||||
public static int FindClosestKeyFrameAtTick(int atTick, int searchDistance = int.MaxValue, int excludedActorID = -1)
|
||||
{
|
||||
List<PawnKeyframe> keyframesToCheck;
|
||||
|
||||
if (excludedActorID >= 0)
|
||||
{
|
||||
keyframesToCheck = animationDef.AnimationStages[StageID].AnimationClips.Where(x =>
|
||||
animationDef.AnimationStages[StageID].AnimationClips.IndexOf(x) != excludedActorID).SelectMany(x => x.Keyframes)?.ToList();
|
||||
}
|
||||
|
||||
else
|
||||
{ keyframesToCheck = animationDef.AnimationStages[StageID].AnimationClips.SelectMany(x => x.Keyframes)?.ToList(); }
|
||||
|
||||
keyframesToCheck = keyframesToCheck.Where(x => Mathf.Abs(atTick - x.atTick.Value) <= searchDistance)?.ToList();
|
||||
|
||||
if (keyframesToCheck.NullOrEmpty())
|
||||
{ return atTick; }
|
||||
|
||||
int minDist = int.MaxValue;
|
||||
int bestAtTick = -1;
|
||||
|
||||
foreach (PawnKeyframe keyframe_ in keyframesToCheck)
|
||||
{
|
||||
if (Mathf.Abs(keyframe_.atTick.Value - atTick) < minDist)
|
||||
{
|
||||
minDist = Mathf.Abs(keyframe_.atTick.Value - atTick);
|
||||
bestAtTick = keyframe_.atTick.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return bestAtTick;
|
||||
}
|
||||
|
||||
public static int GetEarliestAtTickInCopiedKeyframes(int actorID)
|
||||
{
|
||||
IEnumerable<PawnKeyframe> keyframes = copiedKeyframes.Where(x => x.actorID == actorID);
|
||||
if (keyframes == null || keyframes.Any() == false) return -1;
|
||||
|
||||
return keyframes.Min(x => x.atTick).Value;
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
ActorID = 0;
|
||||
StageID = 0;
|
||||
keyframeID.Clear();
|
||||
selectedBodyPart = null;
|
||||
animationSavePath = null;
|
||||
|
||||
ClearHistory();
|
||||
}
|
||||
|
||||
public static void MakeHistoricRecord(string eventDesc)
|
||||
{
|
||||
WorkspaceRecord record = new WorkspaceRecord();
|
||||
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 static void RestoreToHistoricRecord(WorkspaceRecord record)
|
||||
{
|
||||
animationDef = record.animationDef.Copy();
|
||||
StageID = record.stageID;
|
||||
|
||||
StageCardManager.Instance.Initialize();
|
||||
}
|
||||
|
||||
public static void Undo()
|
||||
{
|
||||
WorkspaceRecord recordToRead = pastSnapshots.Last?.Previous?.Value;
|
||||
WorkspaceRecord recordToStore = pastSnapshots.Last?.Value;
|
||||
|
||||
if (recordToRead == null || recordToStore == null) return;
|
||||
|
||||
pastSnapshots.RemoveLast();
|
||||
futureSnapshots.AddLast(recordToStore);
|
||||
|
||||
RestoreToHistoricRecord(recordToRead);
|
||||
Debug.Log("Undoing : " + recordToStore.eventDesc);
|
||||
|
||||
EventsManager.OnAnimationChanged();
|
||||
}
|
||||
|
||||
public static void Redo()
|
||||
{
|
||||
WorkspaceRecord recordToReadAndStore = futureSnapshots.Last?.Value;
|
||||
|
||||
if (recordToReadAndStore == null) return;
|
||||
|
||||
futureSnapshots.RemoveLast();
|
||||
pastSnapshots.AddLast(recordToReadAndStore);
|
||||
|
||||
RestoreToHistoricRecord(recordToReadAndStore);
|
||||
Debug.Log("Redoing : " + recordToReadAndStore.eventDesc);
|
||||
|
||||
EventsManager.OnAnimationChanged();
|
||||
}
|
||||
|
||||
public static void ClearHistory()
|
||||
{
|
||||
pastSnapshots.Clear();
|
||||
futureSnapshots.Clear();
|
||||
}
|
||||
|
||||
public static void RecordEvent(string eventDesc)
|
||||
{
|
||||
//Debug.Log("Recording event: " + eventDesc + " (record ID: " + pastSnapshots.Count + ")");
|
||||
MakeHistoricRecord(eventDesc);
|
||||
}
|
||||
}
|
||||
}
|
11
Source/Assets/Scripts/Workspace/Workspace.cs.meta
Normal file
11
Source/Assets/Scripts/Workspace/Workspace.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bf0f782b7c407bf4896b633d509f5568
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue