mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
Bug fixes plus extra features
- Insert adds a new keyframe to the selected timeline - New stages have frames cloned from the last frame of current stage - Existing key are now replaced when another key is dropped on them - Fixed bug where starting a new animation could result in errors
This commit is contained in:
parent
ca22fa0c18
commit
2989d9a72c
137 changed files with 527 additions and 668 deletions
|
@ -121,5 +121,12 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int GetActorID()
|
||||
{
|
||||
if (Workspace.animationDef == null) return -1;
|
||||
|
||||
return Workspace.animationDef.actors.IndexOf(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
@ -89,17 +90,46 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public override void ValidateData() { }
|
||||
|
||||
public bool MakeNew()
|
||||
public int GetOwningActorID()
|
||||
{
|
||||
PawnKeyframe keyframeA = new PawnKeyframe();
|
||||
keyframeA.tickDuration = Constants.defaultAnimationClipLength - 1;
|
||||
keyframes.Add(keyframeA);
|
||||
if (Workspace.animationDef == null) return -1;
|
||||
|
||||
PawnKeyframe keyframeB = new PawnKeyframe();
|
||||
keyframes.Add(keyframeB);
|
||||
return Workspace.animationDef.animationStages[Workspace.stageID].animationClips.IndexOf(this);
|
||||
}
|
||||
|
||||
public bool MakeNew(int actorID = -1)
|
||||
{
|
||||
PawnKeyframe lastkeyframe = null;
|
||||
|
||||
if (actorID >= 0)
|
||||
{ lastkeyframe = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[actorID]?.keyframes?.Last(); }
|
||||
|
||||
if (lastkeyframe != null)
|
||||
{
|
||||
PawnKeyframe keyframeA = lastkeyframe.Copy();
|
||||
keyframeA.atTick = null;
|
||||
keyframeA.tickDuration = Constants.defaultAnimationClipLength - 1;
|
||||
keyframeA.GenerateKeyframeID(actorID);
|
||||
keyframes.Add(keyframeA);
|
||||
|
||||
PawnKeyframe keyframeB = lastkeyframe.Copy();
|
||||
keyframeB.atTick = null;
|
||||
keyframeB.tickDuration = 1;
|
||||
keyframeB.GenerateKeyframeID(actorID);
|
||||
keyframes.Add(keyframeB);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
PawnKeyframe keyframeA = new PawnKeyframe();
|
||||
keyframeA.tickDuration = Constants.defaultAnimationClipLength - 1;
|
||||
keyframes.Add(keyframeA);
|
||||
|
||||
PawnKeyframe keyframeB = new PawnKeyframe();
|
||||
keyframes.Add(keyframeB);
|
||||
}
|
||||
|
||||
BuildSimpleCurves();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,23 +36,31 @@ namespace RimWorldAnimationStudio
|
|||
{ clip.keyframes = clip.keyframes.OrderBy(x => x.atTick).ToList(); }
|
||||
}
|
||||
|
||||
public int GetStageID()
|
||||
{
|
||||
if (Workspace.animationDef == null) return -1;
|
||||
|
||||
return Workspace.animationDef.animationStages.IndexOf(this);
|
||||
}
|
||||
|
||||
public bool MakeNew()
|
||||
{
|
||||
if (Workspace.animationDef == null)
|
||||
{ Debug.LogWarning("Cannot make new animation stage - there is no AnimationDef"); return false; }
|
||||
|
||||
foreach(Actor actor in Workspace.animationDef.actors)
|
||||
Workspace.animationDef.animationStages.Add(this);
|
||||
|
||||
foreach (Actor actor in Workspace.animationDef.actors)
|
||||
{
|
||||
PawnAnimationClip clip = new PawnAnimationClip();
|
||||
|
||||
if (clip.MakeNew())
|
||||
if (clip.MakeNew(actor.GetActorID()))
|
||||
{ animationClips.Add(clip); }
|
||||
}
|
||||
|
||||
Initialize();
|
||||
playTimeTicksQuick = playTimeTicks;
|
||||
Workspace.animationDef.animationStages.Add(this);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,8 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public void LogMessage(string logString, string stackTrace, LogType type)
|
||||
{
|
||||
if (currentMessages > maxMessages)
|
||||
{ return; }
|
||||
|
||||
currentMessages++;
|
||||
if (currentMessages > maxMessages) return;
|
||||
currentMessages++;
|
||||
|
||||
currentMessage.text = logString;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace RimWorldAnimationStudio
|
|||
public void Start()
|
||||
{
|
||||
keybindLabel = GetComponent<Text>();
|
||||
keybindLabel.text = KeybindConfig.Instance.GetKeybindLabel(command);
|
||||
keybindLabel.text = KeybindConfig.GetKeybindLabel(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ namespace RimWorldAnimationStudio
|
|||
if (Workspace.keyframeID.NullOrEmpty() || Workspace.keyframeID.Contains(keyframeID) == false)
|
||||
{ Workspace.keyframeID = new List<int> { keyframeID }; }
|
||||
|
||||
List<PawnKeyframe> selectedKeyframes = Workspace.Instance.GetPawnKeyframes(Workspace.keyframeID).Except(new List<PawnKeyframe>() { keyframe })?.ToList();
|
||||
List<PawnKeyframe> selectedKeyframes = Workspace.Instance.GetPawnKeyframesByID(Workspace.keyframeID).Except(new List<PawnKeyframe>() { keyframe })?.ToList();
|
||||
|
||||
// Link other slected keyframes to the movement of this one
|
||||
if (selectedKeyframes.NotNullOrEmpty())
|
||||
|
@ -170,12 +170,39 @@ namespace RimWorldAnimationStudio
|
|||
if (keyframe.atTick == Constants.minTick)
|
||||
{ value = Constants.minTick; return; }
|
||||
|
||||
foreach (Selectable linkedSlider in Selectable.allSelectablesArray)
|
||||
List<PawnKeyframe> keyframesToCheck = Workspace.Instance.GetPawnKeyframesAtTick(actorID, keyframe.atTick.Value);
|
||||
if (keyframesToCheck.NotNullOrEmpty())
|
||||
{
|
||||
if (linkedSlider is KeyframeSlider)
|
||||
{
|
||||
(linkedSlider as KeyframeSlider).linkedSlider = null;
|
||||
(linkedSlider as KeyframeSlider).pivotKeyframe = null;
|
||||
foreach (PawnKeyframe _keyframe in keyframesToCheck)
|
||||
{
|
||||
if (_keyframe != keyframe)
|
||||
{ AnimationController.Instance.RemovePawnKeyframe(actorID, _keyframe.keyframeID); }
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Selectable selectable in Selectable.allSelectablesArray)
|
||||
{
|
||||
if (selectable is KeyframeSlider)
|
||||
{
|
||||
KeyframeSlider linkedSlider = selectable.GetComponent<KeyframeSlider>();
|
||||
PawnKeyframe linkedKeyframe = linkedSlider.keyframe;
|
||||
|
||||
if (linkedSlider.linkedSlider != null)
|
||||
{
|
||||
keyframesToCheck = Workspace.Instance.GetPawnKeyframesAtTick(actorID, linkedKeyframe.atTick.Value);
|
||||
|
||||
if (keyframesToCheck.NotNullOrEmpty() && keyframesToCheck.Count > 1)
|
||||
{
|
||||
foreach (PawnKeyframe _keyframe in keyframesToCheck)
|
||||
{
|
||||
if (_keyframe.keyframeID != linkedKeyframe.keyframeID)
|
||||
{ AnimationController.Instance.RemovePawnKeyframe(actorID, _keyframe.keyframeID); Debug.Log("delete"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linkedSlider.linkedSlider = null;
|
||||
linkedSlider.pivotKeyframe = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,26 +8,30 @@ using UnityEngine;
|
|||
|
||||
namespace RimWorldAnimationStudio
|
||||
{
|
||||
public class KeybindConfig : Singleton<KeybindConfig>
|
||||
public class KeybindConfig
|
||||
{
|
||||
private static List<Keybind> keybinds = new List<Keybind>();
|
||||
private static bool initialized = false;
|
||||
|
||||
public void Awake()
|
||||
public static void Initialize()
|
||||
{
|
||||
string path = Path.Combine(Application.streamingAssetsPath, "keybindConfig.xml");
|
||||
|
||||
keybinds = XmlUtility.ReadXML<List<Keybind>>(path);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public List<Keybind> GetAllKeybinds()
|
||||
public static List<Keybind> GetAllKeybinds()
|
||||
{
|
||||
if (initialized == false)
|
||||
{ Initialize(); }
|
||||
|
||||
return keybinds;
|
||||
}
|
||||
|
||||
public string GetKeybindLabel(string command)
|
||||
public static string GetKeybindLabel(string command)
|
||||
{
|
||||
string label = "";
|
||||
Keybind keybind = keybinds.FirstOrDefault(x => x.command == command);
|
||||
Keybind keybind = GetAllKeybinds()?.FirstOrDefault(x => x.command == command);
|
||||
|
||||
if (keybind == null) return label;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace RimWorldAnimationStudio
|
|||
private float playBackSpeed = 1f;
|
||||
|
||||
public void MakeDirty()
|
||||
{ isDirty = true; }
|
||||
{ isDirty = true; isTimelineDirty = true; }
|
||||
|
||||
public void MakeTimelineDirty()
|
||||
{ isTimelineDirty = true; }
|
||||
|
@ -255,10 +255,11 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public void Reset()
|
||||
{
|
||||
Workspace.stageID = 0;
|
||||
isAnimating = false;
|
||||
timeSinceLastUpdate = 0;
|
||||
cycleIndex = 0;
|
||||
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
public void InitializeAnimationTimeline()
|
||||
|
@ -377,7 +378,7 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public void ClonePawnKeyframe()
|
||||
{
|
||||
List<PawnKeyframe> keyframesToClone = Workspace.Instance.GetPawnKeyframes(Workspace.keyframeID);
|
||||
List<PawnKeyframe> keyframesToClone = Workspace.Instance.GetPawnKeyframesByID(Workspace.keyframeID);
|
||||
|
||||
foreach (PawnKeyframe keyframe in keyframesToClone)
|
||||
{
|
||||
|
@ -413,7 +414,7 @@ namespace RimWorldAnimationStudio
|
|||
{
|
||||
Workspace.copiedKeyframes.Clear();
|
||||
|
||||
List<PawnKeyframe> keyframesToClone = Workspace.Instance.GetPawnKeyframes(Workspace.keyframeID);
|
||||
List<PawnKeyframe> keyframesToClone = Workspace.Instance.GetPawnKeyframesByID(Workspace.keyframeID);
|
||||
|
||||
foreach (PawnKeyframe keyframe in keyframesToClone)
|
||||
{ Workspace.copiedKeyframes.Add(keyframe.Copy()); }
|
||||
|
|
|
@ -70,10 +70,9 @@ namespace RimWorldAnimationStudio
|
|||
Workspace.animationDef = animationDef;
|
||||
animationDef.Initialize();
|
||||
|
||||
Workspace.Instance.ClearHistory();
|
||||
AnimationController.Instance.Reset();
|
||||
Workspace.Instance.Reset();
|
||||
Workspace.Instance.RecordEvent("AnimationDef loaded");
|
||||
|
||||
AnimationController.Instance.MakeDirty();
|
||||
}
|
||||
|
||||
public void RunPostLoadOperations(AnimationDef animationDef)
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace RimWorldAnimationStudio
|
|||
bool canRepeatThisUpdate = CanRepeatThisUpdate();
|
||||
|
||||
// Check keybinds
|
||||
foreach (Keybind keybind in KeybindConfig.Instance.GetAllKeybinds())
|
||||
foreach (Keybind keybind in KeybindConfig.GetAllKeybinds())
|
||||
{
|
||||
if (IsModifierKeyHeld() && keybind.keyModifiers.NullOrEmpty()) goto nextKeybind;
|
||||
|
||||
|
@ -207,6 +207,12 @@ namespace RimWorldAnimationStudio
|
|||
AnimationController.Instance.ToggleAnimation();
|
||||
}
|
||||
|
||||
public void AddKeyframe()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
AnimationController.Instance.AddPawnKeyframe();
|
||||
}
|
||||
|
||||
public void CopyKeyframes()
|
||||
{
|
||||
if (Workspace.animationDef == null) return;
|
||||
|
|
|
@ -14,6 +14,8 @@ namespace RimWorldAnimationStudio
|
|||
public string message = "Undefined";
|
||||
public string executedCommand;
|
||||
public float delay = 0f;
|
||||
public Vector2 offset = new Vector2(5f, -15f);
|
||||
public bool flipX = false;
|
||||
|
||||
private GameObject tooltip;
|
||||
private Text tooltipText;
|
||||
|
@ -33,12 +35,13 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
if (isDisplayed == false)
|
||||
{
|
||||
tooltip.GetComponent<RectTransform>().pivot = flipX ? new Vector2(1, 1) : new Vector2(0, 1);
|
||||
tooltipText.text = message;
|
||||
|
||||
if (executedCommand != null && executedCommand != "")
|
||||
{ tooltipText.text += " (" + KeybindConfig.Instance.GetKeybindLabel(executedCommand) + ")"; }
|
||||
{ tooltipText.text += " (" + KeybindConfig.GetKeybindLabel(executedCommand) + ")"; }
|
||||
|
||||
tooltip.transform.position = (Vector2)transform.position + new Vector2(5f, -15f);
|
||||
tooltip.transform.position = (Vector2)transform.position + offset;
|
||||
tooltip.gameObject.SetActive(true);
|
||||
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(tooltip.GetComponent<RectTransform>());
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||
namespace RimWorldAnimationStudio
|
||||
{
|
||||
[Serializable]
|
||||
public class HistoricRecord
|
||||
public class WorkspaceRecord
|
||||
{
|
||||
public int recordID = 0;
|
||||
public string eventDesc;
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public static List<int> keyframeID = new List<int>();
|
||||
|
||||
[SerializeField] private List<HistoricRecord> workspaceHistory = new List<HistoricRecord>();
|
||||
[SerializeField] private List<WorkspaceRecord> workspaceHistory = new List<WorkspaceRecord>();
|
||||
[SerializeField] private int maxHistoryDepth = 100;
|
||||
|
||||
public static ActorManipulationMode actorManipulationMode = ActorManipulationMode.Pan;
|
||||
|
@ -53,6 +53,11 @@ namespace RimWorldAnimationStudio
|
|||
return animationDef?.animationStages[stageID]?.animationClips[actorID]?.keyframes.FirstOrDefault(x => x.atTick == stageTick);
|
||||
}
|
||||
|
||||
public List<PawnKeyframe> GetPawnKeyframesAtTick(int actorID, int atTick)
|
||||
{
|
||||
return animationDef?.animationStages[stageID]?.animationClips[actorID]?.keyframes.Where(x => x.atTick == atTick)?.ToList();
|
||||
}
|
||||
|
||||
public PawnAnimationClip GetCurrentPawnAnimationClip()
|
||||
{
|
||||
return animationDef.animationStages[stageID].animationClips[actorID];
|
||||
|
@ -74,7 +79,7 @@ namespace RimWorldAnimationStudio
|
|||
return animationDef.animationStages[stageID].animationClips[actorID].keyframes.FirstOrDefault(x => x.keyframeID == keyframeID);
|
||||
}
|
||||
|
||||
public List<PawnKeyframe> GetPawnKeyframes(List<int> keyframeIDs)
|
||||
public List<PawnKeyframe> GetPawnKeyframesByID(List<int> keyframeIDs)
|
||||
{
|
||||
List<PawnKeyframe> pawnKeyframes = new List<PawnKeyframe>();
|
||||
|
||||
|
@ -203,12 +208,23 @@ namespace RimWorldAnimationStudio
|
|||
}
|
||||
|
||||
[SerializeField]
|
||||
public LinkedList<HistoricRecord> pastSnapshots = new LinkedList<HistoricRecord>();
|
||||
public LinkedList<HistoricRecord> futureSnapshots = new LinkedList<HistoricRecord>();
|
||||
public LinkedList<WorkspaceRecord> pastSnapshots = new LinkedList<WorkspaceRecord>();
|
||||
public LinkedList<WorkspaceRecord> futureSnapshots = new LinkedList<WorkspaceRecord>();
|
||||
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
actorID = 0;
|
||||
stageID = 0;
|
||||
keyframeID.Clear();
|
||||
selectedBodyPart = null;
|
||||
|
||||
ClearHistory();
|
||||
}
|
||||
|
||||
public void MakeHistoricRecord(string eventDesc)
|
||||
{
|
||||
HistoricRecord record = new HistoricRecord();
|
||||
WorkspaceRecord record = new WorkspaceRecord();
|
||||
record.recordID = pastSnapshots.Count;
|
||||
record.eventDesc = eventDesc;
|
||||
record.animationDef = animationDef.Copy();
|
||||
|
@ -221,7 +237,7 @@ namespace RimWorldAnimationStudio
|
|||
{ pastSnapshots.RemoveFirst(); }
|
||||
}
|
||||
|
||||
public void RestoreToHistoricRecord(HistoricRecord record)
|
||||
public void RestoreToHistoricRecord(WorkspaceRecord record)
|
||||
{
|
||||
animationDef = record.animationDef.Copy();
|
||||
stageID = record.stageID;
|
||||
|
@ -232,8 +248,8 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public void Undo()
|
||||
{
|
||||
HistoricRecord recordToRead = pastSnapshots.Last?.Previous?.Value;
|
||||
HistoricRecord recordToStore = pastSnapshots.Last?.Value;
|
||||
WorkspaceRecord recordToRead = pastSnapshots.Last?.Previous?.Value;
|
||||
WorkspaceRecord recordToStore = pastSnapshots.Last?.Value;
|
||||
|
||||
if (recordToRead == null || recordToStore == null) return;
|
||||
|
||||
|
@ -246,7 +262,7 @@ namespace RimWorldAnimationStudio
|
|||
|
||||
public void Redo()
|
||||
{
|
||||
HistoricRecord recordToReadAndStore = futureSnapshots.Last?.Value;
|
||||
WorkspaceRecord recordToReadAndStore = futureSnapshots.Last?.Value;
|
||||
|
||||
if (recordToReadAndStore == null) return;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue