first commit

This commit is contained in:
SimonSayeBabu
2025-01-17 13:10:20 +01:00
commit bd1057cec0
16967 changed files with 1048699 additions and 0 deletions

View File

@@ -0,0 +1,310 @@
using System.Linq;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.Timeline;
namespace UnityEditor.Timeline
{
interface IClipCurveEditorOwner
{
ClipCurveEditor clipCurveEditor { get; }
bool inlineCurvesSelected { get; }
bool showLoops { get; }
TrackAsset owner { get; }
void SelectCurves();
void ValidateCurvesSelection();
}
class InlineCurveResizeHandle : IBounds
{
public Rect boundingRect { get; private set; }
public TimelineTrackGUI trackGUI { get; }
public InlineCurveResizeHandle(TimelineTrackGUI trackGUI)
{
this.trackGUI = trackGUI;
}
public void Draw(Rect headerRect, WindowState state)
{
const float resizeHandleHeight = WindowConstants.trackResizeHandleHeight;
var rect = new Rect(headerRect.xMin, headerRect.yMax - resizeHandleHeight + 1f, headerRect.width, resizeHandleHeight);
EditorGUIUtility.AddCursorRect(rect, MouseCursor.SplitResizeUpDown);
boundingRect = trackGUI.ToWindowSpace(rect);
if (Event.current.type == EventType.Repaint)
{
state.headerSpacePartitioner.AddBounds(this);
EditorGUI.DrawRect(rect, DirectorStyles.Instance.customSkin.colorAnimEditorBinding);
var dragStyle = DirectorStyles.Instance.inlineCurveHandle;
dragStyle.Draw(rect, GUIContent.none, false, false, false, false);
}
}
}
class InlineCurveEditor : IBounds
{
Rect m_TrackRect;
Rect m_HeaderRect;
readonly TimelineTrackGUI m_TrackGUI;
readonly InlineCurveResizeHandle m_ResizeHandle;
bool m_LastSelectionWasClip;
TimelineClipGUI m_LastSelectedClipGUI;
Rect IBounds.boundingRect { get { return m_TrackGUI.ToWindowSpace(m_TrackRect); } }
[UsedImplicitly] // Used in tests
public TimelineClipGUI currentClipGui
{
get { return m_LastSelectedClipGUI; }
}
public IClipCurveEditorOwner currentCurveEditor
{
get { return m_LastSelectionWasClip ? (IClipCurveEditorOwner)m_LastSelectedClipGUI : (IClipCurveEditorOwner)m_TrackGUI; }
}
public InlineCurveEditor(TimelineTrackGUI trackGUI)
{
m_TrackGUI = trackGUI;
m_ResizeHandle = new InlineCurveResizeHandle(trackGUI);
}
static bool MouseOverTrackArea(Rect curveRect, Rect trackRect)
{
curveRect.y = trackRect.y;
curveRect.height = trackRect.height;
// clamp the curve editor to the track. this allows the menu to scroll properly
curveRect.xMin = Mathf.Max(curveRect.xMin, trackRect.xMin);
curveRect.xMax = trackRect.xMax;
return curveRect.Contains(Event.current.mousePosition);
}
static bool MouseOverHeaderArea(Rect headerRect, Rect trackRect)
{
headerRect.y = trackRect.y;
headerRect.height = trackRect.height;
return headerRect.Contains(Event.current.mousePosition);
}
static void DrawCurveEditor(IClipCurveEditorOwner clipCurveEditorOwner, WindowState state, Rect headerRect, Rect trackRect, Vector2 activeRange, bool locked)
{
ClipCurveEditor clipCurveEditor = clipCurveEditorOwner.clipCurveEditor;
CurveDataSource dataSource = clipCurveEditor.dataSource;
Rect curveRect = dataSource.GetBackgroundRect(state);
var newlySelected = false;
var currentEvent = Event.current;
if (currentEvent.type == EventType.MouseDown || currentEvent.type == EventType.ContextClick)
newlySelected = MouseOverTrackArea(curveRect, trackRect) || MouseOverHeaderArea(headerRect, trackRect);
// make sure to not use any event before drawing the curve.
bool prevEnabledState = GUI.enabled;
GUI.enabled = true;
clipCurveEditorOwner.clipCurveEditor.DrawHeader(headerRect);
GUI.enabled = prevEnabledState;
bool displayAsSelected = !locked && (clipCurveEditorOwner.inlineCurvesSelected || newlySelected);
using (new EditorGUI.DisabledScope(locked))
clipCurveEditor.DrawCurveEditor(trackRect, state, activeRange, clipCurveEditorOwner.showLoops, displayAsSelected);
if (newlySelected && !locked)
OnMouseClick(clipCurveEditorOwner, currentEvent);
}
static void OnMouseClick(IClipCurveEditorOwner clipCurveEditorOwner, Event currentEvent)
{
if (currentEvent.modifiers == ManipulatorsUtils.actionModifier)
{
if (clipCurveEditorOwner.inlineCurvesSelected)
SelectionManager.Clear();
else
clipCurveEditorOwner.SelectCurves();
}
else
{
clipCurveEditorOwner.SelectCurves();
}
HandleCurrentEvent();
}
public void Draw(Rect headerRect, Rect trackRect, WindowState state)
{
const float inlineCurveBottomPadding = WindowConstants.inlineCurveContentPadding;
m_TrackRect = trackRect;
m_TrackRect.height -= inlineCurveBottomPadding;
if (Event.current.type == EventType.Repaint)
state.spacePartitioner.AddBounds(this);
// Remove the indentation of this track to render it properly, otherwise every GUI elements will be offsetted.
headerRect.x -= DirectorStyles.kBaseIndent;
headerRect.width += DirectorStyles.kBaseIndent;
// Remove the width of the color swatch.
headerRect.x += 4.0f;
headerRect.width -= 4.0f;
m_HeaderRect = headerRect;
EditorGUI.DrawRect(m_HeaderRect, DirectorStyles.Instance.customSkin.colorAnimEditorBinding);
if (ShouldShowClipCurves(state))
{
DrawCurveEditorsForClipsOnTrack(m_HeaderRect, m_TrackRect, state);
}
else if (ShouldShowTrackCurves())
{
DrawCurveEditorForTrack(m_HeaderRect, m_TrackRect, state);
}
else
{
DrawCurvesEditorForNothingSelected(m_HeaderRect, m_TrackRect, state);
}
m_ResizeHandle.Draw(headerRect, state);
var bottomPadding = new Rect(trackRect.xMin, trackRect.yMax - inlineCurveBottomPadding, trackRect.width, inlineCurveBottomPadding);
EditorGUI.DrawRect(bottomPadding, DirectorStyles.Instance.customSkin.colorTrackBackground);
// If MouseDown or ContextClick are not consumed by the curves, use the event to prevent it from going deeper into the treeview.
if (Event.current.type == EventType.ContextClick)
{
var r = Rect.MinMaxRect(m_HeaderRect.xMin, m_HeaderRect.yMin, m_TrackRect.xMax, m_TrackRect.yMax);
if (r.Contains(Event.current.mousePosition))
Event.current.Use();
}
UpdateViewModel();
}
void DrawCurveEditorForTrack(Rect headerRect, Rect trackRect, WindowState state)
{
if (m_TrackGUI.clipCurveEditor == null)
return;
var activeRange = new Vector2(state.TimeToPixel(0.0d), state.TimeToPixel(state.editSequence.duration));
DrawCurveEditor(m_TrackGUI, state, headerRect, trackRect, activeRange, m_TrackGUI.locked);
m_LastSelectionWasClip = false;
}
void DrawCurveEditorsForClipsOnTrack(Rect headerRect, Rect trackRect, WindowState state)
{
if (m_TrackGUI.clips.Count == 0)
return;
if (Event.current.type == EventType.Layout)
{
var selectedClip = SelectionManager.SelectedClipGUI().FirstOrDefault(x => x.parent == m_TrackGUI);
if (selectedClip != null)
{
m_LastSelectedClipGUI = selectedClip;
SelectFromCurveOwner(m_LastSelectedClipGUI);
}
else if (state.recording && state.IsArmedForRecord(m_TrackGUI.track))
{
if (m_LastSelectedClipGUI == null || !m_TrackGUI.track.IsRecordingToClip(m_LastSelectedClipGUI.clip))
{
var clip = m_TrackGUI.clips.FirstOrDefault(x => m_TrackGUI.track.IsRecordingToClip(x.clip));
if (clip != null)
m_LastSelectedClipGUI = clip;
}
}
if (m_LastSelectedClipGUI == null)
m_LastSelectedClipGUI = m_TrackGUI.clips[0];
}
if (m_LastSelectedClipGUI == null || m_LastSelectedClipGUI.clipCurveEditor == null || m_LastSelectedClipGUI.isInvalid)
return;
var activeRange = new Vector2(state.TimeToPixel(m_LastSelectedClipGUI.clip.start), state.TimeToPixel(m_LastSelectedClipGUI.clip.end));
DrawCurveEditor(m_LastSelectedClipGUI, state, headerRect, trackRect, activeRange, m_TrackGUI.locked);
m_LastSelectionWasClip = true;
}
void DrawCurvesEditorForNothingSelected(Rect headerRect, Rect trackRect, WindowState state)
{
if (m_LastSelectionWasClip || !TrackHasCurvesToShow() && m_TrackGUI.clips.Count > 0)
{
DrawCurveEditorsForClipsOnTrack(headerRect, trackRect, state);
}
else
{
DrawCurveEditorForTrack(headerRect, trackRect, state);
}
}
bool ShouldShowClipCurves(WindowState state)
{
if (m_TrackGUI.clips.Count == 0)
return false;
// Is a clip selected or being recorded to?
return SelectionManager.SelectedClipGUI().FirstOrDefault(x => x.parent == m_TrackGUI) != null ||
state.recording && state.IsArmedForRecord(m_TrackGUI.track) && m_TrackGUI.clips.FirstOrDefault(x => m_TrackGUI.track.IsRecordingToClip(x.clip)) != null;
}
bool ShouldShowTrackCurves()
{
if (m_TrackGUI == null)
return false;
var isTrackSelected = SelectionManager.SelectedTrackGUI().FirstOrDefault(x => x == m_TrackGUI) != null;
if (!isTrackSelected)
return false;
return TrackHasCurvesToShow();
}
bool TrackHasCurvesToShow()
{
var animTrack = m_TrackGUI.track as AnimationTrack;
if (animTrack != null && !animTrack.inClipMode)
return true;
return m_TrackGUI.track.HasAnyAnimatableParameters();
}
void UpdateViewModel()
{
var curveEditor = currentCurveEditor.clipCurveEditor;
if (curveEditor == null || curveEditor.bindingHierarchy.treeViewController == null)
return;
var vm = TimelineWindowViewPrefs.GetTrackViewModelData(m_TrackGUI.track);
vm.inlineCurvesState = curveEditor.bindingHierarchy.treeViewController.state;
vm.inlineCurvesShownAreaInsideMargins = curveEditor.shownAreaInsideMargins;
vm.lastInlineCurveDataID = curveEditor.dataSource.id;
}
static void HandleCurrentEvent()
{
#if UNITY_EDITOR_OSX
Event.current.type = EventType.Ignore;
#else
Event.current.Use();
#endif
}
static void SelectFromCurveOwner(IClipCurveEditorOwner curveOwner)
{
if (curveOwner.clipCurveEditor == null)
{
SelectionManager.SelectInlineCurveEditor(null);
}
else if (!curveOwner.inlineCurvesSelected && SelectionManager.Count() == 1)
{
SelectionManager.SelectInlineCurveEditor(curveOwner);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e96b886242ab404db69df796f7cd9b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,323 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Timeline;
namespace UnityEditor.Timeline
{
class TimelineGroupGUI : TimelineTrackBaseGUI
{
protected DirectorStyles m_Styles;
protected Rect m_TreeViewRect = new Rect(0, 0, 0, 0);
protected GUIContent m_ProblemIcon = new GUIContent();
bool m_MustRecomputeUnions = true;
int m_GroupDepth;
readonly bool m_IsReferencedTrack;
readonly List<TimelineClipUnion> m_Unions = new List<TimelineClipUnion>();
public override Rect boundingRect
{
get { return ToWindowSpace(m_TreeViewRect); }
}
public Rect ToWindowSpace(Rect localRect)
{
localRect.position += treeViewToWindowTransformation;
return localRect;
}
public override bool expandable
{
get { return !m_IsRoot; }
}
// The expanded rectangle (contains children) as calculated by the the tree gui
public Rect expandedRect { get; set; }
// The row rectangle (header only) as calculated by the tree gui
public Rect rowRect { get; set; }
// the drop rectangle as set by the tree gui when targetted by a drag and drop
public Rect dropRect { get; set; }
public TimelineGroupGUI(TreeViewController treeview, TimelineTreeViewGUI treeviewGUI, int id, int depth, TreeViewItem parent, string displayName, TrackAsset trackAsset, bool isRoot)
: base(id, depth, parent, displayName, trackAsset, treeview, treeviewGUI)
{
m_Styles = DirectorStyles.Instance;
m_IsRoot = isRoot;
var trackPath = AssetDatabase.GetAssetPath(trackAsset);
var sequencePath = AssetDatabase.GetAssetPath(treeviewGUI.TimelineWindow.state.editSequence.asset);
if (trackPath != sequencePath)
m_IsReferencedTrack = true;
m_GroupDepth = CalculateGroupDepth(parent);
}
public virtual float GetHeight(WindowState state)
{
// group tracks don't scale in height
return TrackEditor.DefaultTrackHeight;
}
public override void OnGraphRebuilt() { }
static int CalculateGroupDepth(TreeViewItem parent)
{
int depth = 0;
bool done = false;
do
{
var gui = parent as TimelineGroupGUI;
if (gui == null || gui.track == null)
done = true;
else
{
if (gui.track is GroupTrack)
depth++;
parent = parent.parent;
}
}
while (!done);
return depth;
}
void DrawTrackButtons(Rect headerRect, WindowState state)
{
const float buttonSize = WindowConstants.trackHeaderButtonSize;
const float padding = WindowConstants.trackHeaderButtonPadding;
var buttonRect = new Rect(headerRect.xMax - buttonSize - padding, headerRect.y + ((headerRect.height - buttonSize) / 2f), buttonSize, buttonSize);
if (GUI.Button(buttonRect, EditorGUIUtility.IconContent("CreateAddNew"), m_Styles.trackGroupAddButton))
{
// the drop down will apply to all selected tracks
if (!SelectionManager.Contains(track))
{
SelectionManager.Clear();
SelectionManager.Add(track);
}
SequencerContextMenu.ShowNewTracksContextMenu(SelectionManager.SelectedTracks().ToArray(), TimelineWindow.state, buttonRect);
}
buttonRect.x -= buttonSize;
var suitePadding = DrawButtonSuite(2, ref buttonRect);
DrawMuteButton(buttonRect, state);
buttonRect.x -= buttonSize + padding;
DrawLockButton(buttonRect, state);
buttonRect.x -= suitePadding;
}
public void SetExpanded(bool expanded)
{
var collapseChanged = expanded != isExpanded;
isExpanded = expanded;
if (collapseChanged)
{
track.SetCollapsed(!expanded);
m_MustRecomputeUnions = true;
}
}
public override void Draw(Rect headerRect, Rect contentRect, WindowState state)
{
if (track == null || m_IsRoot)
return;
if (m_MustRecomputeUnions)
RecomputeRectUnions();
if (depth == 1)
Graphics.DrawBackgroundRect(state, headerRect);
var background = headerRect;
background.height = expandedRect.height;
var groupColor = TrackResourceCache.GetTrackColor(track);
m_TreeViewRect = contentRect;
var col = groupColor;
var isSelected = SelectionManager.Contains(track);
if (isSelected)
col = DirectorStyles.Instance.customSkin.colorSelection;
else if (isDropTarget)
col = DirectorStyles.Instance.customSkin.colorDropTarget;
else
{
if (m_GroupDepth % 2 == 1)
{
float h, s, v;
Color.RGBToHSV(col, out h, out s, out v);
v += 0.06f;
col = Color.HSVToRGB(h, s, v);
}
}
if (background.width > 0)
{
using (new GUIColorOverride(col))
GUI.Box(background, GUIContent.none, m_Styles.groupBackground);
}
var trackRectBackground = headerRect;
trackRectBackground.xMin += background.width;
trackRectBackground.width = contentRect.width;
trackRectBackground.height = background.height;
if (isSelected)
{
col = state.IsEditingASubTimeline()
? m_Styles.customSkin.colorTrackSubSequenceBackgroundSelected
: m_Styles.customSkin.colorTrackBackgroundSelected;
}
else
{
col = m_Styles.customSkin.colorGroupTrackBackground;
}
EditorGUI.DrawRect(trackRectBackground, col);
if (!isExpanded && children != null && children.Count > 0)
{
var collapsedTrackRect = contentRect;
foreach (var u in m_Unions)
u.Draw(collapsedTrackRect, state);
}
using (new GUIGroupScope(headerRect))
{
var groupRect = new Rect(0, 0, headerRect.width, headerRect.height);
DrawName(groupRect, isSelected);
DrawTrackButtons(groupRect, state);
}
if (IsTrackRecording(state))
{
using (new GUIColorOverride(DirectorStyles.Instance.customSkin.colorTrackBackgroundRecording))
GUI.Label(background, GUIContent.none, m_Styles.displayBackground);
}
// is this a referenced track?
if (m_IsReferencedTrack)
{
var refRect = contentRect;
refRect.x = state.timeAreaRect.xMax - 20.0f;
refRect.y += 5.0f;
refRect.width = 30.0f;
GUI.Label(refRect, DirectorStyles.referenceTrackLabel, EditorStyles.label);
}
var bgRect = contentRect;
if (track as GroupTrack != null || AllChildrenMuted(this))
bgRect.height = expandedRect.height;
DrawTrackState(contentRect, bgRect, track);
}
void DrawName(Rect rect, bool isSelected)
{
var labelRect = rect;
labelRect.xMin += 20;
var actorName = track != null ? track.name : "missing";
labelRect.width = m_Styles.groupFont.CalcSize(new GUIContent(actorName)).x;
labelRect.width = Math.Max(labelRect.width, 50.0f);
// if we aren't bound to anything, we show a text field that allows to rename the actor
// otherwise we show a ObjectField to allow binding to a go
if (track != null && track is GroupTrack)
{
var textColor = m_Styles.groupFont.normal.textColor;
if (isSelected)
textColor = Color.white;
string newName;
EditorGUI.BeginChangeCheck();
using (new StyleNormalColorOverride(m_Styles.groupFont, textColor))
{
newName = EditorGUI.DelayedTextField(labelRect, GUIContent.none, track.GetInstanceID(), track.name, m_Styles.groupFont);
}
if (EditorGUI.EndChangeCheck() && !string.IsNullOrEmpty(newName))
{
track.SetNameWithUndo(newName);
displayName = track.name;
}
}
}
protected bool IsSubTrack()
{
if (track == null)
return false;
var parentTrack = track.parent as TrackAsset;
if (parentTrack == null)
return false;
return parentTrack.GetType() != typeof(GroupTrack);
}
protected TrackAsset ParentTrack()
{
if (IsSubTrack())
return track.parent as TrackAsset;
return null;
}
// is there currently a recording track
bool IsTrackRecording(WindowState state)
{
if (!state.recording)
return false;
if (track.GetType() != typeof(GroupTrack))
return false;
return state.GetArmedTrack(track) != null;
}
void RecomputeRectUnions()
{
m_MustRecomputeUnions = false;
m_Unions.Clear();
if (children == null)
return;
foreach (var c in children.OfType<TimelineTrackGUI>())
{
c.RebuildGUICacheIfNecessary();
m_Unions.AddRange(TimelineClipUnion.Build(c.clips));
}
}
static bool AllChildrenMuted(TimelineGroupGUI groupGui)
{
if (!groupGui.track.muted)
return false;
if (groupGui.children == null)
return true;
return groupGui.children.OfType<TimelineGroupGUI>().All(AllChildrenMuted);
}
protected static float DrawButtonSuite(int numberOfButtons, ref Rect buttonRect)
{
var style = DirectorStyles.Instance.trackButtonSuite;
var buttonWidth = WindowConstants.trackHeaderButtonSize * numberOfButtons + WindowConstants.trackHeaderButtonPadding * Math.Max(0, numberOfButtons - 1);
var suiteWidth = buttonWidth + style.padding.right + style.padding.left;
var rect = new Rect(buttonRect.xMax - style.margin.right - suiteWidth, buttonRect.y + style.margin.top, suiteWidth, buttonRect.height);
if (Event.current.type == EventType.Repaint)
style.Draw(rect, false, false, false, false);
buttonRect.x -= style.margin.right + style.padding.right;
return style.margin.left + style.padding.left;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7072e9e47288bac4d8c6bdfb2cf785a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,214 @@
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Timeline;
namespace UnityEditor.Timeline
{
abstract class TimelineTrackBaseGUI : TreeViewItem, IBounds
{
static class Styles
{
public static readonly GUIContent s_LockedAndMuted = L10n.TextContent("Locked / Muted");
public static readonly GUIContent s_LockedAndPartiallyMuted = L10n.TextContent("Locked / Partially Muted");
public static readonly GUIContent s_Locked = L10n.TextContent("Locked");
public static readonly GUIContent s_Muted = L10n.TextContent("Muted");
public static readonly GUIContent s_PartiallyMuted = L10n.TextContent("Partially Muted");
public static readonly GUIContent trackMuteBtnOnTooltip = L10n.TextContent(string.Empty, "Umute");
public static readonly GUIContent trackMuteBtnOffTooltip = L10n.TextContent(string.Empty, "Mute");
public static readonly GUIContent trackLockBtnOnTooltip = L10n.TextContent(string.Empty, "Unlock");
public static readonly GUIContent trackLockBtnOffTooltip = L10n.TextContent(string.Empty, "Lock");
public static readonly Texture2D lockBg = DirectorStyles.GetBackgroundImage(DirectorStyles.Instance.trackLockOverlay);
}
protected bool m_IsRoot = false;
readonly TimelineTreeViewGUI m_TreeViewGUI;
readonly TrackDrawer m_Drawer;
public Vector2 treeViewToWindowTransformation { get; set; }
public bool isExpanded { get; set; }
public bool isDropTarget { protected get; set; }
public TrackAsset track { get; }
TreeViewController treeView { get; }
public TimelineWindow TimelineWindow
{
get
{
if (m_TreeViewGUI == null)
return null;
return m_TreeViewGUI.TimelineWindow;
}
}
public TrackDrawer drawer
{
get { return m_Drawer; }
}
public virtual float GetVerticalSpacingBetweenTracks()
{
return 3.0f;
}
public bool visibleRow { get; set; } // is the header row visible
public bool visibleExpanded { get; set; } // is the expanded area (group) visible
public bool drawInsertionMarkerBefore { get; set; }
public bool drawInsertionMarkerAfter { get; set; }
public abstract Rect boundingRect { get; }
public abstract bool expandable { get; }
public abstract void Draw(Rect headerRect, Rect contentRect, WindowState state);
public abstract void OnGraphRebuilt(); // callback when the corresponding graph is rebuilt. This can happen, but not have the GUI rebuilt.
protected TimelineTrackBaseGUI(int id, int depth, TreeViewItem parent, string displayName, TrackAsset trackAsset, TreeViewController tv, TimelineTreeViewGUI tvgui)
: base(id, depth, parent, displayName)
{
m_Drawer = TrackDrawer.CreateInstance(trackAsset);
m_Drawer.sequencerState = tvgui.TimelineWindow.state;
isExpanded = false;
isDropTarget = false;
track = trackAsset;
treeView = tv;
m_TreeViewGUI = tvgui;
}
public static TimelineTrackBaseGUI FindGUITrack(TrackAsset track)
{
var allTracks = TimelineWindow.instance.allTracks;
return allTracks.Find(x => x.track == track);
}
protected void DrawTrackState(Rect trackRect, Rect expandedRect, TrackAsset track)
{
if (Event.current.type == EventType.Layout)
{
bool needStateBox = false;
//Mute
if (track.muted && !TimelineUtility.IsParentMuted(track))
{
Rect bgRect = expandedRect;
TimelineWindow.instance.OverlayDrawData.Add(OverlayDrawer.CreateColorOverlay(
GUIClip.Unclip(bgRect),
DirectorStyles.Instance.customSkin.colorTrackDarken));
needStateBox = true;
}
//Lock
if (!needStateBox && track.locked && !TimelineUtility.IsLockedFromGroup(track))
{
Rect bgRect = expandedRect;
TimelineWindow.instance.OverlayDrawData.Add(OverlayDrawer.CreateTextureOverlay(
GUIClip.Unclip(bgRect),
Styles.lockBg));
needStateBox = true;
}
if (needStateBox)
{
DrawTrackStateBox(trackRect, track);
}
}
}
static void DrawTrackStateBox(Rect trackRect, TrackAsset track)
{
var styles = DirectorStyles.Instance;
bool locked = track.locked && !TimelineUtility.IsLockedFromGroup(track);
bool muted = track.muted && !TimelineUtility.IsParentMuted(track);
bool allSubTrackMuted = TimelineUtility.IsAllSubTrackMuted(track);
GUIContent content = null;
if (locked && muted)
{
content = Styles.s_LockedAndMuted;
if (!allSubTrackMuted)
content = Styles.s_LockedAndPartiallyMuted;
}
else if (locked) content = Styles.s_Locked;
else if (muted)
{
content = Styles.s_Muted;
if (!allSubTrackMuted)
content = Styles.s_PartiallyMuted;
}
// the track could be locked, but we only show the 'locked portion' on the upper most track
// that is causing the lock
if (content == null)
return;
Rect textRect = Graphics.CalculateTextBoxSize(trackRect, styles.fontClip, content, WindowConstants.overlayTextPadding);
TimelineWindow.instance.OverlayDrawData.Add(
OverlayDrawer.CreateTextBoxOverlay(
GUIClip.Unclip(textRect),
content.text, styles.fontClip,
Color.white,
styles.customSkin.colorLockTextBG,
styles.displayBackground));
}
protected void DrawMuteButton(Rect rect, WindowState state)
{
using (new EditorGUI.DisabledScope(TimelineUtility.IsParentMuted(track)))
{
EditorGUI.BeginChangeCheck();
var isMuted = track.mutedInHierarchy;
var tooltip = isMuted ? Styles.trackMuteBtnOnTooltip : Styles.trackMuteBtnOffTooltip;
var muted = GUI.Toggle(rect, isMuted, tooltip, TimelineWindow.styles.trackMuteButton);
if (EditorGUI.EndChangeCheck())
MuteTrack.Mute(new[] { track }, muted);
}
}
protected void DrawLockButton(Rect rect, WindowState state)
{
using (new EditorGUI.DisabledScope(TimelineUtility.IsLockedFromGroup(track)))
{
EditorGUI.BeginChangeCheck();
var isLocked = track.lockedInHierarchy;
var tooltip = isLocked ? Styles.trackLockBtnOnTooltip : Styles.trackLockBtnOffTooltip;
var locked = GUI.Toggle(rect, track.lockedInHierarchy, tooltip, TimelineWindow.styles.trackLockButton);
if (EditorGUI.EndChangeCheck())
LockTrack.SetLockState(new[] { track }, locked);
}
}
public void DrawInsertionMarkers(Rect rowRectWithIndent)
{
const float insertionHeight = WindowConstants.trackInsertionMarkerHeight;
if (Event.current.type == EventType.Repaint && (drawInsertionMarkerAfter || drawInsertionMarkerBefore))
{
if (drawInsertionMarkerBefore)
{
var rect = new Rect(rowRectWithIndent.x, rowRectWithIndent.y - insertionHeight * 0.5f - 2.0f, rowRectWithIndent.width, insertionHeight);
EditorGUI.DrawRect(rect, Color.white);
}
if (drawInsertionMarkerAfter)
{
var rect = new Rect(rowRectWithIndent.x, rowRectWithIndent.y + rowRectWithIndent.height - insertionHeight * 0.5f + 1.0f, rowRectWithIndent.width, insertionHeight);
EditorGUI.DrawRect(rect, Color.white);
}
}
}
public void ClearDrawFlags()
{
if (Event.current.type == EventType.Repaint)
{
isDropTarget = false;
drawInsertionMarkerAfter = false;
drawInsertionMarkerBefore = false;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d6b75424ba2b73c4eb3182b08dbd71ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,185 @@
using System;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Playables;
namespace UnityEditor.Timeline
{
class TimelineTrackErrorGUI : TimelineTrackBaseGUI
{
static class Styles
{
public static readonly GUIContent ErrorText = L10n.TextContent("Track cannot be loaded.", "Please fix any compile errors in the script for this track");
public static readonly Texture2D IconWarn = EditorGUIUtility.LoadIconRequired("console.warnicon.inactive.sml");
public static readonly GUIContent RemoveTrack = L10n.TextContent("Delete");
public static readonly Color WarningBoxBackgroundColor = new Color(115.0f / 255.0f, 115.0f / 255.0f, 115.0f / 255.0f); // approved for both skins
public static readonly Color WarningBoxHighlightColor = new Color(229 / 255.0f, 208 / 255.0f, 54 / 255.0f); // brigher than standard warning color for contrast
}
Rect m_TrackRect;
ScriptableObject m_ScriptableObject;
PlayableAsset m_Owner;
static GUIContent s_GUIContent = new GUIContent();
public TimelineTrackErrorGUI(TreeViewController treeview, TimelineTreeViewGUI treeviewGUI, int id, int depth, TreeViewItem parent, string displayName, ScriptableObject track, PlayableAsset owner)
: base(id, depth, parent, displayName, null, treeview, treeviewGUI)
{
m_ScriptableObject = track;
m_Owner = owner;
}
public override Rect boundingRect
{
get { return m_TrackRect; }
}
public override bool expandable
{
get { return false; }
}
public override void Draw(Rect headerRect, Rect contentRect, WindowState state)
{
m_TrackRect = contentRect;
DrawMissingTrackHeader(headerRect, state);
DrawMissingTrackBody(contentRect);
}
void DrawMissingTrackHeader(Rect headerRect, WindowState state)
{
var styles = DirectorStyles.Instance;
// Draw a header
Color backgroundColor = styles.customSkin.colorTrackHeaderBackground;
var bgRect = headerRect;
bgRect.x += styles.trackSwatchStyle.fixedWidth;
bgRect.width -= styles.trackSwatchStyle.fixedWidth;
EditorGUI.DrawRect(bgRect, backgroundColor);
// draw the warning icon
var errorIcon = Styles.IconWarn;
Rect iconRect = new Rect(headerRect.xMin + styles.trackSwatchStyle.fixedWidth, headerRect.yMin + 0.5f * (headerRect.height - errorIcon.height), errorIcon.width, errorIcon.height);
if (iconRect.width > 0 && iconRect.height > 0)
{
GUI.DrawTexture(iconRect, errorIcon, ScaleMode.ScaleAndCrop, true, 0, DirectorStyles.kClipErrorColor, 0, 0);
}
// Draw the name
// m_ScriptableObject == null will return true because the script can't be loaded. so this checks
// to make sure it is actually not null so we can grab the name
object o = m_ScriptableObject;
if (o != null)
{
s_GUIContent.text = m_ScriptableObject.name;
var textStyle = styles.trackHeaderFont;
textStyle.normal.textColor = styles.customSkin.colorTrackFont; // TODO -- we shouldn't modify the style like this. track header does it though :(
Rect textRect = headerRect;
textRect.xMin = iconRect.xMax + 1;
textRect.xMax = Math.Min(textRect.xMin + styles.trackHeaderFont.CalcSize(s_GUIContent).x, headerRect.xMax - 1);
EditorGUI.LabelField(textRect, s_GUIContent, textStyle);
}
// Draw the color swatch to the left of the track, darkened by the mute
var color = Color.Lerp(DirectorStyles.kClipErrorColor, styles.customSkin.colorTrackDarken, styles.customSkin.colorTrackDarken.a);
color.a = 1;
using (new GUIColorOverride(color))
{
var colorSwatchRect = headerRect;
colorSwatchRect.width = styles.trackSwatchStyle.fixedWidth;
GUI.Label(colorSwatchRect, GUIContent.none, styles.trackSwatchStyle);
}
// draw darken overlay
EditorGUI.DrawRect(bgRect, styles.customSkin.colorTrackDarken);
DrawRemoveMenu(headerRect, state);
}
void DrawRemoveMenu(Rect headerRect, WindowState state)
{
const float pad = 3;
const float buttonSize = 16;
var buttonRect = new Rect(headerRect.xMax - buttonSize - pad, headerRect.y + ((headerRect.height - buttonSize) / 2f) + 2, buttonSize, buttonSize);
if (GUI.Button(buttonRect, GUIContent.none, DirectorStyles.Instance.trackOptions))
{
GenericMenu menu = new GenericMenu();
var owner = m_Owner;
var scriptableObject = m_ScriptableObject;
menu.AddItem(Styles.RemoveTrack, false, () =>
{
if (TrackExtensions.RemoveBrokenTrack(owner, scriptableObject))
state.Refresh();
}
);
menu.ShowAsContext();
}
}
static void DrawMissingTrackBody(Rect contentRect)
{
if (contentRect.width < 0)
return;
var styles = DirectorStyles.Instance;
// draw a track rectangle
EditorGUI.DrawRect(contentRect, styles.customSkin.colorTrackDarken);
// draw the warning box
DrawScriptWarningBox(contentRect, Styles.ErrorText);
}
static void DrawScriptWarningBox(Rect trackRect, GUIContent content)
{
var styles = DirectorStyles.Instance;
const float kTextPadding = 52f;
var errorIcon = Styles.IconWarn;
float textWidth = styles.fontClip.CalcSize(content).x;
var outerRect = trackRect;
outerRect.width = textWidth + kTextPadding + errorIcon.width;
outerRect.x += (trackRect.width - outerRect.width) / 2f;
outerRect.height -= 4f;
outerRect.y += 1f;
bool drawText = true;
if (outerRect.width > trackRect.width)
{
outerRect.x = trackRect.x;
outerRect.width = trackRect.width;
drawText = false;
}
var innerRect = new Rect(outerRect.x + 2, outerRect.y + 2, outerRect.width - 4, outerRect.height - 4);
using (new GUIColorOverride(Styles.WarningBoxHighlightColor))
GUI.Box(outerRect, GUIContent.none, styles.displayBackground);
using (new GUIColorOverride(Styles.WarningBoxBackgroundColor))
GUI.Box(innerRect, GUIContent.none, styles.displayBackground);
if (drawText)
{
var iconRect = new Rect(outerRect.x + kTextPadding / 2.0f - 4.0f, outerRect.y + (outerRect.height - errorIcon.height) / 2.0f, errorIcon.width, errorIcon.height);
var textRect = new Rect(iconRect.xMax + 4.0f, outerRect.y, textWidth, outerRect.height);
GUI.DrawTexture(iconRect, errorIcon, ScaleMode.ScaleAndCrop, true, 0, Styles.WarningBoxHighlightColor, 0, 0);
Graphics.ShadowLabel(textRect, content, styles.fontClip, Color.white, Color.black);
}
else if (errorIcon.width > innerRect.width)
{
var iconRect = new Rect(outerRect.x + (outerRect.width - errorIcon.width) / 2.0f, outerRect.y + (outerRect.height - errorIcon.height) / 2.0f, errorIcon.width, errorIcon.height);
GUI.DrawTexture(iconRect, errorIcon, ScaleMode.ScaleAndCrop, true, 0, Styles.WarningBoxHighlightColor, 0, 0);
}
}
public override void OnGraphRebuilt() { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e00dc5a0cda466b41b09a50bd18b4916
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b3b27007577486c4d8dc088f989b288c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using UnityEngine;
namespace UnityEditor.Timeline
{
class TrackResizeHandle : IBounds
{
public Rect boundingRect { get; private set; }
public TimelineTrackGUI trackGUI { get; }
public TrackResizeHandle(TimelineTrackGUI trackGUI)
{
this.trackGUI = trackGUI;
}
public void Draw(Rect headerRect, WindowState state)
{
const float resizeHandleHeight = WindowConstants.trackResizeHandleHeight;
var rect = new Rect(headerRect.xMin, headerRect.yMax - (0.5f * resizeHandleHeight), headerRect.width, resizeHandleHeight);
boundingRect = trackGUI.ToWindowSpace(rect);
Rect cursorRect = rect;
cursorRect.height--;
if (GUIUtility.hotControl == 0)
{
EditorGUIUtility.AddCursorRect(cursorRect, MouseCursor.SplitResizeUpDown);
state.headerSpacePartitioner.AddBounds(this);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 042c802f94d43dc45a049bf3b5be79ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: