private void UpdateNote(BeatmapNoteContainer container, int lineIndex, int lineLayer, int cutDirection) { var note = (BeatmapNote)container.objectData; note._lineIndex = lineIndex; note._lineLayer = lineLayer; note._cutDirection = cutDirection; container.UpdateGridPosition(); container.transform.localEulerAngles = BeatmapNoteContainer.Directionalize(note); }
public static BeatmapNoteContainer SpawnBeatmapNote(BeatmapNote noteData, ref GameObject notePrefab, ref GameObject bombPrefab, ref NoteAppearanceSO appearanceSO) { bool isBomb = noteData._type == BeatmapNote.NOTE_TYPE_BOMB; BeatmapNoteContainer container = Instantiate(isBomb ? bombPrefab : notePrefab).GetComponent <BeatmapNoteContainer>(); container.isBomb = isBomb; container.mapNoteData = noteData; container.noteAppearance = appearanceSO; appearanceSO.SetNoteAppearance(container); container.Directionalize(noteData._cutDirection); container._timeForEditor = noteData._time; return(container); }
protected override void UpdateContainerData(BeatmapObjectContainer con, BeatmapObject obj) { BeatmapNoteContainer note = con as BeatmapNoteContainer; BeatmapNote noteData = obj as BeatmapNote; note.SetBomb(noteData._type == BeatmapNote.NOTE_TYPE_BOMB); noteAppearanceSO.SetNoteAppearance(note); note.Setup(); note.transform.localEulerAngles = BeatmapNoteContainer.Directionalize(noteData); Track track = tracksManager.GetTrackAtTime(obj._time); track.AttachContainer(con); foreach (Material mat in con.ModelMaterials) { allNoteRenderers.Add(mat); mat.SetFloat("_Rotation", track.RotationValue.y); } }
public void UpdateAppearance(BeatmapObjectContainer obj) { switch (obj) { case BeatmapNoteContainer note: note.transform.localEulerAngles = BeatmapNoteContainer.Directionalize(note.mapNoteData); noteAppearance.SetNoteAppearance(note); break; case BeatmapEventContainer e: eventAppearance.SetEventAppearance(e); break; case BeatmapObstacleContainer o: obstacleAppearance.SetObstacleAppearance(o); break; } tracksManager.RefreshTracks(); obj.UpdateGridPosition(); SelectionController.RefreshMap(); }
private void NotePassedThreshold(bool natural, int id, BeatmapObject obj) { BeatmapNote note = obj as BeatmapNote; if (!InstantiatedNotes.ContainsKey(note._type)) { InstantiatedNotes.Add(note._type, new Dictionary <GameObject, Image>()); } if (lastByType.TryGetValue(note._type, out BeatmapNote lastInTime) && lastInTime._time != obj._time) { foreach (KeyValuePair <GameObject, Image> child in InstantiatedNotes[note._type]) { child.Key.SetActive(false); } } if (note._type == BeatmapNote.NOTE_TYPE_BOMB) { return; } float gridPosX = note._lineIndex, gridPosY = note._lineLayer; if (note._customData?.HasKey("_position") ?? false) { Vector2 pos = note._customData["_position"]; gridPosX = pos.x + 2f; gridPosY = pos.y; } else //mapping extensions ew { if (gridPosX >= 1000) { gridPosX = gridPosX / 1000 - 1f; } else if (gridPosX <= -1000f) { gridPosX = gridPosX / 1000f + 1f; } if (gridPosY >= 1000) { gridPosY = gridPosY / 1000f - 1f; } else if (gridPosY <= -1000f) { gridPosY = gridPosY / 1000f + 1f; } } var position = new Vector3(_gridSize * gridPosX, _gridSize * gridPosY, 1); if (InstantiatedNotes[note._type].Any(x => x.Key.activeSelf && x.Value.transform.localPosition == position)) { // Note already visible return; } GameObject g; //Instead of instantiating new objects every frame (Bad on performance), we are instead using a pooled system to use Image img; //Already existing notes, and only create ones we need. if (InstantiatedNotes[note._type].Any(x => !x.Key.activeSelf)) { g = InstantiatedNotes[note._type].First(x => !x.Key.activeSelf).Key; img = InstantiatedNotes[note._type][g]; g.SetActive(true); g.transform.SetSiblingIndex(g.transform.parent.childCount); foreach (Transform child in g.transform) { child.gameObject.SetActive(true); } } else { g = Instantiate(gridNotePrefab, notes.transform, true); img = g.GetComponent <Image>(); InstantiatedNotes[note._type].Add(g, img); } var transform1 = img.transform; transform1.localPosition = position; float sc = scale / 10f + .06f; transform1.localScale = new Vector3(sc, sc); //I have to do this because the UI scaling is weird //transform1.rotation = o.transform.rotation; //This code breaks when using 360 maps; use local rotation instead. transform1.localEulerAngles = Vector3.forward * BeatmapNoteContainer.Directionalize(note).z; //Sets the rotation of the image to match the same rotation as the block img.color = note._type == BeatmapNote.NOTE_TYPE_A ? noteAppearance.RedColor : noteAppearance.BlueColor; bool dotEnabled = note._cutDirection == BeatmapNote.NOTE_CUT_DIRECTION_ANY; //Checks to see if the Dot is visible on the block if (dotEnabled) { g.transform.GetChild(0).gameObject.SetActive(false); } else { g.transform.GetChild(1).gameObject.SetActive(false); } img.enabled = true; if (!lastByType.ContainsKey(note._type)) { lastByType.Add(note._type, note); } else { lastByType[note._type] = note; } }
public void Mirror() { if (!SelectionController.HasSelectedObjects()) { PersistentUI.Instance.DisplayMessage("Select stuff first!", PersistentUI.DisplayMessageType.BOTTOM); return; } foreach (BeatmapObjectContainer con in SelectionController.SelectedObjects) { if (con is BeatmapObstacleContainer obstacle) { bool precisionWidth = obstacle.obstacleData._width >= 1000; int __state = obstacle.obstacleData._lineIndex; if (__state >= 1000 || __state <= -1000 || precisionWidth) // precision lineIndex { int newIndex = __state; if (newIndex <= -1000) // normalize index values, we'll fix them later { newIndex += 1000; } else if (newIndex >= 1000) { newIndex -= 1000; } else { newIndex = newIndex * 1000; //convert lineIndex to precision if not already } newIndex = (((newIndex - 2000) * -1) + 2000); //flip lineIndex int newWidth = obstacle.obstacleData._width; //normalize wall width if (newWidth < 1000) { newWidth = newWidth * 1000; } else { newWidth -= 1000; } newIndex = newIndex - newWidth; if (newIndex < 0) { //this is where we fix them newIndex -= 1000; } else { newIndex += 1000; } obstacle.obstacleData._lineIndex = newIndex; } else // state > -1000 || state < 1000 assumes no precision width { int mirrorLane = (((__state - 2) * -1) + 2); //flip lineIndex obstacle.obstacleData._lineIndex = mirrorLane - obstacle.obstacleData._width; //adjust for wall width } con.UpdateGridPosition(); } else if (con is BeatmapNoteContainer note) { int __state = note.mapNoteData._lineIndex; // flip line index if (__state > 3 || __state < 0) // precision case { int newIndex = __state; if (newIndex <= -1000) // normalize index values, we'll fix them later { newIndex += 1000; } else if (newIndex >= 1000) { newIndex -= 1000; } newIndex = (((newIndex - 1500) * -1) + 1500); //flip lineIndex if (newIndex < 0) //this is where we fix them { newIndex -= 1000; } else { newIndex += 1000; } note.mapNoteData._lineIndex = newIndex; } else { int mirrorLane = (int)(((__state - 1.5f) * -1) + 1.5f); note.mapNoteData._lineIndex = mirrorLane; } con.UpdateGridPosition(); //flip colors if (note.mapNoteData is BeatmapChromaNote chroma) { note.mapNoteData = chroma.originalNote; //Revert Chroma status, then invert types } if (note.mapNoteData._type != BeatmapNote.NOTE_TYPE_BOMB) { note.mapNoteData._type = note.mapNoteData._type == BeatmapNote.NOTE_TYPE_A ? BeatmapNote.NOTE_TYPE_B : BeatmapNote.NOTE_TYPE_A; //flip cut direction horizontally if (CutDirectionToMirrored.ContainsKey(note.mapNoteData._cutDirection)) { note.mapNoteData._cutDirection = CutDirectionToMirrored[note.mapNoteData._cutDirection]; note.transform.localEulerAngles = BeatmapNoteContainer.Directionalize(note.mapNoteData); } } noteAppearance.SetNoteAppearance(note); } else if (con is BeatmapEventContainer e) { if (e.eventData.IsRotationEvent) { int?rotation = e.eventData.GetRotationDegreeFromValue(); if (rotation != null) { if (e.eventData._value >= 0 && e.eventData._value < MapEvent.LIGHT_VALUE_TO_ROTATION_DEGREES.Length) { e.eventData._value = MapEvent.LIGHT_VALUE_TO_ROTATION_DEGREES.ToList().IndexOf((rotation ?? 0) * -1); } else if (e.eventData._value >= 1000 && e.eventData._value <= 1720) //Invert Mapping Extensions rotation { e.eventData._value = 1720 - (e.eventData._value - 1000); } } eventAppearance?.SetEventAppearance(e); tracksManager?.RefreshTracks(); return; } if (e.eventData.IsUtilityEvent) { return; } if (e.eventData._value > 4 && e.eventData._value < 8) { e.eventData._value -= 4; } else if (e.eventData._value > 0 && e.eventData._value <= 4) { e.eventData._value += 4; } eventAppearance?.SetEventAppearance(e); } } SelectionController.RefreshMap(); }
public void RefreshSpecialAngles(BeatmapObject obj, bool objectWasSpawned, bool isNatural) { // Do not bother refreshing if objects are despawning naturally (while playing back the song) if (!objectWasSpawned && isNatural) { return; } // Do not do special angles for bombs if ((obj as BeatmapNote)._type == BeatmapNote.NOTE_TYPE_BOMB) { return; } // Grab all objects with the same type, and time (within epsilon) objectsAtSameTime.Clear(); foreach (var x in LoadedContainers) { if (!(x.Key._time - Epsilon <= obj._time && x.Key._time + Epsilon >= obj._time && (x.Key as BeatmapNote)._type == (obj as BeatmapNote)._type)) { continue; } objectsAtSameTime.Add(x.Value); } // Only execute if we have exactly 2 notes with the same type if (objectsAtSameTime.Count == 2) { // Due to the potential for "obj" not having a container, we cannot reuse it as "a". BeatmapNote a = objectsAtSameTime.First().objectData as BeatmapNote; BeatmapNote b = objectsAtSameTime.Last().objectData as BeatmapNote; // Grab the containers we will be flipping BeatmapObjectContainer containerA = objectsAtSameTime.First(); BeatmapObjectContainer containerB = objectsAtSameTime.Last(); // Do not execute if cut directions are not the same (and both are not dot notes) if (a._cutDirection != b._cutDirection && a._cutDirection != BeatmapNote.NOTE_CUT_DIRECTION_ANY && b._cutDirection != BeatmapNote.NOTE_CUT_DIRECTION_ANY) { return; } if (a._cutDirection == BeatmapNote.NOTE_CUT_DIRECTION_ANY) { (a, b) = (b, a); // You can flip variables like this in C#. Who knew? (containerA, containerB) = (containerB, containerA); } Vector2 posA = containerA.transform.localPosition; Vector2 posB = containerB.transform.localPosition; Vector2 cutVector = a._cutDirection == BeatmapNote.NOTE_CUT_DIRECTION_ANY ? Vector2.up : Direction(a); Vector2 line = posA - posB; float angle = SignedAngleToLine(cutVector, line); // if both notes are dots, line them up with each other by adding the signed angle. if (a._cutDirection == BeatmapNote.NOTE_CUT_DIRECTION_ANY && b._cutDirection == BeatmapNote.NOTE_CUT_DIRECTION_ANY) { containerA.transform.localEulerAngles = Vector3.forward * angle; containerB.transform.localEulerAngles = Vector3.forward * angle; } else { Vector3 originalA = BeatmapNoteContainer.Directionalize(a); Vector3 originalB = BeatmapNoteContainer.Directionalize(b); // We restrict angles below 40 (For 45 just use diagonal notes KEKW) if (Mathf.Abs(angle) <= 40) { containerA.transform.localEulerAngles = originalA + (Vector3.forward * angle); if (b._cutDirection == BeatmapNote.NOTE_CUT_DIRECTION_ANY && !a.IsMainDirection) { containerB.transform.localEulerAngles = originalB + (Vector3.forward * (angle + 45)); } else { containerB.transform.localEulerAngles = originalB + (Vector3.forward * angle); } } } } else { foreach (var toReset in objectsAtSameTime) { Vector3 direction = BeatmapNoteContainer.Directionalize(toReset.objectData as BeatmapNote); toReset.transform.localEulerAngles = direction; } } }