Add timeline media selection and editing to be global in sync with keyframes editors
This commit is contained in:
@@ -215,7 +215,7 @@ namespace FlaxEditor.GUI.Timeline
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this media can be resized (duration changed).
|
||||
/// </summary>
|
||||
public bool CanResize;
|
||||
public bool CanResize = true;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Media"/> class.
|
||||
@@ -347,8 +347,9 @@ namespace FlaxEditor.GUI.Timeline
|
||||
var isMovingWholeMedia = _isMoving && !_startMoveRightEdge && !_startMoveLeftEdge;
|
||||
var borderHighlightColor = style.BorderHighlighted;
|
||||
var moveColor = style.ProgressNormal;
|
||||
var selectedColor = style.BackgroundSelected;
|
||||
var moveThickness = 2.0f;
|
||||
var borderColor = isMovingWholeMedia ? moveColor : (IsMouseOver ? borderHighlightColor : style.BorderNormal);
|
||||
var borderColor = isMovingWholeMedia ? moveColor : (Timeline.SelectedMedia.Contains(this) ? selectedColor : (IsMouseOver ? borderHighlightColor : style.BorderNormal));
|
||||
Render2D.DrawRectangle(bounds, borderColor, isMovingWholeMedia ? moveThickness : 1.0f);
|
||||
if (_startMoveLeftEdge)
|
||||
{
|
||||
@@ -384,9 +385,25 @@ namespace FlaxEditor.GUI.Timeline
|
||||
_startMoveDuration = DurationFrames;
|
||||
_startMoveLeftEdge = MoveLeftEdgeRect.Contains(ref location) && CanResize;
|
||||
_startMoveRightEdge = MoveRightEdgeRect.Contains(ref location) && CanResize;
|
||||
|
||||
StartMouseCapture(true);
|
||||
if (_startMoveLeftEdge || _startMoveRightEdge)
|
||||
return true;
|
||||
|
||||
if (Root.GetKey(KeyboardKeys.Control))
|
||||
{
|
||||
// Add/Remove selection
|
||||
if (_timeline.SelectedMedia.Contains(this))
|
||||
_timeline.Deselect(this);
|
||||
else
|
||||
_timeline.Select(this, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Select (additive for the move)
|
||||
_timeline.Select(this, true);
|
||||
}
|
||||
|
||||
_timeline.OnKeyframesMove(null, this, location, true, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -417,7 +434,8 @@ namespace FlaxEditor.GUI.Timeline
|
||||
}
|
||||
else
|
||||
{
|
||||
StartFrame = _startMoveStartFrame + moveDelta;
|
||||
// Move with global timeline selection
|
||||
_timeline.OnKeyframesMove(null, this, location, false, false);
|
||||
}
|
||||
|
||||
if (StartFrame != startFrame || DurationFrames != durationFrames)
|
||||
@@ -436,6 +454,15 @@ namespace FlaxEditor.GUI.Timeline
|
||||
{
|
||||
if (button == MouseButton.Left && _isMoving)
|
||||
{
|
||||
if (!_startMoveLeftEdge && !_startMoveRightEdge && !Root.GetKey(KeyboardKeys.Control))
|
||||
{
|
||||
var moveLocationDelta = Root.MousePosition - _startMoveLocation;
|
||||
if (moveLocationDelta.Length < 4.0f)
|
||||
{
|
||||
// No move so just select itself
|
||||
_timeline.Select(this);
|
||||
}
|
||||
}
|
||||
EndMoving();
|
||||
return true;
|
||||
}
|
||||
@@ -501,19 +528,27 @@ namespace FlaxEditor.GUI.Timeline
|
||||
_startMoveLeftEdge = false;
|
||||
_startMoveRightEdge = false;
|
||||
|
||||
// Re-assign the media start/duration inside the undo recording block
|
||||
if (_startMoveStartFrame != _startFrame || _startMoveDuration != _durationFrames)
|
||||
if (_startMoveLeftEdge || _startMoveRightEdge)
|
||||
{
|
||||
var endMoveStartFrame = _startFrame;
|
||||
var endMoveDuration = _durationFrames;
|
||||
_startFrame = _startMoveStartFrame;
|
||||
_durationFrames = _startMoveDuration;
|
||||
using (new TrackUndoBlock(_tack))
|
||||
// Re-assign the media start/duration inside the undo recording block
|
||||
if (_startMoveStartFrame != _startFrame || _startMoveDuration != _durationFrames)
|
||||
{
|
||||
_startFrame = endMoveStartFrame;
|
||||
_durationFrames = endMoveDuration;
|
||||
var endMoveStartFrame = _startFrame;
|
||||
var endMoveDuration = _durationFrames;
|
||||
_startFrame = _startMoveStartFrame;
|
||||
_durationFrames = _startMoveDuration;
|
||||
using (new TrackUndoBlock(_tack))
|
||||
{
|
||||
_startFrame = endMoveStartFrame;
|
||||
_durationFrames = endMoveDuration;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Global timeline selection moving end
|
||||
_timeline.OnKeyframesMove(null, this, _mouseLocation, false, true);
|
||||
}
|
||||
|
||||
EndMouseCapture();
|
||||
}
|
||||
|
||||
@@ -219,6 +219,10 @@ namespace FlaxEditor.GUI.Timeline
|
||||
private bool _isRightMouseButtonDown;
|
||||
private Vector2 _rightMouseButtonDownPos;
|
||||
private Vector2 _rightMouseButtonMovePos;
|
||||
private Vector2 _mediaMoveStartPos;
|
||||
private int[] _mediaMoveStartFrames;
|
||||
private List<Track> _mediaMoveStartTracks;
|
||||
private byte[][] _mediaMoveStartData;
|
||||
private float _zoom = 1.0f;
|
||||
private bool _isMovingPositionHandle;
|
||||
private bool _canPlayPause = true, _canStop = true;
|
||||
@@ -1375,7 +1379,7 @@ namespace FlaxEditor.GUI.Timeline
|
||||
if (!addToSelection)
|
||||
{
|
||||
SelectedTracks.Clear();
|
||||
SelectedMedia.Clear();
|
||||
OnKeyframesDeselect(null);
|
||||
}
|
||||
SelectedMedia.Add(media);
|
||||
OnSelectionChanged();
|
||||
@@ -1425,47 +1429,40 @@ namespace FlaxEditor.GUI.Timeline
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the selected tracks/media events.
|
||||
/// Deletes the selected tracks.
|
||||
/// </summary>
|
||||
/// <param name="withUndo">True if use undo/redo action for track removing.</param>
|
||||
public void DeleteSelection(bool withUndo = true)
|
||||
public void DeleteSelectedTracks(bool withUndo = true)
|
||||
{
|
||||
if (SelectedMedia.Count > 0)
|
||||
if (SelectedTracks.Count == 0)
|
||||
return;
|
||||
var tracks = new List<Track>(SelectedTracks.Count);
|
||||
for (int i = 0; i < SelectedTracks.Count; i++)
|
||||
{
|
||||
throw new NotImplementedException("TODO: removing selected media events");
|
||||
GetTracks(SelectedTracks[i], tracks);
|
||||
}
|
||||
|
||||
if (SelectedTracks.Count > 0)
|
||||
SelectedTracks.Clear();
|
||||
if (withUndo && Undo != null && Undo.Enabled)
|
||||
{
|
||||
// Delete selected tracks
|
||||
var tracks = new List<Track>(SelectedTracks.Count);
|
||||
for (int i = 0; i < SelectedTracks.Count; i++)
|
||||
if (tracks.Count == 1)
|
||||
{
|
||||
GetTracks(SelectedTracks[i], tracks);
|
||||
Undo.AddAction(new AddRemoveTrackAction(this, tracks[0], false));
|
||||
}
|
||||
SelectedTracks.Clear();
|
||||
if (withUndo && Undo != null && Undo.Enabled)
|
||||
else
|
||||
{
|
||||
if (tracks.Count == 1)
|
||||
{
|
||||
Undo.AddAction(new AddRemoveTrackAction(this, tracks[0], false));
|
||||
}
|
||||
else
|
||||
{
|
||||
var actions = new List<IUndoAction>();
|
||||
for (int i = tracks.Count - 1; i >= 0; i--)
|
||||
actions.Add(new AddRemoveTrackAction(this, tracks[i], false));
|
||||
Undo.AddAction(new MultiUndoAction(actions, "Remove tracks"));
|
||||
}
|
||||
var actions = new List<IUndoAction>();
|
||||
for (int i = tracks.Count - 1; i >= 0; i--)
|
||||
actions.Add(new AddRemoveTrackAction(this, tracks[i], false));
|
||||
Undo.AddAction(new MultiUndoAction(actions, "Remove tracks"));
|
||||
}
|
||||
for (int i = tracks.Count - 1; i >= 0; i--)
|
||||
{
|
||||
tracks[i].ParentTrack = null;
|
||||
OnDeleteTrack(tracks[i]);
|
||||
}
|
||||
OnTracksChanged();
|
||||
MarkAsEdited();
|
||||
}
|
||||
for (int i = tracks.Count - 1; i >= 0; i--)
|
||||
{
|
||||
tracks[i].ParentTrack = null;
|
||||
OnDeleteTrack(tracks[i]);
|
||||
}
|
||||
OnTracksChanged();
|
||||
MarkAsEdited();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1539,6 +1536,32 @@ namespace FlaxEditor.GUI.Timeline
|
||||
MarkAsEdited();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the media.
|
||||
/// </summary>
|
||||
/// <param name="track">The track to add media to.</param>
|
||||
/// <param name="media">The media to add.</param>
|
||||
/// <param name="withUndo">True if use undo/redo action for media adding.</param>
|
||||
public void AddMedia(Track track, Media media, bool withUndo = true)
|
||||
{
|
||||
if (track == null || media == null)
|
||||
throw new ArgumentNullException();
|
||||
if (media.Track != null)
|
||||
throw new InvalidOperationException();
|
||||
if (withUndo && Undo != null && Undo.Enabled)
|
||||
{
|
||||
var before = EditTrackAction.CaptureData(track);
|
||||
track.AddMedia(media);
|
||||
var after = EditTrackAction.CaptureData(track);
|
||||
Undo.AddAction(new EditTrackAction(this, track, before, after));
|
||||
}
|
||||
else
|
||||
{
|
||||
track.AddMedia(media);
|
||||
}
|
||||
MarkAsEdited();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to delete media.
|
||||
/// </summary>
|
||||
@@ -1551,89 +1574,82 @@ namespace FlaxEditor.GUI.Timeline
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Duplicates the selected tracks/media events.
|
||||
/// Duplicates the selected tracks.
|
||||
/// </summary>
|
||||
/// <param name="withUndo">True if use undo/redo action for track duplication.</param>
|
||||
public void DuplicateSelection(bool withUndo = true)
|
||||
public void DuplicateSelectedTracks(bool withUndo = true)
|
||||
{
|
||||
if (SelectedMedia.Count > 0)
|
||||
if (SelectedTracks.Count == 0)
|
||||
return;
|
||||
var tracks = new List<Track>(SelectedTracks.Count);
|
||||
for (int i = 0; i < SelectedTracks.Count; i++)
|
||||
{
|
||||
throw new NotImplementedException("TODO: duplicating selected media events");
|
||||
GetTracks(SelectedTracks[i], tracks);
|
||||
}
|
||||
|
||||
if (SelectedTracks.Count > 0)
|
||||
var clones = new Track[tracks.Count];
|
||||
for (int i = 0; i < tracks.Count; i++)
|
||||
{
|
||||
// Duplicate selected tracks
|
||||
var tracks = new List<Track>(SelectedTracks.Count);
|
||||
for (int i = 0; i < SelectedTracks.Count; i++)
|
||||
var track = tracks[i];
|
||||
var options = new TrackCreateOptions
|
||||
{
|
||||
GetTracks(SelectedTracks[i], tracks);
|
||||
Archetype = track.Archetype,
|
||||
Flags = track.Flags,
|
||||
};
|
||||
var clone = options.Archetype.Create(options);
|
||||
clone.Name = track.CanRename ? GetValidTrackName(track.Name) : track.Name;
|
||||
clone.Color = track.Color;
|
||||
clone.IsExpanded = track.IsExpanded;
|
||||
byte[] data;
|
||||
using (var memory = new MemoryStream(512))
|
||||
using (var stream = new BinaryWriter(memory))
|
||||
{
|
||||
// TODO: reuse memory stream to improve tracks duplication performance
|
||||
options.Archetype.Save(track, stream);
|
||||
data = memory.ToArray();
|
||||
}
|
||||
var clones = new Track[tracks.Count];
|
||||
for (int i = 0; i < tracks.Count; i++)
|
||||
using (var memory = new MemoryStream(data))
|
||||
using (var stream = new BinaryReader(memory))
|
||||
{
|
||||
var track = tracks[i];
|
||||
var options = new TrackCreateOptions
|
||||
track.Archetype.Load(Timeline.FormatVersion, clone, stream);
|
||||
}
|
||||
var trackParent = track.ParentTrack;
|
||||
var trackIndex = track.TrackIndex + 1;
|
||||
if (trackParent != null && tracks.Contains(trackParent))
|
||||
{
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
Archetype = track.Archetype,
|
||||
Flags = track.Flags,
|
||||
};
|
||||
var clone = options.Archetype.Create(options);
|
||||
clone.Name = track.CanRename ? GetValidTrackName(track.Name) : track.Name;
|
||||
clone.Color = track.Color;
|
||||
clone.IsExpanded = track.IsExpanded;
|
||||
byte[] data;
|
||||
using (var memory = new MemoryStream(512))
|
||||
using (var stream = new BinaryWriter(memory))
|
||||
{
|
||||
// TODO: reuse memory stream to improve tracks duplication performance
|
||||
options.Archetype.Save(track, stream);
|
||||
data = memory.ToArray();
|
||||
}
|
||||
using (var memory = new MemoryStream(data))
|
||||
using (var stream = new BinaryReader(memory))
|
||||
{
|
||||
track.Archetype.Load(Timeline.FormatVersion, clone, stream);
|
||||
}
|
||||
var trackParent = track.ParentTrack;
|
||||
var trackIndex = track.TrackIndex + 1;
|
||||
if (trackParent != null && tracks.Contains(trackParent))
|
||||
{
|
||||
for (int j = 0; j < i; j++)
|
||||
if (tracks[j] == trackParent)
|
||||
{
|
||||
if (tracks[j] == trackParent)
|
||||
{
|
||||
trackParent = clones[j];
|
||||
break;
|
||||
}
|
||||
trackParent = clones[j];
|
||||
break;
|
||||
}
|
||||
trackIndex--;
|
||||
}
|
||||
clone.ParentTrack = trackParent;
|
||||
clone.TrackIndex = trackIndex;
|
||||
track.OnDuplicated(clone);
|
||||
AddTrack(clone, false);
|
||||
clones[i] = clone;
|
||||
trackIndex--;
|
||||
}
|
||||
OnTracksOrderChanged();
|
||||
if (withUndo && Undo != null && Undo.Enabled)
|
||||
{
|
||||
if (clones.Length == 1)
|
||||
{
|
||||
Undo.AddAction(new AddRemoveTrackAction(this, clones[0], true));
|
||||
}
|
||||
else
|
||||
{
|
||||
var actions = new List<IUndoAction>();
|
||||
for (int i = 0; i < clones.Length; i++)
|
||||
actions.Add(new AddRemoveTrackAction(this, clones[i], true));
|
||||
Undo.AddAction(new MultiUndoAction(actions, "Remove tracks"));
|
||||
}
|
||||
}
|
||||
OnTracksChanged();
|
||||
MarkAsEdited();
|
||||
SelectedTracks[0].Focus();
|
||||
clone.ParentTrack = trackParent;
|
||||
clone.TrackIndex = trackIndex;
|
||||
track.OnDuplicated(clone);
|
||||
AddTrack(clone, false);
|
||||
clones[i] = clone;
|
||||
}
|
||||
OnTracksOrderChanged();
|
||||
if (withUndo && Undo != null && Undo.Enabled)
|
||||
{
|
||||
if (clones.Length == 1)
|
||||
{
|
||||
Undo.AddAction(new AddRemoveTrackAction(this, clones[0], true));
|
||||
}
|
||||
else
|
||||
{
|
||||
var actions = new List<IUndoAction>();
|
||||
for (int i = 0; i < clones.Length; i++)
|
||||
actions.Add(new AddRemoveTrackAction(this, clones[i], true));
|
||||
Undo.AddAction(new MultiUndoAction(actions, "Remove tracks"));
|
||||
}
|
||||
}
|
||||
OnTracksChanged();
|
||||
MarkAsEdited();
|
||||
SelectedTracks[0].Focus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2067,6 +2083,9 @@ namespace FlaxEditor.GUI.Timeline
|
||||
case KeyboardKeys.S:
|
||||
Split(CurrentFrame);
|
||||
return true;
|
||||
case KeyboardKeys.Delete:
|
||||
OnKeyframesDelete(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -2145,6 +2164,11 @@ namespace FlaxEditor.GUI.Timeline
|
||||
if (_tracks[i] is IKeyframesEditorContext trackContext)
|
||||
trackContext.OnKeyframesDeselect(editor);
|
||||
}
|
||||
if (SelectedMedia.Count != 0)
|
||||
{
|
||||
SelectedMedia.Clear();
|
||||
OnSelectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -2152,17 +2176,38 @@ namespace FlaxEditor.GUI.Timeline
|
||||
{
|
||||
var globalControl = _backgroundArea;
|
||||
var globalRect = Rectangle.FromPoints(control.PointToParent(globalControl, selection.UpperLeft), control.PointToParent(globalControl, selection.BottomRight));
|
||||
var mediaControl = MediaPanel;
|
||||
var mediaRect = Rectangle.FromPoints(mediaControl.PointFromParent(globalRect.UpperLeft), mediaControl.PointFromParent(globalRect.BottomRight));
|
||||
var selectionChanged = false;
|
||||
if (SelectedMedia.Count != 0)
|
||||
{
|
||||
SelectedMedia.Clear();
|
||||
selectionChanged = true;
|
||||
}
|
||||
for (int i = 0; i < _tracks.Count; i++)
|
||||
{
|
||||
if (_tracks[i] is IKeyframesEditorContext trackContext)
|
||||
trackContext.OnKeyframesSelection(editor, globalControl, globalRect);
|
||||
|
||||
foreach (var media in _tracks[i].Media)
|
||||
{
|
||||
if (media.Bounds.Intersects(ref mediaRect))
|
||||
{
|
||||
SelectedMedia.Add(media);
|
||||
selectionChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectionChanged)
|
||||
{
|
||||
OnSelectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int OnKeyframesSelectionCount()
|
||||
{
|
||||
int result = 0;
|
||||
int result = SelectedMedia.Count;
|
||||
for (int i = 0; i < _tracks.Count; i++)
|
||||
{
|
||||
if (_tracks[i] is IKeyframesEditorContext trackContext)
|
||||
@@ -2179,6 +2224,45 @@ namespace FlaxEditor.GUI.Timeline
|
||||
if (_tracks[i] is IKeyframesEditorContext trackContext)
|
||||
trackContext.OnKeyframesDelete(editor);
|
||||
}
|
||||
|
||||
// Delete selected media events
|
||||
if (SelectedMedia.Count != 0)
|
||||
{
|
||||
if (Undo != null && Undo.Enabled)
|
||||
{
|
||||
// Undo per-track
|
||||
if (_mediaMoveStartTracks == null)
|
||||
_mediaMoveStartTracks = new List<Track>();
|
||||
else
|
||||
_mediaMoveStartTracks.Clear();
|
||||
for (var i = 0; i < SelectedMedia.Count; i++)
|
||||
{
|
||||
var media = SelectedMedia[i];
|
||||
if (!_mediaMoveStartTracks.Contains(media.Track))
|
||||
_mediaMoveStartTracks.Add(media.Track);
|
||||
}
|
||||
_mediaMoveStartData = new byte[_mediaMoveStartTracks.Count][];
|
||||
for (int i = 0; i < _mediaMoveStartData.Length; i++)
|
||||
_mediaMoveStartData[i] = EditTrackAction.CaptureData(_mediaMoveStartTracks[i]);
|
||||
}
|
||||
|
||||
foreach (var media in SelectedMedia.ToArray())
|
||||
OnDeleteMedia(media);
|
||||
|
||||
if (Undo != null && Undo.Enabled)
|
||||
{
|
||||
for (int i = 0; i < _mediaMoveStartData.Length; i++)
|
||||
{
|
||||
var track = _mediaMoveStartTracks[i];
|
||||
var before = _mediaMoveStartData[i];
|
||||
var after = EditTrackAction.CaptureData(track);
|
||||
if (!Utils.ArraysEqual(before, after))
|
||||
AddBatchedUndoAction(new EditTrackAction(this, track, before, after));
|
||||
}
|
||||
}
|
||||
|
||||
MarkAsEdited();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -2190,6 +2274,60 @@ namespace FlaxEditor.GUI.Timeline
|
||||
if (_tracks[i] is IKeyframesEditorContext trackContext)
|
||||
trackContext.OnKeyframesMove(editor, _backgroundArea, location, start, end);
|
||||
}
|
||||
if (SelectedMedia.Count != 0)
|
||||
{
|
||||
location = MediaPanel.PointFromParent(location);
|
||||
if (start)
|
||||
{
|
||||
// Start moving selected media events
|
||||
_mediaMoveStartPos = location;
|
||||
_mediaMoveStartFrames = new int[SelectedMedia.Count];
|
||||
if (_mediaMoveStartTracks == null)
|
||||
_mediaMoveStartTracks = new List<Track>();
|
||||
else
|
||||
_mediaMoveStartTracks.Clear();
|
||||
for (var i = 0; i < SelectedMedia.Count; i++)
|
||||
{
|
||||
var media = SelectedMedia[i];
|
||||
_mediaMoveStartFrames[i] = media.StartFrame;
|
||||
if (!_mediaMoveStartTracks.Contains(media.Track))
|
||||
_mediaMoveStartTracks.Add(media.Track);
|
||||
}
|
||||
if (Undo != null && Undo.Enabled)
|
||||
{
|
||||
// Undo per-track
|
||||
_mediaMoveStartData = new byte[_mediaMoveStartTracks.Count][];
|
||||
for (int i = 0; i < _mediaMoveStartData.Length; i++)
|
||||
_mediaMoveStartData[i] = EditTrackAction.CaptureData(_mediaMoveStartTracks[i]);
|
||||
}
|
||||
}
|
||||
else if (end)
|
||||
{
|
||||
// End moving selected media events
|
||||
if (_mediaMoveStartData != null)
|
||||
{
|
||||
for (int i = 0; i < _mediaMoveStartData.Length; i++)
|
||||
{
|
||||
var track = _mediaMoveStartTracks[i];
|
||||
var before = _mediaMoveStartData[i];
|
||||
var after = EditTrackAction.CaptureData(track);
|
||||
if (!Utils.ArraysEqual(before, after))
|
||||
AddBatchedUndoAction(new EditTrackAction(this, track, before, after));
|
||||
}
|
||||
}
|
||||
MarkAsEdited();
|
||||
_mediaMoveStartTracks.Clear();
|
||||
_mediaMoveStartFrames = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move selected media events
|
||||
var moveLocationDelta = location - _mediaMoveStartPos;
|
||||
var moveDelta = (int)(moveLocationDelta.X / (UnitsPerSecond * Zoom) * FramesPerSecond);
|
||||
for (var i = 0; i < SelectedMedia.Count; i++)
|
||||
SelectedMedia[i].StartFrame = _mediaMoveStartFrames[i] + moveDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -1051,7 +1051,7 @@ namespace FlaxEditor.GUI.Timeline
|
||||
if (CanRename)
|
||||
menu.AddButton("Rename", "F2", StartRenaming);
|
||||
if (CanCopyPaste)
|
||||
menu.AddButton("Duplicate", "Ctrl+D", () => Timeline.DuplicateSelection());
|
||||
menu.AddButton("Duplicate", "Ctrl+D", () => Timeline.DuplicateSelectedTracks());
|
||||
menu.AddButton("Delete", "Del", Delete);
|
||||
if (CanExpand)
|
||||
{
|
||||
@@ -1292,12 +1292,12 @@ namespace FlaxEditor.GUI.Timeline
|
||||
StartRenaming();
|
||||
return true;
|
||||
case KeyboardKeys.Delete:
|
||||
_timeline.DeleteSelection();
|
||||
_timeline.DeleteSelectedTracks();
|
||||
return true;
|
||||
case KeyboardKeys.D:
|
||||
if (Root.GetKey(KeyboardKeys.Control) && CanCopyPaste)
|
||||
{
|
||||
_timeline.DuplicateSelection();
|
||||
_timeline.DuplicateSelectedTracks();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user