/// <summary> /// Creates a new mapset with an audio file. /// </summary> /// <param name="audioFile"></param> public static void HandleNewMapsetCreation(string audioFile) { try { var game = GameBase.Game as QuaverGame; // Add a fade effect and make butotns not clickable // so the user can't perform any actions during this time. Transitioner.FadeIn(); Button.IsGloballyClickable = false; var tagFile = TagLib.File.Create(audioFile); // Create a fresh .qua with the available metadata from the file var qua = new Qua() { AudioFile = Path.GetFileName(audioFile), Artist = tagFile.Tag.FirstPerformer ?? "", Title = tagFile.Tag.Title ?? "", Source = tagFile.Tag.Album ?? "", Tags = string.Join(" ", tagFile.Tag.Genres) ?? "", Creator = ConfigManager.Username.Value, DifficultyName = "", // Makes the file different to prevent exception thrown in the DB for same md5 checksum Description = $"Created at {TimeHelper.GetUnixTimestampMilliseconds()}", BackgroundFile = "", Mode = GameMode.Keys4 }; // Create a new directory to house the map. var dir = $"{ConfigManager.SongDirectory.Value}/{TimeHelper.GetUnixTimestampMilliseconds()}"; Directory.CreateDirectory(dir); // Copy over the audio file into the directory File.Copy(audioFile, $"{dir}/{Path.GetFileName(audioFile)}"); // Save the new .qua file into the directory var path = $"{dir}/{StringHelper.FileNameSafeString($"{qua.Artist} - {qua.Title} [{qua.DifficultyName}] - {TimeHelper.GetUnixTimestampMilliseconds()}")}.qua"; qua.Save(path); // Place the new map inside of the database and make sure all the loaded maps are correct var map = Map.FromQua(qua, path); map.Id = MapDatabaseCache.InsertMap(map, path); MapDatabaseCache.OrderAndSetMapsets(); MapManager.Selected.Value = map; MapManager.Selected.Value.Qua = qua; var selectedMapset = MapManager.Mapsets.Find(x => x.Maps.Any(y => y.Id == MapManager.Selected.Value.Id)); // Find the new object from the loaded maps that contains the same id. MapManager.Selected.Value = selectedMapset.Maps.Find(x => x.Id == MapManager.Selected.Value.Id); MapManager.Selected.Value.Qua = qua; MapManager.Selected.Value.NewlyCreated = true; game?.CurrentScreen.Exit(() => new EditorScreen(qua)); } catch (Exception e) { Logger.Error(e, LogType.Runtime); var game = GameBase.Game as QuaverGame; game?.CurrentScreen.Exit(() => { NotificationManager.Show(NotificationLevel.Error, "Could not create new mapset with that audio file."); return(new SelectScreen()); }); } }
private static int Merge(string ancestorPath, string ourPath, string theirPath, int blockSize = 1000) { // hitobjects, timing points, scroll velocities, preview points, editor layers // key counts, diff names // audio file, background file, banner file // map id, mapset id // song title, song artist, song source // tags, creator, description, genre // initial sv, sv mode, scratch key // custom audio samples, sound effects Qua ancestor = Qua.Parse(ancestorPath, false); Qua ours = Qua.Parse(ourPath, false); Qua theirs = Qua.Parse(theirPath, false); ancestor.Sort(); ours.Sort(); theirs.Sort(); int mergeConflicts = 0; Console.WriteLine("Merging Layers..."); List <EditorLayerInfo> mergeLayers = GenerateIndexBasedMergeObjects <EditorLayerInfo>(ancestor.EditorLayers, ours.EditorLayers, theirs.EditorLayers, ancestor.HitObjects, ours.HitObjects, theirs.HitObjects, EditorLayerInfo.ByValueComparer, ApplyLayerIndexChanges); // untested Console.WriteLine("Merging Custom Audio Samples..."); List <CustomAudioSampleInfo> mergeCustomAudioSamples = GenerateIndexBasedMergeObjects <CustomAudioSampleInfo>(ancestor.CustomAudioSamples, ours.CustomAudioSamples, theirs.CustomAudioSamples, ancestor.HitObjects, ours.HitObjects, theirs.HitObjects, CustomAudioSampleInfo.ByValueComparer, ApplyKeySoundSampleIndexChanges); // untested Console.WriteLine("Merging Sound Effects..."); List <SoundEffectInfo> mergeSoundEffects = MergeLists(ancestor.SoundEffects, ours.SoundEffects, theirs.SoundEffects, new List <SoundEffectInfo>(), SoundEffectInfo.ByValueComparer, ref mergeConflicts); float?minTime = new float?[9] { ancestor.HitObjects.Count > 0 ? (float)ancestor.HitObjects[0].StartTime : (float?)null, ancestor.TimingPoints.Count > 0 ? ancestor.TimingPoints[0].StartTime : (float?)null, ancestor.SliderVelocities.Count > 0 ? ancestor.SliderVelocities[0].StartTime : (float?)null, ours.HitObjects.Count > 0 ? (float)ours.HitObjects[0].StartTime : (float?)null, ours.TimingPoints.Count > 0 ? ours.TimingPoints[0].StartTime : (float?)null, ours.SliderVelocities.Count > 0 ? ours.SliderVelocities[0].StartTime : (float?)null, theirs.HitObjects.Count > 0 ? (float)theirs.HitObjects[0].StartTime : (float?)null, theirs.TimingPoints.Count > 0 ? theirs.TimingPoints[0].StartTime : (float?)null, theirs.SliderVelocities.Count > 0 ? theirs.SliderVelocities[0].StartTime : (float?)null }.Min(); Console.WriteLine("minTime: " + minTime); float?maxTime = new float?[9] { ancestor.HitObjects.Count > 0 ? (float)ancestor.HitObjects.Last().StartTime : (float?)null, ancestor.TimingPoints.Count > 0 ? ancestor.TimingPoints.Last().StartTime : (float?)null, ancestor.SliderVelocities.Count > 0 ? ancestor.SliderVelocities.Last().StartTime : (float?)null, ours.HitObjects.Count > 0 ? (float)ours.HitObjects.Last().StartTime : (float?)null, ours.TimingPoints.Count > 0 ? ours.TimingPoints.Last().StartTime : (float?)null, ours.SliderVelocities.Count > 0 ? ours.SliderVelocities.Last().StartTime : (float?)null, theirs.HitObjects.Count > 0 ? (float)theirs.HitObjects.Last().StartTime : (float?)null, theirs.TimingPoints.Count > 0 ? theirs.TimingPoints.Last().StartTime : (float?)null, theirs.SliderVelocities.Count > 0 ? theirs.SliderVelocities.Last().StartTime : (float?)null }.Max(); Console.WriteLine("maxTime: " + maxTime); List <Block> mergeBlocks; if (minTime != null && maxTime != null) { mergeBlocks = GenerateMergeBlocks(ancestor, ours, theirs, (float)minTime, (float)maxTime, blockSize, ref mergeConflicts); } else { mergeBlocks = new List <Block>(); } Console.WriteLine("Generating Merged Map"); Qua mergeQua = new Qua { AudioFile = MergeMetadata <string>(ancestor.AudioFile, ours.AudioFile, theirs.AudioFile, "MERGE CONFLICT", ref mergeConflicts), SongPreviewTime = MergeMetadata <int>(ancestor.SongPreviewTime, ours.SongPreviewTime, theirs.SongPreviewTime, -1, ref mergeConflicts), BackgroundFile = MergeMetadata <string>(ancestor.BackgroundFile, ours.BackgroundFile, theirs.BackgroundFile, "MERGE CONFLICT", ref mergeConflicts), BannerFile = MergeMetadata <string>(ancestor.BannerFile, ours.BannerFile, theirs.BannerFile, "MERGE CONFLICT", ref mergeConflicts), MapId = MergeMetadata <int>(ancestor.MapId, ours.MapId, theirs.MapId, -1, ref mergeConflicts), MapSetId = MergeMetadata <int>(ancestor.MapSetId, ours.MapSetId, theirs.MapSetId, -1, ref mergeConflicts), // why would anyone merge 4k and 7k together Mode = MergeMetadata <GameMode>(ancestor.Mode, ours.Mode, theirs.Mode, (GameMode)(-1), ref mergeConflicts), Title = MergeMetadata <string>(ancestor.Title, ours.Title, theirs.Title, "MERGE CONFLICT", ref mergeConflicts), Artist = MergeMetadata <string>(ancestor.Artist, ours.Artist, theirs.Artist, "MERGE CONFLICT", ref mergeConflicts), Source = MergeMetadata <string>(ancestor.Source, ours.Source, theirs.Source, "MERGE CONFLICT", ref mergeConflicts), Tags = MergeMetadata <string>(ancestor.Tags, ours.Tags, theirs.Tags, "MERGE CONFLICT", ref mergeConflicts), Creator = MergeMetadata <string>(ancestor.Creator, ours.Creator, theirs.Creator, "MERGE CONFLICT", ref mergeConflicts), DifficultyName = MergeMetadata <string>(ancestor.DifficultyName, ours.DifficultyName, theirs.DifficultyName, "MERGE CONFLICT", ref mergeConflicts), Description = MergeMetadata <string>(ancestor.Description, ours.Description, theirs.Description, "MERGE CONFLICT", ref mergeConflicts), Genre = MergeMetadata <string>(ancestor.Genre, ours.Genre, theirs.Genre, "MERGE CONFLICT", ref mergeConflicts), BPMDoesNotAffectScrollVelocity = MergeMetadata <bool>(ancestor.BPMDoesNotAffectScrollVelocity, ours.BPMDoesNotAffectScrollVelocity, theirs.BPMDoesNotAffectScrollVelocity, true, ref mergeConflicts), InitialScrollVelocity = MergeMetadata <float>(ancestor.InitialScrollVelocity, ours.InitialScrollVelocity, theirs.InitialScrollVelocity, -1, ref mergeConflicts), HasScratchKey = MergeMetadata <bool>(ancestor.HasScratchKey, ours.HasScratchKey, theirs.HasScratchKey, false, ref mergeConflicts), CustomAudioSamples = mergeCustomAudioSamples }; mergeQua.EditorLayers.AddRange(mergeLayers); mergeQua.SoundEffects.AddRange(mergeSoundEffects); // untested var objects = GenerateListsFromBlocks(mergeBlocks); mergeQua.HitObjects.AddRange(objects.HitObjects); mergeQua.TimingPoints.AddRange(objects.TimingPoints); mergeQua.SliderVelocities.AddRange(objects.ScrollVelocities); Console.WriteLine("Writing .qua File at " + ourPath); // git expected behavior: overwrite our file mergeQua.Save(ourPath); return(mergeConflicts); }