public void MoveSelection(float beats, bool snapObjects = false) { List <BeatmapAction> allActions = new List <BeatmapAction>(); foreach (BeatmapObject data in SelectedObjects) { BeatmapObjectContainerCollection collection = BeatmapObjectContainerCollection.GetCollectionForType(data.beatmapType); BeatmapObject original = BeatmapObject.GenerateCopy(data); collection.LoadedObjects.Remove(data); data._time += beats; if (snapObjects) { data._time = Mathf.Round(beats / (1f / atsc.gridMeasureSnapping)) * (1f / atsc.gridMeasureSnapping); } collection.LoadedObjects.Add(data); if (collection.LoadedContainers.TryGetValue(data, out BeatmapObjectContainer con)) { con.UpdateGridPosition(); } if (collection is NotesContainer notesContainer) { notesContainer.RefreshSpecialAngles(original, false, false); notesContainer.RefreshSpecialAngles(data, false, false); } allActions.Add(new BeatmapObjectModifiedAction(data, data, original, "", true)); } BeatmapActionContainer.AddAction(new ActionCollectionAction(allActions, true, true, "Shifted a selection of objects.")); BeatmapObjectContainerCollection.RefreshAllPools(); }
/// <summary> /// Deletes a <see cref="BeatmapObject"/>. /// </summary> /// <param name="obj">To delete.</param> /// <param name="triggersAction">Whether or not it triggers a <see cref="BeatmapObjectDeletionAction"/></param> /// <param name="refreshesPool">Whether or not the pool will be refreshed as a result of this deletion.</param> /// <param name="comment">A comment that provides further description on why it was deleted.</param> public void DeleteObject(BeatmapObject obj, bool triggersAction = true, bool refreshesPool = true, string comment = "No comment.") { var removed = UnsortedObjects.Remove(obj); var removed2 = LoadedObjects.Remove(obj); if (removed && removed2) { //Debug.Log($"Deleting container with hash code {toDelete.GetHashCode()}"); SelectionController.Deselect(obj, triggersAction); if (triggersAction) { BeatmapActionContainer.AddAction(new BeatmapObjectDeletionAction(obj, comment)); } RecycleContainer(obj); if (refreshesPool) { RefreshPool(); } OnObjectDelete(obj); } else { // The objects are not in the collection, but are still being removed. // This could be because of ghost blocks, so let's try forcefully recycling that container. Debug.LogError($"Object could not be deleted, please report this ({removed}, {removed2})"); } }
public void TweakValue(BeatmapEventContainer e, int modifier) { BeatmapObject original = BeatmapObject.GenerateCopy(e.objectData); e.eventData._value += modifier; if (e.eventData._value == 4 && !e.eventData.IsUtilityEvent) { e.eventData._value += modifier; } if (e.eventData._value < 0) { e.eventData._value = 0; } if (!e.eventData.IsLaserSpeedEvent) { if (e.eventData._value > 7) { e.eventData._value = 7; } } if (e.eventData.IsRotationEvent) { tracksManager?.RefreshTracks(); } eventAppearanceSO.SetEventAppearance(e); BeatmapActionContainer.AddAction(new BeatmapObjectModifiedAction(e.objectData, e.objectData, original)); }
public void ObjectWasSelected() { queuedUpdate = !IsActive; if (queuedUpdate) { return; } if (!SelectionController.HasSelectedObjects()) { isEditing = false; return; } BeatmapActionContainer.RemoveAllActionsOfType <NodeEditorTextChangedAction>(); isEditing = true; if (!Settings.Instance.NodeEditor_UseKeybind) { StopAllCoroutines(); closeButton.gameObject.SetActive(false); StartCoroutine(UpdateGroup(true, transform as RectTransform)); if (firstActive) { firstActive = false; PersistentUI.Instance.DisplayMessage("Mapper", "node.warning", PersistentUI.DisplayMessageType.BOTTOM); } } UpdateJSON(); }
public BeatmapActionParams(BeatmapActionContainer container) { notes = container.notes; obstacles = container.obstacles; events = container.events; bpm = container.bpm; selection = container.selection; nodeEditor = container.nodeEditor; }
private IEnumerator GenerateStrobeCoroutine(int valueA, int valueB, bool regular, bool chroma, bool dynamic, bool swapColors, int interval, int chromaOffset) { generatedObjects.Clear(); //yield return PersistentUI.Instance.FadeInLoadingScreen(); List <BeatmapEventContainer> containers = SelectionController.SelectedObjects.Where(x => x is BeatmapEventContainer).Cast <BeatmapEventContainer>().ToList(); //Grab selected objects List <BeatmapObject> conflictingObjects = new List <BeatmapObject>(); //For the Action //Order by type, then by descending time containers = containers.OrderBy(x => x.eventData._type).ThenByDescending(x => x.eventData._time).ToList(); for (var i = 0; i < 15; i++) { if (containers.Count(x => (x.objectData as MapEvent)._type == i) >= 2) { List <BeatmapEventContainer> filteredContainers = containers.Where(x => x.eventData._type == i).ToList(); BeatmapEventContainer end = filteredContainers.First(); BeatmapEventContainer start = filteredContainers.Last(); List <BeatmapEventContainer> containersBetween = eventsContainer.LoadedContainers.Where(x => (x.objectData as MapEvent)._type == i && //Grab all events between start and end point. x.objectData._time >= start.objectData._time && x.objectData._time <= end.objectData._time ).OrderBy(x => x.objectData._time).Cast <BeatmapEventContainer>().ToList(); List <MapEvent> regularEventData = containersBetween.Select(x => x.eventData).Where(x => x._value < ColourManager.RGB_INT_OFFSET).ToList(); List <MapEvent> chromaEvents = new List <MapEvent>() { FindAttachedChromaEvent(start)?.eventData }; chromaEvents.AddRange(containersBetween.Where(x => x.eventData._value >= ColourManager.RGB_INT_OFFSET).Select(x => x.eventData)); chromaEvents = chromaEvents.Where(x => x != null).DistinctBy(x => x._time).ToList(); conflictingObjects.AddRange(chromaEvents.Concat(regularEventData)); foreach (BeatmapEventContainer e in containersBetween) { eventsContainer.DeleteObject(e); } if (regular) { yield return(StartCoroutine(GenerateRegularStrobe(i, valueA, valueB, end.eventData._time, start.eventData._time, swapColors, dynamic, interval, regularEventData))); } if (chroma && chromaEvents.Count > 0) { yield return(StartCoroutine(GenerateChromaStrobe(i, end.eventData._time, start.eventData._time, interval, 1f / chromaOffset, chromaEvents))); } } } generatedObjects.OrderBy(x => x.objectData._time); SelectionController.RefreshMap(); //yield return PersistentUI.Instance.FadeOutLoadingScreen(); SelectionController.DeselectAll(); SelectionController.SelectedObjects.AddRange(generatedObjects); SelectionController.RefreshSelectionMaterial(false); BeatmapActionContainer.AddAction(new StrobeGeneratorGenerationAction(generatedObjects, conflictingObjects)); generatedObjects.Clear(); }
internal virtual void ApplyToMap() { objectData = queuedData; objectData._time = RoundedTime; //objectContainerCollection.RemoveConflictingObjects(new[] { objectData }, out List<BeatmapObject> conflicting); objectContainerCollection.SpawnObject(objectData, out List <BeatmapObject> conflicting); BeatmapActionContainer.AddAction(GenerateAction(objectData, conflicting)); queuedData = BeatmapObject.GenerateCopy(queuedData); }
public IEnumerator LoadMap() { yield return(TestUtils.LoadMapper()); _actionContainer = Object.FindObjectOfType <BeatmapActionContainer>(); _mirror = Object.FindObjectOfType <MirrorSelection>(); _notesContainer = BeatmapObjectContainerCollection.GetCollectionForType(BeatmapObject.Type.NOTE); _root = _notesContainer.transform.root; _notePlacement = _root.GetComponentInChildren <NotePlacement>(); }
public void ToggleHyperWall(BeatmapObstacleContainer obs) { if (BeatmapObject.GenerateCopy(obs.objectData) is BeatmapObstacle edited) { edited._time += obs.obstacleData._duration; edited._duration *= -1f; BeatmapActionContainer.AddAction(new BeatmapObjectModifiedAction(edited, obs.objectData, obs.objectData), true); } }
public void DeleteObject(BeatmapObjectContainer obj) { if (LoadedContainers.Contains(obj)) { BeatmapActionContainer.AddAction(new BeatmapObjectDeletionAction(obj)); LoadedContainers.Remove(obj); Destroy(obj.gameObject); SelectionController.RefreshMap(); } }
internal virtual void ApplyToMap() { objectData = BeatmapObject.GenerateCopy(queuedData); objectData._time = RoundedTime; BOC spawned = objectContainerCollection.SpawnObject(objectData, out BeatmapObjectContainer conflicting) as BOC; BeatmapActionContainer.AddAction(GenerateAction(spawned, conflicting)); SelectionController.RefreshMap(); queuedData = BeatmapObject.GenerateCopy(queuedData); }
public void NodeEditor_EndEdit(string nodeText) { CMInputCallbackInstaller.ClearDisabledActionMaps(typeof(NodeEditorController), new[] { typeof(CMInput.INodeEditorActions) }); CMInputCallbackInstaller.ClearDisabledActionMaps(typeof(NodeEditorController), actionMapsDisabled); try { if (!isEditing || !IsActive) { return; } JSONNode newNode = JSON.Parse(nodeText); //Parse JSON, and do some basic checks. if (string.IsNullOrEmpty(newNode.ToString())) //Damn you Jackz { throw new Exception("Node cannot be empty."); } // Super sneaky clone, maybe not needed var dict = editingObjects.ToDictionary(it => it, it => it.ConvertToJSON().Clone()); ApplyJSON(editingNode.AsObject, newNode.AsObject, dict); var beatmapActions = dict.Select(entry => new BeatmapObjectModifiedAction( Activator.CreateInstance(entry.Key.GetType(), new object[] { entry.Value }) as BeatmapObject, entry.Key, entry.Key, $"Edited a {entry.Key.beatmapType} with Node Editor.", true) ).ToList(); BeatmapActionContainer.AddAction(new ActionCollectionAction(beatmapActions, true, true, $"Edited ({editingObjects.Count()}) objects with Node Editor."), true); UpdateJSON(); } catch (Exception e) { string message = e.Message; switch (e) { case JSONParseException jsonParse: // Error parsing input JSON; tell them what's wrong! message = jsonParse.ToUIFriendlyString(); break; case TargetInvocationException invocationException: // Error when converting JSON to an object; tell them what's wrong! message = invocationException.InnerException.Message; break; default: //Log the full error to the console Debug.LogError(e); break; } PersistentUI.Instance.ShowDialogBox(message, null, PersistentUI.DialogBoxPresetType.Ok); } }
private void FinishDrag() { if (!(isDraggingObject || isDraggingObjectAtTime)) { return; } //First, find and delete anything that's overlapping our dragged object. var selected = SelectionController.IsObjectSelected(draggedObjectData); // To delete properly we need to set the original time float _time = draggedObjectData._time; draggedObjectData._time = originalDraggedObjectData._time; objectContainerCollection.DeleteObject(draggedObjectData, false, false); draggedObjectData._time = _time; objectContainerCollection.SpawnObject(draggedObjectData, out List <BeatmapObject> conflicting, true, true); if (conflicting.Contains(draggedObjectData)) { conflicting.Remove(draggedObjectData); if (selected) { SelectionController.Select(draggedObjectData); } } queuedData = BeatmapObject.GenerateCopy(originalQueued); BeatmapAction action; // Don't queue an action if we didn't actually change anything if (draggedObjectData.ToString() != originalDraggedObjectData.ToString()) { if (conflicting.Any()) { action = new BeatmapObjectModifiedWithConflictingAction(draggedObjectData, draggedObjectData, originalDraggedObjectData, conflicting.First(), "Modified via alt-click and drag."); } else { action = new BeatmapObjectModifiedAction(draggedObjectData, draggedObjectData, originalDraggedObjectData, "Modified via alt-click and drag."); } BeatmapActionContainer.AddAction(action); } draggedObjectContainer.dragging = false; draggedObjectContainer = null; ClickAndDragFinished(); isDraggingObject = isDraggingObjectAtTime = false; }
/// <summary> /// Deletes and clears the current selection. /// </summary> public void Delete(bool triggersAction = true) { IEnumerable <BeatmapObject> objects = SelectedObjects.ToArray(); if (triggersAction) { BeatmapActionContainer.AddAction(new SelectionDeletedAction(objects)); } DeselectAll(); foreach (BeatmapObject con in objects) { BeatmapObjectContainerCollection.GetCollectionForType(con.beatmapType).DeleteObject(con, false, false); } BeatmapObjectContainerCollection.RefreshAllPools(); }