Unity-jump-proj
This commit is contained in:
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
interface ISelectable : ILayerable
|
||||
{
|
||||
void Select();
|
||||
bool IsSelected();
|
||||
void Deselect();
|
||||
bool CanSelect(UnityEngine.Event evt);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4acbfc0398bab674f922f693e58f4afc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,796 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Timeline;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class TimelineClipGUI : TimelineItemGUI, IClipCurveEditorOwner, ISnappable, IAttractable
|
||||
{
|
||||
EditorClip m_EditorItem;
|
||||
|
||||
Rect m_ClipCenterSection;
|
||||
readonly List<Rect> m_LoopRects = new List<Rect>();
|
||||
|
||||
ClipDrawData m_ClipDrawData;
|
||||
Rect m_MixOutRect;
|
||||
Rect m_MixInRect;
|
||||
int m_MinLoopIndex = 1;
|
||||
|
||||
// clip dirty detection
|
||||
int m_LastDirtyIndex = Int32.MinValue;
|
||||
bool m_ClipViewDirty = true;
|
||||
|
||||
bool supportResize { get; }
|
||||
public ClipCurveEditor clipCurveEditor { get; set; }
|
||||
public TimelineClipGUI previousClip { get; set; }
|
||||
public TimelineClipGUI nextClip { get; set; }
|
||||
|
||||
static readonly float k_MinMixWidth = 2;
|
||||
static readonly float k_MaxHandleWidth = 10f;
|
||||
static readonly float k_MinHandleWidth = 1f;
|
||||
|
||||
bool? m_ShowDrillIcon;
|
||||
ClipEditor m_ClipEditor;
|
||||
|
||||
static List<PlayableDirector> s_TempSubDirectors = new List<PlayableDirector>();
|
||||
|
||||
static readonly IconData k_DiggableClipIcon = new IconData(DirectorStyles.LoadIcon("TimelineDigIn"));
|
||||
|
||||
string name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(clip.displayName))
|
||||
return "(Empty)";
|
||||
|
||||
return clip.displayName;
|
||||
}
|
||||
}
|
||||
|
||||
public bool inlineCurvesSelected => SelectionManager.IsCurveEditorFocused(this);
|
||||
|
||||
public Rect mixOutRect
|
||||
{
|
||||
get
|
||||
{
|
||||
var percent = clip.mixOutPercentage;
|
||||
var x = Mathf.Round(treeViewRect.width * (1 - percent));
|
||||
var width = Mathf.Round(treeViewRect.width * percent);
|
||||
m_MixOutRect.Set(x, 0.0f, width, treeViewRect.height);
|
||||
return m_MixOutRect;
|
||||
}
|
||||
}
|
||||
|
||||
public Rect mixInRect
|
||||
{
|
||||
get
|
||||
{
|
||||
var width = Mathf.Round(treeViewRect.width * clip.mixInPercentage);
|
||||
m_MixInRect.Set(0.0f, 0.0f, width, treeViewRect.height);
|
||||
return m_MixInRect;
|
||||
}
|
||||
}
|
||||
|
||||
public ClipBlends GetClipBlends()
|
||||
{
|
||||
var _mixInRect = mixInRect;
|
||||
var _mixOutRect = mixOutRect;
|
||||
|
||||
var blendInKind = BlendKind.None;
|
||||
if (_mixInRect.width > k_MinMixWidth && clip.hasBlendIn)
|
||||
blendInKind = BlendKind.Mix;
|
||||
else if (_mixInRect.width > k_MinMixWidth)
|
||||
blendInKind = BlendKind.Ease;
|
||||
|
||||
var blendOutKind = BlendKind.None;
|
||||
if (_mixOutRect.width > k_MinMixWidth && clip.hasBlendOut)
|
||||
blendOutKind = BlendKind.Mix;
|
||||
else if (_mixOutRect.width > k_MinMixWidth)
|
||||
blendOutKind = BlendKind.Ease;
|
||||
|
||||
return new ClipBlends(blendInKind, _mixInRect, blendOutKind, _mixOutRect);
|
||||
}
|
||||
|
||||
public override double start
|
||||
{
|
||||
get { return clip.start; }
|
||||
}
|
||||
|
||||
public override double end
|
||||
{
|
||||
get { return clip.end; }
|
||||
}
|
||||
|
||||
public bool supportsLooping
|
||||
{
|
||||
get { return clip.SupportsLooping(); }
|
||||
}
|
||||
|
||||
// for the inline curve editor, only show loops if we recorded the asset
|
||||
bool IClipCurveEditorOwner.showLoops
|
||||
{
|
||||
get { return clip.SupportsLooping() && (clip.asset is AnimationPlayableAsset); }
|
||||
}
|
||||
|
||||
TrackAsset IClipCurveEditorOwner.owner
|
||||
{
|
||||
get { return clip.GetParentTrack(); }
|
||||
}
|
||||
|
||||
public bool supportsSubTimelines
|
||||
{
|
||||
get { return m_ClipEditor.supportsSubTimelines; }
|
||||
}
|
||||
|
||||
public int minLoopIndex
|
||||
{
|
||||
get { return m_MinLoopIndex; }
|
||||
}
|
||||
|
||||
public Rect clippedRect { get; private set; }
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
MoveToTop();
|
||||
SelectionManager.Add(clip);
|
||||
if (clipCurveEditor != null && SelectionManager.Count() == 1)
|
||||
SelectionManager.SelectInlineCurveEditor(this);
|
||||
}
|
||||
|
||||
public override bool IsSelected()
|
||||
{
|
||||
return SelectionManager.Contains(clip);
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
SelectionManager.Remove(clip);
|
||||
if (inlineCurvesSelected)
|
||||
SelectionManager.SelectInlineCurveEditor(null);
|
||||
}
|
||||
|
||||
public override bool CanSelect(Event evt)
|
||||
{
|
||||
ClipBlends clipBlends = GetClipBlends();
|
||||
Vector2 mousePos = evt.mousePosition - rect.position;
|
||||
return m_ClipCenterSection.Contains(mousePos) || IsPointLocatedInClipBlend(mousePos, clipBlends);
|
||||
}
|
||||
|
||||
static bool IsPointLocatedInClipBlend(Vector2 pt, ClipBlends blends)
|
||||
{
|
||||
if (blends.inRect.Contains(pt))
|
||||
{
|
||||
if (blends.inKind == BlendKind.Mix)
|
||||
return Sign(pt, blends.inRect.min, blends.inRect.max) < 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (blends.outRect.Contains(pt))
|
||||
{
|
||||
if (blends.outKind == BlendKind.Mix)
|
||||
return Sign(pt, blends.outRect.min, blends.outRect.max) >= 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static float Sign(Vector2 point, Vector2 linePoint1, Vector2 linePoint2)
|
||||
{
|
||||
return (point.x - linePoint2.x) * (linePoint1.y - linePoint2.y) - (linePoint1.x - linePoint2.x) * (point.y - linePoint2.y);
|
||||
}
|
||||
|
||||
public override ITimelineItem item
|
||||
{
|
||||
get { return ItemsUtils.ToItem(clip); }
|
||||
}
|
||||
|
||||
IZOrderProvider zOrderProvider { get; }
|
||||
|
||||
public TimelineClipHandle leftHandle { get; }
|
||||
public TimelineClipHandle rightHandle { get; }
|
||||
|
||||
public TimelineClipGUI(TimelineClip clip, IRowGUI parent, IZOrderProvider provider) : base(parent)
|
||||
{
|
||||
zOrderProvider = provider;
|
||||
zOrder = provider.Next();
|
||||
|
||||
m_EditorItem = EditorClipFactory.GetEditorClip(clip);
|
||||
m_ClipEditor = CustomTimelineEditorCache.GetClipEditor(clip);
|
||||
|
||||
supportResize = true;
|
||||
|
||||
leftHandle = new TimelineClipHandle(this, TrimEdge.Start);
|
||||
rightHandle = new TimelineClipHandle(this, TrimEdge.End);
|
||||
|
||||
ItemToItemGui.Add(clip, this);
|
||||
}
|
||||
|
||||
void CreateInlineCurveEditor(WindowState state)
|
||||
{
|
||||
if (clipCurveEditor != null)
|
||||
return;
|
||||
|
||||
var animationClip = clip.animationClip;
|
||||
|
||||
if (animationClip != null && animationClip.empty)
|
||||
animationClip = null;
|
||||
|
||||
// prune out clips coming from FBX
|
||||
if (animationClip != null && !clip.recordable)
|
||||
return; // don't show, even if there are curves
|
||||
|
||||
if (animationClip == null && !clip.HasAnyAnimatableParameters())
|
||||
return; // nothing to show
|
||||
|
||||
state.AddEndFrameDelegate((istate, currentEvent) =>
|
||||
{
|
||||
clipCurveEditor = new ClipCurveEditor(CurveDataSource.Create(this), TimelineWindow.instance, clip.GetParentTrack());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public TimelineClip clip
|
||||
{
|
||||
get { return m_EditorItem.clip; }
|
||||
}
|
||||
|
||||
// Draw the actual clip. Defers to the track drawer for customization
|
||||
void UpdateDrawData(WindowState state, Rect drawRect, string title, bool selected, bool previousClipSelected, float rectXOffset)
|
||||
{
|
||||
m_ClipDrawData.clip = clip;
|
||||
m_ClipDrawData.targetRect = drawRect;
|
||||
m_ClipDrawData.clipCenterSection = m_ClipCenterSection;
|
||||
m_ClipDrawData.unclippedRect = treeViewRect;
|
||||
m_ClipDrawData.title = title;
|
||||
m_ClipDrawData.selected = selected;
|
||||
m_ClipDrawData.inlineCurvesSelected = inlineCurvesSelected;
|
||||
m_ClipDrawData.previousClip = previousClip != null ? previousClip.clip : null;
|
||||
m_ClipDrawData.previousClipSelected = previousClipSelected;
|
||||
|
||||
Vector3 shownAreaTime = state.timeAreaShownRange;
|
||||
m_ClipDrawData.localVisibleStartTime = clip.ToLocalTimeUnbound(Math.Max(clip.start, shownAreaTime.x));
|
||||
m_ClipDrawData.localVisibleEndTime = clip.ToLocalTimeUnbound(Math.Min(clip.end, shownAreaTime.y));
|
||||
|
||||
m_ClipDrawData.clippedRect = new Rect(clippedRect.x - rectXOffset, 0.0f, clippedRect.width, clippedRect.height);
|
||||
|
||||
m_ClipDrawData.minLoopIndex = minLoopIndex;
|
||||
m_ClipDrawData.loopRects = m_LoopRects;
|
||||
m_ClipDrawData.supportsLooping = supportsLooping;
|
||||
m_ClipDrawData.clipBlends = GetClipBlends();
|
||||
m_ClipDrawData.clipEditor = m_ClipEditor;
|
||||
m_ClipDrawData.ClipDrawOptions = UpdateClipDrawOptions(m_ClipEditor, clip);
|
||||
|
||||
UpdateClipIcons(state);
|
||||
}
|
||||
|
||||
void UpdateClipIcons(WindowState state)
|
||||
{
|
||||
// Pass 1 - gather size
|
||||
int required = 0;
|
||||
bool requiresDigIn = ShowDrillIcon(state.editSequence.director);
|
||||
if (requiresDigIn)
|
||||
required++;
|
||||
|
||||
var icons = m_ClipDrawData.ClipDrawOptions.icons;
|
||||
foreach (var icon in icons)
|
||||
{
|
||||
if (icon != null)
|
||||
required++;
|
||||
}
|
||||
|
||||
// Pass 2 - copy icon data
|
||||
if (required == 0)
|
||||
{
|
||||
m_ClipDrawData.rightIcons = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ClipDrawData.rightIcons == null || m_ClipDrawData.rightIcons.Length != required)
|
||||
m_ClipDrawData.rightIcons = new IconData[required];
|
||||
|
||||
int index = 0;
|
||||
if (requiresDigIn)
|
||||
m_ClipDrawData.rightIcons[index++] = k_DiggableClipIcon;
|
||||
|
||||
foreach (var icon in icons)
|
||||
{
|
||||
if (icon != null)
|
||||
m_ClipDrawData.rightIcons[index++] = new IconData(icon);
|
||||
}
|
||||
}
|
||||
|
||||
static ClipDrawOptions UpdateClipDrawOptions(ClipEditor clipEditor, TimelineClip clip)
|
||||
{
|
||||
try
|
||||
{
|
||||
return clipEditor.GetClipOptions(clip);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
return CustomTimelineEditorCache.GetDefaultClipEditor().GetClipOptions(clip);
|
||||
}
|
||||
|
||||
static void DrawClip(ClipDrawData drawData)
|
||||
{
|
||||
ClipDrawer.DrawDefaultClip(drawData);
|
||||
|
||||
if (drawData.clip.asset is AnimationPlayableAsset)
|
||||
{
|
||||
var state = TimelineWindow.instance.state;
|
||||
if (state.recording && state.IsArmedForRecord(drawData.clip.GetParentTrack()))
|
||||
{
|
||||
ClipDrawer.DrawAnimationRecordBorder(drawData);
|
||||
ClipDrawer.DrawRecordProhibited(drawData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawGhostClip(Rect targetRect)
|
||||
{
|
||||
DrawSimpleClip(targetRect, ClipBorder.Selection(), new Color(1.0f, 1.0f, 1.0f, 0.5f));
|
||||
}
|
||||
|
||||
public void DrawInvalidClip(Rect targetRect)
|
||||
{
|
||||
DrawSimpleClip(targetRect, ClipBorder.Selection(), DirectorStyles.Instance.customSkin.colorInvalidClipOverlay);
|
||||
}
|
||||
|
||||
void DrawSimpleClip(Rect targetRect, ClipBorder border, Color overlay)
|
||||
{
|
||||
var drawOptions = UpdateClipDrawOptions(CustomTimelineEditorCache.GetClipEditor(clip), clip);
|
||||
ClipDrawer.DrawSimpleClip(clip, targetRect, border, overlay, drawOptions);
|
||||
}
|
||||
|
||||
void DrawInto(Rect drawRect, WindowState state)
|
||||
{
|
||||
if (Event.current.type != EventType.Repaint)
|
||||
return;
|
||||
|
||||
// create the inline curve editor if not already created
|
||||
CreateInlineCurveEditor(state);
|
||||
|
||||
// @todo optimization, most of the calculations (rect, offsets, colors, etc.) could be cached
|
||||
// and rebuilt when the hash of the clip changes.
|
||||
|
||||
if (isInvalid)
|
||||
{
|
||||
DrawInvalidClip(treeViewRect);
|
||||
return;
|
||||
}
|
||||
|
||||
GUI.BeginClip(drawRect);
|
||||
|
||||
var originRect = new Rect(0.0f, 0.0f, drawRect.width, drawRect.height);
|
||||
string clipLabel = name;
|
||||
var selected = SelectionManager.Contains(clip);
|
||||
var previousClipSelected = previousClip != null && SelectionManager.Contains(previousClip.clip);
|
||||
|
||||
if (selected && 1.0 != clip.timeScale)
|
||||
clipLabel += " " + clip.timeScale.ToString("F2") + "x";
|
||||
|
||||
UpdateDrawData(state, originRect, clipLabel, selected, previousClipSelected, drawRect.x);
|
||||
DrawClip(m_ClipDrawData);
|
||||
|
||||
GUI.EndClip();
|
||||
|
||||
if (clip.GetParentTrack() != null && !clip.GetParentTrack().lockedInHierarchy)
|
||||
{
|
||||
if (selected && supportResize)
|
||||
{
|
||||
var cursorRect = rect;
|
||||
cursorRect.xMin += leftHandle.boundingRect.width;
|
||||
cursorRect.xMax -= rightHandle.boundingRect.width;
|
||||
EditorGUIUtility.AddCursorRect(cursorRect, MouseCursor.MoveArrow);
|
||||
}
|
||||
|
||||
if (supportResize)
|
||||
{
|
||||
var handleWidth = Mathf.Clamp(drawRect.width * 0.3f, k_MinHandleWidth, k_MaxHandleWidth);
|
||||
|
||||
leftHandle.Draw(drawRect, handleWidth, state);
|
||||
rightHandle.Draw(drawRect, handleWidth, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalculateClipRectangle(Rect trackRect, WindowState state)
|
||||
{
|
||||
if (m_ClipViewDirty)
|
||||
{
|
||||
var clipRect = RectToTimeline(trackRect, state);
|
||||
treeViewRect = clipRect;
|
||||
|
||||
// calculate clipped rect
|
||||
clipRect.xMin = Mathf.Max(clipRect.xMin, trackRect.xMin);
|
||||
clipRect.xMax = Mathf.Min(clipRect.xMax, trackRect.xMax);
|
||||
|
||||
if (clipRect.width > 0 && clipRect.width < 2)
|
||||
{
|
||||
clipRect.width = 5.0f;
|
||||
}
|
||||
|
||||
clippedRect = clipRect;
|
||||
}
|
||||
}
|
||||
|
||||
void AddToSpacePartitioner(WindowState state)
|
||||
{
|
||||
if (Event.current.type == EventType.Repaint && !parent.locked)
|
||||
state.spacePartitioner.AddBounds(this, rect);
|
||||
}
|
||||
|
||||
void CalculateBlendRect()
|
||||
{
|
||||
m_ClipCenterSection = treeViewRect;
|
||||
m_ClipCenterSection.x = 0;
|
||||
m_ClipCenterSection.y = 0;
|
||||
|
||||
m_ClipCenterSection.xMin = mixInRect.xMax;
|
||||
m_ClipCenterSection.width = Mathf.Round(treeViewRect.width - mixInRect.width - mixOutRect.width);
|
||||
m_ClipCenterSection.xMax = m_ClipCenterSection.xMin + m_ClipCenterSection.width;
|
||||
}
|
||||
|
||||
// Entry point to the Clip Drawing...
|
||||
public override void Draw(Rect trackRect, bool trackRectChanged, WindowState state)
|
||||
{
|
||||
// if the clip has changed, fire the appropriate callback
|
||||
DetectClipChanged(trackRectChanged);
|
||||
|
||||
// update the clip projected rectangle on the timeline
|
||||
CalculateClipRectangle(trackRect, state);
|
||||
|
||||
AddToSpacePartitioner(state);
|
||||
|
||||
// update the blend rects (when clip overlaps with others)
|
||||
CalculateBlendRect();
|
||||
|
||||
// update the loop rects (when clip loops)
|
||||
CalculateLoopRects(trackRect, state);
|
||||
|
||||
DrawExtrapolation(trackRect, treeViewRect);
|
||||
|
||||
DrawInto(treeViewRect, state);
|
||||
|
||||
ResetClipChanged();
|
||||
}
|
||||
|
||||
void DetectClipChanged(bool trackRectChanged)
|
||||
{
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
if (clip.DirtyIndex != m_LastDirtyIndex)
|
||||
{
|
||||
m_ClipViewDirty = true;
|
||||
|
||||
try
|
||||
{
|
||||
m_ClipEditor.OnClipChanged(clip);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
m_LastDirtyIndex = clip.DirtyIndex;
|
||||
}
|
||||
m_ClipViewDirty |= trackRectChanged;
|
||||
}
|
||||
}
|
||||
|
||||
void ResetClipChanged()
|
||||
{
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
m_ClipViewDirty = false;
|
||||
}
|
||||
|
||||
internal void MoveToTop()
|
||||
{
|
||||
zOrder = zOrderProvider.Next();
|
||||
}
|
||||
|
||||
GUIStyle GetExtrapolationIcon(TimelineClip.ClipExtrapolation mode)
|
||||
{
|
||||
GUIStyle extrapolationIcon = null;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case TimelineClip.ClipExtrapolation.None: return null;
|
||||
case TimelineClip.ClipExtrapolation.Hold: extrapolationIcon = m_Styles.extrapolationHold; break;
|
||||
case TimelineClip.ClipExtrapolation.Loop: extrapolationIcon = m_Styles.extrapolationLoop; break;
|
||||
case TimelineClip.ClipExtrapolation.PingPong: extrapolationIcon = m_Styles.extrapolationPingPong; break;
|
||||
case TimelineClip.ClipExtrapolation.Continue: extrapolationIcon = m_Styles.extrapolationContinue; break;
|
||||
}
|
||||
|
||||
return extrapolationIcon;
|
||||
}
|
||||
|
||||
Rect GetPreExtrapolationBounds(Rect trackRect, Rect clipRect, GUIStyle icon)
|
||||
{
|
||||
float x = clipRect.xMin - (icon.fixedWidth + 10.0f);
|
||||
float y = trackRect.yMin + (trackRect.height - icon.fixedHeight) / 2.0f;
|
||||
|
||||
if (previousClip != null)
|
||||
{
|
||||
float distance = Mathf.Abs(treeViewRect.xMin - previousClip.treeViewRect.xMax);
|
||||
|
||||
if (distance < icon.fixedWidth)
|
||||
return new Rect(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (distance < icon.fixedWidth + 20.0f)
|
||||
{
|
||||
float delta = (distance - icon.fixedWidth) / 2.0f;
|
||||
x = clipRect.xMin - (icon.fixedWidth + delta);
|
||||
}
|
||||
}
|
||||
|
||||
return new Rect(x, y, icon.fixedWidth, icon.fixedHeight);
|
||||
}
|
||||
|
||||
Rect GetPostExtrapolationBounds(Rect trackRect, Rect clipRect, GUIStyle icon)
|
||||
{
|
||||
float x = clipRect.xMax + 10.0f;
|
||||
float y = trackRect.yMin + (trackRect.height - icon.fixedHeight) / 2.0f;
|
||||
|
||||
if (nextClip != null)
|
||||
{
|
||||
float distance = Mathf.Abs(nextClip.treeViewRect.xMin - treeViewRect.xMax);
|
||||
|
||||
if (distance < icon.fixedWidth)
|
||||
return new Rect(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (distance < icon.fixedWidth + 20.0f)
|
||||
{
|
||||
float delta = (distance - icon.fixedWidth) / 2.0f;
|
||||
x = clipRect.xMax + delta;
|
||||
}
|
||||
}
|
||||
|
||||
return new Rect(x, y, icon.fixedWidth, icon.fixedHeight);
|
||||
}
|
||||
|
||||
static void DrawExtrapolationIcon(Rect rect, GUIStyle icon)
|
||||
{
|
||||
GUI.Label(rect, GUIContent.none, icon);
|
||||
}
|
||||
|
||||
void DrawExtrapolation(Rect trackRect, Rect clipRect)
|
||||
{
|
||||
if (clip.hasPreExtrapolation)
|
||||
{
|
||||
GUIStyle icon = GetExtrapolationIcon(clip.preExtrapolationMode);
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
Rect iconBounds = GetPreExtrapolationBounds(trackRect, clipRect, icon);
|
||||
|
||||
if (iconBounds.width > 1 && iconBounds.height > 1)
|
||||
DrawExtrapolationIcon(iconBounds, icon);
|
||||
}
|
||||
}
|
||||
|
||||
if (clip.hasPostExtrapolation)
|
||||
{
|
||||
GUIStyle icon = GetExtrapolationIcon(clip.postExtrapolationMode);
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
Rect iconBounds = GetPostExtrapolationBounds(trackRect, clipRect, icon);
|
||||
|
||||
if (iconBounds.width > 1 && iconBounds.height > 1)
|
||||
DrawExtrapolationIcon(iconBounds, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Rect ProjectRectOnTimeline(Rect rect, Rect trackRect, WindowState state)
|
||||
{
|
||||
Rect newRect = rect;
|
||||
// transform clipRect into pixel-space
|
||||
newRect.x *= state.timeAreaScale.x;
|
||||
newRect.width *= state.timeAreaScale.x;
|
||||
|
||||
newRect.x += state.timeAreaTranslation.x + trackRect.xMin;
|
||||
|
||||
// adjust clipRect height and vertical centering
|
||||
const int clipPadding = 2;
|
||||
newRect.y = trackRect.y + clipPadding;
|
||||
newRect.height = trackRect.height - (2 * clipPadding);
|
||||
return newRect;
|
||||
}
|
||||
|
||||
void CalculateLoopRects(Rect trackRect, WindowState state)
|
||||
{
|
||||
if (!m_ClipViewDirty)
|
||||
return;
|
||||
|
||||
m_LoopRects.Clear();
|
||||
if (clip.duration < WindowState.kTimeEpsilon)
|
||||
return;
|
||||
|
||||
var times = TimelineHelpers.GetLoopTimes(clip);
|
||||
var loopDuration = TimelineHelpers.GetLoopDuration(clip);
|
||||
m_MinLoopIndex = -1;
|
||||
|
||||
// we have a hold, no need to compute all loops
|
||||
if (!supportsLooping)
|
||||
{
|
||||
if (times.Length > 1)
|
||||
{
|
||||
var t = times[1];
|
||||
float loopTime = (float)(clip.duration - t);
|
||||
m_LoopRects.Add(ProjectRectOnTimeline(new Rect((float)(t + clip.start), 0, loopTime, 0), trackRect, state));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var range = state.timeAreaShownRange;
|
||||
var visibleStartTime = range.x - clip.start;
|
||||
var visibleEndTime = range.y - clip.start;
|
||||
|
||||
for (int i = 1; i < times.Length; i++)
|
||||
{
|
||||
var t = times[i];
|
||||
|
||||
// don't draw off screen loops
|
||||
if (t > visibleEndTime)
|
||||
break;
|
||||
|
||||
float loopTime = Mathf.Min((float)(clip.duration - t), (float)loopDuration);
|
||||
var loopEnd = t + loopTime;
|
||||
|
||||
if (loopEnd < visibleStartTime)
|
||||
continue;
|
||||
|
||||
m_LoopRects.Add(ProjectRectOnTimeline(new Rect((float)(t + clip.start), 0, loopTime, 0), trackRect, state));
|
||||
|
||||
if (m_MinLoopIndex == -1)
|
||||
m_MinLoopIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
public override Rect RectToTimeline(Rect trackRect, WindowState state)
|
||||
{
|
||||
var offsetFromTimeSpaceToPixelSpace = state.timeAreaTranslation.x + trackRect.xMin;
|
||||
|
||||
var start = (float)(DiscreteTime)clip.start;
|
||||
var end = (float)(DiscreteTime)clip.end;
|
||||
|
||||
return Rect.MinMaxRect(
|
||||
Mathf.Round(start * state.timeAreaScale.x + offsetFromTimeSpaceToPixelSpace), Mathf.Round(trackRect.yMin),
|
||||
Mathf.Round(end * state.timeAreaScale.x + offsetFromTimeSpaceToPixelSpace), Mathf.Round(trackRect.yMax)
|
||||
);
|
||||
}
|
||||
|
||||
public IEnumerable<Edge> SnappableEdgesFor(IAttractable attractable, ManipulateEdges manipulateEdges)
|
||||
{
|
||||
var edges = new List<Edge>();
|
||||
|
||||
bool canAddEdges = !parent.muted;
|
||||
|
||||
if (canAddEdges)
|
||||
{
|
||||
// Hack: Trim Start in Ripple mode should not have any snap point added
|
||||
if (EditMode.editType == EditMode.EditType.Ripple && manipulateEdges == ManipulateEdges.Left)
|
||||
return edges;
|
||||
|
||||
if (attractable != this)
|
||||
{
|
||||
if (EditMode.editType == EditMode.EditType.Ripple)
|
||||
{
|
||||
bool skip = false;
|
||||
|
||||
// Hack: Since Trim End and Move in Ripple mode causes other snap point to move on the same track (which is not supported), disable snapping for this special cases...
|
||||
// TODO Find a proper way to have different snap edges for each edit mode.
|
||||
if (manipulateEdges == ManipulateEdges.Right)
|
||||
{
|
||||
var otherClipGUI = attractable as TimelineClipGUI;
|
||||
skip = otherClipGUI != null && otherClipGUI.parent == parent;
|
||||
}
|
||||
else if (manipulateEdges == ManipulateEdges.Both)
|
||||
{
|
||||
var moveHandler = attractable as MoveItemHandler;
|
||||
skip = moveHandler != null && moveHandler.movingItems.Any(clips => clips.targetTrack == clip.GetParentTrack() && clip.start >= clips.start);
|
||||
}
|
||||
|
||||
if (skip)
|
||||
return edges;
|
||||
}
|
||||
|
||||
AddEdge(edges, clip.start);
|
||||
AddEdge(edges, clip.end);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (manipulateEdges == ManipulateEdges.Right)
|
||||
{
|
||||
var d = TimelineHelpers.GetClipAssetEndTime(clip);
|
||||
|
||||
if (d < double.MaxValue)
|
||||
{
|
||||
if (clip.SupportsLooping())
|
||||
{
|
||||
var l = TimelineHelpers.GetLoopDuration(clip);
|
||||
|
||||
var shownTime = TimelineWindow.instance.state.timeAreaShownRange;
|
||||
do
|
||||
{
|
||||
AddEdge(edges, d, false);
|
||||
d += l;
|
||||
}
|
||||
while (d < shownTime.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddEdge(edges, d, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manipulateEdges == ManipulateEdges.Left)
|
||||
{
|
||||
var clipInfo = AnimationClipCurveCache.Instance.GetCurveInfo(clip.animationClip);
|
||||
if (clipInfo != null && clipInfo.keyTimes.Any())
|
||||
AddEdge(edges, clip.FromLocalTimeUnbound(clipInfo.keyTimes.Min()), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return edges;
|
||||
}
|
||||
|
||||
public bool ShouldSnapTo(ISnappable snappable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShowDrillIcon(PlayableDirector resolver)
|
||||
{
|
||||
if (!m_ShowDrillIcon.HasValue || TimelineWindow.instance.hierarchyChangedThisFrame)
|
||||
{
|
||||
var nestable = m_ClipEditor.supportsSubTimelines;
|
||||
m_ShowDrillIcon = nestable && resolver != null;
|
||||
if (m_ShowDrillIcon.Value)
|
||||
{
|
||||
s_TempSubDirectors.Clear();
|
||||
try
|
||||
{
|
||||
m_ClipEditor.GetSubTimelines(clip, resolver, s_TempSubDirectors);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
}
|
||||
|
||||
m_ShowDrillIcon &= s_TempSubDirectors.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
return m_ShowDrillIcon.Value;
|
||||
}
|
||||
|
||||
static void AddEdge(List<Edge> edges, double time, bool showEdgeHint = true)
|
||||
{
|
||||
var shownTime = TimelineWindow.instance.state.timeAreaShownRange;
|
||||
if (time >= shownTime.x && time <= shownTime.y)
|
||||
edges.Add(new Edge(time, showEdgeHint));
|
||||
}
|
||||
|
||||
public void SelectCurves()
|
||||
{
|
||||
SelectionManager.SelectOnly(clip);
|
||||
SelectionManager.SelectInlineCurveEditor(this);
|
||||
}
|
||||
|
||||
public void ValidateCurvesSelection()
|
||||
{
|
||||
if (!IsSelected()) //if clip is not selected, deselect the inline curve
|
||||
SelectionManager.SelectInlineCurveEditor(null);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c01b61b3a6887c49a15276fd38be918
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Timeline;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
static class ItemToItemGui
|
||||
{
|
||||
static Dictionary<object, TimelineItemGUI> s_ItemToItemGUI =
|
||||
new Dictionary<object, TimelineItemGUI>();
|
||||
|
||||
public static void Add(TimelineClip clip, TimelineItemGUI gui)
|
||||
{
|
||||
s_ItemToItemGUI[clip] = gui;
|
||||
}
|
||||
|
||||
public static void Add(IMarker marker, TimelineItemGUI gui)
|
||||
{
|
||||
s_ItemToItemGUI[marker] = gui;
|
||||
}
|
||||
|
||||
public static TimelineClipGUI GetGuiForClip(TimelineClip clip)
|
||||
{
|
||||
return GetGuiForItem(clip) as TimelineClipGUI;
|
||||
}
|
||||
|
||||
public static TimelineMarkerGUI GetGuiForMarker(IMarker marker)
|
||||
{
|
||||
return GetGuiForItem(marker) as TimelineMarkerGUI;
|
||||
}
|
||||
|
||||
static TimelineItemGUI GetGuiForItem(object item)
|
||||
{
|
||||
if (item == null)
|
||||
return null;
|
||||
|
||||
TimelineItemGUI gui;
|
||||
s_ItemToItemGUI.TryGetValue(item, out gui);
|
||||
return gui;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TimelineItemGUI : ISelectable
|
||||
{
|
||||
protected readonly DirectorStyles m_Styles;
|
||||
|
||||
public abstract ITimelineItem item { get; }
|
||||
public abstract double start { get; }
|
||||
public abstract double end { get; }
|
||||
public abstract void Draw(Rect rect, bool rectChanged, WindowState state);
|
||||
public abstract Rect RectToTimeline(Rect trackRect, WindowState state);
|
||||
|
||||
public virtual void Select() { }
|
||||
public virtual bool IsSelected() { return false; }
|
||||
public virtual void Deselect() { }
|
||||
public virtual bool CanSelect(Event evt) { return true; }
|
||||
|
||||
public virtual void StartDrag() { }
|
||||
public virtual void StopDrag() { }
|
||||
|
||||
public LayerZOrder zOrder { get; set; }
|
||||
|
||||
public bool visible { get; set; }
|
||||
public bool isInvalid { get; set; }
|
||||
|
||||
public IRowGUI parent { get; }
|
||||
|
||||
public Rect rect
|
||||
{
|
||||
get { return parent.ToWindowSpace(treeViewRect); }
|
||||
}
|
||||
|
||||
public Rect treeViewRect
|
||||
{
|
||||
get { return m_TreeViewRect; }
|
||||
protected set
|
||||
{
|
||||
m_TreeViewRect = value;
|
||||
if (value.width < 0.0f)
|
||||
m_TreeViewRect.width = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Rect m_TreeViewRect;
|
||||
|
||||
protected TimelineItemGUI(IRowGUI parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
m_Styles = DirectorStyles.Instance;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f515f8ecd3b6a546b90abaae2553f99
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
using UnityObject = UnityEngine.Object;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class TimelineMarkerClusterGUI : TimelineItemGUI
|
||||
{
|
||||
readonly List<TimelineMarkerGUI> m_MarkerGUIs;
|
||||
readonly IZOrderProvider m_ZOrderProvider;
|
||||
|
||||
public TimelineMarkerGUI topMarker
|
||||
{
|
||||
get { return m_MarkerGUIs.LastOrDefault(); }
|
||||
}
|
||||
|
||||
TimelineMarkerGUI m_ManipulatedMarker;
|
||||
|
||||
public TimelineMarkerClusterGUI(List<TimelineMarkerGUI> guis, IRowGUI parent,
|
||||
IZOrderProvider zOrderProvider, LayerZOrder layerZOrder)
|
||||
: base(parent)
|
||||
{
|
||||
m_MarkerGUIs = guis;
|
||||
m_ZOrderProvider = zOrderProvider;
|
||||
zOrder = layerZOrder;
|
||||
SortMarkers();
|
||||
topMarker.onStartDrag += OnDragTopMarker;
|
||||
}
|
||||
|
||||
public override double start
|
||||
{
|
||||
get { return topMarker.start; }
|
||||
}
|
||||
|
||||
public override double end
|
||||
{
|
||||
get { return topMarker.end; }
|
||||
}
|
||||
|
||||
public override ITimelineItem item
|
||||
{
|
||||
get { return topMarker.item; }
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
foreach (var marker in m_MarkerGUIs)
|
||||
{
|
||||
if (!marker.IsSelected())
|
||||
marker.Select();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
foreach (var marker in m_MarkerGUIs)
|
||||
{
|
||||
if (marker.IsSelected())
|
||||
marker.Deselect();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(Rect trackRect, bool trackRectChanged, WindowState state)
|
||||
{
|
||||
RegisterRect(state);
|
||||
|
||||
topMarker.Draw(trackRect, trackRectChanged, state);
|
||||
|
||||
if (m_MarkerGUIs.Count > 1)
|
||||
GUI.Box(treeViewRect, String.Empty, DirectorStyles.Instance.markerMultiOverlay);
|
||||
|
||||
if (m_ManipulatedMarker != null)
|
||||
m_ManipulatedMarker.Draw(trackRect, trackRectChanged, state);
|
||||
}
|
||||
|
||||
public override Rect RectToTimeline(Rect trackRect, WindowState state)
|
||||
{
|
||||
return topMarker.RectToTimeline(trackRect, state);
|
||||
}
|
||||
|
||||
public void CycleTop()
|
||||
{
|
||||
if (m_MarkerGUIs.Count < 2)
|
||||
return;
|
||||
|
||||
topMarker.onStartDrag -= OnDragTopMarker;
|
||||
|
||||
var last = topMarker;
|
||||
for (int i = 0; i < m_MarkerGUIs.Count; ++i)
|
||||
{
|
||||
var next = m_MarkerGUIs[i];
|
||||
m_MarkerGUIs[i] = last;
|
||||
last = next;
|
||||
}
|
||||
|
||||
topMarker.zOrder = m_ZOrderProvider.Next();
|
||||
|
||||
topMarker.onStartDrag += OnDragTopMarker;
|
||||
}
|
||||
|
||||
void OnDragTopMarker()
|
||||
{
|
||||
m_ManipulatedMarker = topMarker;
|
||||
m_ManipulatedMarker.onStartDrag -= OnDragTopMarker;
|
||||
m_MarkerGUIs.RemoveAt(m_MarkerGUIs.Count - 1);
|
||||
}
|
||||
|
||||
void SortMarkers()
|
||||
{
|
||||
m_MarkerGUIs.Sort((lhs, rhs) => lhs.zOrder.CompareTo(rhs.zOrder));
|
||||
}
|
||||
|
||||
void RegisterRect(WindowState state)
|
||||
{
|
||||
treeViewRect = topMarker.treeViewRect;
|
||||
|
||||
if (Event.current.type == EventType.Repaint && !parent.locked)
|
||||
state.spacePartitioner.AddBounds(this, rect);
|
||||
}
|
||||
|
||||
public static bool CanCycleMarkers()
|
||||
{
|
||||
if (!SelectionManager.SelectedMarkers().Any())
|
||||
return false;
|
||||
|
||||
var cluster = PickerUtils.TopmostPickedItemOfType<TimelineMarkerClusterGUI>();
|
||||
|
||||
if (cluster == null)
|
||||
return false;
|
||||
|
||||
// Only cycle if the marker is selected and nothing else is selected
|
||||
return cluster.topMarker.IsSelected() && SelectionManager.Count() == 1;
|
||||
}
|
||||
|
||||
public static void CycleMarkers()
|
||||
{
|
||||
var cluster = PickerUtils.TopmostPickedItemOfType<TimelineMarkerClusterGUI>();
|
||||
|
||||
if (cluster == null)
|
||||
return;
|
||||
|
||||
cluster.topMarker.Deselect();
|
||||
cluster.CycleTop();
|
||||
cluster.topMarker.Select();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c03ae9aa36a4fd44a983831f44654be
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Timeline;
|
||||
using UnityObject = UnityEngine.Object;
|
||||
|
||||
namespace UnityEditor.Timeline
|
||||
{
|
||||
class TimelineMarkerGUI : TimelineItemGUI, ISnappable, IAttractable
|
||||
{
|
||||
public event System.Action onStartDrag;
|
||||
|
||||
int m_ProjectedClipHash = -1;
|
||||
int m_MarkerHash;
|
||||
bool m_Selectable;
|
||||
|
||||
MarkerDrawOptions m_MarkerDrawOptions;
|
||||
MarkerEditor m_Editor;
|
||||
|
||||
IMarker marker { get; }
|
||||
|
||||
bool selectable
|
||||
{
|
||||
get { return m_Selectable; }
|
||||
}
|
||||
|
||||
public double time
|
||||
{
|
||||
get { return marker.time; }
|
||||
}
|
||||
|
||||
public override double start
|
||||
{
|
||||
get { return time; }
|
||||
}
|
||||
|
||||
public override double end
|
||||
{
|
||||
get { return time; }
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
zOrder = zOrderProvider.Next();
|
||||
SelectionManager.Add(marker);
|
||||
TimelineWindowViewPrefs.GetTrackViewModelData(parent.asset).markerTimeStamps[m_MarkerHash] = DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
||||
public override bool IsSelected()
|
||||
{
|
||||
return SelectionManager.Contains(marker);
|
||||
}
|
||||
|
||||
public override void Deselect()
|
||||
{
|
||||
SelectionManager.Remove(marker);
|
||||
}
|
||||
|
||||
public override ITimelineItem item
|
||||
{
|
||||
get { return ItemsUtils.ToItem(marker); }
|
||||
}
|
||||
|
||||
IZOrderProvider zOrderProvider { get; }
|
||||
|
||||
public TimelineMarkerGUI(IMarker theMarker, IRowGUI parent, IZOrderProvider provider) : base(parent)
|
||||
{
|
||||
marker = theMarker;
|
||||
m_Selectable = marker.GetType().IsSubclassOf(typeof(UnityObject));
|
||||
|
||||
m_MarkerHash = 0;
|
||||
var o = marker as object;
|
||||
if (!o.Equals(null))
|
||||
m_MarkerHash = o.GetHashCode();
|
||||
|
||||
zOrderProvider = provider;
|
||||
zOrder = zOrderProvider.Next();
|
||||
ItemToItemGui.Add(marker, this);
|
||||
m_Editor = CustomTimelineEditorCache.GetMarkerEditor(theMarker);
|
||||
}
|
||||
|
||||
int ComputeDirtyHash()
|
||||
{
|
||||
return time.GetHashCode();
|
||||
}
|
||||
|
||||
static void DrawMarker(Rect drawRect, Type type, bool isSelected, bool isCollapsed, MarkerDrawOptions options)
|
||||
{
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
{
|
||||
bool hasError = !string.IsNullOrEmpty(options.errorText);
|
||||
|
||||
var style = StyleManager.UssStyleForType(type);
|
||||
style.Draw(drawRect, GUIContent.none, false, false, !isCollapsed, isSelected);
|
||||
|
||||
// case1141836: Use of GUI.Box instead of GUI.Label causes desync in UI controlID
|
||||
if (hasError)
|
||||
GUI.Label(drawRect, String.Empty, DirectorStyles.Instance.markerWarning);
|
||||
|
||||
var tooltip = hasError ? options.errorText : options.tooltip;
|
||||
if (!string.IsNullOrEmpty(tooltip) && drawRect.Contains(Event.current.mousePosition))
|
||||
{
|
||||
GUIStyle.SetMouseTooltip(tooltip, drawRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateDrawData()
|
||||
{
|
||||
if (Event.current.type == EventType.Layout)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_MarkerDrawOptions = m_Editor.GetMarkerOptions(marker);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogException(e);
|
||||
m_MarkerDrawOptions = CustomTimelineEditorCache.GetDefaultMarkerEditor().GetMarkerOptions(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(Rect trackRect, bool trackRectChanged, WindowState state)
|
||||
{
|
||||
UpdateDrawData();
|
||||
|
||||
// compute marker hash
|
||||
var currentMarkerHash = ComputeDirtyHash();
|
||||
|
||||
// update the clip projected rectangle on the timeline
|
||||
CalculateClipRectangle(trackRect, state, currentMarkerHash, trackRectChanged);
|
||||
|
||||
var isSelected = selectable && SelectionManager.Contains(marker);
|
||||
var showMarkers = parent.showMarkers;
|
||||
|
||||
QueueOverlay(treeViewRect, isSelected, !showMarkers);
|
||||
DrawMarker(treeViewRect, marker.GetType(), isSelected, !showMarkers, m_MarkerDrawOptions);
|
||||
|
||||
if (Event.current.type == EventType.Repaint && showMarkers && !parent.locked)
|
||||
state.spacePartitioner.AddBounds(this, rect);
|
||||
}
|
||||
|
||||
public void QueueOverlay(Rect rect, bool isSelected, bool isCollapsed)
|
||||
{
|
||||
if (Event.current.type == EventType.Repaint && m_Editor.supportsDrawOverlay)
|
||||
{
|
||||
rect = GUIClip.Unclip(rect);
|
||||
TimelineWindow.instance.AddUserOverlay(marker, rect, m_Editor, isCollapsed, isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
public override void StartDrag()
|
||||
{
|
||||
if (onStartDrag != null)
|
||||
onStartDrag.Invoke();
|
||||
}
|
||||
|
||||
void CalculateClipRectangle(Rect trackRect, WindowState state, int projectedClipHash, bool trackRectChanged)
|
||||
{
|
||||
if (m_ProjectedClipHash == projectedClipHash && !trackRectChanged)
|
||||
return;
|
||||
|
||||
m_ProjectedClipHash = projectedClipHash;
|
||||
treeViewRect = RectToTimeline(trackRect, state);
|
||||
}
|
||||
|
||||
public override Rect RectToTimeline(Rect trackRect, WindowState state)
|
||||
{
|
||||
var style = StyleManager.UssStyleForType(marker.GetType());
|
||||
var width = style.fixedWidth;
|
||||
var height = style.fixedHeight;
|
||||
var x = ((float)marker.time * state.timeAreaScale.x) + state.timeAreaTranslation.x + trackRect.xMin;
|
||||
x -= 0.5f * width;
|
||||
return new Rect(x, trackRect.y, width, height);
|
||||
}
|
||||
|
||||
public IEnumerable<Edge> SnappableEdgesFor(IAttractable attractable, ManipulateEdges manipulateEdges)
|
||||
{
|
||||
var edges = new List<Edge>();
|
||||
var attractableGUI = attractable as TimelineMarkerGUI;
|
||||
var canAddEdges = !(attractableGUI != null && attractableGUI.parent == parent);
|
||||
if (canAddEdges)
|
||||
edges.Add(new Edge(time));
|
||||
return edges;
|
||||
}
|
||||
|
||||
public bool ShouldSnapTo(ISnappable snappable)
|
||||
{
|
||||
return snappable != this;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d34348f8b97a334291f5cf31adc5d67
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user