New paste functions plus keyframe drag select

This commit is contained in:
AbstractConcept 2022-10-13 00:33:18 -05:00
parent 3d2c11f469
commit f449a9b4e2
117 changed files with 399 additions and 81 deletions

View file

@ -5,16 +5,20 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace RimWorldAnimationStudio
{
public class AnimationTimeline : MonoBehaviour
public class AnimationTimeline : MonoBehaviour, IPointerClickHandler
{
public int actorID;
public KeyframeSlider keyframeSliderPrefab;
private Transform anchorTransform;
public void Initialize(int actorID)
{
anchorTransform = transform.parent;
this.actorID = actorID;
Reset();
@ -71,8 +75,8 @@ namespace RimWorldAnimationStudio
public void OnMoveTimeline(int delta)
{
int? siblingIndex = transform.parent.GetComponentsInChildren<AnimationTimeline>()?.ToList()?.IndexOf(this);
int? siblingCount = transform.parent.GetComponentsInChildren<AnimationTimeline>()?.ToList()?.Count();
int? siblingIndex = anchorTransform.parent.GetComponentsInChildren<AnimationTimeline>()?.ToList()?.IndexOf(this);
int? siblingCount = anchorTransform.parent.GetComponentsInChildren<AnimationTimeline>()?.ToList()?.Count();
if (siblingIndex != null && siblingCount != null && MoveAnimationTimeline(siblingIndex.Value, delta))
{
@ -102,5 +106,11 @@ namespace RimWorldAnimationStudio
return true;
}
public void OnPointerClick(PointerEventData eventData)
{
Workspace.actorID = actorID;
Workspace.keyframeID.Clear();
}
}
}

View file

@ -382,6 +382,62 @@ namespace RimWorldAnimationStudio
}
public void PastePawnKeyframes()
{
List<int> actorsInvolved = Workspace.copiedKeyframes.Select(x => x.actorID)?.ToList();
actorsInvolved = actorsInvolved?.Distinct()?.ToList();
foreach (int i in actorsInvolved) { Debug.Log("Actor: " + i); }
if (actorsInvolved.NullOrEmpty()) { Debug.Log("Cannot paste keyframes - there were no copied keyframes to paste"); return; }
if (actorsInvolved.Count > 1 && actorsInvolved.Contains(Workspace.actorID) == false) { Debug.Log("Cannot paste keyframes - keyframes copied across multiple timelines can only be pasted back into these source timelines"); return; }
int earliestTick = actorsInvolved.Count == 1 ? Workspace.Instance.GetEarliestAtTickInCopiedKeyframes(actorsInvolved[0]) : Workspace.Instance.GetEarliestAtTickInCopiedKeyframes(Workspace.actorID);
if (earliestTick < 1) { Debug.Log("Unknown error occured during keyframe paste operation"); return; }
foreach (PawnKeyframe copiedKeyframe in Workspace.copiedKeyframes)
{
int tickToPasteAt = stageTick + (copiedKeyframe.atTick.Value - earliestTick);
if (tickToPasteAt < 1) continue;
if (tickToPasteAt > Workspace.StageWindowSize)
{
if (stretchkeyframesToggle.isOn)
{ ResizeStageWindowSize(tickToPasteAt); }
else continue;
}
int targetActorID = actorsInvolved.Count == 1 ? Workspace.actorID : copiedKeyframe.actorID;
if (Workspace.Instance.DoesPawnKeyframeExistAtTick(Workspace.stageID, targetActorID, tickToPasteAt))
{
PawnKeyframe oldKeyframe = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[targetActorID].keyframes.First(x => x.atTick == tickToPasteAt);
RemovePawnKeyframe(targetActorID, oldKeyframe.keyframeID, true);
}
PawnKeyframe clonedKeyframe = copiedKeyframe.Copy();
clonedKeyframe.GenerateKeyframeID(targetActorID);
clonedKeyframe.atTick = tickToPasteAt;
PawnAnimationClip clip = Workspace.animationDef.animationStages[Workspace.stageID].animationClips[targetActorID];
PawnKeyframe nextKeyframe = clip.keyframes.FirstOrDefault(x => x.atTick > stageTick);
if (nextKeyframe != null)
{ clip.keyframes.Insert(clip.keyframes.IndexOf(nextKeyframe), clonedKeyframe); }
else
{ clip.keyframes.Add(clonedKeyframe); }
clip.BuildSimpleCurves();
animationTimelines.GetComponentsInChildren<AnimationTimeline>()[clonedKeyframe.actorID].AddPawnKeyFrame(clonedKeyframe.keyframeID);
}
Workspace.Instance.RecordEvent("Keyframe pasted");
}
/*public void PastePawnKeyframes()
{
foreach (PawnKeyframe keyframe in Workspace.copiedKeyframes)
{
@ -413,7 +469,7 @@ namespace RimWorldAnimationStudio
}
Workspace.Instance.RecordEvent("Keyframe pasted");
}
}*/
public void RemovePawnKeyframe()
{
@ -507,13 +563,7 @@ namespace RimWorldAnimationStudio
}
}
animationClipLengthField.text = newStageWindowSize.ToString();
Workspace.animationDef.animationStages[Workspace.stageID].stageWindowSize = newStageWindowSize;
Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicks = newStageWindowSize * int.Parse(cyclesNormalField.text);
Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicksQuick = newStageWindowSize * int.Parse(cyclesFastField.text);
Workspace.Instance.RecordEvent("Stage length");
ResizeStageWindowSize(newStageWindowSize);
}
public void StretchKeyframes(int newStageWindowSize)
@ -532,6 +582,17 @@ namespace RimWorldAnimationStudio
}
}
public void ResizeStageWindowSize(int newStageWindowSize)
{
animationClipLengthField.text = newStageWindowSize.ToString();
Workspace.animationDef.animationStages[Workspace.stageID].stageWindowSize = newStageWindowSize;
Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicks = newStageWindowSize * int.Parse(cyclesNormalField.text);
Workspace.animationDef.animationStages[Workspace.stageID].playTimeTicksQuick = newStageWindowSize * int.Parse(cyclesFastField.text);
Workspace.Instance.RecordEvent("Stage length");
}
public void OnCycleNormalFieldChange()
{
if (Workspace.animationDef == null) return;

View file

@ -4,18 +4,24 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace RimWorldAnimationStudio
{
public class InputManager : Singleton<InputManager>
{
public Transform dialogBoxes;
public GameObject keyframeSelector;
private float lastUpdate = -1f;
private float timeBetweenUpdates = 0.15f;
private float largeStep = 0.1f;
private float smallStep = 0.03f;
private bool isDragging;
private Vector2 v0;
public bool CanRepeatThisUpdate()
{
if (Time.unscaledTime > lastUpdate + timeBetweenUpdates)
@ -55,6 +61,7 @@ namespace RimWorldAnimationStudio
bool canRepeatThisUpdate = CanRepeatThisUpdate();
// Check keybinds
foreach (Keybind keybind in KeybindConfig.Instance.GetAllKeybinds())
{
if (IsModifierKeyHeld() && keybind.keyModifiers.NullOrEmpty()) goto nextKeybind;
@ -73,6 +80,89 @@ namespace RimWorldAnimationStudio
nextKeybind:;
}
// Drag selection
if (Input.GetMouseButtonDown(0))
{ StartKeyframeSelectionDrag(); }
else if (Input.GetMouseButtonUp(0))
{ EndKeyframeSelectionDrag(); }
else if (isDragging)
{ UpdateKeyframeSelector(); }
else
{ HideKeyframeSelector(); }
}
public void StartKeyframeSelectionDrag()
{
PointerEventData pointer = new PointerEventData(EventSystem.current);
pointer.position = Input.mousePosition;
List<RaycastResult> raycastResults = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointer, raycastResults);
if (raycastResults.Count > 0)
{
foreach (var go in raycastResults)
{
//Debug.Log(go.gameObject);
if (go.gameObject?.GetComponent<Button>() != null) return;
if (go.gameObject?.GetComponent<IDragHandler>() != null) return;
if (go.gameObject?.GetComponentInParent<IDragHandler>() != null) return;
}
}
v0 = (Vector2)Input.mousePosition;
isDragging = true;
}
public void EndKeyframeSelectionDrag()
{
if (isDragging == false) return;
isDragging = false;
Vector2 v1 = (Vector2)Input.mousePosition;
List<int> keyframeIDs = new List<int>();
IEnumerable<KeyframeSlider> sliders = Selectable.allSelectablesArray.Select(x => x.GetComponent<KeyframeSlider>());
foreach (KeyframeSlider slider in sliders)
{
Transform handle = slider?.transform?.FindDeepChild("Handle");
if (handle == null) continue;
Vector2 vi = (Vector2)handle.GetComponent<RectTransform>().position;
if (vi.x < Mathf.Min(v0.x, v1.x)) continue;
if (vi.x > Mathf.Max(v0.x, v1.x)) continue;
if (vi.y < Mathf.Min(v0.y, v1.y)) continue;
if (vi.y > Mathf.Max(v0.y, v1.y)) continue;
keyframeIDs.Add(slider.keyframeID);
}
if (keyframeIDs.NotNullOrEmpty())
{ Workspace.keyframeID = keyframeIDs; }
}
public void UpdateKeyframeSelector()
{
Vector2 v1 = (Vector2)Input.mousePosition;
Vector2 pos = new Vector2(Mathf.Min(v0.x, v1.x), Mathf.Min(v0.y, v1.y));
Vector2 dim = new Vector2(Mathf.Abs(v1.x - v0.x), Mathf.Abs(v1.y - v0.y));
keyframeSelector.GetComponent<RectTransform>().anchoredPosition = pos;
keyframeSelector.GetComponent<RectTransform>().sizeDelta = dim;
if (keyframeSelector.activeSelf == false)
{ keyframeSelector.SetActive(true); }
}
public void HideKeyframeSelector()
{
if (keyframeSelector.activeSelf)
{ keyframeSelector.SetActive(false); }
}
public void QuitApplication()

View file

@ -194,6 +194,14 @@ namespace RimWorldAnimationStudio
return bestAtTick;
}
public int GetEarliestAtTickInCopiedKeyframes(int actorID)
{
IEnumerable<Keyframe> keyframes = copiedKeyframes.Where(x => x.actorID == actorID);
if (keyframes == null || keyframes.Any() == false) return -1;
return keyframes.Min(x => x.atTick).Value;
}
[SerializeField]
public LinkedList<HistoricRecord> pastSnapshots = new LinkedList<HistoricRecord>();
public LinkedList<HistoricRecord> futureSnapshots = new LinkedList<HistoricRecord>();