mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
New paste functions plus keyframe drag select
This commit is contained in:
parent
3d2c11f469
commit
f449a9b4e2
117 changed files with 399 additions and 81 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue