public override void Undo(BeatmapActionContainer.BeatmapActionParams param)
    {
        if (_originalObject != _editedObject || _editedData._time.CompareTo(_originalData._time) != 0)
        {
            _collection.DeleteObject(_editedObject, false, false);
            SelectionController.Deselect(_editedObject, false);

            _originalObject.Apply(_originalData);
            _collection.SpawnObject(_originalObject, false, !InCollection);
        }
        else
        {
            // This is an optimisation only possible if the object has not changed position in the SortedSet
            _originalObject.Apply(_originalData);
            if (!InCollection)
            {
                RefreshPools(Data);
            }
        }

        SelectionController.Select(_originalObject, _addToSelection, true, !InCollection);
    }
Ejemplo n.º 2
0
        public void MirrorInTime()
        {
            _mirror.MirrorTime();

            // Check we can still delete our objects
            var toDelete = _notesContainer.UnsortedObjects.FirstOrDefault();

            _notesContainer.DeleteObject(toDelete);
            Assert.AreEqual(1, _notesContainer.LoadedObjects.Count);

            _actionContainer.Undo();

            Assert.AreEqual(2, _notesContainer.LoadedObjects.Count);

            NoteTest.CheckNote(_notesContainer, 0, 2, BeatmapNote.NOTE_TYPE_B, BeatmapNote.LINE_INDEX_FAR_RIGHT, BeatmapNote.LINE_LAYER_TOP, BeatmapNote.NOTE_CUT_DIRECTION_UP_RIGHT);
            NoteTest.CheckNote(_notesContainer, 1, 3, BeatmapNote.NOTE_TYPE_A, BeatmapNote.LINE_INDEX_FAR_LEFT, BeatmapNote.LINE_LAYER_BOTTOM, BeatmapNote.NOTE_CUT_DIRECTION_LEFT);

            // Undo mirror
            _actionContainer.Undo();

            NoteTest.CheckNote(_notesContainer, 0, 2, BeatmapNote.NOTE_TYPE_A, BeatmapNote.LINE_INDEX_FAR_LEFT, BeatmapNote.LINE_LAYER_BOTTOM, BeatmapNote.NOTE_CUT_DIRECTION_LEFT);
            NoteTest.CheckNote(_notesContainer, 1, 3, BeatmapNote.NOTE_TYPE_B, BeatmapNote.LINE_INDEX_FAR_RIGHT, BeatmapNote.LINE_LAYER_TOP, BeatmapNote.NOTE_CUT_DIRECTION_UP_RIGHT);
        }
Ejemplo n.º 3
0
    public IEnumerator LoadObjects <T>(IEnumerable <T> objects) where T : BeatmapObject
    {
        if (!objects.Any())
        {
            yield break;
        }
        BeatmapObjectContainerCollection collection = BeatmapObjectContainerCollection.GetCollectionForType((objects.First() as T).beatmapType);

        if (collection == null)
        {
            yield break;
        }
        foreach (BeatmapObjectContainer obj in new List <BeatmapObjectContainer>(collection.LoadedContainers))
        {
            collection.DeleteObject(obj);
        }
        PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(true);
        Queue <T> queuedData = new Queue <T>(objects);

        batchSize          = Settings.Instance.InitialLoadBatchSize;
        totalObjectsToLoad = queuedData.Count;
        totalObjectsLoaded = 0;
        while (queuedData.Count > 0)
        { //Batch loading is loading a certain amount of objects (Batch Size) every frame, so at least ChroMapper remains active.
            for (int i = 0; i < batchSize; i++)
            {
                if (queuedData.Count == 0)
                {
                    break;
                }
                BeatmapObject          data = queuedData.Dequeue(); //Dequeue and load them into ChroMapper.
                BeatmapObjectContainer obj  = collection.SpawnObject(data, false, false);
                if (data is BeatmapNote noteData)
                {
                    if (noteData._lineIndex >= 1000 || noteData._lineIndex <= -1000 || noteData._lineLayer >= 1000 || noteData._lineLayer <= -1000)
                    {
                        continue;
                    }
                    if (2 - noteData._lineIndex > noteLaneSize)
                    {
                        noteLaneSize = 2 - noteData._lineIndex;
                    }
                    if (noteData._lineIndex - 1 > noteLaneSize)
                    {
                        noteLaneSize = noteData._lineIndex - 1;
                    }
                    if (noteData._lineLayer + 1 > noteLayerSize)
                    {
                        noteLayerSize = noteData._lineLayer + 1;
                    }
                }
                else if (data is BeatmapObstacle obstacleData)
                {
                    if (obstacleData._lineIndex >= 1000 || obstacleData._lineIndex <= -1000)
                    {
                        continue;
                    }
                    if (2 - obstacleData._lineIndex > noteLaneSize)
                    {
                        noteLaneSize = 2 - obstacleData._lineIndex;
                    }
                    if (obstacleData._lineIndex - 1 > noteLaneSize)
                    {
                        noteLaneSize = obstacleData._lineIndex - 1;
                    }
                }
            }
            UpdateSlider <T>(batchSize);
            yield return(new WaitForEndOfFrame());
        }
        collection.RemoveConflictingObjects();
        if (objects.First() is BeatmapNote || objects.First() is BeatmapObstacle)
        {
            if (Settings.NonPersistentSettings.ContainsKey("NoteLanes"))
            {
                Settings.NonPersistentSettings["NoteLanes"] = (noteLaneSize * 2).ToString();
            }
            else
            {
                Settings.NonPersistentSettings.Add("NoteLanes", (noteLaneSize * 2).ToString());
            }
            noteLanesController.UpdateNoteLanes((noteLaneSize * 2).ToString());
        }
        if (objects.First() is MapEvent)
        {
            manager.RefreshTracks();
        }
        PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(false);
    }
Ejemplo n.º 4
0
    public IEnumerator LoadObjects <T>(IEnumerable <T> objects) where T : BeatmapObject
    {
        if (!objects.Any())
        {
            yield break;
        }
        BeatmapObjectContainerCollection collection = BeatmapObjectContainerCollection.GetCollectionForType(objects.First().beatmapType);

        if (collection == null)
        {
            yield break;
        }
        foreach (BeatmapObject obj in collection.LoadedObjects.ToArray())
        {
            collection.DeleteObject(obj, false, false);
        }
        PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(true);
        collection.LoadedObjects   = new SortedSet <BeatmapObject>(objects, new BeatmapObjectComparer());
        collection.UnsortedObjects = collection.LoadedObjects.ToList();
        UpdateSlider <T>();
        if (typeof(T) == typeof(BeatmapNote) || typeof(T) == typeof(BeatmapObstacle))
        {
            for (int i = 0; i < objects.Count(); i++)
            {
                BeatmapObject data = objects.ElementAt(i);
                if (data is BeatmapNote noteData)
                {
                    if (noteData._lineIndex >= 1000 || noteData._lineIndex <= -1000 || noteData._lineLayer >= 1000 || noteData._lineLayer <= -1000)
                    {
                        continue;
                    }
                    if (2 - noteData._lineIndex > noteLaneSize)
                    {
                        noteLaneSize = 2 - noteData._lineIndex;
                    }
                    if (noteData._lineIndex - 1 > noteLaneSize)
                    {
                        noteLaneSize = noteData._lineIndex - 1;
                    }
                    if (noteData._lineLayer + 1 > noteLayerSize)
                    {
                        noteLayerSize = noteData._lineLayer + 1;
                    }
                }
                else if (data is BeatmapObstacle obstacleData)
                {
                    if (obstacleData._lineIndex >= 1000 || obstacleData._lineIndex <= -1000)
                    {
                        continue;
                    }
                    if (2 - obstacleData._lineIndex > noteLaneSize)
                    {
                        noteLaneSize = 2 - obstacleData._lineIndex;
                    }
                    if (obstacleData._lineIndex - 1 > noteLaneSize)
                    {
                        noteLaneSize = obstacleData._lineIndex - 1;
                    }
                }
            }
            if (Settings.NonPersistentSettings.ContainsKey("NoteLanes"))
            {
                Settings.NonPersistentSettings["NoteLanes"] = (noteLaneSize * 2).ToString();
            }
            else
            {
                Settings.NonPersistentSettings.Add("NoteLanes", (noteLaneSize * 2).ToString());
            }
            noteLanesController.UpdateNoteLanes((noteLaneSize * 2).ToString());
        }
        if (typeof(T) == typeof(MapEvent))
        {
            manager.RefreshTracks();
            EventsContainer events = collection as EventsContainer;
            events.AllRotationEvents = objects.Cast <MapEvent>().Where(x => x.IsRotationEvent).ToList();
            events.AllBoostEvents    = objects.Cast <MapEvent>().Where(x => x._type == MapEvent.EVENT_TYPE_BOOST_LIGHTS).ToList();
        }
        collection.RefreshPool(true);
    }
