|
|
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; }
internal static float Spaced(float width) { return width > 0 ? width + WindowConstants.trackHeaderButtonSpacing : 0; }
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; buttonRect.x -= Spaced(DrawMuteButton(buttonRect, state)); buttonRect.x -= Spaced(DrawLockButton(buttonRect, state)); }
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.name = 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); } }}
|