private IEnumerator ConvertToLegacy() { List <BeatmapObject> ToSpawn = new List <BeatmapObject>(); List <BeatmapObjectContainer> ToDestroy = new List <BeatmapObjectContainer>(); yield return(PersistentUI.Instance.FadeInLoadingScreen()); if (BeatSaberSongContainer.Instance != null) { foreach (BeatmapObjectContainer container in notesContainer.LoadedContainers) { BeatmapNoteContainer note = container as BeatmapNoteContainer; if (note.mapNoteData is BeatmapChromaNote) { ToSpawn.Add((note.mapNoteData as BeatmapChromaNote).ConvertToNote()); BeatmapNote bombData = new BeatmapNote((note.mapNoteData as BeatmapChromaNote).ConvertToNote().ConvertToJSON()); bombData._type = BeatmapNote.NOTE_TYPE_BOMB; bombData._cutDirection = (note.mapNoteData as BeatmapChromaNote).BombRotation; ToSpawn.Add(bombData); ToDestroy.Add(note); } } } notesContainer.SortObjects(); foreach (BeatmapObjectContainer con in ToDestroy) { notesContainer.DeleteObject(con); } foreach (BeatmapObject data in ToSpawn) { notesContainer.SpawnObject(data, out _); } SelectionController.RefreshMap(); yield return(PersistentUI.Instance.FadeOutLoadingScreen()); }
public override BeatmapObjectContainer SpawnObject(BeatmapObject obj, out BeatmapObjectContainer conflicting, bool removeConflicting = true, bool refreshMap = true) { conflicting = null; if (removeConflicting) { conflicting = LoadedContainers.FirstOrDefault(x => x.objectData._time == obj._time && ((BeatmapNote)obj)._lineLayer == ((BeatmapNote)x.objectData)._lineLayer && ((BeatmapNote)obj)._lineIndex == ((BeatmapNote)x.objectData)._lineIndex && ((BeatmapNote)obj)._type == ((BeatmapNote)x.objectData)._type && ConflictingByTrackIDs(obj, x.objectData) ); if (conflicting != null) { DeleteObject(conflicting, true, $"Conflicted with a newer object at time {obj._time}"); } } BeatmapNoteContainer beatmapNote = BeatmapNoteContainer.SpawnBeatmapNote(obj as BeatmapNote, ref notePrefab, ref bombPrefab, ref noteAppearanceSO); beatmapNote.transform.SetParent(GridTransform); beatmapNote.UpdateGridPosition(); LoadedContainers.Add(beatmapNote); if (Settings.Instance.HighlightLastPlacedNotes) { beatmapNote.SetOutlineColor(Color.magenta); } if (refreshMap) { SelectionController.RefreshMap(); } return(beatmapNote); }
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 override BeatmapObjectContainer SpawnObject(BeatmapObject obj) { BeatmapObjectContainer conflicting = LoadedContainers.FirstOrDefault(x => x.objectData._time == obj._time && (obj as BeatmapNote)._lineLayer == (x.objectData as BeatmapNote)._lineLayer && (obj as BeatmapNote)._lineIndex == (x.objectData as BeatmapNote)._lineIndex ); if (conflicting != null) { DeleteObject(conflicting); } BeatmapNoteContainer beatmapNote = BeatmapNoteContainer.SpawnBeatmapNote(obj as BeatmapNote, ref notePrefab, ref bombPrefab, ref noteAppearanceSO); beatmapNote.transform.SetParent(GridTransform); beatmapNote.UpdateGridPosition(); LoadedContainers.Add(beatmapNote); return(beatmapNote); }
public override BeatmapObjectContainer SpawnObject(BeatmapObject obj, out BeatmapObjectContainer conflicting, bool removeConflicting = true) { conflicting = LoadedContainers.FirstOrDefault(x => x.objectData._time == obj._time && (obj as BeatmapNote)._lineLayer == (x.objectData as BeatmapNote)._lineLayer && (obj as BeatmapNote)._lineIndex == (x.objectData as BeatmapNote)._lineIndex && (obj as BeatmapNote)._type == (x.objectData as BeatmapNote)._type && ConflictingByTrackIDs(obj, x.objectData) ); if (conflicting != null && removeConflicting) { DeleteObject(conflicting); } BeatmapNoteContainer beatmapNote = BeatmapNoteContainer.SpawnBeatmapNote(obj as BeatmapNote, ref notePrefab, ref bombPrefab, ref noteAppearanceSO); beatmapNote.transform.SetParent(GridTransform); beatmapNote.UpdateGridPosition(); LoadedContainers.Add(beatmapNote); SelectionController.RefreshMap(); return(beatmapNote); }
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 IEnumerator ConvertFromLegacy() { yield return(PersistentUI.Instance.FadeInLoadingScreen()); List <BeatmapObject> ToSpawn = new List <BeatmapObject>(); List <BeatmapObjectContainer> ToDestroy = new List <BeatmapObjectContainer>(); if (BeatSaberSongContainer.Instance != null) { foreach (BeatmapObjectContainer container in notesContainer.LoadedContainers) { BeatmapNoteContainer note = container as BeatmapNoteContainer; BeatmapNoteContainer chromaBomb = notesContainer.LoadedContainers.Where((BeatmapObjectContainer x) => x.objectData._time == note.objectData._time && (x as BeatmapNoteContainer).mapNoteData._type == BeatmapNote.NOTE_TYPE_BOMB && (x as BeatmapNoteContainer).mapNoteData._lineIndex == note.mapNoteData._lineIndex && (x as BeatmapNoteContainer).mapNoteData._lineLayer == note.mapNoteData._lineLayer ).FirstOrDefault() as BeatmapNoteContainer; if (chromaBomb != null && note.mapNoteData._type != BeatmapNote.NOTE_TYPE_BOMB) //Chroma note PogU { BeatmapChromaNote chromaNote = new BeatmapChromaNote(note.mapNoteData); chromaNote.BombRotation = chromaBomb.mapNoteData._cutDirection; ToDestroy.Add(container); ToDestroy.Add(chromaBomb); ToSpawn.Add(chromaNote); } } } notesContainer.SortObjects(); foreach (BeatmapObjectContainer con in ToDestroy) { notesContainer.DeleteObject(con); } foreach (BeatmapObject data in ToSpawn) { notesContainer.SpawnObject(data, out _); } SelectionController.RefreshMap(); yield return(PersistentUI.Instance.FadeOutLoadingScreen()); }
public BeatmapNotePlacementAction(BeatmapNoteContainer note) : base(note) { }
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 SetNoteAppearance(BeatmapNoteContainer note) { if (!note.isBomb) { if (note.gameObject.transform.Find("Bidirectional")) { Destroy(note.gameObject.transform.Find("Bidirectional").gameObject); } Transform dot = note.gameObject.transform.Find("NoteDot"); dot.localScale = new Vector3(0.2f, 0.2f, 0.2f); switch (note.mapNoteData._cutDirection) { case BeatmapNote.NOTE_CUT_DIRECTION_UP: case BeatmapNote.NOTE_CUT_DIRECTION_DOWN: case BeatmapNote.NOTE_CUT_DIRECTION_LEFT: case BeatmapNote.NOTE_CUT_DIRECTION_RIGHT: case BeatmapNote.NOTE_CUT_DIRECTION_UP_RIGHT: case BeatmapNote.NOTE_CUT_DIRECTION_UP_LEFT: case BeatmapNote.NOTE_CUT_DIRECTION_DOWN_LEFT: case BeatmapNote.NOTE_CUT_DIRECTION_DOWN_RIGHT: //note.SetArrowSprite(arrowSprite); note.SetArrowVisible(true); note.SetDotVisible(false); break; case BeatmapNote.NOTE_CUT_DIRECTION_ANY: note.SetDotSprite(dotSprite); note.SetArrowVisible(false); note.SetDotVisible(true); break; default: note.SetDotSprite(dotSprite); note.SetArrowVisible(true); note.SetDotVisible(false); break; } switch (note.mapNoteData._type) { case BeatmapNote.NOTE_TYPE_A: note.SetModelMaterial(RedInstance); break; case BeatmapNote.NOTE_TYPE_B: note.SetModelMaterial(BlueInstance); break; default: note.SetModelMaterial(unknownNoteMaterial); break; } if (note.mapNoteData is BeatmapChromaNote) { BeatmapChromaNote chromaNote = note.mapNoteData as BeatmapChromaNote; switch (chromaNote.BombRotation) { case BeatmapChromaNote.ALTERNATE: if (note.mapNoteData._type == BeatmapNote.NOTE_TYPE_A) { note.SetModelMaterial(magentaNoteSharedMaterial); } else if (note.mapNoteData._type == BeatmapNote.NOTE_TYPE_B) { note.SetModelMaterial(greenNoteSharedMaterial); } break; case BeatmapChromaNote.BIDIRECTIONAL: note.SetArrowVisible(true); note.SetDotVisible(false); Transform copied = Instantiate(note.gameObject.transform.Find("Direction"), note.transform); copied.gameObject.name = "Bidirectional"; copied.localEulerAngles = new Vector3(0, 0, 180); copied.localPosition = new Vector3(0, -0.1f, -0.25f); break; case BeatmapChromaNote.DUOCHROME: note.SetModelMaterial(duochromeSharedNoteMaterial); break; case BeatmapChromaNote.HOT_GARBAGE: note.SetModelMaterial(superNoteSharedMaterial); break; case BeatmapChromaNote.DEFLECT: dot.localScale = new Vector3(0.2f, 0.5f, 0.2f); note.SetArrowVisible(false); note.SetDotVisible(true); break; case BeatmapChromaNote.MONOCHROME: note.SetModelMaterial(monochromeSharedNoteMaterial); break; } } } }
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; } } }
public BeatmapNoteDeletionAction(BeatmapNoteContainer note) : base(note) { }
public IEnumerator LoadMap() { if (BeatSaberSongContainer.Instance == null) { yield break; } PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(true); yield return(new WaitUntil(() => atsc.gridStartPosition != -1)); //I need a way to find out when Start has been called. song = BeatSaberSongContainer.Instance.song; float offset = 0; int environmentID = 0; int batchSize = Settings.Instance.InitialLoadBatchSize; bool customPlat = false; environmentID = SongInfoEditUI.GetEnvironmentIDFromString(song.environmentName); if (song.customData != null && song.customData["_customEnvironment"] != null && song.customData["_customEnvironment"].Value != "") { environmentID = SongInfoEditUI.GetCustomPlatformsIndexFromString(song.customData["_customEnvironment"]); customPlat = true; } GameObject platform = (customPlat ? CustomPlatformPrefabs[environmentID] : PlatformPrefabs[environmentID]) ?? PlatformPrefabs[0]; GameObject instantiate = Instantiate(platform, new Vector3(0, -0.5f, -1.5f), Quaternion.identity); PlatformDescriptor descriptor = instantiate.GetComponent <PlatformDescriptor>(); BeatmapEventContainer.ModifyTypeMode = descriptor.SortMode; PlatformLoadedEvent.Invoke(descriptor); descriptor.RedColor = BeatSaberSongContainer.Instance.difficultyData.colorLeft; descriptor.BlueColor = BeatSaberSongContainer.Instance.difficultyData.colorRight; map = BeatSaberSongContainer.Instance.map; offset = (song.beatsPerMinute / 60) * (BeatSaberSongContainer.Instance.song.songTimeOffset / 1000); int noteLaneSize = 2; //Half of it, anyways int noteLayerSize = 3; Queue <BeatmapObject> queuedData = new Queue <BeatmapObject>( //Take all of our object data and combine them for batch loading. map._notes.Concat <BeatmapObject>(map._obstacles).Concat(map._events).Concat(map._BPMChanges)); totalObjectsToLoad = queuedData.Count; if (map != null) { while (queuedData.Count > 0) { for (int i = 0; i < batchSize; i++) { if (queuedData.Count == 0) { break; } BeatmapObject data = queuedData.Dequeue(); if (data is BeatmapNote noteData) { BeatmapNoteContainer beatmapNote = notesContainer.SpawnObject(noteData) as BeatmapNoteContainer; 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) { BeatmapObstacleContainer beatmapObstacle = obstaclesContainer.SpawnObject(obstacleData) as BeatmapObstacleContainer; 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; } } else if (data is MapEvent eventData) { eventsContainer.SpawnObject(eventData); } else if (data is BeatmapBPMChange bpmData) { bpmContainer.SpawnObject(bpmData); } } UpdateSlider(batchSize); yield return(new WaitForEndOfFrame()); } notesContainer.SortObjects(); obstaclesContainer.SortObjects(); eventsContainer.SortObjects(); bpmContainer.SortObjects(); noteGrid.localScale = new Vector3((float)(noteLaneSize * 2) / 10 + 0.01f, 1, 1); } PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(false); }
public void SetNoteAppearance(BeatmapNoteContainer note) { if (note.mapNoteData._type != BeatmapNote.NOTE_TYPE_BOMB) { if (note.gameObject.transform.Find("Bidirectional")) { Destroy(note.gameObject.transform.Find("Bidirectional").gameObject); } Transform dot = note.gameObject.transform.Find("NoteDot"); dot.localScale = new Vector3(0.25f, 0.25f, 0.25f); switch (note.mapNoteData._cutDirection) { case BeatmapNote.NOTE_CUT_DIRECTION_UP: case BeatmapNote.NOTE_CUT_DIRECTION_DOWN: case BeatmapNote.NOTE_CUT_DIRECTION_LEFT: case BeatmapNote.NOTE_CUT_DIRECTION_RIGHT: case BeatmapNote.NOTE_CUT_DIRECTION_UP_RIGHT: case BeatmapNote.NOTE_CUT_DIRECTION_UP_LEFT: case BeatmapNote.NOTE_CUT_DIRECTION_DOWN_LEFT: case BeatmapNote.NOTE_CUT_DIRECTION_DOWN_RIGHT: note.SetArrowVisible(true); note.SetDotVisible(false); break; case BeatmapNote.NOTE_CUT_DIRECTION_ANY: note.SetArrowVisible(false); note.SetDotVisible(true); break; default: note.SetArrowVisible(true); note.SetDotVisible(false); break; } //Since sometimes the user can hover over the note grid before all the notes are loading, //we create material instances here to prevent NullReferenceExceptions. switch (note.mapNoteData._type) { case BeatmapNote.NOTE_TYPE_A: note.SetColor(RedColor); break; case BeatmapNote.NOTE_TYPE_B: note.SetColor(BlueColor); break; default: note.SetColor(null); break; } if (note.mapNoteData is BeatmapChromaNote) { BeatmapChromaNote chromaNote = note.mapNoteData as BeatmapChromaNote; switch (chromaNote.BombRotation) { case BeatmapChromaNote.ALTERNATE: if (note.mapNoteData._type == BeatmapNote.NOTE_TYPE_A) { note.SetModelMaterial(magentaNoteSharedMaterial); } else if (note.mapNoteData._type == BeatmapNote.NOTE_TYPE_B) { note.SetModelMaterial(greenNoteSharedMaterial); } break; case BeatmapChromaNote.BIDIRECTIONAL: note.SetArrowVisible(true); note.SetDotVisible(false); Transform copied = Instantiate(note.gameObject.transform.Find("Direction"), note.transform); copied.gameObject.name = "Bidirectional"; copied.localEulerAngles = new Vector3(0, 0, 180); copied.localPosition = new Vector3(0, -0.1f, -0.25f); break; case BeatmapChromaNote.DUOCHROME: note.SetModelMaterial(duochromeSharedNoteMaterial); break; case BeatmapChromaNote.HOT_GARBAGE: note.SetModelMaterial(superNoteSharedMaterial); break; case BeatmapChromaNote.DEFLECT: dot.localScale = new Vector3(0.25f, 0.5f, 0.25f); note.SetArrowVisible(false); note.SetDotVisible(true); break; case BeatmapChromaNote.MONOCHROME: note.SetModelMaterial(monochromeSharedNoteMaterial); break; } } } else { note.SetArrowVisible(false); note.SetDotVisible(false); note.SetColor(null); } if (note.mapNoteData._customData?.HasKey("_color") ?? false) { note.SetColor(note.mapNoteData._customData["_color"]); } }
public IEnumerator LoadMap() { if (BeatSaberSongContainer.Instance == null) { yield break; } PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(true); PersistentUI.Instance.LevelLoadSliderLabel.text = ""; yield return(new WaitUntil(() => atsc.gridStartPosition != -1)); //I need a way to find out when Start has been called. song = BeatSaberSongContainer.Instance.song; //Grab songe data diff = BeatSaberSongContainer.Instance.difficultyData; //Set up some local variables int environmentID = 0; int batchSize = Settings.Instance.InitialLoadBatchSize; bool customPlat = false; environmentID = SongInfoEditUI.GetEnvironmentIDFromString(song.environmentName); //Grab platform by name (Official or Custom) if (song.customData != null && song.customData["_customEnvironment"] != null && song.customData["_customEnvironment"].Value != "") { if (SongInfoEditUI.GetCustomPlatformsIndexFromString(song.customData["_customEnvironment"]) >= 0) { environmentID = SongInfoEditUI.GetCustomPlatformsIndexFromString(song.customData["_customEnvironment"]); customPlat = true; } } //Instantiate platform, grab descriptor GameObject platform = (customPlat ? CustomPlatformPrefabs[environmentID] : PlatformPrefabs[environmentID]) ?? PlatformPrefabs[0]; GameObject instantiate = Instantiate(platform, new Vector3(0, -0.5f, -1.5f), Quaternion.identity); PlatformDescriptor descriptor = instantiate.GetComponent <PlatformDescriptor>(); BeatmapEventContainer.ModifyTypeMode = descriptor.SortMode; //Change sort mode //Update Colors Color leftNote = BeatSaberSong.DEFAULT_LEFTNOTE; //Have default note as base if (descriptor.RedColor != BeatSaberSong.DEFAULT_LEFTCOLOR) { leftNote = descriptor.RedColor; //Prioritize platforms } if (diff.colorLeft != BeatSaberSong.DEFAULT_LEFTNOTE) { leftNote = diff.colorLeft; //Then prioritize custom colors } Color rightNote = BeatSaberSong.DEFAULT_RIGHTNOTE; if (descriptor.BlueColor != BeatSaberSong.DEFAULT_RIGHTCOLOR) { rightNote = descriptor.BlueColor; } if (diff.colorRight != BeatSaberSong.DEFAULT_RIGHTNOTE) { rightNote = diff.colorRight; } notesContainer.UpdateColor(leftNote, rightNote); obstaclesContainer.UpdateColor(diff.obstacleColor); if (diff.colorLeft != BeatSaberSong.DEFAULT_LEFTNOTE) { descriptor.RedColor = diff.colorLeft; } if (diff.colorRight != BeatSaberSong.DEFAULT_RIGHTNOTE) { descriptor.BlueColor = diff.colorRight; } if (diff.envColorLeft != BeatSaberSong.DEFAULT_LEFTCOLOR) { descriptor.RedColor = diff.envColorLeft; } if (diff.envColorRight != BeatSaberSong.DEFAULT_RIGHTCOLOR) { descriptor.BlueColor = diff.envColorRight; } PlatformLoadedEvent.Invoke(descriptor); //Trigger event for classes that use the platform map = BeatSaberSongContainer.Instance.map; //Grab map info, do some stuff int noteLaneSize = 2; //Half of it, anyways int noteLayerSize = 3; Queue <BeatmapObject> queuedData = new Queue <BeatmapObject>( //Take all of our object data and combine them for batch loading. map._notes.Concat <BeatmapObject>(map._obstacles).Concat(map._events).Concat(map._BPMChanges).Concat(map._customEvents)); totalObjectsToLoad = queuedData.Count; if (map != null) { 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. if (data is BeatmapNote noteData) { BeatmapNoteContainer beatmapNote = notesContainer.SpawnObject(noteData, out _) as BeatmapNoteContainer; 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) { BeatmapObstacleContainer beatmapObstacle = obstaclesContainer.SpawnObject(obstacleData, out _) as BeatmapObstacleContainer; 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; } } else if (data is MapEvent eventData) { eventsContainer.SpawnObject(eventData, out _); } else if (data is BeatmapBPMChange bpmData) { bpmContainer.SpawnObject(bpmData, out _); } else if (data is BeatmapCustomEvent customData) { customEventsContainer.SpawnObject(customData, out _); } } UpdateSlider(batchSize); yield return(new WaitForEndOfFrame()); } notesContainer.SortObjects(); //Sort these boyes. obstaclesContainer.SortObjects(); eventsContainer.SortObjects(); bpmContainer.SortObjects(); customEventsContainer.SortObjects(); noteGrid.localScale = new Vector3((float)(noteLaneSize * 2) / 10 + 0.01f, 1, 1); //Set note lanes appropriately } PersistentUI.Instance.LevelLoadSlider.gameObject.SetActive(false); //Disable progress bar LevelLoadedEvent?.Invoke(); }
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 override BeatmapObjectContainer CreateContainer() { BeatmapObjectContainer con = BeatmapNoteContainer.SpawnBeatmapNote(null, ref notePrefab); return(con); }