diff --git a/Assets/Scripts/LevelEditor/Commands/Space.cs b/Assets/Scripts/LevelEditor/Commands/Space.cs new file mode 100644 index 00000000..9761aa35 --- /dev/null +++ b/Assets/Scripts/LevelEditor/Commands/Space.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Jukebox; + +using HeavenStudio.Editor.Track; +using Newtonsoft.Json; +using UnityEditor; +using UnityEngine.Timeline; + +namespace HeavenStudio.Editor.Commands +{ + // Insert / Delete Space + public class MoveEntity : ICommand + { + private readonly List entityIDs = new(); + private List newMoveBeat; + private List lastMoveBeat; + + public MoveEntity(List originalEntities, List newBeat) + { + entityIDs = originalEntities.Select(c => c.guid).ToList(); + newMoveBeat = newBeat; + } + + public void Execute() + { + lastMoveBeat = new(); + var beatmap = GameManager.instance.Beatmap; + var entities = new[] { beatmap.Entities, beatmap.TempoChanges, beatmap.VolumeChanges, beatmap.SectionMarkers } + .SelectMany(list => list); + + for (var i = 0; i < entityIDs.Count; i++) + { + var movedEntity = entities.FirstOrDefault(c => c.guid == entityIDs[i]); + + lastMoveBeat.Add(movedEntity.beat); + movedEntity.beat = newMoveBeat[i]; + } + } + + public void Undo() + { + var beatmap = GameManager.instance.Beatmap; + var entities = new[] { beatmap.Entities, beatmap.TempoChanges, beatmap.VolumeChanges, beatmap.SectionMarkers } + .SelectMany(list => list); + + for (var i = 0; i < entityIDs.Count; i++) + { + var movedEntity = entities.FirstOrDefault(c => c.guid == entityIDs[i]); + + movedEntity.beat = lastMoveBeat[i]; + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/LevelEditor/Commands/Space.cs.meta b/Assets/Scripts/LevelEditor/Commands/Space.cs.meta new file mode 100644 index 00000000..8d3c184d --- /dev/null +++ b/Assets/Scripts/LevelEditor/Commands/Space.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6bb50347e9fcfa143aa79f3ef0f0b436 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/LevelEditor/Editor.cs b/Assets/Scripts/LevelEditor/Editor.cs index d85ad599..800c894b 100644 --- a/Assets/Scripts/LevelEditor/Editor.cs +++ b/Assets/Scripts/LevelEditor/Editor.cs @@ -199,6 +199,18 @@ namespace HeavenStudio.Editor { Timeline.instance.Paste(); } + + if (Input.GetKey(KeyCode.LeftShift)) + { + if (Input.GetKeyDown(KeyCode.I)) + { + Timeline.instance.InsertSpace(); + } + else if (Input.GetKeyDown(KeyCode.U)) + { + Timeline.instance.DeleteSpace(); + } + } } if (Input.GetKey(KeyCode.LeftControl)) diff --git a/Assets/Scripts/LevelEditor/Timeline/Timeline.cs b/Assets/Scripts/LevelEditor/Timeline/Timeline.cs index d393ca8b..aa2a8d6e 100644 --- a/Assets/Scripts/LevelEditor/Timeline/Timeline.cs +++ b/Assets/Scripts/LevelEditor/Timeline/Timeline.cs @@ -935,6 +935,68 @@ namespace HeavenStudio.Editor.Track return dup; } + public void InsertSpace() + { + List originalEntities = new(); + List newBeats = new(); + + var beatmap = GameManager.instance.Beatmap; + var specialEntities = new[] { beatmap.TempoChanges, beatmap.VolumeChanges, beatmap.SectionMarkers } + .SelectMany(list => list); + + foreach (var entity in beatmap.Entities) + { + var entityBeat = entity.beat; + if (entityBeat >= PlaybackBeat) + { + originalEntities.Add(entity); + newBeats.Add(entityBeat + snapInterval); + } + } + foreach (var entity in specialEntities) + { + var entityBeat = entity.beat; + if (entityBeat >= PlaybackBeat && entityBeat > 0) + { + originalEntities.Add(entity); + newBeats.Add(entityBeat + snapInterval); + } + } + + if (originalEntities.Count > 0) CommandManager.Instance.AddCommand(new Commands.MoveEntity(originalEntities, newBeats)); + } + + public void DeleteSpace() + { + List originalEntities = new(); + List newBeats = new(); + + var beatmap = GameManager.instance.Beatmap; + var specialEntities = new[] { beatmap.TempoChanges, beatmap.VolumeChanges, beatmap.SectionMarkers } + .SelectMany(list => list); + + foreach (var entity in beatmap.Entities) + { + var entityBeat = entity.beat; + if (entityBeat - snapInterval >= PlaybackBeat) + { + originalEntities.Add(entity); + newBeats.Add(entityBeat - snapInterval); + } + } + foreach (var entity in specialEntities) + { + var entityBeat = entity.beat; + if (entityBeat - snapInterval >= PlaybackBeat && entityBeat > 0) + { + originalEntities.Add(entity); + newBeats.Add(entityBeat - snapInterval); + } + } + + if (originalEntities.Count > 0) CommandManager.Instance.AddCommand(new Commands.MoveEntity(originalEntities, newBeats)); + } + public float SnapToLayer(float y) { float size = LayerHeight(); diff --git a/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs b/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs index d4f62068..2fa61659 100644 --- a/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs +++ b/Assets/Scripts/LevelEditor/Timeline/TimelineEventObj.cs @@ -62,6 +62,8 @@ namespace HeavenStudio.Editor.Track private double initMoveX = 0; private float initMoveY = 0; + private double selectedMinInitMoveX, selectedMaxInitMoveX; + private float selectedMinInitMoveY, selectedMaxInitMoveY; private bool movedEntity = false; private double lastBeat = 0; @@ -238,8 +240,10 @@ namespace HeavenStudio.Editor.Track { foreach (var marker in Selections.instance.eventsSelected) { - marker.entity.beat = System.Math.Max(Timeline.instance.MousePos2BeatSnap - marker.initMoveX, 0); - marker.entity["track"] = Mathf.Clamp(Timeline.instance.MousePos2Layer - marker.initMoveY, 0, Timeline.instance.LayerCount - 1); + var nextBeat = System.Math.Max(Timeline.instance.MousePos2BeatSnap, selectedMaxInitMoveX) - marker.initMoveX; + var nextTrack = Mathf.Clamp(Timeline.instance.MousePos2Layer, selectedMaxInitMoveY, Timeline.instance.LayerCount - 1 + selectedMinInitMoveY) - marker.initMoveY; + marker.entity.beat = System.Math.Max(nextBeat, 0); + marker.entity["track"] = Mathf.Clamp(nextTrack, 0, Timeline.instance.LayerCount - 1); marker.SetColor((int)entity["track"]); marker.SetWidthHeight(); } @@ -293,6 +297,10 @@ namespace HeavenStudio.Editor.Track marker.initMoveX = Timeline.instance.MousePos2BeatSnap - marker.entity.beat; marker.initMoveY = Timeline.instance.MousePos2Layer - (int)marker.entity["track"]; } + selectedMinInitMoveX = Selections.instance.eventsSelected.Min(marker => marker.initMoveX); + selectedMaxInitMoveX = Selections.instance.eventsSelected.Max(marker => marker.initMoveX); + selectedMinInitMoveY = Selections.instance.eventsSelected.Min(marker => marker.initMoveY); + selectedMaxInitMoveY = Selections.instance.eventsSelected.Max(marker => marker.initMoveY); } #region ClickEvents