FEditorList.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. using UnityEngine;
  2. using UnityEditor;
  3. using UnityEditor.AnimatedValues;
  4. using System.Collections.Generic;
  5. using Flux;
  6. namespace FluxEditor
  7. {
  8. public abstract class FEditorList<T> : FEditor where T : FEditor {
  9. private List<T> _editors = new List<T>();
  10. public List<T> Editors { get { return _editors; } }
  11. private AnimFloat _showPercentage = new AnimFloat(1);
  12. public float ShowPercentage { get { return _showPercentage.value; } }
  13. public bool ShowEditorList {
  14. get { return _showPercentage.target > 0; }
  15. set { _showPercentage.target = value ? 1 : 0; }
  16. }
  17. public override void ClearOffset()
  18. {
  19. base.ClearOffset();
  20. foreach( T editor in Editors )
  21. {
  22. editor.ClearOffset();
  23. }
  24. }
  25. public virtual float HeaderHeight { get { return 0; } }
  26. private Rect _headerRect = new Rect();
  27. public Rect HeaderRect { get { return _headerRect; } set { _headerRect = value; } }
  28. private float _height = 0;
  29. public override float Height { get { return _height; } }
  30. protected GUIContent _icon = null;
  31. protected virtual Color BackgroundColor { get { return FGUI.GetTimelineColor(); } }
  32. protected abstract string HeaderText { get; }
  33. protected virtual float IconSize { get { return 16; } }
  34. protected virtual bool IconOnLeft { get { return true; } }
  35. protected virtual Transform ContentTransform { get { return Obj.transform; } }
  36. public override void ReserveGuiIds()
  37. {
  38. base.ReserveGuiIds();
  39. _height = HeaderHeight;
  40. if( ShowPercentage > 0 )
  41. {
  42. float contentHeight = 0;
  43. for( int i = 0; i != Editors.Count; ++i )
  44. {
  45. Editors[i].ReserveGuiIds();
  46. contentHeight += Editors[i].Height;
  47. }
  48. _height += contentHeight * ShowPercentage;
  49. }
  50. }
  51. public override void Init( FObject obj, FEditor owner )
  52. {
  53. base.Init( obj, owner );
  54. _showPercentage.valueChanged.RemoveAllListeners();
  55. _showPercentage.valueChanged.AddListener( SequenceEditor.Repaint );
  56. _contentOffset = new Vector2( 8, HeaderHeight );
  57. }
  58. public override void Render( Rect rect, float headerWidth )
  59. {
  60. Rect = rect;
  61. Rect headerRect = rect;
  62. headerRect.height = HeaderHeight;
  63. RenderHeader( headerRect, headerWidth );
  64. Rect headerTimelineRect = rect;
  65. headerTimelineRect.xMin += headerWidth;
  66. if( headerTimelineRect.Contains( Event.current.mousePosition ) )
  67. SequenceEditor.SetMouseHover( Event.current.mousePosition.x - headerWidth, this );
  68. headerRect.width = headerWidth;
  69. HeaderRect = headerRect;
  70. Rect listRect = rect;
  71. listRect.yMin += HeaderHeight;
  72. _contentOffset.y = listRect.y;
  73. if( _showPercentage.value > 0 )
  74. {
  75. listRect.height *= _showPercentage.value;
  76. RenderList( listRect, headerWidth );
  77. }
  78. if( IsSelected && Event.current.type == EventType.Repaint )
  79. {
  80. float lineWidth = 3;
  81. float halfLineWidth = lineWidth * 0.33f;
  82. Color c = Handles.selectedColor;
  83. c.a = 1f;
  84. Handles.color = c;
  85. Vector3 pt0 = new Vector3( rect.xMin+halfLineWidth, rect.yMin+halfLineWidth );
  86. Vector3 pt1 = new Vector3( rect.xMin+halfLineWidth, rect.yMax-halfLineWidth );
  87. Vector3 pt2 = new Vector3( rect.xMax-halfLineWidth, rect.yMax-halfLineWidth );
  88. Vector3 pt3 = new Vector3( rect.xMax-halfLineWidth, rect.yMin+halfLineWidth );
  89. // Handles.DrawAAPolyLine( lineWidth, pt0, pt1, pt2, pt3, pt0 );
  90. Handles.DrawSolidRectangleWithOutline( new Vector3[]{ pt0, pt1, pt2, pt3 }, new Color( 0, 0, 0, 0 ), c );
  91. // Handles.DrawPolyLine( pt0, pt1, pt2, pt3, pt0 );
  92. }
  93. Handles.color = FGUI.GetLineColor();
  94. Handles.DrawLine( Rect.min, Rect.min + new Vector2(Rect.width, 0) );
  95. Handles.DrawLine( Rect.max - new Vector2(Rect.width, 0), Rect.max );
  96. }
  97. protected virtual void RenderHeader( Rect headerRect, float headerWidth )
  98. {
  99. if( HeaderHeight == 0 )
  100. return;
  101. //if( Event.current.type == EventType.Repaint )
  102. //{
  103. // GUI.color = BackgroundColor;
  104. // EditorGUI.DrawTextureAlpha( headerRect, EditorGUIUtility.whiteTexture );
  105. // GUI.color = Color.white;
  106. //}
  107. Rect foldoutRect = headerRect;
  108. foldoutRect.width = 16;
  109. GUI.backgroundColor = Color.white;
  110. EditorGUI.BeginChangeCheck();
  111. ShowEditorList = EditorGUI.Foldout( foldoutRect, ShowEditorList, string.Empty );
  112. if( EditorGUI.EndChangeCheck() )
  113. {
  114. if( Event.current.shift )
  115. {
  116. if( this is FContainerEditor )
  117. ShowAllContainers( ShowEditorList );
  118. else if( this is FTimelineEditor )
  119. ShowAllTimelines( ShowEditorList );
  120. }
  121. }
  122. Rect labelRect = headerRect;
  123. labelRect.width = headerWidth;
  124. labelRect.xMin += 16;
  125. Rect iconRect = labelRect;
  126. if( _icon != null )
  127. {
  128. if( IconOnLeft )
  129. {
  130. labelRect.xMin += IconSize;
  131. }
  132. else
  133. {
  134. labelRect.xMax -= IconSize;
  135. iconRect.xMin = labelRect.xMax;
  136. }
  137. iconRect.width = IconSize;
  138. iconRect.height = IconSize;
  139. GUI.color = FGUI.GetIconColor();
  140. GUI.DrawTexture( iconRect, _icon.image );
  141. GUI.color = Color.white;
  142. }
  143. GUI.contentColor = FGUI.GetTextColor();
  144. GUI.Label( labelRect, HeaderText, EditorStyles.boldLabel );
  145. OnHeaderInput( labelRect, iconRect );
  146. }
  147. protected virtual void OnHeaderInput( Rect labelRect, Rect iconRect )
  148. {
  149. if( Event.current.type == EventType.MouseDown && labelRect.Contains( Event.current.mousePosition ) )
  150. {
  151. if( Event.current.button == 0 )
  152. {
  153. if( Event.current.shift )
  154. SequenceEditor.Select( this );
  155. else
  156. SequenceEditor.SelectExclusive( this );
  157. } else if( Event.current.button == 1 )
  158. ShowHeaderContextMenu();
  159. Event.current.Use();
  160. }
  161. }
  162. protected virtual void ShowHeaderContextMenu()
  163. {
  164. GenericMenu menu = new GenericMenu();
  165. PopulateContextMenu(menu);
  166. if( CanPaste( FSequenceEditor.CopyObject ) )
  167. {
  168. menu.AddItem( new GUIContent( "Paste " + FSequenceEditor.CopyObject.name ), false, Paste, FSequenceEditor.CopyObject );
  169. }
  170. menu.AddItem( new GUIContent( "Copy" ), false, Copy );
  171. menu.AddItem( new GUIContent( "Cut" ), false, Cut );
  172. menu.AddItem( new GUIContent( "Duplicate" ), false, Duplicate );
  173. menu.AddItem( new GUIContent( "Delete" ), false, Delete );
  174. menu.ShowAsContext();
  175. }
  176. private void Copy()
  177. {
  178. SequenceEditor.CopyEditor( this );
  179. }
  180. private void Cut()
  181. {
  182. SequenceEditor.CutEditor( this );
  183. }
  184. protected abstract bool CanPaste(FObject obj);
  185. protected abstract void Paste( object obj );
  186. private void Duplicate()
  187. {
  188. GameObject go = GameObject.Instantiate( Obj.gameObject );
  189. go.transform.parent = Obj.transform.parent;
  190. go.name = SequenceEditor.GetUniqueContainerName( Obj.gameObject.name );
  191. Undo.RegisterCreatedObjectUndo( go, "duplicate " + Obj.gameObject.name );
  192. }
  193. protected abstract void Delete();
  194. protected virtual void PopulateContextMenu( GenericMenu menu )
  195. {
  196. }
  197. protected virtual void RenderList( Rect listRect, float headerWidth )
  198. {
  199. if( ContentOffset.x > 0 )
  200. {
  201. Rect sideRect = listRect;
  202. sideRect.width = ContentOffset.x;
  203. if( Event.current.type == EventType.Repaint )
  204. {
  205. GUI.color = BackgroundColor;
  206. EditorGUI.DrawTextureAlpha( sideRect, EditorGUIUtility.whiteTexture );
  207. GUI.color = Color.white;
  208. }
  209. }
  210. listRect.xMin += ContentOffset.x;
  211. headerWidth -= ContentOffset.x;
  212. Rect editorRect = listRect;
  213. GUI.BeginGroup( listRect );
  214. editorRect.y = 0;
  215. editorRect.x = 0;
  216. editorRect.height = 0;
  217. for( int i = 0; i != _editors.Count; ++i )
  218. {
  219. editorRect.yMin = editorRect.yMax;
  220. editorRect.height = _editors[i].Height;
  221. if( SequenceEditor.EditorDragged == _editors[i] )
  222. {
  223. Rect editorDraggedRect = editorRect;
  224. editorDraggedRect.y = - _editors[i].Offset.value.y;
  225. SequenceEditor.EditorDraggedRect = editorDraggedRect;
  226. SequenceEditor.Repaint();
  227. }
  228. else
  229. {
  230. if( SequenceEditor.EditorDragged != null && SequenceEditor.EditorDragged.Owner == this )
  231. {
  232. float mouseOffsetY = SequenceEditor.EditorDragged.Offset.value.y;
  233. float editorDraggedTop = Event.current.mousePosition.y - mouseOffsetY;
  234. float editorDraggedBot = editorDraggedTop + SequenceEditor.EditorDraggedRect.height;
  235. if( i < SequenceEditor.EditorDragged.Obj.GetId() )
  236. {
  237. if( _editors[i].Offset.target.y == 0 )
  238. {
  239. if( editorDraggedTop < editorRect.center.y )
  240. _editors[i].Offset.target = new Vector3(0, SequenceEditor.EditorDragged.Height, 0);
  241. else
  242. _editors[i].Offset.target = Vector3.zero;
  243. }
  244. else
  245. {
  246. if( editorDraggedBot > editorRect.center.y + SequenceEditor.EditorDragged.Height )
  247. _editors[i].Offset.target = Vector3.zero;
  248. else
  249. _editors[i].Offset.target = new Vector3(0, SequenceEditor.EditorDragged.Height, 0);
  250. }
  251. }
  252. else if( i > SequenceEditor.EditorDragged.Obj.GetId() )
  253. {
  254. if( _editors[i].Offset.target.y == 0 )
  255. {
  256. if( editorDraggedBot > editorRect.center.y )
  257. _editors[i].Offset.target = new Vector3(0, -SequenceEditor.EditorDragged.Height, 0);
  258. else
  259. _editors[i].Offset.target = Vector3.zero;
  260. }
  261. else
  262. {
  263. if( editorDraggedTop < editorRect.center.y - SequenceEditor.EditorDragged.Height )
  264. _editors[i].Offset.target = Vector3.zero;
  265. else
  266. _editors[i].Offset.target = new Vector3(0, -SequenceEditor.EditorDragged.Height, 0);
  267. }
  268. }
  269. }
  270. Rect editorRenderRect = editorRect;
  271. editorRenderRect.y += _editors[i].Offset.value.y;
  272. _editors[i].Render( editorRenderRect, headerWidth );
  273. Rect editorHeaderRect = editorRect;
  274. editorHeaderRect.width = headerWidth;
  275. if( EditorGUIUtility.hotControl == 0 && Event.current.type == EventType.MouseDrag && Event.current.button == 0 && editorHeaderRect.Contains( Event.current.mousePosition ) )
  276. {
  277. SequenceEditor.StartDraggingEditor( _editors[i] );
  278. if( EditorGUIUtility.hotControl == _editors[i].GuiId ) // make sure we're the one being dragged
  279. _editors[i].Offset.target = _editors[i].Offset.value = new Vector3( 0, Event.current.mousePosition.y - editorRect.y, 0 );
  280. }
  281. }
  282. }
  283. GUI.EndGroup();
  284. }
  285. private void ShowAllContainers( bool show )
  286. {
  287. foreach( FContainerEditor containerEditor in SequenceEditor.Editors )
  288. {
  289. containerEditor.ShowEditorList = show;
  290. }
  291. }
  292. private void ShowAllTimelines( bool show )
  293. {
  294. foreach( FContainerEditor containerEditor in SequenceEditor.Editors )
  295. {
  296. foreach( FTimelineEditor timelineEditor in containerEditor.Editors )
  297. {
  298. timelineEditor.ShowEditorList = show;
  299. }
  300. }
  301. }
  302. public void UpdateListFromOffsets()
  303. {
  304. if( SequenceEditor.EditorDragged == null ) return;
  305. int currentIndex = SequenceEditor.EditorDragged.Obj.GetId();
  306. int newIndex = currentIndex;
  307. for( int i = 0; i != Editors.Count; ++i )
  308. {
  309. if( i == currentIndex )
  310. continue;
  311. if( _editors[i].Offset.target.y > 0 )
  312. --newIndex;
  313. else if( _editors[i].Offset.target.y < 0 )
  314. ++newIndex;
  315. }
  316. if( newIndex != currentIndex )
  317. {
  318. string undoText = "reorder";
  319. Undo.SetTransformParent( SequenceEditor.EditorDragged.Obj.transform, ContentTransform, undoText );
  320. SequenceEditor.EditorDragged.Obj.transform.SetSiblingIndex( newIndex );
  321. Editors.RemoveAt(currentIndex);
  322. Editors.Insert( newIndex, (T)SequenceEditor.EditorDragged );
  323. }
  324. }
  325. }
  326. }