Ejemplo n.º 5
0
    /// <summary>
    /// Pastes any copied objects into the map, selecting them immediately.
    /// </summary>
    public void Paste(bool triggersAction = true, bool overwriteSection = false)
    {
        DeselectAll();

        // Set up stuff that we need
        List <BeatmapObject> pasted = new List <BeatmapObject>();
        Dictionary <BeatmapObject.Type, BeatmapObjectContainerCollection> collections = new Dictionary <BeatmapObject.Type, BeatmapObjectContainerCollection>();

        // Grab the last BPM Change to warp distances between copied objects and maintain BPM.
        var bpmChanges = BeatmapObjectContainerCollection.GetCollectionForType <BPMChangesContainer>(BeatmapObject.Type.BPM_CHANGE);

        var lowerValue = new BeatmapBPMChange(420, atsc.CurrentBeat - 0.01f);
        var upperValue = new BeatmapBPMChange(69, atsc.CurrentBeat);

        var lastBPMChangeBeforePaste = bpmChanges.FindLastBPM(atsc.CurrentBeat, true);

        // This first loop creates copy of the data to be pasted.
        foreach (BeatmapObject data in CopiedObjects)
        {
            if (data == null)
            {
                continue;
            }

            upperValue._time = atsc.CurrentBeat + data._time;

            var bpmChangeView = bpmChanges.LoadedObjects.GetViewBetween(lowerValue, upperValue);

            float bpmTime = data._time * (copiedBPM / (lastBPMChangeBeforePaste?._BPM ?? copiedBPM));

            if (bpmChangeView.Any())
            {
                var firstBPMChange = bpmChangeView.First() as BeatmapBPMChange;

                bpmTime = firstBPMChange._time - atsc.CurrentBeat;

                for (var i = 0; i < bpmChangeView.Count - 1; i++)
                {
                    var leftBPM  = bpmChangeView.ElementAt(i) as BeatmapBPMChange;
                    var rightBPM = bpmChangeView.ElementAt(i + 1) as BeatmapBPMChange;

                    bpmTime += (rightBPM._time - leftBPM._time) * (copiedBPM / leftBPM._BPM);
                }

                var lastBPMChange = bpmChangeView.Last() as BeatmapBPMChange;
                bpmTime += (atsc.CurrentBeat + data._time - lastBPMChange._time) * (copiedBPM / lastBPMChange._BPM);
            }

            float newTime = bpmTime + atsc.CurrentBeat;

            BeatmapObject newData = BeatmapObject.GenerateCopy(data);
            newData._time = newTime;

            if (!collections.TryGetValue(newData.beatmapType, out BeatmapObjectContainerCollection collection))
            {
                collection = BeatmapObjectContainerCollection.GetCollectionForType(newData.beatmapType);
                collections.Add(newData.beatmapType, collection);
            }

            pasted.Add(newData);
        }

        List <BeatmapObject> totalRemoved = new List <BeatmapObject>();

        // We remove conflicting objects with our to-be-pasted objects.
        foreach (var kvp in collections)
        {
            kvp.Value.RemoveConflictingObjects(pasted.Where(x => x.beatmapType == kvp.Key), out var conflicting);
            totalRemoved.AddRange(conflicting);
        }
        // While we're at it, we will also overwrite the entire section if we have to.
        if (overwriteSection)
        {
            float start = pasted.First()._time;
            float end   = pasted.First()._time;
            foreach (BeatmapObject beatmapObject in pasted)
            {
                if (start > beatmapObject._time)
                {
                    start = beatmapObject._time;
                }
                if (end < beatmapObject._time)
                {
                    end = beatmapObject._time;
                }
            }
            GetObjectTypes(pasted, out bool hasNoteOrObstacle, out bool hasEvent, out bool hasBpmChange);
            List <(BeatmapObjectContainerCollection, BeatmapObject)> toRemove = new List <(BeatmapObjectContainerCollection, BeatmapObject)>();
            ForEachObjectBetweenTimeByGroup(start, end, hasNoteOrObstacle, hasEvent, hasBpmChange, (collection, beatmapObject) =>
            {
                if (pasted.Contains(beatmapObject))
                {
                    return;
                }
                toRemove.Add((collection, beatmapObject));
            });
            foreach ((BeatmapObjectContainerCollection, BeatmapObject)pair in toRemove)
            {
                BeatmapObjectContainerCollection collection = pair.Item1;
                BeatmapObject beatmapObject = pair.Item2;
                collection.DeleteObject(beatmapObject, false);
                totalRemoved.Add(beatmapObject);
            }
        }
        // We then spawn our pasted objects into the map and select them.
        foreach (BeatmapObject data in pasted)
        {
            collections[data.beatmapType].SpawnObject(data, false, false);
            Select(data, true, false, false);
        }
        foreach (BeatmapObjectContainerCollection collection in collections.Values)
        {
            collection.RefreshPool();

            if (collection is BPMChangesContainer con)
            {
                con.RefreshGridShaders();
            }
        }
        if (CopiedObjects.Any(x => (x is MapEvent e) && e.IsRotationEvent))
        {
            tracksManager.RefreshTracks();
        }
        if (triggersAction)
        {
            BeatmapActionContainer.AddAction(new SelectionPastedAction(pasted, totalRemoved));
        }
        SelectionPastedEvent?.Invoke(pasted);
        SelectionChangedEvent?.Invoke();
        RefreshSelectionMaterial(false);

        if (eventPlacement.objectContainerCollection.PropagationEditing != EventsContainer.PropMode.Off)
        {
            eventPlacement.objectContainerCollection.PropagationEditing = eventPlacement.objectContainerCollection.PropagationEditing;
        }
        Debug.Log("Pasted!");
    }