mirror of
https://gitgud.io/AbstractConcept/rimworld-animation-studio.git
synced 2024-08-15 00:43:27 +00:00
Initial commit
This commit is contained in:
commit
3c7cc0c973
8391 changed files with 704313 additions and 0 deletions
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class EaseClip : Manipulator
|
||||
{
|
||||
bool m_IsCaptured;
|
||||
bool m_UndoSaved;
|
||||
TimelineClipHandle m_EaseClipHandler;
|
||||
ManipulateEdges m_Edges;
|
||||
TimelineClip m_Clip;
|
||||
StringBuilder m_OverlayText = new StringBuilder("");
|
||||
double m_OriginalValue;
|
||||
|
||||
public static readonly string EaseInClipText = L10n.Tr("Ease In Clip");
|
||||
public static readonly string EaseOutClipText = L10n.Tr("Ease Out Clip");
|
||||
public static readonly string EaseInText = L10n.Tr("Ease In");
|
||||
public static readonly string EaseOutText = L10n.Tr("Ease Out");
|
||||
public static readonly string DurationFrameText = L10n.Tr(" Duration {0:0.00;-0.00} frames ");
|
||||
public static readonly string DurationSecText = L10n.Tr(" Duration {0:0.00;-0.00} s ");
|
||||
public static readonly string DeltaFrameText = L10n.Tr("({0:+0.00;-0.00} frames)");
|
||||
public static readonly string DeltaSecText = L10n.Tr("({0:+0.00;-0.00} s)");
|
||||
|
||||
protected override bool MouseDown(Event evt, WindowState state)
|
||||
{
|
||||
if (evt.modifiers != ManipulatorsUtils.actionModifier)
|
||||
return false;
|
||||
return MouseDownInternal(evt, state, PickerUtils.PickedLayerableOfType<TimelineClipHandle>());
|
||||
}
|
||||
|
||||
protected bool MouseDownInternal(Event evt, WindowState state, TimelineClipHandle handle)
|
||||
{
|
||||
if (handle == null)
|
||||
return false;
|
||||
|
||||
if (handle.clipGUI.clip != null && !handle.clipGUI.clip.clipCaps.HasAny(ClipCaps.Blending))
|
||||
return false;
|
||||
|
||||
m_Edges = ManipulateEdges.Right;
|
||||
if (handle.trimDirection == TrimEdge.Start)
|
||||
m_Edges = ManipulateEdges.Left;
|
||||
|
||||
if (m_Edges == ManipulateEdges.Left && handle.clipGUI.clip.hasBlendIn || m_Edges == ManipulateEdges.Right && handle.clipGUI.clip.hasBlendOut)
|
||||
return false;
|
||||
|
||||
m_IsCaptured = true;
|
||||
m_UndoSaved = false;
|
||||
|
||||
m_EaseClipHandler = handle;
|
||||
m_Clip = handle.clipGUI.clip;
|
||||
m_OriginalValue = m_Edges == ManipulateEdges.Left ? m_Clip.easeInDuration : m_Clip.easeOutDuration;
|
||||
|
||||
|
||||
// Change cursor only when OnGUI Process (not in test)
|
||||
if (GUIUtility.guiDepth > 0)
|
||||
TimelineCursors.SetCursor(m_Edges == ManipulateEdges.Left ? TimelineCursors.CursorType.MixRight : TimelineCursors.CursorType.MixLeft);
|
||||
|
||||
state.AddCaptured(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool MouseUp(Event evt, WindowState state)
|
||||
{
|
||||
if (!m_IsCaptured)
|
||||
return false;
|
||||
m_IsCaptured = false;
|
||||
m_UndoSaved = false;
|
||||
state.captured.Clear();
|
||||
|
||||
// Clear cursor only when OnGUI Process (not in test)
|
||||
if (GUIUtility.guiDepth > 0)
|
||||
TimelineCursors.ClearCursor();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool MouseDrag(Event evt, WindowState state)
|
||||
{
|
||||
if (!m_IsCaptured)
|
||||
return false;
|
||||
if (!m_UndoSaved)
|
||||
{
|
||||
var uiClip = m_EaseClipHandler.clipGUI;
|
||||
string undoName = m_Edges == ManipulateEdges.Left ? EaseInClipText : EaseOutClipText;
|
||||
TimelineUndo.PushUndo(uiClip.clip.parentTrack, undoName);
|
||||
m_UndoSaved = true;
|
||||
}
|
||||
|
||||
double d = state.PixelDeltaToDeltaTime(evt.delta.x);
|
||||
if (m_Edges == ManipulateEdges.Left)
|
||||
{
|
||||
m_Clip.easeInDuration = Math.Max(0, m_Clip.easeInDuration + d);
|
||||
}
|
||||
else if (m_Edges == ManipulateEdges.Right)
|
||||
{
|
||||
m_Clip.easeOutDuration = Math.Max(0, m_Clip.easeOutDuration - d);
|
||||
}
|
||||
RefreshOverlayStrings(m_EaseClipHandler, state);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Overlay(Event evt, WindowState state)
|
||||
{
|
||||
if (!m_IsCaptured)
|
||||
return;
|
||||
if (m_OverlayText.Length > 0)
|
||||
{
|
||||
int stringLength = m_OverlayText.Length;
|
||||
var r = new Rect(evt.mousePosition.x - (stringLength / 2.0f),
|
||||
m_EaseClipHandler.clipGUI.rect.yMax,
|
||||
stringLength, 20);
|
||||
GUI.Label(r, m_OverlayText.ToString(), TimelineWindow.styles.tinyFont);
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshOverlayStrings(TimelineClipHandle handle, WindowState state)
|
||||
{
|
||||
m_OverlayText.Length = 0;
|
||||
m_OverlayText.Append(m_Edges == ManipulateEdges.Left ? EaseInText : EaseOutText);
|
||||
double easeDuration = m_Edges == ManipulateEdges.Left ? m_Clip.easeInDuration : m_Clip.easeOutDuration;
|
||||
double deltaDuration = easeDuration - m_OriginalValue;
|
||||
bool hasDurationDelta = Math.Abs(deltaDuration) > double.Epsilon;
|
||||
if (state.timeInFrames)
|
||||
{
|
||||
easeDuration *= state.editSequence.frameRate;
|
||||
deltaDuration *= state.editSequence.frameRate;
|
||||
m_OverlayText.AppendFormat(DurationFrameText, easeDuration);
|
||||
if (hasDurationDelta)
|
||||
{
|
||||
m_OverlayText.AppendFormat(DeltaFrameText, deltaDuration);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OverlayText.AppendFormat(DurationSecText, easeDuration);
|
||||
if (hasDurationDelta)
|
||||
{
|
||||
m_OverlayText.AppendFormat(DeltaSecText, deltaDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b7cabea05434bb9479aee1e121b0d103
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,61 @@
|
|||
using UnityEditor.ShortcutManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class Jog : Manipulator
|
||||
{
|
||||
Vector2 m_MouseDownOrigin = Vector2.zero;
|
||||
|
||||
[ClutchShortcut("Timeline/Jog", typeof(TimelineWindow), KeyCode.J)]
|
||||
static void JogShortcut(ShortcutArguments args)
|
||||
{
|
||||
if (args.stage == ShortcutStage.Begin)
|
||||
{
|
||||
(args.context as TimelineWindow).state.isJogging = true;
|
||||
}
|
||||
else if (args.stage == ShortcutStage.End)
|
||||
{
|
||||
(args.context as TimelineWindow).state.isJogging = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool MouseDown(Event evt, WindowState state)
|
||||
{
|
||||
if (!state.isJogging)
|
||||
return false;
|
||||
|
||||
m_MouseDownOrigin = evt.mousePosition;
|
||||
state.playbackSpeed = 0.0f;
|
||||
state.Play();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool MouseUp(Event evt, WindowState state)
|
||||
{
|
||||
if (!state.isJogging)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_MouseDownOrigin = evt.mousePosition;
|
||||
state.playbackSpeed = 0.0f;
|
||||
state.Play();
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool MouseDrag(Event evt, WindowState state)
|
||||
{
|
||||
if (!state.isJogging)
|
||||
return false;
|
||||
|
||||
var distance = evt.mousePosition - m_MouseDownOrigin;
|
||||
|
||||
state.playbackSpeed = distance.x * 0.002f;
|
||||
state.Play();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 949b7e126b3f27940885a6808a15458e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Timeline;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class TimelineMarkerHeaderContextMenu : Manipulator
|
||||
{
|
||||
protected override bool ContextClick(Event evt, WindowState state)
|
||||
{
|
||||
if (!state.showMarkerHeader)
|
||||
return false;
|
||||
|
||||
if (!(state.GetWindow().markerHeaderRect.Contains(evt.mousePosition)
|
||||
|| state.GetWindow().markerContentRect.Contains(evt.mousePosition)))
|
||||
return false;
|
||||
|
||||
SequencerContextMenu.ShowMarkerHeaderContextMenu(evt.mousePosition, state);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e74ddf4132f3401409c824bed60280ee
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,36 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class RectangleSelect : RectangleTool
|
||||
{
|
||||
protected override bool enableAutoPan { get { return false; } }
|
||||
|
||||
protected override bool CanStartRectangle(Event evt, Vector2 mousePosition, WindowState state)
|
||||
{
|
||||
if (evt.button != 0 || evt.alt)
|
||||
return false;
|
||||
|
||||
return PickerUtils.pickedElements.All(e => e is IRowGUI);
|
||||
}
|
||||
|
||||
protected override bool OnFinish(Event evt, WindowState state, Rect rect)
|
||||
{
|
||||
var selectables = state.spacePartitioner.GetItemsInArea<ISelectable>(rect).ToList();
|
||||
|
||||
if (!selectables.Any())
|
||||
return false;
|
||||
|
||||
if (ItemSelection.CanClearSelection(evt))
|
||||
SelectionManager.Clear();
|
||||
|
||||
foreach (var selectable in selectables)
|
||||
{
|
||||
ItemSelection.HandleItemSelection(evt, selectable);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: edd4f4b395430604d935bcf0b14c7d42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,169 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
abstract class RectangleTool
|
||||
{
|
||||
struct TimelinePoint
|
||||
{
|
||||
readonly double m_Time;
|
||||
readonly float m_YPos;
|
||||
readonly float m_YScrollPos;
|
||||
|
||||
readonly WindowState m_State;
|
||||
readonly TimelineTreeViewGUI m_TreeViewGUI;
|
||||
|
||||
public TimelinePoint(WindowState state, Vector2 mousePosition)
|
||||
{
|
||||
m_State = state;
|
||||
m_TreeViewGUI = state.GetWindow().treeView;
|
||||
|
||||
m_Time = m_State.PixelToTime(mousePosition.x);
|
||||
m_YPos = mousePosition.y;
|
||||
m_YScrollPos = m_TreeViewGUI.scrollPosition.y;
|
||||
}
|
||||
|
||||
public Vector2 ToPixel()
|
||||
{
|
||||
return new Vector2(m_State.TimeToPixel(m_Time), m_YPos - (m_TreeViewGUI.scrollPosition.y - m_YScrollPos));
|
||||
}
|
||||
}
|
||||
|
||||
TimeAreaAutoPanner m_TimeAreaAutoPanner;
|
||||
|
||||
TimelinePoint m_StartPoint;
|
||||
Vector2 m_EndPixel = Vector2.zero;
|
||||
|
||||
Rect m_ActiveRect;
|
||||
|
||||
protected abstract bool enableAutoPan { get; }
|
||||
protected abstract bool CanStartRectangle(Event evt, Vector2 mousePosition, WindowState state);
|
||||
protected abstract bool OnFinish(Event evt, WindowState state, Rect rect);
|
||||
|
||||
int m_Id;
|
||||
|
||||
public void OnGUI(WindowState state, EventType rawType, Vector2 mousePosition)
|
||||
{
|
||||
if (m_Id == 0)
|
||||
m_Id = GUIUtility.GetPermanentControlID();
|
||||
|
||||
if (state == null || state.GetWindow().treeView == null)
|
||||
return;
|
||||
|
||||
var evt = Event.current;
|
||||
|
||||
if (rawType == EventType.MouseDown || evt.type == EventType.MouseDown)
|
||||
{
|
||||
if (state.IsCurrentEditingASequencerTextField())
|
||||
return;
|
||||
|
||||
m_ActiveRect = TimelineWindow.instance.sequenceContentRect;
|
||||
|
||||
if (!m_ActiveRect.Contains(mousePosition))
|
||||
return;
|
||||
|
||||
if (!CanStartRectangle(evt, mousePosition, state))
|
||||
return;
|
||||
|
||||
if (enableAutoPan)
|
||||
m_TimeAreaAutoPanner = new TimeAreaAutoPanner(state);
|
||||
|
||||
m_StartPoint = new TimelinePoint(state, mousePosition);
|
||||
m_EndPixel = mousePosition;
|
||||
|
||||
GUIUtility.hotControl = m_Id; //HACK: Because the treeView eats all the events, steal the hotControl if necessary...
|
||||
evt.Use();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (evt.GetTypeForControl(m_Id))
|
||||
{
|
||||
case EventType.KeyDown:
|
||||
{
|
||||
if (GUIUtility.hotControl == m_Id)
|
||||
{
|
||||
if (evt.keyCode == KeyCode.Escape)
|
||||
{
|
||||
m_TimeAreaAutoPanner = null;
|
||||
|
||||
GUIUtility.hotControl = 0;
|
||||
evt.Use();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case EventType.MouseDrag:
|
||||
{
|
||||
if (GUIUtility.hotControl != m_Id)
|
||||
return;
|
||||
|
||||
m_EndPixel = mousePosition;
|
||||
evt.Use();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case EventType.MouseUp:
|
||||
{
|
||||
if (GUIUtility.hotControl != m_Id)
|
||||
return;
|
||||
|
||||
m_TimeAreaAutoPanner = null;
|
||||
|
||||
var rect = CurrentRectangle();
|
||||
|
||||
if (IsValidRect(rect))
|
||||
OnFinish(evt, state, rect);
|
||||
|
||||
GUIUtility.hotControl = 0;
|
||||
evt.Use();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GUIUtility.hotControl == m_Id)
|
||||
{
|
||||
if (evt.type == EventType.Repaint)
|
||||
{
|
||||
var r = CurrentRectangle();
|
||||
|
||||
if (IsValidRect(r))
|
||||
{
|
||||
using (new GUIViewportScope(m_ActiveRect))
|
||||
{
|
||||
DrawRectangle(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_TimeAreaAutoPanner != null)
|
||||
m_TimeAreaAutoPanner.OnGUI(evt);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DrawRectangle(Rect rect)
|
||||
{
|
||||
EditorStyles.selectionRect.Draw(rect, GUIContent.none, false, false, false, false);
|
||||
}
|
||||
|
||||
static bool IsValidRect(Rect rect)
|
||||
{
|
||||
return rect.width >= 1.0f && rect.height >= 1.0f;
|
||||
}
|
||||
|
||||
Rect CurrentRectangle()
|
||||
{
|
||||
var startPixel = m_StartPoint.ToPixel();
|
||||
return Rect.MinMaxRect(
|
||||
Math.Min(startPixel.x, m_EndPixel.x),
|
||||
Math.Min(startPixel.y, m_EndPixel.y),
|
||||
Math.Max(startPixel.x, m_EndPixel.x),
|
||||
Math.Max(startPixel.y, m_EndPixel.y));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 24a7ce8b48db53747a4e8abbda77eac4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,23 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class RectangleZoom : RectangleTool
|
||||
{
|
||||
protected override bool enableAutoPan { get { return true; } }
|
||||
|
||||
protected override bool CanStartRectangle(Event evt, Vector2 mousePosition, WindowState state)
|
||||
{
|
||||
return evt.button == 1 && evt.modifiers == (EventModifiers.Alt | EventModifiers.Shift);
|
||||
}
|
||||
|
||||
protected override bool OnFinish(Event evt, WindowState state, Rect rect)
|
||||
{
|
||||
var x = state.PixelToTime(rect.xMin);
|
||||
var y = state.PixelToTime(rect.xMax);
|
||||
state.SetTimeAreaShownRange(x, y);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5aa8f57287fc17149bcd798be813180b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,297 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class ClearSelection : Manipulator
|
||||
{
|
||||
protected override bool MouseDown(Event evt, WindowState state)
|
||||
{
|
||||
// If we hit this point this means no one used the mouse down events. We can safely clear the selection if needed
|
||||
if (evt.button != 0)
|
||||
return false;
|
||||
|
||||
var window = state.GetWindow();
|
||||
|
||||
if (!window.sequenceRect.Contains(evt.mousePosition))
|
||||
return false;
|
||||
|
||||
if (ItemSelection.CanClearSelection(evt))
|
||||
{
|
||||
SelectionManager.Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static class ItemSelection
|
||||
{
|
||||
public static bool CanClearSelection(Event evt)
|
||||
{
|
||||
return !evt.control && !evt.command && !evt.shift;
|
||||
}
|
||||
|
||||
public static void RangeSelectItems(ITimelineItem lastItemToSelect)
|
||||
{
|
||||
var selectSorted = SelectionManager.SelectedItems().ToList();
|
||||
var firstSelect = selectSorted.FirstOrDefault();
|
||||
if (firstSelect == null)
|
||||
{
|
||||
SelectionManager.Add(lastItemToSelect);
|
||||
return;
|
||||
}
|
||||
|
||||
var allTracks = TimelineEditor.inspectedAsset.flattenedTracks;
|
||||
var allItems = allTracks.SelectMany(ItemsUtils.GetItems).ToList();
|
||||
TimelineHelpers.RangeSelect(allItems, selectSorted, lastItemToSelect, SelectionManager.Add, SelectionManager.Remove);
|
||||
}
|
||||
|
||||
public static ISelectable HandleSingleSelection(Event evt)
|
||||
{
|
||||
var item = PickerUtils.PickedLayerableOfType<ISelectable>();
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
var selected = item.IsSelected();
|
||||
if (!selected && CanClearSelection(evt))
|
||||
SelectionManager.Clear();
|
||||
|
||||
if (evt.modifiers == EventModifiers.Shift)
|
||||
{
|
||||
if (!selected)
|
||||
RangeSelectItems((item as TimelineItemGUI).item);
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleItemSelection(evt, item);
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public static void HandleItemSelection(Event evt, ISelectable item)
|
||||
{
|
||||
if (evt.modifiers == ManipulatorsUtils.actionModifier)
|
||||
{
|
||||
if (item.IsSelected())
|
||||
item.Deselect();
|
||||
else
|
||||
item.Select();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!item.IsSelected())
|
||||
item.Select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SelectAndMoveItem : Manipulator
|
||||
{
|
||||
bool m_Dragged;
|
||||
SnapEngine m_SnapEngine;
|
||||
TimeAreaAutoPanner m_TimeAreaAutoPanner;
|
||||
Vector2 m_MouseDownPosition;
|
||||
|
||||
bool m_HorizontalMovementDone;
|
||||
bool m_VerticalMovementDone;
|
||||
|
||||
MoveItemHandler m_MoveItemHandler;
|
||||
bool m_CycleMarkersPending;
|
||||
|
||||
protected override bool MouseDown(Event evt, WindowState state)
|
||||
{
|
||||
if (evt.alt || evt.button != 0)
|
||||
return false;
|
||||
|
||||
m_Dragged = false;
|
||||
|
||||
// Cycling markers and selection are mutually exclusive operations
|
||||
if (!HandleMarkerCycle() && !HandleSingleSelection(evt))
|
||||
return false;
|
||||
|
||||
m_MouseDownPosition = evt.mousePosition;
|
||||
m_VerticalMovementDone = false;
|
||||
m_HorizontalMovementDone = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool MouseUp(Event evt, WindowState state)
|
||||
{
|
||||
if (!m_Dragged)
|
||||
{
|
||||
var item = PickerUtils.PickedLayerableOfType<ISelectable>();
|
||||
|
||||
if (item == null)
|
||||
return false;
|
||||
|
||||
if (!item.IsSelected())
|
||||
return false;
|
||||
|
||||
// Re-selecting an item part of a multi-selection should only keep this item selected.
|
||||
if (SelectionManager.Count() > 1 && ItemSelection.CanClearSelection(evt))
|
||||
{
|
||||
SelectionManager.Clear();
|
||||
item.Select();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_CycleMarkersPending)
|
||||
{
|
||||
m_CycleMarkersPending = false;
|
||||
TimelineMarkerClusterGUI.CycleMarkers();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_TimeAreaAutoPanner = null;
|
||||
|
||||
DropItems();
|
||||
|
||||
m_SnapEngine = null;
|
||||
m_MoveItemHandler = null;
|
||||
|
||||
state.Evaluate();
|
||||
state.RemoveCaptured(this);
|
||||
m_Dragged = false;
|
||||
TimelineCursors.ClearCursor();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool DoubleClick(Event evt, WindowState state)
|
||||
{
|
||||
return MouseDown(evt, state) && MouseUp(evt, state);
|
||||
}
|
||||
|
||||
protected override bool MouseDrag(Event evt, WindowState state)
|
||||
{
|
||||
if (state.editSequence.isReadOnly)
|
||||
return false;
|
||||
|
||||
// case 1099285 - ctrl-click can cause no clips to be selected
|
||||
var selectedItemsGUI = SelectionManager.SelectedItems();
|
||||
if (!selectedItemsGUI.Any())
|
||||
{
|
||||
m_Dragged = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
const float hDeadZone = 5.0f;
|
||||
const float vDeadZone = 5.0f;
|
||||
|
||||
bool vDone = m_VerticalMovementDone || Math.Abs(evt.mousePosition.y - m_MouseDownPosition.y) > vDeadZone;
|
||||
bool hDone = m_HorizontalMovementDone || Math.Abs(evt.mousePosition.x - m_MouseDownPosition.x) > hDeadZone;
|
||||
|
||||
m_CycleMarkersPending = false;
|
||||
|
||||
if (!m_Dragged)
|
||||
{
|
||||
var canStartMove = vDone || hDone;
|
||||
|
||||
if (canStartMove)
|
||||
{
|
||||
state.AddCaptured(this);
|
||||
m_Dragged = true;
|
||||
|
||||
var referenceTrack = GetTrackDropTargetAt(state, m_MouseDownPosition);
|
||||
|
||||
foreach (var item in selectedItemsGUI)
|
||||
item.gui.StartDrag();
|
||||
|
||||
m_MoveItemHandler = new MoveItemHandler(state);
|
||||
|
||||
m_MoveItemHandler.Grab(selectedItemsGUI, referenceTrack, m_MouseDownPosition);
|
||||
|
||||
m_SnapEngine = new SnapEngine(m_MoveItemHandler, m_MoveItemHandler, ManipulateEdges.Both,
|
||||
state, m_MouseDownPosition);
|
||||
|
||||
m_TimeAreaAutoPanner = new TimeAreaAutoPanner(state);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_VerticalMovementDone)
|
||||
{
|
||||
m_VerticalMovementDone = vDone;
|
||||
|
||||
if (m_VerticalMovementDone)
|
||||
m_MoveItemHandler.OnTrackDetach();
|
||||
}
|
||||
|
||||
if (!m_HorizontalMovementDone)
|
||||
{
|
||||
m_HorizontalMovementDone = hDone;
|
||||
}
|
||||
|
||||
if (m_Dragged)
|
||||
{
|
||||
if (m_HorizontalMovementDone)
|
||||
m_SnapEngine.Snap(evt.mousePosition, evt.modifiers);
|
||||
|
||||
if (m_VerticalMovementDone)
|
||||
{
|
||||
var track = GetTrackDropTargetAt(state, evt.mousePosition);
|
||||
m_MoveItemHandler.UpdateTrackTarget(track);
|
||||
}
|
||||
|
||||
state.Evaluate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Overlay(Event evt, WindowState state)
|
||||
{
|
||||
if (!m_Dragged)
|
||||
return;
|
||||
|
||||
if (m_TimeAreaAutoPanner != null)
|
||||
m_TimeAreaAutoPanner.OnGUI(evt);
|
||||
|
||||
m_MoveItemHandler.OnGUI(evt);
|
||||
|
||||
if (!m_MoveItemHandler.allowTrackSwitch || m_MoveItemHandler.targetTrack != null)
|
||||
{
|
||||
TimeIndicator.Draw(state, m_MoveItemHandler.start, m_MoveItemHandler.end);
|
||||
m_SnapEngine.OnGUI();
|
||||
}
|
||||
}
|
||||
|
||||
bool HandleMarkerCycle()
|
||||
{
|
||||
m_CycleMarkersPending = TimelineMarkerClusterGUI.CanCycleMarkers();
|
||||
return m_CycleMarkersPending;
|
||||
}
|
||||
|
||||
bool HandleSingleSelection(Event evt)
|
||||
{
|
||||
return ItemSelection.HandleSingleSelection(evt) != null;
|
||||
}
|
||||
|
||||
void DropItems()
|
||||
{
|
||||
// Order matters here: m_MoveItemHandler.movingItems is destroyed during call to Drop()
|
||||
foreach (var movingItem in m_MoveItemHandler.movingItems)
|
||||
{
|
||||
foreach (var item in movingItem.items)
|
||||
item.gui.StopDrag();
|
||||
}
|
||||
|
||||
m_MoveItemHandler.Drop();
|
||||
}
|
||||
|
||||
static TrackAsset GetTrackDropTargetAt(WindowState state, Vector2 point)
|
||||
{
|
||||
var track = state.spacePartitioner.GetItemsAtPosition<IRowGUI>(point).FirstOrDefault();
|
||||
return track != null ? track.asset : null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f4f988528bbbb0846a4cb50efb4587a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,20 @@
|
|||
using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class TrackZoom : Manipulator
|
||||
{
|
||||
// only handles 'vertical' zoom. horizontal is handled in timelineGUI
|
||||
protected override bool MouseWheel(Event evt, WindowState state)
|
||||
{
|
||||
if (EditorGUI.actionKey)
|
||||
{
|
||||
state.trackScale = Mathf.Min(Mathf.Max(state.trackScale + (evt.delta.y * 0.1f), 1.0f), 100.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6e7c80eefe2def5459e0b486b3ab96e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,232 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class TrimClip : Manipulator
|
||||
{
|
||||
class TrimClipAttractionHandler : IAttractionHandler
|
||||
{
|
||||
public void OnAttractedEdge(IAttractable attractable, ManipulateEdges manipulateEdges, AttractedEdge edge, double time)
|
||||
{
|
||||
var clipGUI = attractable as TimelineClipGUI;
|
||||
if (clipGUI == null)
|
||||
return;
|
||||
|
||||
var clipItem = ItemsUtils.ToItem(clipGUI.clip);
|
||||
if (manipulateEdges == ManipulateEdges.Right)
|
||||
{
|
||||
bool affectTimeScale = Event.current.modifiers == EventModifiers.Shift; // TODO Do not use Event.current from here.
|
||||
EditMode.TrimEnd(clipItem, time, affectTimeScale);
|
||||
}
|
||||
else if (manipulateEdges == ManipulateEdges.Left)
|
||||
{
|
||||
EditMode.TrimStart(clipItem, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool m_IsCaptured;
|
||||
TimelineClipHandle m_TrimClipHandler;
|
||||
|
||||
double m_OriginalDuration;
|
||||
double m_OriginalTimeScale;
|
||||
bool m_UndoSaved;
|
||||
SnapEngine m_SnapEngine;
|
||||
|
||||
readonly StringBuilder m_OverlayText = new StringBuilder();
|
||||
readonly List<string> m_OverlayStrings = new List<string>();
|
||||
|
||||
static readonly double kEpsilon = 0.0000001;
|
||||
|
||||
protected override bool MouseDown(Event evt, WindowState state)
|
||||
{
|
||||
var handle = PickerUtils.PickedLayerableOfType<TimelineClipHandle>();
|
||||
if (handle == null)
|
||||
return false;
|
||||
|
||||
if (handle.clipGUI.clip.parentTrack != null && handle.clipGUI.clip.parentTrack.lockedInHierarchy)
|
||||
return false;
|
||||
|
||||
if (ItemSelection.CanClearSelection(evt))
|
||||
SelectionManager.Clear();
|
||||
|
||||
if (!SelectionManager.Contains(handle.clipGUI.clip))
|
||||
SelectionManager.Add(handle.clipGUI.clip);
|
||||
|
||||
m_TrimClipHandler = handle;
|
||||
|
||||
m_IsCaptured = true;
|
||||
state.AddCaptured(this);
|
||||
|
||||
m_UndoSaved = false;
|
||||
|
||||
var clip = m_TrimClipHandler.clipGUI.clip;
|
||||
|
||||
m_OriginalDuration = clip.duration;
|
||||
m_OriginalTimeScale = clip.timeScale;
|
||||
|
||||
RefreshOverlayStrings(m_TrimClipHandler, state);
|
||||
|
||||
// in ripple trim, the right edge moves and needs to snap
|
||||
var edges = ManipulateEdges.Right;
|
||||
if (EditMode.editType != EditMode.EditType.Ripple && m_TrimClipHandler.trimDirection == TrimEdge.Start)
|
||||
edges = ManipulateEdges.Left;
|
||||
m_SnapEngine = new SnapEngine(m_TrimClipHandler.clipGUI, new TrimClipAttractionHandler(), edges, state,
|
||||
evt.mousePosition);
|
||||
|
||||
EditMode.BeginTrim(ItemsUtils.ToItem(clip), m_TrimClipHandler.trimDirection);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool MouseUp(Event evt, WindowState state)
|
||||
{
|
||||
if (!m_IsCaptured)
|
||||
return false;
|
||||
|
||||
m_IsCaptured = false;
|
||||
m_TrimClipHandler = null;
|
||||
m_UndoSaved = false;
|
||||
m_SnapEngine = null;
|
||||
EditMode.FinishTrim();
|
||||
|
||||
state.captured.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool MouseDrag(Event evt, WindowState state)
|
||||
{
|
||||
if (state.editSequence.isReadOnly)
|
||||
return false;
|
||||
|
||||
if (!m_IsCaptured)
|
||||
return false;
|
||||
|
||||
if (!m_UndoSaved)
|
||||
{
|
||||
var uiClip = m_TrimClipHandler.clipGUI;
|
||||
TimelineUndo.PushUndo(uiClip.clip.parentTrack, "Trim Clip");
|
||||
if (TimelineUtility.IsRecordableAnimationClip(uiClip.clip))
|
||||
{
|
||||
TimelineUndo.PushUndo(uiClip.clip.animationClip, "Trim Clip");
|
||||
}
|
||||
|
||||
m_UndoSaved = true;
|
||||
}
|
||||
|
||||
if (m_SnapEngine != null)
|
||||
m_SnapEngine.Snap(evt.mousePosition, evt.modifiers);
|
||||
|
||||
RefreshOverlayStrings(m_TrimClipHandler, state);
|
||||
|
||||
if (Selection.activeObject != null)
|
||||
EditorUtility.SetDirty(Selection.activeObject);
|
||||
|
||||
// updates the duration of the graph without rebuilding
|
||||
state.UpdateRootPlayableDuration(state.editSequence.duration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Overlay(Event evt, WindowState state)
|
||||
{
|
||||
if (!m_IsCaptured)
|
||||
return;
|
||||
|
||||
EditMode.DrawTrimGUI(state, m_TrimClipHandler.clipGUI, m_TrimClipHandler.trimDirection);
|
||||
|
||||
bool trimStart = m_TrimClipHandler.trimDirection == TrimEdge.Start;
|
||||
|
||||
TimeIndicator.Draw(state, trimStart ? m_TrimClipHandler.clipGUI.start : m_TrimClipHandler.clipGUI.end);
|
||||
|
||||
if (m_SnapEngine != null)
|
||||
m_SnapEngine.OnGUI(trimStart, !trimStart);
|
||||
|
||||
if (m_OverlayStrings.Count > 0)
|
||||
{
|
||||
const float padding = 4.0f;
|
||||
var labelStyle = TimelineWindow.styles.tinyFont;
|
||||
var longestLine = labelStyle.CalcSize(
|
||||
new GUIContent(m_OverlayStrings.Aggregate("", (max, cur) => max.Length > cur.Length ? max : cur)));
|
||||
var stringLength = longestLine.x + padding;
|
||||
var lineHeight = longestLine.y + padding;
|
||||
|
||||
var r = new Rect(evt.mousePosition.x - (stringLength / 2.0f),
|
||||
m_TrimClipHandler.clipGUI.rect.yMax,
|
||||
stringLength, lineHeight);
|
||||
|
||||
foreach (var s in m_OverlayStrings)
|
||||
{
|
||||
GUI.Label(r, s, labelStyle);
|
||||
r.y += lineHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshOverlayStrings(TimelineClipHandle handle, WindowState state)
|
||||
{
|
||||
m_OverlayStrings.Clear();
|
||||
|
||||
m_OverlayText.Length = 0;
|
||||
|
||||
var differenceDuration = handle.clipGUI.clip.duration - m_OriginalDuration;
|
||||
bool hasDurationDelta = Math.Abs(differenceDuration) > kEpsilon;
|
||||
|
||||
if (state.timeInFrames)
|
||||
{
|
||||
var durationInFrame = handle.clipGUI.clip.duration * state.referenceSequence.frameRate;
|
||||
m_OverlayText.Append("duration: ").Append(durationInFrame.ToString("f2")).Append(" frames");
|
||||
|
||||
if (hasDurationDelta)
|
||||
{
|
||||
m_OverlayText.Append(" (");
|
||||
|
||||
if (differenceDuration > 0.0)
|
||||
m_OverlayText.Append("+");
|
||||
|
||||
var valueInFrame = differenceDuration * state.referenceSequence.frameRate;
|
||||
m_OverlayText.Append(valueInFrame.ToString("f2")).Append(" frames)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OverlayText.Append("duration: ").Append(handle.clipGUI.clip.duration.ToString("f2")).Append("s");
|
||||
|
||||
if (hasDurationDelta)
|
||||
{
|
||||
m_OverlayText.Append(" (");
|
||||
|
||||
if (differenceDuration > 0.0)
|
||||
m_OverlayText.Append("+");
|
||||
|
||||
m_OverlayText.Append(differenceDuration.ToString("f2")).Append("s)");
|
||||
}
|
||||
}
|
||||
|
||||
m_OverlayStrings.Add(m_OverlayText.ToString());
|
||||
|
||||
m_OverlayText.Length = 0;
|
||||
|
||||
var differenceSpeed = m_OriginalTimeScale - handle.clipGUI.clip.timeScale;
|
||||
if (Math.Abs(differenceSpeed) > kEpsilon)
|
||||
{
|
||||
m_OverlayText.Append("speed: ").Append(handle.clipGUI.clip.timeScale.ToString("p2"));
|
||||
|
||||
m_OverlayText.Append(" (");
|
||||
|
||||
if (differenceSpeed > 0.0)
|
||||
m_OverlayText.Append("+");
|
||||
|
||||
m_OverlayText.Append(differenceSpeed.ToString("p2")).Append(")");
|
||||
|
||||
m_OverlayStrings.Add(m_OverlayText.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 511aa760b8728a940a41c29837945292
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue