Files

179 lines
6.2 KiB
C#

using System;
using System.Linq;
using DG.DemiEditor;
using DG.Tweening;
using JetBrains.Annotations;
using UnityEngine;
namespace Dott.Editor
{
public class DottView
{
private bool isTimeDragging;
private bool isTweenDragging;
private static readonly AddMoreItem[] AddMoreItems = CreateAddMoreItems();
public float TimeScale { get; private set; }
public bool IsTimeDragging => isTimeDragging;
public bool IsTweenDragging => isTweenDragging;
public bool IsSnapping { get; set; }
public event Action<Event> TimeDragEnd;
public event Action<float> TimeDrag;
public event Action<IDOTweenAnimation> TweenSelected;
public event Action<float> TweenDrag;
public event Action AddClicked;
public event Action<Type> AddMore;
public event Action RemoveClicked;
public event Action DuplicateClicked;
public event Action StopClicked;
public event Action PlayClicked;
public event Action<bool> LoopToggled;
public event Action SnapToggled;
public event Action PreviewDisabled;
public event Action InspectorUpButtonClicked;
public event Action InspectorDownButtonClicked;
public void DrawTimeline(IDOTweenAnimation[] animations, [CanBeNull] IDOTweenAnimation selected, bool isPlaying, float currentPlayingTime, bool isLooping, bool isPaused)
{
var rect = DottGUI.GetTimelineControlRect(animations.Length);
DottGUI.Background(rect);
var headerRect = DottGUI.Header(rect);
TimeScale = CalculateTimeScale(animations);
var timeDragStarted = false;
var timeRect = DottGUI.Time(rect, TimeScale, ref isTimeDragging, () => timeDragStarted = true, TimeDragEnd);
var tweensRect = DottGUI.Tweens(rect, animations, TimeScale, selected, ref isTweenDragging, TweenSelected);
if (DottGUI.AddButton(rect))
{
AddClicked?.Invoke();
}
DottGUI.AddMoreButton(rect, AddMoreItems, item => AddMore?.Invoke(item.Type));
if (selected != null && DottGUI.RemoveButton(rect))
{
RemoveClicked?.Invoke();
}
if (selected != null && DottGUI.DuplicateButton(rect))
{
DuplicateClicked?.Invoke();
}
if (isPlaying || isPaused)
{
var scaledTime = currentPlayingTime * TimeScale;
var verticalRect = timeRect.Add(tweensRect);
DottGUI.TimeVerticalLine(verticalRect, scaledTime, isPaused);
if (isPaused)
{
DottGUI.PlayheadLabel(timeRect, scaledTime, currentPlayingTime);
}
}
if (isTimeDragging)
{
var scaledTime = DottGUI.GetScaledTimeUnderMouse(timeRect);
var rawTime = scaledTime / TimeScale;
DottGUI.TimeVerticalLine(timeRect.Add(tweensRect), scaledTime, underLabel: true);
DottGUI.PlayheadLabel(timeRect, scaledTime, rawTime);
if (Event.current.type is EventType.MouseDrag || timeDragStarted)
{
TimeDrag?.Invoke(rawTime);
}
}
if (isTweenDragging && selected != null)
{
var time = DottGUI.GetScaledTimeUnderMouse(timeRect);
if (Event.current.type == EventType.MouseDrag)
{
var rawTime = time / TimeScale;
TweenDrag?.Invoke(rawTime);
}
}
switch (isPlaying)
{
case true when DottGUI.StopButton(rect):
StopClicked?.Invoke();
break;
case false when DottGUI.PlayButton(rect):
PlayClicked?.Invoke();
break;
}
var snapToggle = DottGUI.SnapToggle(rect, IsSnapping);
if (snapToggle != IsSnapping)
{
IsSnapping = snapToggle;
SnapToggled?.Invoke();
}
var loopResult = DottGUI.LoopToggle(rect, isLooping);
if (loopResult != isLooping)
{
LoopToggled?.Invoke(loopResult);
}
if (DottGUI.PreviewEye(headerRect, isPlaying, isPaused, isTimeDragging))
{
PreviewDisabled?.Invoke();
}
if (Event.current.type == EventType.MouseDown)
{
var mousePosition = Event.current.mousePosition;
if (selected != null && rect.Contains(mousePosition))
{
TweenSelected?.Invoke(null);
}
}
}
public void DrawInspector(UnityEditor.Editor editor)
{
DottGUI.Inspector(editor, InspectorUpButtonClicked, InspectorDownButtonClicked);
}
private static float CalculateTimeScale(IDOTweenAnimation[] animations)
{
var maxTime = animations.Length > 0
? animations.Max(animation => animation.Delay + animation.Duration * Mathf.Max(1, animation.Loops))
: 1f;
return 1f / maxTime;
}
private static AddMoreItem[] CreateAddMoreItems()
{
var types = AppDomain.CurrentDomain.GetAssemblies()
.Where(assembly => !assembly.IsDynamic)
.SelectMany(assembly => assembly.GetExportedTypes())
.Where(type => type.IsClass && !type.IsAbstract && typeof(IDOTweenAnimation).IsAssignableFrom(type))
.ToArray();
return types
.Select((type, _) => new AddMoreItem(new GUIContent($"Add {type.Name.Replace("DOTween", "")}"), type))
.Prepend(new AddMoreItem(new GUIContent("Add Tween"), typeof(DOTweenAnimation)))
.ToArray();
}
public struct AddMoreItem
{
public readonly GUIContent Content;
public readonly Type Type;
public AddMoreItem(GUIContent content, Type type)
{
Content = content;
Type = type;
}
}
}
}