diff --git a/Source/Editor/GUI/Timeline/Timeline.Data.cs b/Source/Editor/GUI/Timeline/Timeline.Data.cs new file mode 100644 index 000000000..e1a4b69a7 --- /dev/null +++ b/Source/Editor/GUI/Timeline/Timeline.Data.cs @@ -0,0 +1,230 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +using System; +using System.IO; +using FlaxEngine; + +namespace FlaxEditor.GUI.Timeline +{ + partial class Timeline + { + /// + /// Loads the timeline data. + /// + /// The version. + /// The input stream. + protected virtual void LoadTimelineData(int version, BinaryReader stream) + { + } + + /// + /// Saves the timeline data. + /// + /// The output stream. + protected virtual void SaveTimelineData(BinaryWriter stream) + { + } + + /// + /// Loads the timeline data after reading the timeline tracks. + /// + /// The version. + /// The input stream. + protected virtual void LoadTimelineCustomData(int version, BinaryReader stream) + { + } + + /// + /// Saves the timeline data after saving the timeline tracks. + /// + /// The output stream. + protected virtual void SaveTimelineCustomData(BinaryWriter stream) + { + } + + /// + /// Loads the timeline from the specified data. + /// + /// The data. + public virtual void Load(byte[] data) + { + Profiler.BeginEvent("Clear"); + Clear(); + LockChildrenRecursive(); + Profiler.EndEvent(); + + using (var memory = new MemoryStream(data)) + using (var stream = new BinaryReader(memory)) + { + Profiler.BeginEvent("LoadData"); + int version = stream.ReadInt32(); + switch (version) + { + case 1: + { + // [Deprecated on 23.07.2019, expires on 27.04.2021] + + // Load properties + FramesPerSecond = stream.ReadSingle(); + DurationFrames = stream.ReadInt32(); + LoadTimelineData(version, stream); + + // Load tracks + int tracksCount = stream.ReadInt32(); + _tracks.Capacity = Math.Max(_tracks.Capacity, tracksCount); + for (int i = 0; i < tracksCount; i++) + { + var type = stream.ReadByte(); + var flag = stream.ReadByte(); + Track track = null; + var mute = (flag & 1) == 1; + for (int j = 0; j < TrackArchetypes.Count; j++) + { + if (TrackArchetypes[j].TypeId == type) + { + var options = new TrackCreateOptions + { + Archetype = TrackArchetypes[j], + Mute = mute, + }; + track = TrackArchetypes[j].Create(options); + break; + } + } + if (track == null) + throw new Exception("Unknown timeline track type " + type); + int parentIndex = stream.ReadInt32(); + int childrenCount = stream.ReadInt32(); + track.Name = Utilities.Utils.ReadStr(stream, -13); + track.Tag = parentIndex; + + track.Archetype.Load(version, track, stream); + + AddLoadedTrack(track); + } + break; + } + case 2: + case 3: + { + // Load properties + FramesPerSecond = stream.ReadSingle(); + DurationFrames = stream.ReadInt32(); + LoadTimelineData(version, stream); + + // Load tracks + int tracksCount = stream.ReadInt32(); + _tracks.Capacity = Math.Max(_tracks.Capacity, tracksCount); + for (int i = 0; i < tracksCount; i++) + { + var type = stream.ReadByte(); + var flag = stream.ReadByte(); + Track track = null; + var mute = (flag & 1) == 1; + var loop = (flag & 2) == 2; + for (int j = 0; j < TrackArchetypes.Count; j++) + { + if (TrackArchetypes[j].TypeId == type) + { + var options = new TrackCreateOptions + { + Archetype = TrackArchetypes[j], + Mute = mute, + Loop = loop, + }; + track = TrackArchetypes[j].Create(options); + break; + } + } + if (track == null) + throw new Exception("Unknown timeline track type " + type); + int parentIndex = stream.ReadInt32(); + int childrenCount = stream.ReadInt32(); + track.Name = Utilities.Utils.ReadStr(stream, -13); + track.Tag = parentIndex; + track.Color = stream.ReadColor32(); + + Profiler.BeginEvent("LoadTack"); + track.Archetype.Load(version, track, stream); + Profiler.EndEvent(); + + AddLoadedTrack(track); + } + break; + } + default: throw new Exception("Unknown timeline version " + version); + } + LoadTimelineCustomData(version, stream); + Profiler.EndEvent(); + + Profiler.BeginEvent("ParentTracks"); + for (int i = 0; i < _tracks.Count; i++) + { + var parentIndex = (int)_tracks[i].Tag; + _tracks[i].Tag = null; + if (parentIndex != -1) + _tracks[i].ParentTrack = _tracks[parentIndex]; + } + Profiler.EndEvent(); + Profiler.BeginEvent("SetupTracks"); + for (int i = 0; i < _tracks.Count; i++) + { + _tracks[i].OnLoaded(); + } + Profiler.EndEvent(); + } + + Profiler.BeginEvent("ArrangeTracks"); + ArrangeTracks(); + PerformLayout(true); + UnlockChildrenRecursive(); + PerformLayout(true); + Profiler.EndEvent(); + + ClearEditedFlag(); + } + + /// + /// Saves the timeline data. + /// + /// The saved timeline data. + public virtual byte[] Save() + { + // Serialize timeline to stream + using (var memory = new MemoryStream(512)) + using (var stream = new BinaryWriter(memory)) + { + // Save properties + stream.Write(FormatVersion); + stream.Write(FramesPerSecond); + stream.Write(DurationFrames); + SaveTimelineData(stream); + + // Save tracks + int tracksCount = Tracks.Count; + stream.Write(tracksCount); + for (int i = 0; i < tracksCount; i++) + { + var track = Tracks[i]; + + stream.Write((byte)track.Archetype.TypeId); + byte flag = 0; + if (track.Mute) + flag |= 1; + if (track.Loop) + flag |= 2; + stream.Write(flag); + stream.Write(_tracks.IndexOf(track.ParentTrack)); + stream.Write(track.SubTracks.Count); + Utilities.Utils.WriteStr(stream, track.Name, -13); + stream.Write((Color32)track.Color); + track.Archetype.Save(track, stream); + } + + SaveTimelineCustomData(stream); + + return memory.ToArray(); + } + } + } +} diff --git a/Source/Editor/GUI/Timeline/Timeline.UI.cs b/Source/Editor/GUI/Timeline/Timeline.UI.cs new file mode 100644 index 000000000..d124e87cf --- /dev/null +++ b/Source/Editor/GUI/Timeline/Timeline.UI.cs @@ -0,0 +1,301 @@ +// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. + +using FlaxEditor.CustomEditors; +using FlaxEditor.GUI.ContextMenu; +using FlaxEditor.GUI.Timeline.Undo; +using FlaxEngine; +using FlaxEngine.GUI; + +namespace FlaxEditor.GUI.Timeline +{ + partial class Timeline + { + private sealed class TimeIntervalsHeader : ContainerControl + { + private Timeline _timeline; + private bool _isLeftMouseButtonDown; + + public TimeIntervalsHeader(Timeline timeline) + { + _timeline = timeline; + } + + /// + public override bool OnMouseDown(Vector2 location, MouseButton button) + { + if (base.OnMouseDown(location, button)) + return true; + + if (button == MouseButton.Left) + { + _isLeftMouseButtonDown = true; + _timeline._isMovingPositionHandle = true; + StartMouseCapture(); + Seek(ref location); + Focus(); + return true; + } + + return false; + } + + /// + public override void OnMouseMove(Vector2 location) + { + base.OnMouseMove(location); + + if (_isLeftMouseButtonDown) + { + Seek(ref location); + } + } + + private void Seek(ref Vector2 location) + { + if (_timeline.PlaybackState == PlaybackStates.Disabled) + return; + + var locationTimeline = PointToParent(_timeline, location); + var locationTime = _timeline._backgroundArea.PointFromParent(_timeline, locationTimeline); + var frame = (locationTime.X - StartOffset * 2.0f) / _timeline.Zoom / UnitsPerSecond * _timeline.FramesPerSecond; + _timeline.OnSeek((int)frame); + } + + /// + public override bool OnMouseUp(Vector2 location, MouseButton button) + { + if (base.OnMouseUp(location, button)) + return true; + + if (button == MouseButton.Left && _isLeftMouseButtonDown) + { + Seek(ref location); + EndMouseCapture(); + return true; + } + + return false; + } + + /// + public override void OnEndMouseCapture() + { + _isLeftMouseButtonDown = false; + _timeline._isMovingPositionHandle = false; + + base.OnEndMouseCapture(); + } + + /// + public override void OnDestroy() + { + _timeline = null; + + base.OnDestroy(); + } + } + + class PropertiesEditPopup : ContextMenuBase + { + private Timeline _timeline; + private bool _isDirty; + private byte[] _beforeData; + private object _undoContext; + + public PropertiesEditPopup(Timeline timeline, object obj, object undoContext) + { + const float width = 280.0f; + const float height = 160.0f; + Size = new Vector2(width, height); + + var panel1 = new Panel(ScrollBars.Vertical) + { + Bounds = new Rectangle(0, 0.0f, width, height), + Parent = this + }; + var editor = new CustomEditorPresenter(null); + editor.Panel.AnchorPreset = AnchorPresets.HorizontalStretchTop; + editor.Panel.IsScrollable = true; + editor.Panel.Parent = panel1; + editor.Modified += OnModified; + + editor.Select(obj); + + _timeline = timeline; + if (timeline.Undo != null && timeline.Undo.Enabled && undoContext != null) + { + _undoContext = undoContext; + if (undoContext is Track track) + _beforeData = EditTrackAction.CaptureData(track); + else if (undoContext is Timeline) + _beforeData = EditTimelineAction.CaptureData(timeline); + } + } + + private void OnModified() + { + _isDirty = true; + } + + /// + protected override void OnShow() + { + Focus(); + + base.OnShow(); + } + + /// + public override void Hide() + { + if (!Visible) + return; + + Focus(null); + + if (_isDirty) + { + if (_beforeData != null) + { + if (_undoContext is Track track) + { + var after = EditTrackAction.CaptureData(track); + if (!Utils.ArraysEqual(_beforeData, after)) + _timeline.Undo.AddAction(new EditTrackAction(_timeline, track, _beforeData, after)); + } + else if (_undoContext is Timeline) + { + var after = EditTimelineAction.CaptureData(_timeline); + if (!Utils.ArraysEqual(_beforeData, after)) + _timeline.Undo.AddAction(new EditTimelineAction(_timeline, _beforeData, after)); + } + } + _timeline.MarkAsEdited(); + } + + base.Hide(); + } + + /// + public override bool OnKeyDown(KeyboardKeys key) + { + if (key == KeyboardKeys.Escape) + { + Hide(); + return true; + } + + return base.OnKeyDown(key); + } + + /// + public override void OnDestroy() + { + _timeline = null; + _beforeData = null; + _undoContext = null; + + base.OnDestroy(); + } + } + + class TracksPanelArea : Panel + { + private DragDropEffect _currentDragEffect = DragDropEffect.None; + private Timeline _timeline; + private bool _needSetup = true; + + public TracksPanelArea(Timeline timeline) + : base(ScrollBars.Vertical) + { + _timeline = timeline; + } + + /// + public override DragDropEffect OnDragEnter(ref Vector2 location, DragData data) + { + var result = base.OnDragEnter(ref location, data); + if (result == DragDropEffect.None) + { + if (_needSetup) + { + _needSetup = false; + _timeline.SetupDragDrop(); + } + for (int i = 0; i < _timeline.DragHandlers.Count; i++) + { + var dragHelper = _timeline.DragHandlers[i].Helper; + if (dragHelper.OnDragEnter(data)) + { + result = dragHelper.Effect; + break; + } + } + _currentDragEffect = result; + } + + return result; + } + + /// + public override DragDropEffect OnDragMove(ref Vector2 location, DragData data) + { + var result = base.OnDragEnter(ref location, data); + if (result == DragDropEffect.None) + { + result = _currentDragEffect; + } + + return result; + } + + /// + public override void OnDragLeave() + { + _currentDragEffect = DragDropEffect.None; + _timeline.DragHandlers.ForEach(x => x.Helper.OnDragLeave()); + + base.OnDragLeave(); + } + + /// + public override DragDropEffect OnDragDrop(ref Vector2 location, DragData data) + { + var result = base.OnDragDrop(ref location, data); + if (result == DragDropEffect.None && _currentDragEffect != DragDropEffect.None) + { + for (int i = 0; i < _timeline.DragHandlers.Count; i++) + { + var e = _timeline.DragHandlers[i]; + if (e.Helper.HasValidDrag) + { + e.Action(_timeline, e.Helper); + } + } + } + + return result; + } + + /// + public override void Draw() + { + if (IsDragOver && _currentDragEffect != DragDropEffect.None) + { + var style = Style.Current; + Render2D.FillRectangle(new Rectangle(Vector2.Zero, Size), style.BackgroundSelected * 0.4f); + } + + base.Draw(); + } + + /// + public override void OnDestroy() + { + _timeline = null; + + base.OnDestroy(); + } + } + } +} diff --git a/Source/Editor/GUI/Timeline/Timeline.cs b/Source/Editor/GUI/Timeline/Timeline.cs index e87c797b6..98037052a 100644 --- a/Source/Editor/GUI/Timeline/Timeline.cs +++ b/Source/Editor/GUI/Timeline/Timeline.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using FlaxEditor.CustomEditors; using FlaxEditor.GUI.ContextMenu; using FlaxEditor.GUI.Drag; using FlaxEditor.GUI.Input; @@ -19,9 +18,8 @@ namespace FlaxEditor.GUI.Timeline /// /// The timeline control that contains tracks section and headers. Can be used to create time-based media interface for camera tracks editing, audio mixing and events tracking. /// - /// [HideInEditor] - public class Timeline : ContainerControl, IKeyframesEditorContext + public partial class Timeline : ContainerControl, IKeyframesEditorContext { private static readonly KeyValuePair[] FPSValues = { @@ -42,91 +40,6 @@ namespace FlaxEditor.GUI.Timeline internal const int FormatVersion = 3; - private sealed class TimeIntervalsHeader : ContainerControl - { - private Timeline _timeline; - private bool _isLeftMouseButtonDown; - - public TimeIntervalsHeader(Timeline timeline) - { - _timeline = timeline; - } - - /// - public override bool OnMouseDown(Vector2 location, MouseButton button) - { - if (base.OnMouseDown(location, button)) - return true; - - if (button == MouseButton.Left) - { - _isLeftMouseButtonDown = true; - _timeline._isMovingPositionHandle = true; - StartMouseCapture(); - Seek(ref location); - Focus(); - return true; - } - - return false; - } - - /// - public override void OnMouseMove(Vector2 location) - { - base.OnMouseMove(location); - - if (_isLeftMouseButtonDown) - { - Seek(ref location); - } - } - - private void Seek(ref Vector2 location) - { - if (_timeline.PlaybackState == PlaybackStates.Disabled) - return; - - var locationTimeline = PointToParent(_timeline, location); - var locationTime = _timeline._backgroundArea.PointFromParent(_timeline, locationTimeline); - var frame = (locationTime.X - StartOffset * 2.0f) / _timeline.Zoom / UnitsPerSecond * _timeline.FramesPerSecond; - _timeline.OnSeek((int)frame); - } - - /// - public override bool OnMouseUp(Vector2 location, MouseButton button) - { - if (base.OnMouseUp(location, button)) - return true; - - if (button == MouseButton.Left && _isLeftMouseButtonDown) - { - Seek(ref location); - EndMouseCapture(); - return true; - } - - return false; - } - - /// - public override void OnEndMouseCapture() - { - _isLeftMouseButtonDown = false; - _timeline._isMovingPositionHandle = false; - - base.OnEndMouseCapture(); - } - - /// - public override void OnDestroy() - { - _timeline = null; - - base.OnDestroy(); - } - } - /// /// The base class for timeline properties proxy objects. /// @@ -1313,225 +1226,6 @@ namespace FlaxEditor.GUI.Timeline return archetype.Create(options); } - /// - /// Loads the timeline data. - /// - /// The version. - /// The input stream. - protected virtual void LoadTimelineData(int version, BinaryReader stream) - { - } - - /// - /// Saves the timeline data. - /// - /// The output stream. - protected virtual void SaveTimelineData(BinaryWriter stream) - { - } - - /// - /// Loads the timeline data after reading the timeline tracks. - /// - /// The version. - /// The input stream. - protected virtual void LoadTimelineCustomData(int version, BinaryReader stream) - { - } - - /// - /// Saves the timeline data after saving the timeline tracks. - /// - /// The output stream. - protected virtual void SaveTimelineCustomData(BinaryWriter stream) - { - } - - /// - /// Loads the timeline from the specified data. - /// - /// The data. - public virtual void Load(byte[] data) - { - Profiler.BeginEvent("Clear"); - Clear(); - LockChildrenRecursive(); - Profiler.EndEvent(); - - using (var memory = new MemoryStream(data)) - using (var stream = new BinaryReader(memory)) - { - Profiler.BeginEvent("LoadData"); - int version = stream.ReadInt32(); - switch (version) - { - case 1: - { - // [Deprecated on 23.07.2019, expires on 27.04.2021] - - // Load properties - FramesPerSecond = stream.ReadSingle(); - DurationFrames = stream.ReadInt32(); - LoadTimelineData(version, stream); - - // Load tracks - int tracksCount = stream.ReadInt32(); - _tracks.Capacity = Math.Max(_tracks.Capacity, tracksCount); - for (int i = 0; i < tracksCount; i++) - { - var type = stream.ReadByte(); - var flag = stream.ReadByte(); - Track track = null; - var mute = (flag & 1) == 1; - for (int j = 0; j < TrackArchetypes.Count; j++) - { - if (TrackArchetypes[j].TypeId == type) - { - var options = new TrackCreateOptions - { - Archetype = TrackArchetypes[j], - Mute = mute, - }; - track = TrackArchetypes[j].Create(options); - break; - } - } - if (track == null) - throw new Exception("Unknown timeline track type " + type); - int parentIndex = stream.ReadInt32(); - int childrenCount = stream.ReadInt32(); - track.Name = Utilities.Utils.ReadStr(stream, -13); - track.Tag = parentIndex; - - track.Archetype.Load(version, track, stream); - - AddLoadedTrack(track); - } - break; - } - case 2: - case 3: - { - // Load properties - FramesPerSecond = stream.ReadSingle(); - DurationFrames = stream.ReadInt32(); - LoadTimelineData(version, stream); - - // Load tracks - int tracksCount = stream.ReadInt32(); - _tracks.Capacity = Math.Max(_tracks.Capacity, tracksCount); - for (int i = 0; i < tracksCount; i++) - { - var type = stream.ReadByte(); - var flag = stream.ReadByte(); - Track track = null; - var mute = (flag & 1) == 1; - var loop = (flag & 2) == 2; - for (int j = 0; j < TrackArchetypes.Count; j++) - { - if (TrackArchetypes[j].TypeId == type) - { - var options = new TrackCreateOptions - { - Archetype = TrackArchetypes[j], - Mute = mute, - Loop = loop, - }; - track = TrackArchetypes[j].Create(options); - break; - } - } - if (track == null) - throw new Exception("Unknown timeline track type " + type); - int parentIndex = stream.ReadInt32(); - int childrenCount = stream.ReadInt32(); - track.Name = Utilities.Utils.ReadStr(stream, -13); - track.Tag = parentIndex; - track.Color = stream.ReadColor32(); - - Profiler.BeginEvent("LoadTack"); - track.Archetype.Load(version, track, stream); - Profiler.EndEvent(); - - AddLoadedTrack(track); - } - break; - } - default: throw new Exception("Unknown timeline version " + version); - } - LoadTimelineCustomData(version, stream); - Profiler.EndEvent(); - - Profiler.BeginEvent("ParentTracks"); - for (int i = 0; i < _tracks.Count; i++) - { - var parentIndex = (int)_tracks[i].Tag; - _tracks[i].Tag = null; - if (parentIndex != -1) - _tracks[i].ParentTrack = _tracks[parentIndex]; - } - Profiler.EndEvent(); - Profiler.BeginEvent("SetupTracks"); - for (int i = 0; i < _tracks.Count; i++) - { - _tracks[i].OnLoaded(); - } - Profiler.EndEvent(); - } - - Profiler.BeginEvent("ArrangeTracks"); - ArrangeTracks(); - PerformLayout(true); - UnlockChildrenRecursive(); - PerformLayout(true); - Profiler.EndEvent(); - - ClearEditedFlag(); - } - - /// - /// Saves the timeline data. - /// - /// The saved timeline data. - public virtual byte[] Save() - { - // Serialize timeline to stream - using (var memory = new MemoryStream(512)) - using (var stream = new BinaryWriter(memory)) - { - // Save properties - stream.Write(FormatVersion); - stream.Write(FramesPerSecond); - stream.Write(DurationFrames); - SaveTimelineData(stream); - - // Save tracks - int tracksCount = Tracks.Count; - stream.Write(tracksCount); - for (int i = 0; i < tracksCount; i++) - { - var track = Tracks[i]; - - stream.Write((byte)track.Archetype.TypeId); - byte flag = 0; - if (track.Mute) - flag |= 1; - if (track.Loop) - flag |= 2; - stream.Write(flag); - stream.Write(_tracks.IndexOf(track.ParentTrack)); - stream.Write(track.SubTracks.Count); - Utilities.Utils.WriteStr(stream, track.Name, -13); - stream.Write((Color32)track.Color); - track.Archetype.Save(track, stream); - } - - SaveTimelineCustomData(stream); - - return memory.ToArray(); - } - } - /// /// Finds the track by the name. /// @@ -2259,209 +1953,6 @@ namespace FlaxEditor.GUI.Timeline Zoom = viewWidth / timelineWidth; } - class PropertiesEditPopup : ContextMenuBase - { - private Timeline _timeline; - private bool _isDirty; - private byte[] _beforeData; - private object _undoContext; - - public PropertiesEditPopup(Timeline timeline, object obj, object undoContext) - { - const float width = 280.0f; - const float height = 160.0f; - Size = new Vector2(width, height); - - var panel1 = new Panel(ScrollBars.Vertical) - { - Bounds = new Rectangle(0, 0.0f, width, height), - Parent = this - }; - var editor = new CustomEditorPresenter(null); - editor.Panel.AnchorPreset = AnchorPresets.HorizontalStretchTop; - editor.Panel.IsScrollable = true; - editor.Panel.Parent = panel1; - editor.Modified += OnModified; - - editor.Select(obj); - - _timeline = timeline; - if (timeline.Undo != null && timeline.Undo.Enabled && undoContext != null) - { - _undoContext = undoContext; - if (undoContext is Track track) - _beforeData = EditTrackAction.CaptureData(track); - else if (undoContext is Timeline) - _beforeData = EditTimelineAction.CaptureData(timeline); - } - } - - private void OnModified() - { - _isDirty = true; - } - - /// - protected override void OnShow() - { - Focus(); - - base.OnShow(); - } - - /// - public override void Hide() - { - if (!Visible) - return; - - Focus(null); - - if (_isDirty) - { - if (_beforeData != null) - { - if (_undoContext is Track track) - { - var after = EditTrackAction.CaptureData(track); - if (!Utils.ArraysEqual(_beforeData, after)) - _timeline.Undo.AddAction(new EditTrackAction(_timeline, track, _beforeData, after)); - } - else if (_undoContext is Timeline) - { - var after = EditTimelineAction.CaptureData(_timeline); - if (!Utils.ArraysEqual(_beforeData, after)) - _timeline.Undo.AddAction(new EditTimelineAction(_timeline, _beforeData, after)); - } - } - _timeline.MarkAsEdited(); - } - - base.Hide(); - } - - /// - public override bool OnKeyDown(KeyboardKeys key) - { - if (key == KeyboardKeys.Escape) - { - Hide(); - return true; - } - - return base.OnKeyDown(key); - } - - /// - public override void OnDestroy() - { - _timeline = null; - _beforeData = null; - _undoContext = null; - - base.OnDestroy(); - } - } - - class TracksPanelArea : Panel - { - private DragDropEffect _currentDragEffect = DragDropEffect.None; - private Timeline _timeline; - private bool _needSetup = true; - - public TracksPanelArea(Timeline timeline) - : base(ScrollBars.Vertical) - { - _timeline = timeline; - } - - /// - public override DragDropEffect OnDragEnter(ref Vector2 location, DragData data) - { - var result = base.OnDragEnter(ref location, data); - if (result == DragDropEffect.None) - { - if (_needSetup) - { - _needSetup = false; - _timeline.SetupDragDrop(); - } - for (int i = 0; i < _timeline.DragHandlers.Count; i++) - { - var dragHelper = _timeline.DragHandlers[i].Helper; - if (dragHelper.OnDragEnter(data)) - { - result = dragHelper.Effect; - break; - } - } - _currentDragEffect = result; - } - - return result; - } - - /// - public override DragDropEffect OnDragMove(ref Vector2 location, DragData data) - { - var result = base.OnDragEnter(ref location, data); - if (result == DragDropEffect.None) - { - result = _currentDragEffect; - } - - return result; - } - - /// - public override void OnDragLeave() - { - _currentDragEffect = DragDropEffect.None; - _timeline.DragHandlers.ForEach(x => x.Helper.OnDragLeave()); - - base.OnDragLeave(); - } - - /// - public override DragDropEffect OnDragDrop(ref Vector2 location, DragData data) - { - var result = base.OnDragDrop(ref location, data); - if (result == DragDropEffect.None && _currentDragEffect != DragDropEffect.None) - { - for (int i = 0; i < _timeline.DragHandlers.Count; i++) - { - var e = _timeline.DragHandlers[i]; - if (e.Helper.HasValidDrag) - { - e.Action(_timeline, e.Helper); - } - } - } - - return result; - } - - /// - public override void Draw() - { - if (IsDragOver && _currentDragEffect != DragDropEffect.None) - { - var style = Style.Current; - Render2D.FillRectangle(new Rectangle(Vector2.Zero, Size), style.BackgroundSelected * 0.4f); - } - - base.Draw(); - } - - /// - public override void OnDestroy() - { - _timeline = null; - - base.OnDestroy(); - } - } - /// /// Shows the timeline object editing popup. ///