private IEnumerator RefreshMap(bool notes, bool obstacles, bool events, bool others, bool full) { yield return(PersistentUI.Instance.FadeInLoadingScreen()); map = song.GetMapFromDifficultyBeatmap(diff); loader.UpdateMapData(map); float currentBeat = atsc.CurrentBeat; atsc.MoveToTimeInBeats(0); if (notes || full) { yield return(StartCoroutine(loader.LoadObjects(map._notes))); } if (obstacles || full) { yield return(StartCoroutine(loader.LoadObjects(map._obstacles))); } if (events || full) { yield return(StartCoroutine(loader.LoadObjects(map._events))); } if (others || full) { yield return(StartCoroutine(loader.LoadObjects(map._BPMChanges))); } if (others || full) { yield return(StartCoroutine(loader.LoadObjects(map._customEvents))); } tracksManager.RefreshTracks(); SelectionController.RefreshMap(); atsc.MoveToTimeInBeats(currentBeat); yield return(PersistentUI.Instance.FadeOutLoadingScreen()); }
public void RefreshRequirementsAndWarnings(BeatSaberMap map) { //Saving Map Requirement Info JSONArray requiredArray = new JSONArray(); //Generate suggestions and requirements array JSONArray suggestedArray = new JSONArray(); if (HasChromaEvents(map)) { suggestedArray.Add("Chroma"); } if (HasLegacyChromaEvents(map)) { suggestedArray.Add("Chroma Lighting Events"); } if (HasNoodleExtensions(map)) { requiredArray.Add("Noodle Extensions"); } if (HasMappingExtensions(map)) { requiredArray.Add("Mapping Extensions"); } if (requiredArray.Count > 0 || suggestedArray.Count > 0) { if (customData == null) { customData = new JSONObject(); } customData["_suggestions"] = suggestedArray; customData["_requirements"] = requiredArray; } }
private bool HasLegacyChromaEvents(BeatSaberMap map) { if (map is null) { return(false); } return(map?._events?.Any(mapevent => mapevent._value > ColourManager.RGB_INT_OFFSET) ?? false); }
private bool RequiresChroma(BeatSaberMap map) { if (map is null) { return(false); } return((customData != null && customData.HasKey("_requirements") && customData["_requirements"].Linq.Any(x => x.Value == "Chroma")) || map._notes.Any(x => x._type != BeatmapNote.NOTE_TYPE_BOMB && (x._customData?.HasKey("_color") ?? false))); }
void TransitionToEditor(BeatSaberMap map) { Debug.Log("Transitioning..."); if (map != null) { BeatSaberSongContainer.Instance.map = map; SceneTransitionManager.Instance.LoadScene(3, GetSongFromDifficultyData(map)); } }
private bool HasMappingExtensions(BeatSaberMap map) { if (map is null) { return(false); } return(map._notes.Any(note => note._lineIndex < 0 || note._lineIndex > 3 || note._lineLayer < 0 || note._lineLayer > 2) || map._obstacles.Any(ob => ob._lineIndex < 0 || ob._lineIndex > 3 || ob._type >= 2 || ob._width >= 1000) || map._events.Any(ob => ob.IsRotationEvent && ob._value >= 1000 && ob._value <= 1720)); }
private bool HasChromaEvents(BeatSaberMap map) { if (map is null) { return(false); } return(map._notes.Any(note => note._customData?["_color"] != null) || map._obstacles.Any(ob => ob._customData?["_color"] != null) || map._events.Any(ob => ob._customData?["_color"] != null || ob._customData?["_lightGradient"] != null || ob._customData?["_propID"] != null)); }
private bool HasNoodleExtensions(BeatSaberMap map) { if (map is null) { return(false); } return(map._obstacles.Any(ob => ob._customData?["_position"] != null || ob._customData?["_scale"] != null || ob._customData?["_rotation"] != null || ob._customData?["_localRotation"] != null) || map._notes.Any(ob => ob._customData?["_position"] != null || ob._customData?["_cutDirection"] != null)); }
public static BeatSaberMap ConvertFilesJpgToPng(BeatSaberMap beatSaberMap) { string[] files = Directory.GetFiles(beatSaberMap.ExtractedFilePath, "*.jpg*", SearchOption.AllDirectories); beatSaberMap.InfoData.CoverImageFilename = beatSaberMap.InfoData.CoverImageFilename.Replace(".jpg", ".png"); foreach (string path in files) { string newName = path.Replace(".jpg", ".png"); SafeFileManagement.MoveFile(path, newName); } return(beatSaberMap); }
private bool HasMappingExtensions(BeatSaberMap map) { if (map is null) { return(false); } // idk why the customdata checks should be necessary, but they are. return(map._notes.Any(note => (note._lineIndex < 0 || note._lineIndex > 3 || note._lineLayer < 0 || note._lineLayer > 2) && note._customData.Count <= 0) || map._obstacles.Any(ob => (ob._lineIndex < 0 || ob._lineIndex > 3 || ob._type >= 2 || ob._width >= 1000) && ob._customData.Count <= 0) || map._events.Any(ob => ob.IsRotationEvent && ob._value >= 1000 && ob._value <= 1720)); }
private bool HasChromaEvents(BeatSaberMap map) { if (map is null) { return(false); } return(map._notes.Any(note => note._customData?["_color"] != null) || map._obstacles.Any(ob => ob._customData?["_color"] != null) || map._events.Any(ob => ob._customData != null)); //Bold assumption for events, but so far Chroma is the only mod that uses Custom Data in vanilla events. }
public void UpdateMapData(BeatSaberMap map) { BeatSaberMap copy = new BeatSaberMap(); copy._notes = new List <BeatmapNote>(map._notes); copy._obstacles = new List <BeatmapObstacle>(map._obstacles); copy._events = new List <MapEvent>(map._events); copy._BPMChanges = new List <BeatmapBPMChange>(map._BPMChanges); copy._customEvents = new List <BeatmapCustomEvent>(map._customEvents); this.map = copy; }
public BeatSaberMap GetMapFromDifficultyBeatmap(DifficultyBeatmap data) { JSONNode mainNode = GetNodeFromFile(directory + "/" + data.beatmapFilename); if (mainNode == null) { Debug.LogWarning("Failed to get difficulty json file " + (directory + "/" + data.beatmapFilename)); return(null); } return(BeatSaberMap.GetBeatSaberMapFromJSON(mainNode, directory + "/" + data.beatmapFilename)); }
/// <summary> /// Save the diff /// </summary> /// <param name="row">UI row that was clicked on</param> private void SaveDiff(DifficultyRow row) { var localDiff = diffs[row.Name]; var firstSave = localDiff.ForceDirty; localDiff.Commit(); row.ShowDirtyObjects(false, true); var Song = BeatSaberSongContainer.Instance.song; var diff = localDiff.DifficultyBeatmap; if (!Song.difficultyBeatmapSets.Contains(currentCharacteristic)) { Song.difficultyBeatmapSets.Add(currentCharacteristic); } if (!currentCharacteristic.difficultyBeatmaps.Contains(diff)) { currentCharacteristic.difficultyBeatmaps.Add(diff); } BeatSaberMap map = TryGetExistingMapFromDiff(diff) ?? new BeatSaberMap { mainNode = new JSONObject() }; string oldPath = map?.directoryAndFile; diff.UpdateName(); map.directoryAndFile = Path.Combine(Song.directory, diff.beatmapFilename); if (File.Exists(oldPath) && oldPath != map.directoryAndFile && !File.Exists(map.directoryAndFile)) { if (firstSave) { File.Copy(oldPath, map.directoryAndFile); } else { File.Move(oldPath, map.directoryAndFile); //This should properly "convert" difficulties just fine } } else { map.Save(); } diff.RefreshRequirementsAndWarnings(map); Song.SaveSong(); characteristicSelect.Recalculate(); Debug.Log("Saved " + row.Name); }
public void EditMapButtonPressed() { if (selectedDifficultyIndex >= songDifficultyData.Count || selectedDifficultyIndex < 0) { return; } BeatSaberMap map = Song.GetMapFromDifficultyBeatmap(songDifficultyData[selectedDifficultyIndex]); PersistentUI.UpdateBackground(Song); Debug.Log("Loading Song..."); TransitionToEditor(map); //StartCoroutine(GetSongFromDifficultyData(map)); }
private bool HasNoodleExtensions(BeatSaberMap map) { if (map is null) { return(false); } return(map._obstacles.Any(ob => ob._customData?["_position"] != null || ob._customData?["_scale"] != null || ob._customData?["_rotation"] != null || ob._customData?["_localRotation"] != null || ob._customData?["_animation"] != null) || map._notes.Any(ob => ob._customData?["_position"] != null || ob._customData?["_cutDirection"] != null || ob._customData?["_fake"] != null || ob._customData?["_interactable"] != null || ob._customData?["_animation"] != null) || map._customEvents.Any(ob => CustomEventsToModRequirements.TryGetValue(ob._type, out string mod) && mod == "Noodle Extensions")); }
public DataPackData(string unzippedFolderPath, string datapackOutputPath, BeatSaberMap beatSaberMap) { var packInfo = beatSaberMap.InfoData; keyVars = new Dictionary <string, string>(); folder_uuid = SafeFileManagement.GetFileName(Path.GetFileName(unzippedFolderPath)).MakeMinecraftSafe(); packName = Globals.DATAPACK + folder_uuid; songGuid = beatSaberMap.GuidId.ToString(); // Paths datapackRootPath = Path.Combine(unzippedFolderPath, packName); fullOutputPath = Path.Combine(datapackOutputPath, packName + Globals.ZIP); blockSaberBaseFunctionsPath = Path.Combine(datapackRootPath, Globals.DATA, Globals.BLOCK_SABER_BASE, Globals.FUNCTIONS); folder_uuidFunctionsPath = Path.Combine(datapackRootPath, Globals.DATA, folder_uuid, Globals.FUNCTIONS); spawnNotesBasePath = Path.Combine(folder_uuidFunctionsPath, Globals.SPAWN_NOTES_BASE_FUNCTION); // Values metersPerTick = packInfo.BeatsPerMinute / 60.0d * 24 * 0.21 / 20; ticksStartOffset = (int)(Mathf.Clamp((float)(packInfo.BeatsPerMinute / 60d * 10), 7, 20) / metersPerTick); // Set up Keys keyVars["MAPPER_NAME"] = packInfo.LevelAuthorName; keyVars["BEATS_PER_MINUTE"] = packInfo.BeatsPerMinute.ToString(); keyVars["SONGID"] = beatSaberMap.GuidId.GetHashCode().ToString(); keyVars["MOVESPEED"] = metersPerTick.ToString(); keyVars["SONGTITLE"] = packInfo.SongName + " " + packInfo.SongSubName; keyVars["SONGSHORTNAME"] = packInfo.SongName; keyVars["SONGARTIST"] = packInfo.SongAuthorName; keyVars["folder_uuid"] = folder_uuid; keyVars["SONGDIFFICULTYID"] = songGuid + "1"; StringBuilder listOfDifficulties = new StringBuilder(); var beatMapSets = beatSaberMap.InfoData.DifficultyBeatmapSets; for (int beatMapCounts = 0; beatMapCounts < beatMapSets.Length; beatMapCounts++) { var beatMapInfos = beatMapSets[beatMapCounts].DifficultyBeatmaps; int beatMapCount = beatMapInfos.Length; for (int difficulty = 0; difficulty < beatMapCount; difficulty++) { listOfDifficulties.Append(beatMapInfos[difficulty].Difficulty); if (difficulty < beatMapCount - 1) { listOfDifficulties.Append(" | "); } } } keyVars["DIFFICULTYLIST"] = listOfDifficulties.ToString(); }
public static BeatSaberMap ConvertFilesEggToOgg(BeatSaberMap beatSaberMap) { string[] files = Directory.GetFiles(beatSaberMap.ExtractedFilePath, "*.egg*", SearchOption.AllDirectories); string[] alreadyConvertedfiles = Directory.GetFiles(beatSaberMap.ExtractedFilePath, "*.ogg*", SearchOption.AllDirectories); if (files.Length == 0 && alreadyConvertedfiles.Length == 0) { return(beatSaberMap); } beatSaberMap.InfoData.SongFilename = beatSaberMap.InfoData.SongFilename.Replace(".egg", ".ogg"); foreach (string path in files) { string newName = path.Replace(".egg", ".ogg"); SafeFileManagement.MoveFile(path, newName); } return(beatSaberMap); }
private bool HasChromaEvents() { try { BeatSaberMap map = Song.GetMapFromDifficultyBeatmap(songDifficultyData[selectedDifficultyIndex]); foreach (MapEvent mapevent in map._events) { if (mapevent._value > ColourManager.RGB_INT_OFFSET) { return(true); } } return(false); } catch { return(false); } }
/// <summary> /// Load the editor scene /// </summary> /// <param name="r">Confirmation from the user</param> private void HandleEditMapButtonPressed(int r) { if (r == 0) { BeatSaberMap map = Song.GetMapFromDifficultyBeatmap(BeatSaberSongContainer.Instance.difficultyData); PersistentUI.UpdateBackground(Song); Debug.Log("Transitioning..."); if (map != null) { Settings.Instance.LastLoadedMap = Song.directory; Settings.Instance.LastLoadedChar = BeatSaberSongContainer.Instance.difficultyData.parentBeatmapSet.beatmapCharacteristicName; Settings.Instance.LastLoadedDiff = BeatSaberSongContainer.Instance.difficultyData.difficulty; BeatSaberSongContainer.Instance.map = map; SceneTransitionManager.Instance.LoadScene("03_Mapper", LoadAudio(false)); } } }
private bool HasMappingExtensionsObjects() { BeatSaberMap map = Song.GetMapFromDifficultyBeatmap(songDifficultyData[selectedDifficultyIndex]); foreach (BeatmapNote note in map?._notes) { if (note._lineIndex < 0 || note._lineIndex > 3) { return(true); } } foreach (BeatmapObstacle ob in map?._obstacles) { if (ob._lineIndex < 0 || ob._lineIndex > 3 || ob._type >= 2 || ob._width >= 1000) { return(true); } } return(false); }
// Use this for initialization void Start() { try { //Init dat stuff clip = BeatSaberSongContainer.Instance.loadedSong; song = BeatSaberSongContainer.Instance.song; data = BeatSaberSongContainer.Instance.map; diff = BeatSaberSongContainer.Instance.difficultyData; offsetMS = (song.songTimeOffset) / 1000; ResetTime(); offsetBeat = currentBeat; gridStartPosition = currentBeat * EditorScaleController.EditorScale; IsPlaying = false; songAudioSource.clip = clip; UpdateMovables(); } catch (Exception e) { Debug.LogException(e); } }
IEnumerator GetSongFromDifficultyData(BeatSaberMap map) { BeatSaberSong.DifficultyBeatmap data = songDifficultyData[selectedDifficultyIndex]; string directory = Song.directory; if (File.Exists(directory + "/" + Song.songFilename)) { if (Song.songFilename.ToLower().EndsWith("ogg") || Song.songFilename.ToLower().EndsWith("egg")) { UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip($"file:///{Uri.EscapeDataString($"{directory}/{Song.songFilename}")}", AudioType.OGGVORBIS); //Escaping should fix the issue where half the people can't open ChroMapper's editor (I believe this is caused by spaces in the directory, hence escaping) yield return(www.SendWebRequest()); Debug.Log("Song loaded!"); AudioClip clip = DownloadHandlerAudioClip.GetContent(www); if (clip == null) { Debug.Log("Error getting Audio data!"); SceneTransitionManager.Instance.CancelLoading("Error getting Audio data!"); } clip.name = "Song"; BeatSaberSongContainer.Instance.loadedSong = clip; BeatSaberSongContainer.Instance.difficultyData = data; //TransitionToEditor(map, clip, data); } else { Debug.Log("Incompatible file type! WTF!?"); SceneTransitionManager.Instance.CancelLoading("Incompatible audio type!"); } } else { SceneTransitionManager.Instance.CancelLoading("Audio file does not exist!"); Debug.Log("Song does not exist! WTF!?"); Debug.Log(directory + "/" + Song.songFilename); } }
public static BeatSaberMap GetBeatSaberMapFromJSON(JSONNode mainNode, string directoryAndFile) { try { BeatSaberMap map = new BeatSaberMap(); map.mainNode = mainNode; map.directoryAndFile = directoryAndFile; List <MapEvent> eventsList = new List <MapEvent>(); List <BeatmapNote> notesList = new List <BeatmapNote>(); List <BeatmapObstacle> obstaclesList = new List <BeatmapObstacle>(); List <BeatmapBPMChange> bpmList = new List <BeatmapBPMChange>(); List <BeatmapBookmark> bookmarksList = new List <BeatmapBookmark>(); List <BeatmapCustomEvent> customEventsList = new List <BeatmapCustomEvent>(); JSONNode.Enumerator nodeEnum = mainNode.GetEnumerator(); while (nodeEnum.MoveNext()) { string key = nodeEnum.Current.Key; JSONNode node = nodeEnum.Current.Value; switch (key) { case "_version": map._version = node.Value; break; case "_events": foreach (JSONNode n in node) { eventsList.Add(new MapEvent(n)); } break; case "_notes": foreach (JSONNode n in node) { notesList.Add(new BeatmapNote(n)); } break; case "_obstacles": foreach (JSONNode n in node) { obstaclesList.Add(new BeatmapObstacle(n)); } break; case "_customData": JSONNode.Enumerator dataNodeEnum = node.GetEnumerator(); while (dataNodeEnum.MoveNext()) { string dataKey = dataNodeEnum.Current.Key; JSONNode dataNode = dataNodeEnum.Current.Value; switch (dataKey) { case "_BPMChanges": foreach (JSONNode n in dataNode) { bpmList.Add(new BeatmapBPMChange(n)); } break; case "_bpmChanges": foreach (JSONNode n in dataNode) { bpmList.Add(new BeatmapBPMChange(n)); } break; case "_bookmarks": foreach (JSONNode n in dataNode) { bookmarksList.Add(new BeatmapBookmark(n)); } break; case "_customEvents": foreach (JSONNode n in dataNode) { customEventsList.Add(new BeatmapCustomEvent(n)); } break; case "_time": map._time = dataNode.AsFloat; break; } } break; case "_BPMChanges": foreach (JSONNode n in node) { bpmList.Add(new BeatmapBPMChange(n)); } break; case "_bpmChanges": foreach (JSONNode n in node) { bpmList.Add(new BeatmapBPMChange(n)); } break; case "_bookmarks": foreach (JSONNode n in node) { bookmarksList.Add(new BeatmapBookmark(n)); } break; case "_customEvents": foreach (JSONNode n in node) { customEventsList.Add(new BeatmapCustomEvent(n)); } break; } } map._events = eventsList; map._notes = notesList; map._obstacles = obstaclesList; map._BPMChanges = bpmList.DistinctBy(x => x.ConvertToJSON().ToString()).ToList(); map._bookmarks = bookmarksList; map._customEvents = customEventsList.DistinctBy(x => x.ConvertToJSON().ToString()).ToList(); return(map); } catch (Exception e) { Debug.LogException(e); return(null); } }
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 SaveDifficulty() { if (songDifficultyData[selectedDifficultyIndex].customData == null) { songDifficultyData[selectedDifficultyIndex].customData = new JSONObject(); } BeatSaberMap map = Song.GetMapFromDifficultyBeatmap(songDifficultyData[selectedDifficultyIndex]); string oldPath = map?.directoryAndFile; switch (difficultyDifficultyDropdown.value) { case 0: songDifficultyData[selectedDifficultyIndex].difficulty = "Easy"; songDifficultyData[selectedDifficultyIndex].difficultyRank = 1; break; case 1: songDifficultyData[selectedDifficultyIndex].difficulty = "Normal"; songDifficultyData[selectedDifficultyIndex].difficultyRank = 3; break; case 2: songDifficultyData[selectedDifficultyIndex].difficulty = "Hard"; songDifficultyData[selectedDifficultyIndex].difficultyRank = 5; break; case 3: songDifficultyData[selectedDifficultyIndex].difficulty = "Expert"; songDifficultyData[selectedDifficultyIndex].difficultyRank = 7; break; case 4: Debug.Log("E+"); songDifficultyData[selectedDifficultyIndex].difficulty = "ExpertPlus"; songDifficultyData[selectedDifficultyIndex].difficultyRank = 9; break; default: Debug.Log("Difficulty doesnt seem to exist! Default to Easy..."); songDifficultyData[selectedDifficultyIndex].difficulty = "Easy"; songDifficultyData[selectedDifficultyIndex].difficultyRank = 1; break; } songDifficultyData[selectedDifficultyIndex].UpdateName(); if (map is null) { map = new BeatSaberMap(); map.mainNode = new JSONObject(); } map.directoryAndFile = $"{Song.directory}\\{songDifficultyData[selectedDifficultyIndex].beatmapFilename}"; if (File.Exists(oldPath) && oldPath != map.directoryAndFile) { File.Move(oldPath, map.directoryAndFile); //This should properly "convert" difficulties just fine } else { map.Save(); } songDifficultyData[selectedDifficultyIndex].noteJumpMovementSpeed = float.Parse(noteJumpSpeed.text); songDifficultyData[selectedDifficultyIndex].noteJumpStartBeatOffset = float.Parse(startBeatOffset.text); if (difficultyLabel.text != "") { songDifficultyData[selectedDifficultyIndex].customData["_difficultyLabel"] = difficultyLabel.text; } else { songDifficultyData[selectedDifficultyIndex].customData.Remove("_difficultyLabel"); } JSONArray requiredArray = new JSONArray(); JSONArray suggestedArray = new JSONArray(); if (WillChromaBeRequired.isOn && HasChromaEvents()) { requiredArray.Add(new JSONString("Chroma Lighting Events")); } else if (HasChromaEvents()) { suggestedArray.Add(new JSONString("Chroma Lighting Events")); } if (HasMappingExtensionsObjects()) { requiredArray.Add(new JSONString("Mapping Extensions")); } //if () requiredArray.Add(new JSONString("ChromaToggle")); //TODO: ChromaToggle if (suggestedArray.Linq.Any()) { songDifficultyData[selectedDifficultyIndex].customData["_suggestions"] = suggestedArray; } if (requiredArray.Linq.Any()) { songDifficultyData[selectedDifficultyIndex].customData["_requirements"] = requiredArray; } SelectedSet.difficultyBeatmaps = songDifficultyData; songDifficultySets[selectedBeatmapSet] = SelectedSet; Song.difficultyBeatmapSets = songDifficultySets; Song.SaveSong(); InitializeDifficultyPanel(selectedDifficultyIndex); }
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 SelectMapForEditing(BeatSaberMap map) { this.map = map; SceneTransitionManager.Instance.LoadScene(3); }
private void Start() { song = BeatSaberSongContainer.Instance.song; diff = BeatSaberSongContainer.Instance.difficultyData; map = BeatSaberSongContainer.Instance.map; }
public void LoadDifficulty() { if (songDifficultyData[selectedDifficultyIndex].customData != null) { if (songDifficultyData[selectedDifficultyIndex].customData["_difficultyLabel"] != null) { difficultyLabel.text = songDifficultyData[selectedDifficultyIndex].customData["_difficultyLabel"].Value; } } noteJumpSpeed.text = songDifficultyData[selectedDifficultyIndex].noteJumpMovementSpeed.ToString(); switch (songDifficultyData[selectedDifficultyIndex].difficulty) { case "Easy": difficultyDifficultyDropdown.value = 0; break; case "Normal": difficultyDifficultyDropdown.value = 1; break; case "Hard": difficultyDifficultyDropdown.value = 2; break; case "Expert": difficultyDifficultyDropdown.value = 3; break; case "ExpertPlus": difficultyDifficultyDropdown.value = 4; break; default: difficultyDifficultyDropdown.value = 0; break; } try { BeatSaberMap map = Song.GetMapFromDifficultyBeatmap(songDifficultyData[selectedDifficultyIndex]); foreach (BeatmapNote note in map._notes) { if (note._lineIndex < 0 || note._lineIndex > 3) { MappingExtensionsRequirement.isOn = true; break; } } foreach (BeatmapObstacle ob in map._obstacles) { if (ob._lineIndex < 0 || ob._lineIndex > 3 || ob._type >= 2 || ob._width >= 1000) { MappingExtensionsRequirement.isOn = true; break; } } if (HasChromaEvents() && WillChromaBeRequired.isOn) { ChromaRequirement.isOn = true; } //TODO ChromaToggle. Don't know how to detect legacy ChromaToggle w/o potentially freezing ChroMapper } catch { } }