Esempio n. 1
0
        public HitsoundPreviewHelperVm()
        {
            _items = new ObservableCollection <HitsoundZone>();

            RhythmGuideCommand = new CommandImplementation(
                _ => {
                try {
                    if (_rhythmGuideWindow == null)
                    {
                        _rhythmGuideWindow         = new RhythmGuideWindow();
                        _rhythmGuideWindow.Closed += RhythmGuideWindowOnClosed;
                        _rhythmGuideWindow.Show();
                    }
                    else
                    {
                        _rhythmGuideWindow.Focus();
                    }
                } catch (Exception ex) { ex.Show(); }
            });
            AddCommand = new CommandImplementation(
                _ => {
                try {
                    var newZone = new HitsoundZone();
                    if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
                    {
                        var editor = EditorReaderStuff.GetBeatmapEditor(EditorReaderStuff.GetFullEditorReader(),
                                                                        out var selected);
                        if (selected.Count > 0)
                        {
                            newZone.XPos = selected[0].Pos.X;
                            newZone.YPos = editor.Beatmap.General["Mode"].IntValue == 3 ? -1 : selected[0].Pos.Y;
                        }
                        else
                        {
                            MessageBox.Show("Please select a hit object to fetch the coordinates.");
                        }
                    }
                    Items.Add(newZone);
                } catch (Exception ex) { ex.Show(); }
            });
            CopyCommand = new CommandImplementation(
                _ => {
                try {
                    int initialCount = Items.Count;
                    for (int i = 0; i < initialCount; i++)
                    {
                        if (Items[i].IsSelected)
                        {
                            Items.Add(Items[i].Copy());
                        }
                    }
                } catch (Exception ex) { ex.Show(); }
            });
            RemoveCommand = new CommandImplementation(
                _ => {
                try {
                    Items.RemoveAll(o => o.IsSelected);
                } catch (Exception ex) { ex.Show(); }
            });
        }
Esempio n. 2
0
 private async void CoolSave(object sender, RoutedEventArgs e)
 {
     try {
         await Task.Run(() => EditorReaderStuff.BetterSave());
     } catch (Exception ex) {
         ex.Show();
     }
 }
Esempio n. 3
0
 private void CoolSave(object sender, RoutedEventArgs e)
 {
     try {
         EditorReaderStuff.BetterSave();
     }
     catch (Exception ex) {
         ex.Show();
     }
 }
Esempio n. 4
0
 private static void QuickBetterSave()
 {
     try {
         EditorReaderStuff.BetterSave();
     }
     catch (Exception e) {
         e.Show();
     }
 }
Esempio n. 5
0
        private string Run_Program(MapCleanerVm args, BackgroundWorker worker, DoWorkEventArgs _)
        {
            var result = new Classes.Tools.MapCleaner.MapCleanerResult();

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            if (args.Paths.Length == 1)
            {
                var editor = EditorReaderStuff.GetNewestVersionOrNot(args.Paths[0], reader);

                List <TimingPoint> orgininalTimingPoints = editor.Beatmap.BeatmapTiming.TimingPoints.Select(tp => tp.Copy()).ToList();
                int oldTimingPointsCount = editor.Beatmap.BeatmapTiming.TimingPoints.Count;

                result.Add(Classes.Tools.MapCleaner.CleanMap(editor, args.MapCleanerArgs, worker));

                // Update result with removed count
                int removed = oldTimingPointsCount - editor.Beatmap.BeatmapTiming.TimingPoints.Count;
                result.TimingPointsRemoved += removed;

                List <TimingPoint> newTimingPoints = editor.Beatmap.BeatmapTiming.TimingPoints;
                Monitor_Differences(orgininalTimingPoints, newTimingPoints);

                // Save the file
                editor.SaveFile();
            }
            else
            {
                foreach (string path in args.Paths)
                {
                    var editor = EditorReaderStuff.GetNewestVersionOrNot(path, reader);

                    int oldTimingPointsCount = editor.Beatmap.BeatmapTiming.TimingPoints.Count;

                    result.Add(Classes.Tools.MapCleaner.CleanMap(editor, args.MapCleanerArgs, worker));

                    // Update result with removed count
                    int removed = oldTimingPointsCount - editor.Beatmap.BeatmapTiming.TimingPoints.Count;
                    result.TimingPointsRemoved += removed;

                    // Save the file
                    editor.SaveFile();
                }
            }

            // Do stuff
            if (args.Quick)
            {
                RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, reader != null));
            }

            // Make an accurate message
            string message = $"Successfully {(result.TimingPointsRemoved < 0 ? "added" : "removed")} {Math.Abs(result.TimingPointsRemoved)} {(Math.Abs(result.TimingPointsRemoved) == 1 ? "greenline" : "greenlines")}" +
                             (args.MapCleanerArgs.ResnapObjects ? $" and resnapped {result.ObjectsResnapped} {(result.ObjectsResnapped == 1 ? "object" : "objects")}" : "") +
                             (args.MapCleanerArgs.RemoveUnusedSamples ? $" and removed {result.SamplesRemoved} unused {(result.SamplesRemoved == 1 ? "sample" : "samples")}" : "") + "!";

            return(args.Quick ? string.Empty : message);
        }
        private string PlaceHitsounds(Arguments args, BackgroundWorker worker, DoWorkEventArgs _)
        {
            if (args.Zones.Count == 0)
            {
                return("There are no zones!");
            }

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            foreach (string path in args.Paths)
            {
                var      editor   = EditorReaderStuff.GetNewestVersionOrNot(path, reader);
                Beatmap  beatmap  = editor.Beatmap;
                Timeline timeline = beatmap.GetTimeline();

                for (int i = 0; i < timeline.TimelineObjects.Count; i++)
                {
                    var tlo = timeline.TimelineObjects[i];

                    var    column = args.Zones.FirstOrDefault();
                    double best   = double.MaxValue;
                    foreach (var c in args.Zones)
                    {
                        double dist = c.Distance(tlo.Origin.Pos);
                        if (dist < best)
                        {
                            best   = dist;
                            column = c;
                        }
                    }

                    if (column == null)
                    {
                        continue;
                    }

                    tlo.Filename     = column.Filename;
                    tlo.SampleSet    = column.SampleSet;
                    tlo.AdditionSet  = column.AdditionsSet;
                    tlo.CustomIndex  = column.CustomIndex;
                    tlo.SampleVolume = 0;
                    tlo.SetHitsound(column.Hitsound);
                    tlo.HitsoundsToOrigin();

                    UpdateProgressBar(worker, (int)(100f * i / beatmap.HitObjects.Count));
                }

                // Save the file
                editor.SaveFile();
            }

            // Do stuff
            RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, reader != null, args.Quick));

            return(args.Quick ? "" : "Done!");
        }
Esempio n. 7
0
        public static List <HitsoundLayer> ImportStoryboard(string path, bool volumes, bool removeDuplicates)
        {
            var     editor  = EditorReaderStuff.GetNewestVersionOrNot(path);
            Beatmap beatmap = editor.Beatmap;
            string  mapDir  = editor.GetParentFolder();

            var hitsoundLayers = ImportStoryboard(path, volumes, removeDuplicates, beatmap, mapDir);

            return(hitsoundLayers);
        }
Esempio n. 8
0
        /// <summary>
        /// Generates a temp file with the newest version of specified map and returns the path to that temp file.
        /// </summary>
        /// <param name="mapPath"></param>
        /// <returns></returns>
        private static string GetNewestVersionPath(string mapPath)
        {
            var editor = EditorReaderStuff.GetNewestVersionOrNot(mapPath);

            // Save temp version
            var tempPath = Path.Combine(MainWindow.AppDataPath, "temp.osu");

            Editor.SaveFile(tempPath, editor.Beatmap.GetLines());

            return(tempPath);
        }
        public static void ExportHitsounds(IEnumerable <HitsoundEvent> hitsounds, string baseBeatmap, string exportFolder, bool useGreenlines = true, bool useStoryboard = false)
        {
            EditorReaderStuff.TryGetNewestVersion(baseBeatmap, out var editor);
            Beatmap beatmap = editor.Beatmap;

            if (useStoryboard)
            {
                beatmap.StoryboardSoundSamples = hitsounds.Select(h =>
                                                                  new StoryboardSoundSample(h.Time, 0, h.Filename, h.Volume))
                                                 .ToList();
            }
            else
            {
                // Make new timing points
                // Add red lines
                List <TimingPoint>        timingPoints        = beatmap.BeatmapTiming.GetAllRedlines();
                List <TimingPointsChange> timingPointsChanges = timingPoints.Select(tp =>
                                                                                    new TimingPointsChange(tp, mpb: true, meter: true, inherited: true, omitFirstBarLine: true))
                                                                .ToList();

                // Add hitsound stuff
                // Replace all hitobjects with the hitsounds
                beatmap.HitObjects.Clear();
                foreach (HitsoundEvent h in hitsounds)
                {
                    if (useGreenlines)
                    {
                        TimingPoint tp = beatmap.BeatmapTiming.GetTimingPointAtTime(h.Time + 5).Copy();
                        tp.Offset      = h.Time;
                        tp.SampleIndex = h.CustomIndex;
                        h.CustomIndex  = 0; // Set it to default value because it gets handled by greenlines now
                        tp.Volume      = Math.Round(tp.Volume * h.Volume);
                        h.Volume       = 0; // Set it to default value because it gets handled by greenlines now
                        timingPointsChanges.Add(new TimingPointsChange(tp, index: true, volume: true));
                    }

                    beatmap.HitObjects.Add(new HitObject(h.Pos, h.Time, 5, h.GetHitsounds(), h.SampleSet, h.Additions,
                                                         h.CustomIndex, h.Volume * 100, h.Filename));
                }

                // Replace the old timingpoints
                beatmap.BeatmapTiming.TimingPoints.Clear();
                TimingPointsChange.ApplyChanges(beatmap.BeatmapTiming, timingPointsChanges);
            }

            // Change version to hitsounds
            beatmap.General["StackLeniency"] = new TValue("0.0");
            beatmap.General["Mode"]          = new TValue("0");
            beatmap.Metadata["Version"]      = new TValue("Hitsounds");
            beatmap.Difficulty["CircleSize"] = new TValue("4");

            // Save the file to the export folder
            editor.SaveFile(Path.Combine(exportFolder, beatmap.GetFileName()));
        }
Esempio n. 10
0
        public ComboColourProject()
        {
            ColourPoints = new ObservableCollection <ColourPoint>();
            ComboColours = new ObservableCollection <SpecialColour>();

            MaxBurstLength = 1;

            AddColourPointCommand = new CommandImplementation(_ => {
                double time = ColourPoints.Count > 1 ?
                              ColourPoints.Count(o => o.IsSelected) > 0 ? ColourPoints.Where(o => o.IsSelected).Max(o => o.Time) :
                              ColourPoints.Last().Time
                    : 0;
                if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
                {
                    try {
                        time = EditorReaderStuff.GetEditorTime();
                    } catch (Exception ex) {
                        ex.Show();
                    }
                }

                ColourPoints.Add(GenerateNewColourPoint(time));
            });

            RemoveColourPointCommand = new CommandImplementation(_ => {
                if (ColourPoints.Any(o => o.IsSelected))
                {
                    ColourPoints.RemoveAll(o => o.IsSelected);
                    return;
                }
                if (ColourPoints.Count > 0)
                {
                    ColourPoints.RemoveAt(ColourPoints.Count - 1);
                }
            });

            AddComboCommand = new CommandImplementation(_ => {
                if (ComboColours.Count >= 8)
                {
                    return;
                }
                ComboColours.Add(ComboColours.Count > 0
                    ? new SpecialColour(ComboColours[ComboColours.Count - 1].Color, $"Combo{ComboColours.Count + 1}")
                    : new SpecialColour(Colors.White, $"Combo{ComboColours.Count + 1}"));
            });

            RemoveComboCommand = new CommandImplementation(_ => {
                if (ComboColours.Count > 0)
                {
                    ComboColours.RemoveAt(ComboColours.Count - 1);
                }
            });
        }
Esempio n. 11
0
        private static void GenerateBetterSaveMD5(List <string> lines)
        {
            var tempPath = System.IO.Path.Combine(MainWindow.AppDataPath, "temp.osu");

            if (!File.Exists(tempPath))
            {
                File.Create(tempPath).Dispose();
            }
            File.WriteAllLines(tempPath, lines);

            EditorReaderStuff.DontCoolSaveWhenMD5EqualsThisString = EditorReaderStuff.GetMD5FromPath(tempPath);
        }
Esempio n. 12
0
        private string Run_Program(Arguments args, BackgroundWorker worker, DoWorkEventArgs _) {
            var result = new MapCleaner.MapCleanerResult();

            bool editorRead = EditorReaderStuff.TryGetFullEditorReader(out var reader);

            if (args.Paths.Length == 1) {
                var editor = EditorReaderStuff.GetBeatmapEditor(args.Paths[0], reader, editorRead);

                List<TimingPoint> orgininalTimingPoints = new List<TimingPoint>();
                foreach (TimingPoint tp in editor.Beatmap.BeatmapTiming.TimingPoints) { orgininalTimingPoints.Add(tp.Copy()); }
                int oldTimingPointsCount = editor.Beatmap.BeatmapTiming.TimingPoints.Count;

                result.Add(MapCleaner.CleanMap(editor, args.CleanerArguments, worker));

                // Update result with removed count
                int removed = oldTimingPointsCount - editor.Beatmap.BeatmapTiming.TimingPoints.Count;
                result.TimingPointsRemoved += removed;

                List<TimingPoint> newTimingPoints = editor.Beatmap.BeatmapTiming.TimingPoints;
                Monitor_Differences(orgininalTimingPoints, newTimingPoints);

                // Save the file
                editor.SaveFile();
            } else {
                foreach (string path in args.Paths) {
                    var editor = EditorReaderStuff.GetBeatmapEditor(path, reader, editorRead);

                    int oldTimingPointsCount = editor.Beatmap.BeatmapTiming.TimingPoints.Count;

                    result.Add(MapCleaner.CleanMap(editor, args.CleanerArguments, worker));

                    // Update result with removed count
                    int removed = oldTimingPointsCount - editor.Beatmap.BeatmapTiming.TimingPoints.Count;
                    result.TimingPointsRemoved += removed;

                    // Save the file
                    editor.SaveFile();
                }
            }

            // Do stuff
            if (args.Quick)
                RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, editorRead));

            // Make an accurate message
            string message = $"Successfully {(result.TimingPointsRemoved < 0 ? "added" : "removed")} {Math.Abs(result.TimingPointsRemoved)} {(Math.Abs(result.TimingPointsRemoved) == 1 ? "greenline" : "greenlines")}" +
                (args.CleanerArguments.ResnapObjects ? $" and resnapped {result.ObjectsResnapped} {(result.ObjectsResnapped == 1 ? "object" : "objects")}" : "") + 
                (args.CleanerArguments.RemoveUnusedSamples ? $" and removed {result.SamplesRemoved} unused {(result.SamplesRemoved == 1 ? "sample" : "samples")}" : "") + "!";
            return args.Quick ? "" : message;
        }
        public override void SaveFile()
        {
            var tempPath = System.IO.Path.Combine(MainWindow.AppDataPath, "temp.osu");

            if (!File.Exists(tempPath))
            {
                File.Create(tempPath).Dispose();
            }
            File.WriteAllLines(tempPath, TextFile.GetLines());

            EditorReaderStuff.DontCoolSaveWhenMD5EqualsThisString = EditorReaderStuff.GetMD5FromPath(tempPath);

            base.SaveFile();
        }
Esempio n. 14
0
        public static string GetCurrentBeatmap()
        {
            string path;

            try {
                string songs = SettingsManager.GetSongsPath();

                if (string.IsNullOrEmpty(songs))
                {
                    throw new Exception(
                              @"Can't fetch current in-game beatmap, because there is no Songs path specified in Preferences.");
                }

                string folder   = PioReader.GetMapFolderName();
                string filename = PioReader.GetOsuFileName();

                if (string.IsNullOrEmpty(folder))
                {
                    throw new Exception(@"Can't fetch the folder name of the current in-game beatmap.");
                }

                if (string.IsNullOrEmpty(filename))
                {
                    throw new Exception(@"Can't fetch the file name of the current in-game beatmap.");
                }

                path = Path.Combine(songs, folder, filename);
            }
            catch (Exception ex) {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                try {
                    var reader = EditorReaderStuff.GetEditorReader();
                    reader.FetchEditor();
                    reader.SetHOM();
                    reader.ReadHOM();
                    reader.FetchBeatmap();
                    path = EditorReaderStuff.GetCurrentBeatmap(reader);
                }
                catch (Exception ex2) {
                    Console.WriteLine(ex2.Message);
                    Console.WriteLine(ex2.StackTrace);
                    throw ex;
                }
            }

            return(path);
        }
        private void PeriodicBackupTimerOnTick(object sender, EventArgs e)
        {
            try {
                // Get the newest beatmap, save a temp version, get the hash and compare it to the previous hash, backup temp file
                var path = IOHelper.GetCurrentBeatmap();

                if (string.IsNullOrEmpty(path))
                {
                    return;
                }

                // Don't make period backup if the editor is not open
                if (!EditorReaderStuff.IsEditorOpen())
                {
                    return;
                }

                EditorReader reader = null;
                try {
                    reader = EditorReaderStuff.GetFullEditorReader();
                } catch (Exception ex) {
                    Console.WriteLine(ex.MessageStackTrace());
                }

                var editor = EditorReaderStuff.GetNewestVersionOrNot(path, reader);

                // Save temp version
                var tempPath = Path.Combine(MainWindow.AppDataPath, "temp.osu");

                Editor.SaveFile(tempPath, editor.Beatmap.GetLines());

                // Get MD5 from temp file
                var currentMapHash = EditorReaderStuff.GetMD5FromPath(tempPath);

                // Comparing with previously made periodic backup
                if (currentMapHash == previousPeriodicBackupHash)
                {
                    return;
                }

                // Saving backup of the map
                BackupManager.SaveMapBackup(tempPath, true, Path.GetFileName(path), "PB");  // PB stands for Periodic Backup

                previousPeriodicBackupHash = currentMapHash;
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
        }
Esempio n. 16
0
        public static List <double> TimesFromStack(string path, double x, double y)
        {
            List <double> times  = new List <double>();
            var           editor = EditorReaderStuff.GetNewestVersionOrNot(path);

            bool xIgnore = x == -1;
            bool yIgnore = y == -1;

            foreach (HitObject ho in editor.Beatmap.HitObjects)
            {
                if ((Math.Abs(ho.Pos.X - x) < 3 || xIgnore) && (Math.Abs(ho.Pos.Y - y) < 3 || yIgnore))
                {
                    times.Add(ho.Time);
                }
            }
            return(times);
        }
        private static string Copy_Metadata(MetadataManagerVm arg, BackgroundWorker worker, DoWorkEventArgs _)
        {
            var paths    = arg.ExportPath.Split('|');
            var mapsDone = 0;

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            foreach (var path in paths)
            {
                var editor  = EditorReaderStuff.GetNewestVersionOrNot(path, reader);
                var beatmap = editor.Beatmap;

                beatmap.Metadata["ArtistUnicode"].Value = arg.Artist;
                beatmap.Metadata["Artist"].Value        = arg.RomanisedArtist;
                beatmap.Metadata["TitleUnicode"].Value  = arg.Title;
                beatmap.Metadata["Title"].Value         = arg.RomanisedTitle;
                beatmap.Metadata["Creator"].Value       = arg.BeatmapCreator;
                beatmap.Metadata["Source"].Value        = arg.Source;
                beatmap.Metadata["Tags"].Value          = arg.Tags;

                beatmap.General["PreviewTime"] = new TValue(arg.PreviewTime.ToRoundInvariant());
                if (arg.UseComboColours)
                {
                    beatmap.ComboColours = new List <ComboColour>(arg.ComboColours);
                    beatmap.SpecialColours.Clear();
                    foreach (var specialColour in arg.SpecialColours)
                    {
                        beatmap.SpecialColours.Add(specialColour.Name, specialColour);
                    }
                }

                // Save the file with name update because we updated the metadata
                editor.SaveFileWithNameUpdate();

                // Update progressbar
                if (worker != null && worker.WorkerReportsProgress)
                {
                    worker.ReportProgress(++mapsDone * 100 / paths.Length);
                }
            }

            // Make an accurate message
            var message = $"Successfully exported metadata to {mapsDone} {(mapsDone == 1 ? "beatmap" : "beatmaps")}!";

            return(message);
        }
Esempio n. 18
0
        private string ExportPattern(PatternGalleryVm args, BackgroundWorker worker, DoWorkEventArgs _)
        {
            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();
            var editor = EditorReaderStuff.GetNewestVersionOrNot(IOHelper.GetCurrentBeatmapOrCurrentBeatmap(), reader);

            var pattern = args.Patterns.FirstOrDefault(o => o.IsSelected);

            if (pattern == null)
            {
                throw new Exception("No pattern has been selected to export.");
            }

            var patternBeatmap = pattern.GetPatternBeatmap(args.FileHandler);

            var patternPlacer = args.OsuPatternPlacer;

            if (reader != null)
            {
                patternPlacer.PlaceOsuPatternAtTime(patternBeatmap, editor.Beatmap, reader.EditorTime(), false);
            }
            else
            {
                patternPlacer.PlaceOsuPattern(patternBeatmap, editor.Beatmap, protectBeatmapPattern: false);
            }

            editor.SaveFile();

            // Increase pattern use count and time
            pattern.UseCount++;
            pattern.LastUsedTime = DateTime.Now;

            // Complete progressbar
            if (worker != null && worker.WorkerReportsProgress)
            {
                worker.ReportProgress(100);
            }

            // Do stuff
            if (args.Quick)
            {
                RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, reader != null));
            }

            return("Successfully exported pattern!");
        }
        private static void OnChangedFsWatcher(object sender, FileSystemEventArgs e)
        {
            try {
                var currentPath = IOHelper.GetCurrentBeatmap();

                if (e.FullPath != currentPath)
                {
                    return;
                }

                var proc = System.Diagnostics.Process.GetProcessesByName("osu!").FirstOrDefault();
                if (proc != null)
                {
                    var oldHandle = GetForegroundWindow();
                    if (oldHandle != proc.MainWindowHandle)
                    {
                        return;
                    }
                }

                string hashString = "";
                try {
                    if (File.Exists(currentPath))
                    {
                        hashString = EditorReaderStuff.GetMD5FromPath(currentPath);
                    }
                }
                catch {
                    return;
                }

                if (EditorReaderStuff.DontCoolSaveWhenMD5EqualsThisString == hashString)
                {
                    return;
                }

                EditorReaderStuff.BetterSave();
            }
            catch (Exception ex) {
                MessageBox.Show("Failed to overwrite osu! save with BetterSave.");
                ex.Show();
            }
        }
Esempio n. 20
0
        public static void ExportHitsounds(List<HitsoundEvent> hitsounds, string baseBeatmap, string exportFolder) {
            EditorReaderStuff.TryGetNewestVersion(baseBeatmap, out var editor);
            Beatmap beatmap = editor.Beatmap;

            // Make new timing points
            List<TimingPointsChange> timingPointsChanges = new List<TimingPointsChange>();

            // Add red lines
            List<TimingPoint> timingPoints = beatmap.BeatmapTiming.GetAllRedlines();
            foreach (TimingPoint tp in timingPoints) {
                timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true, meter: true, inherited: true, omitFirstBarLine: true));
            }

            // Add hitsound stuff
            foreach (HitsoundEvent h in hitsounds) {
                TimingPoint tp = beatmap.BeatmapTiming.GetTimingPointAtTime(h.Time + 5).Copy();
                tp.Offset = h.Time;
                tp.SampleIndex = h.CustomIndex;
                tp.Volume = Math.Round(tp.Volume * h.Volume);
                timingPointsChanges.Add(new TimingPointsChange(tp, index: true, volume: true));
            }

            // Replace the old timingpoints
            beatmap.BeatmapTiming.TimingPoints.Clear();
            TimingPointsChange.ApplyChanges(beatmap.BeatmapTiming, timingPointsChanges);

            // Replace all hitobjects with the hitsounds
            beatmap.HitObjects.Clear();
            foreach (HitsoundEvent h in hitsounds) {
                beatmap.HitObjects.Add(new HitObject(h.Time, h.GetHitsounds(), h.SampleSet, h.Additions));
            }

            // Change version to hitsounds
            beatmap.General["StackLeniency"] = new TValue("0.0");
            beatmap.General["Mode"] = new TValue("0");
            beatmap.Metadata["Version"] = new TValue("Hitsounds");
            beatmap.Difficulty["CircleSize"] = new TValue("4");

            // Save the file to the export folder
            editor.SaveFile(Path.Combine(exportFolder, beatmap.GetFileName()));
        }
Esempio n. 21
0
        private void PeriodicBackupTimerOnTick(object sender, EventArgs e)
        {
            try {
                // Get the newest beatmap, save a temp version, get the hash and compare it to the previous hash, backup temp file
                var path = IOHelper.GetCurrentBeatmap();

                if (string.IsNullOrEmpty(path))
                {
                    return;
                }

                EditorReaderStuff.TryGetNewestVersion(path, out var editor);

                // Save temp version
                var tempPath = Path.Combine(MainWindow.AppDataPath, "temp.osu");

                if (!File.Exists(tempPath))
                {
                    File.Create(tempPath).Dispose();
                }

                File.WriteAllLines(tempPath, editor.Beatmap.GetLines());

                // Get MD5 from temp file
                var currentMapHash = EditorReaderStuff.GetMD5FromPath(tempPath);

                // Comparing with previously made periodic backup
                if (currentMapHash == previousPeriodicBackupHash)
                {
                    return;
                }

                // Saving backup of the map
                IOHelper.SaveMapBackup(tempPath, true, Path.GetFileName(path));

                previousPeriodicBackupHash = currentMapHash;
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
        }
        private string Copy_Timing(TimingCopierVm arg, BackgroundWorker worker, DoWorkEventArgs _)
        {
            string[] paths    = arg.ExportPath.Split('|');
            int      mapsDone = 0;

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            foreach (string exportPath in paths)
            {
                var editorTo   = EditorReaderStuff.GetNewestVersionOrNot(exportPath, reader);
                var editorFrom = EditorReaderStuff.GetNewestVersionOrNot(arg.ImportPath, reader);

                Beatmap beatmapTo   = editorTo.Beatmap;
                Beatmap beatmapFrom = editorFrom.Beatmap;

                Timing timingTo   = beatmapTo.BeatmapTiming;
                Timing timingFrom = beatmapFrom.BeatmapTiming;

                // Get markers for hitobjects if mode 1 is used
                List <Marker> markers = new List <Marker>();
                if (arg.ResnapMode == "Number of beats between objects stays the same")
                {
                    markers = GetMarkers(beatmapTo, timingTo);
                }

                // Rid the beatmap of redlines
                // If a greenline exists at the same time as a redline then the redline ceizes to exist
                // Else convert the redline to a greenline: Inherited = false & MpB = -100
                List <TimingPoint> removeList = new List <TimingPoint>();
                foreach (TimingPoint redline in timingTo.GetAllRedlines())
                {
                    TimingPoint greenlineHere = timingTo.GetGreenlineAtTime(redline.Offset);
                    if (greenlineHere.Offset == redline.Offset)
                    {
                        removeList.Add(redline);
                    }
                    else
                    {
                        redline.Uninherited = false;
                        redline.MpB         = -100;
                    }
                }
                foreach (TimingPoint tp in removeList)
                {
                    timingTo.TimingPoints.Remove(tp);
                }

                // Make new timing points changes
                List <TimingPointsChange> timingPointsChanges = new List <TimingPointsChange>();

                // Add redlines
                List <TimingPoint> redlines = timingFrom.GetAllRedlines();
                foreach (TimingPoint tp in redlines)
                {
                    timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true, meter: true, inherited: true, omitFirstBarLine: true));
                }

                // Apply timing changes
                TimingPointsChange.ApplyChanges(timingTo, timingPointsChanges);

                if (arg.ResnapMode == "Number of beats between objects stays the same")
                {
                    redlines = timingTo.GetAllRedlines();
                    List <double> newBookmarks = new List <double>();
                    double        lastTime     = redlines.FirstOrDefault().Offset;
                    foreach (Marker marker in markers)
                    {
                        // Get redlines between this and last marker
                        TimingPoint redline = timingTo.GetRedlineAtTime(lastTime, redlines.FirstOrDefault());

                        double beatsFromLastTime = marker.BeatsFromLastMarker;
                        while (true)
                        {
                            List <TimingPoint> redlinesBetween = redlines.Where(o => o.Offset <= lastTime + redline.MpB * beatsFromLastTime && o.Offset > lastTime).ToList();

                            if (redlinesBetween.Count == 0)
                            {
                                break;
                            }

                            TimingPoint first = redlinesBetween.First();
                            double      diff  = first.Offset - lastTime;
                            beatsFromLastTime -= diff / redline.MpB;

                            redline  = first;
                            lastTime = first.Offset;
                        }

                        // Last time is the time of the last redline in between
                        double newTime = lastTime + redline.MpB * beatsFromLastTime;
                        newTime     = timingTo.Resnap(newTime, arg.Snap1, arg.Snap2, firstTp: redlines.FirstOrDefault());
                        marker.Time = newTime;

                        lastTime = marker.Time;
                    }

                    // Add the bookmarks
                    foreach (Marker marker in markers)
                    {
                        // Check whether the marker is a bookmark
                        if (marker.Object is double)
                        {
                            // Don't resnap bookmarks
                            newBookmarks.Add((double)marker.Object);
                        }
                    }
                    beatmapTo.SetBookmarks(newBookmarks);
                }
                else if (arg.ResnapMode == "Just resnap")
                {
                    // Resnap hitobjects
                    foreach (HitObject ho in beatmapTo.HitObjects)
                    {
                        ho.ResnapSelf(timingTo, arg.Snap1, arg.Snap2, firstTp: redlines.FirstOrDefault());
                        ho.ResnapEnd(timingTo, arg.Snap1, arg.Snap2, firstTp: redlines.FirstOrDefault());
                    }

                    // Resnap greenlines
                    foreach (TimingPoint tp in timingTo.GetAllGreenlines())
                    {
                        tp.ResnapSelf(timingTo, arg.Snap1, arg.Snap2, firstTP: redlines.FirstOrDefault());
                    }
                }
                else
                {
                    // Don't move objects
                }

                // Save the file
                editorTo.SaveFile();

                // Update progressbar
                if (worker != null && worker.WorkerReportsProgress)
                {
                    worker.ReportProgress(++mapsDone * 100 / paths.Length);
                }
            }

            // Make an accurate message
            string message = $"Successfully copied timing to {mapsDone} {(mapsDone == 1 ? "beatmap" : "beatmaps")}!";

            return(message);
        }
Esempio n. 23
0
        /// <summary>
        /// Extract every used sample in a beatmap and return them as hitsound layers.
        /// </summary>
        /// <param name="path">The path to the beatmap.</param>
        /// <param name="volumes">Taking the volumes from the map and making different layers for different volumes.</param>
        /// <param name="detectDuplicateSamples">Detect duplicate samples and optimise hitsound layer count with that.</param>
        /// <param name="removeDuplicates">Removes duplicate sounds at the same millisecond.</param>
        /// <param name="includeStoryboard">Also imports storyboarded samples.</param>
        /// <returns>The hitsound layers</returns>
        public static List <HitsoundLayer> ImportHitsounds(string path, bool volumes, bool detectDuplicateSamples, bool removeDuplicates, bool includeStoryboard)
        {
            var      editor   = EditorReaderStuff.GetNewestVersionOrNot(path);
            Beatmap  beatmap  = editor.Beatmap;
            Timeline timeline = beatmap.GetTimeline();

            GameMode mode   = (GameMode)beatmap.General["Mode"].IntValue;
            string   mapDir = editor.GetParentFolder();
            Dictionary <string, string> firstSamples = AnalyzeSamples(mapDir, false, detectDuplicateSamples);

            List <HitsoundLayer> hitsoundLayers = new List <HitsoundLayer>();

            foreach (TimelineObject tlo in timeline.TimelineObjects)
            {
                if (!tlo.HasHitsound)
                {
                    continue;
                }

                double volume = volumes ? tlo.FenoSampleVolume / 100 : 1;

                List <string> samples = tlo.GetPlayingFilenames(mode);

                foreach (string filename in samples)
                {
                    bool isFilename = tlo.UsesFilename;

                    SampleSet sampleSet = isFilename ? tlo.FenoSampleSet : GetSamplesetFromFilename(filename);
                    Hitsound  hitsound  = isFilename ? tlo.GetHitsound() : GetHitsoundFromFilename(filename);

                    string samplePath      = Path.Combine(mapDir, filename);
                    string fullPathExtLess = Path.Combine(
                        Path.GetDirectoryName(samplePath) ?? throw new InvalidOperationException(),
                        Path.GetFileNameWithoutExtension(samplePath));

                    // Get the first occurence of this sound to not get duplicated
                    if (firstSamples.Keys.Contains(fullPathExtLess))
                    {
                        samplePath = firstSamples[fullPathExtLess];
                    }
                    else
                    {
                        // Sample doesn't exist
                        if (!isFilename)
                        {
                            samplePath = Path.Combine(
                                Path.GetDirectoryName(samplePath) ?? throw new InvalidOperationException(),
                                $"{sampleSet.ToString().ToLower()}-hit{hitsound.ToString().ToLower()}-1.wav");
                        }
                    }

                    string extLessFilename = Path.GetFileNameWithoutExtension(samplePath);
                    var    importArgs      = new LayerImportArgs(ImportType.Hitsounds)
                    {
                        Path   = path, SamplePath = samplePath,
                        Volume = volume, DetectDuplicateSamples = detectDuplicateSamples, DiscriminateVolumes = volumes, RemoveDuplicates = removeDuplicates
                    };

                    // Find the hitsoundlayer with this path
                    HitsoundLayer layer = hitsoundLayers.Find(o => o.ImportArgs == importArgs);

                    if (layer != null)
                    {
                        // Find hitsound layer with this path and add this time
                        layer.Times.Add(tlo.Time);
                    }
                    else
                    {
                        // Add new hitsound layer with this path
                        HitsoundLayer newLayer = new HitsoundLayer(extLessFilename,
                                                                   sampleSet,
                                                                   hitsound,
                                                                   new SampleGeneratingArgs(samplePath)
                        {
                            Volume = volume
                        },
                                                                   importArgs);
                        newLayer.Times.Add(tlo.Time);

                        hitsoundLayers.Add(newLayer);
                    }
                }
            }

            if (includeStoryboard)
            {
                hitsoundLayers.AddRange(ImportStoryboard(path, volumes, removeDuplicates, beatmap, mapDir, "SB: "));
            }

            // Sort layers by name
            hitsoundLayers = hitsoundLayers.OrderBy(o => o.Name).ToList();

            if (removeDuplicates)
            {
                foreach (var hitsoundLayer in hitsoundLayers)
                {
                    hitsoundLayer.Times.Sort();
                    hitsoundLayer.RemoveDuplicates();
                }
            }

            return(hitsoundLayers);
        }
Esempio n. 24
0
        private string Copy_Hitsounds(HitsoundCopierVm arg, BackgroundWorker worker)
        {
            var doMutedIndex = arg.MutedIndex >= 0;

            var paths        = arg.PathTo.Split('|');
            var mapsDone     = 0;
            var sampleSchema = new SampleSchema();

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            foreach (var pathTo in paths)
            {
                BeatmapEditor editorTo  = EditorReaderStuff.GetNewestVersionOrNot(pathTo, reader);;
                Beatmap       beatmapTo = editorTo.Beatmap;
                Beatmap       beatmapFrom;

                if (!string.IsNullOrEmpty(arg.PathFrom))
                {
                    var editorFrom = EditorReaderStuff.GetNewestVersionOrNot(arg.PathFrom, reader);
                    beatmapFrom = editorFrom.Beatmap;
                }
                else
                {
                    // Copy from an empty beatmap similar to the map to copy to
                    beatmapFrom = beatmapTo.DeepCopy();
                    beatmapFrom.HitObjects.Clear();
                    beatmapFrom.BeatmapTiming.Clear();
                }

                Timeline processedTimeline;

                if (arg.CopyMode == 0)
                {
                    // Every defined hitsound and sampleset on hitsound gets copied to their copyTo destination
                    // Timelines
                    var tlTo   = beatmapTo.GetTimeline();
                    var tlFrom = beatmapFrom.GetTimeline();

                    var volumeMuteTimes = arg.CopyVolumes && arg.AlwaysPreserve5Volume ? new List <double>() : null;

                    if (arg.CopyHitsounds)
                    {
                        ResetHitObjectHitsounds(beatmapTo);
                        CopyHitsounds(arg, tlFrom, tlTo);
                    }

                    // Save tlo times where timingpoint volume is 5%
                    // Timingpointchange all the undefined tlo from copyFrom
                    volumeMuteTimes?.AddRange(from tloTo in tlTo.TimelineObjects
                                              where tloTo.CanCopy && Math.Abs(tloTo.SampleVolume) < Precision.DOUBLE_EPSILON &&
                                              Math.Abs(tloTo.FenoSampleVolume - 5) < Precision.DOUBLE_EPSILON
                                              select tloTo.Time);

                    // Volumes and samplesets and customindices greenlines get copied with timingpointchanges and allafter enabled
                    var timingPointsChanges = beatmapFrom.BeatmapTiming.TimingPoints.Select(tp =>
                                                                                            new TimingPointsChange(tp, sampleset: arg.CopySampleSets, index: arg.CopySampleSets,
                                                                                                                   volume: arg.CopyVolumes)).ToList();

                    // Apply the timingpoint changes
                    TimingPointsChange.ApplyChanges(beatmapTo.BeatmapTiming, timingPointsChanges, true);

                    processedTimeline = tlTo;

                    // Return 5% volume to tlo that had it before
                    if (volumeMuteTimes != null)
                    {
                        var timingPointsChangesMute = new List <TimingPointsChange>();
                        processedTimeline.GiveTimingPoints(beatmapTo.BeatmapTiming);

                        // Exclude objects which use their own sample volume property instead
                        foreach (var tloTo in processedTimeline.TimelineObjects.Where(o => Math.Abs(o.SampleVolume) < Precision.DOUBLE_EPSILON))
                        {
                            if (volumeMuteTimes.Contains(tloTo.Time))
                            {
                                // Add timingpointschange to copy timingpoint hitsounds
                                var tp = tloTo.HitsoundTimingPoint.Copy();
                                tp.Offset = tloTo.Time;
                                tp.Volume = 5;
                                timingPointsChangesMute.Add(new TimingPointsChange(tp, volume: true));
                            }
                            else
                            {
                                // Add timingpointschange to preserve index and volume
                                var tp = tloTo.HitsoundTimingPoint.Copy();
                                tp.Offset = tloTo.Time;
                                tp.Volume = tloTo.FenoSampleVolume;
                                timingPointsChangesMute.Add(new TimingPointsChange(tp, volume: true));
                            }
                        }

                        // Apply the timingpoint changes
                        TimingPointsChange.ApplyChanges(beatmapTo.BeatmapTiming, timingPointsChangesMute);
                    }
                }
                else
                {
                    // Smarty mode
                    // Copy the defined hitsounds literally (not feno, that will be reserved for cleaner). Only the tlo that have been defined by copyFrom get overwritten.
                    var tlTo   = beatmapTo.GetTimeline();
                    var tlFrom = beatmapFrom.GetTimeline();

                    var timingPointsChanges = new List <TimingPointsChange>();
                    var mode         = (GameMode)beatmapTo.General["Mode"].IntValue;
                    var mapDir       = editorTo.GetParentFolder();
                    var firstSamples = HitsoundImporter.AnalyzeSamples(mapDir);

                    if (arg.CopyHitsounds)
                    {
                        CopyHitsounds(arg, beatmapTo, tlFrom, tlTo, timingPointsChanges, mode, mapDir, firstSamples, ref sampleSchema);
                    }

                    if (arg.CopyBodyHitsounds)
                    {
                        // Remove timingpoints in beatmapTo that are in a sliderbody/spinnerbody for both beatmapTo and BeatmapFrom
                        foreach (var tp in from ho in beatmapTo.HitObjects
                                 from tp in ho.BodyHitsounds
                                 where beatmapFrom.HitObjects.Any(o => o.Time <tp.Offset && o.EndTime> tp.Offset)
                                 where !tp.Uninherited
                                 select tp)
                        {
                            beatmapTo.BeatmapTiming.Remove(tp);
                        }

                        // Get timingpointschanges for every timingpoint from beatmapFrom that is in a sliderbody/spinnerbody for both beatmapTo and BeatmapFrom
                        timingPointsChanges.AddRange(from ho in beatmapFrom.HitObjects
                                                     from tp in ho.BodyHitsounds
                                                     where beatmapTo.HitObjects.Any(o => o.Time <tp.Offset && o.EndTime> tp.Offset)
                                                     select new TimingPointsChange(tp.Copy(), sampleset: arg.CopySampleSets, index: arg.CopySampleSets,
                                                                                   volume: arg.CopyVolumes));
                    }

                    // Apply the timingpoint changes
                    TimingPointsChange.ApplyChanges(beatmapTo.BeatmapTiming, timingPointsChanges);

                    processedTimeline = tlTo;
                }

                if (arg.CopyStoryboardedSamples)
                {
                    if (arg.CopyMode == 0)
                    {
                        beatmapTo.StoryboardSoundSamples.Clear();
                    }

                    beatmapTo.GiveObjectsGreenlines();
                    processedTimeline.GiveTimingPoints(beatmapTo.BeatmapTiming);

                    var mapDir       = editorTo.GetParentFolder();
                    var firstSamples = HitsoundImporter.AnalyzeSamples(mapDir, true);

                    var samplesTo = new HashSet <StoryboardSoundSample>(beatmapTo.StoryboardSoundSamples);
                    var mode      = (GameMode)beatmapTo.General["Mode"].IntValue;

                    foreach (var sampleFrom in beatmapFrom.StoryboardSoundSamples)
                    {
                        if (arg.IgnoreHitsoundSatisfiedSamples)
                        {
                            var tloHere = processedTimeline.TimelineObjects.FindAll(o =>
                                                                                    Math.Abs(o.Time - sampleFrom.StartTime) <= arg.TemporalLeniency);
                            var samplesHere = new HashSet <string>();
                            foreach (var tlo in tloHere)
                            {
                                foreach (var filename in tlo.GetPlayingFilenames(mode))
                                {
                                    var samplePath      = Path.Combine(mapDir, filename);
                                    var fullPathExtLess = Path.Combine(Path.GetDirectoryName(samplePath),
                                                                       Path.GetFileNameWithoutExtension(samplePath));

                                    if (firstSamples.Keys.Contains(fullPathExtLess))
                                    {
                                        samplePath = firstSamples[fullPathExtLess];
                                    }

                                    samplesHere.Add(samplePath);
                                }
                            }

                            var sbSamplePath      = Path.Combine(mapDir, sampleFrom.FilePath);
                            var sbFullPathExtLess = Path.Combine(Path.GetDirectoryName(sbSamplePath),
                                                                 Path.GetFileNameWithoutExtension(sbSamplePath));

                            if (firstSamples.Keys.Contains(sbFullPathExtLess))
                            {
                                sbSamplePath = firstSamples[sbFullPathExtLess];
                            }

                            if (samplesHere.Contains(sbSamplePath))
                            {
                                continue;
                            }
                        }

                        // Add the StoryboardSoundSamples from beatmapFrom to beatmapTo if it doesn't already have the sample
                        if (!samplesTo.Contains(sampleFrom))
                        {
                            beatmapTo.StoryboardSoundSamples.Add(sampleFrom);
                        }
                    }

                    // Sort the storyboarded samples
                    beatmapTo.StoryboardSoundSamples.Sort();
                }

                if (arg.MuteSliderends)
                {
                    var timingPointsChanges = new List <TimingPointsChange>();
                    beatmapTo.GiveObjectsGreenlines();
                    processedTimeline.GiveTimingPoints(beatmapTo.BeatmapTiming);

                    foreach (var tloTo in processedTimeline.TimelineObjects)
                    {
                        if (FilterMuteTlo(tloTo, beatmapTo, arg))
                        {
                            // Set volume to 5%, remove all hitsounds, apply customindex and sampleset
                            tloTo.SampleSet   = arg.MutedSampleSet;
                            tloTo.AdditionSet = 0;
                            tloTo.Normal      = false;
                            tloTo.Whistle     = false;
                            tloTo.Finish      = false;
                            tloTo.Clap        = false;

                            tloTo.HitsoundsToOrigin();

                            // Add timingpointschange to copy timingpoint hitsounds
                            var tp = tloTo.HitsoundTimingPoint.Copy();
                            tp.Offset      = tloTo.Time;
                            tp.SampleSet   = arg.MutedSampleSet;
                            tp.SampleIndex = arg.MutedIndex;
                            tp.Volume      = 5;
                            timingPointsChanges.Add(new TimingPointsChange(tp, sampleset: true, index: doMutedIndex,
                                                                           volume: true));
                        }
                        else
                        {
                            // Add timingpointschange to preserve index and volume and sampleset
                            var tp = tloTo.HitsoundTimingPoint.Copy();
                            tp.Offset = tloTo.Time;
                            timingPointsChanges.Add(new TimingPointsChange(tp, sampleset: true, index: doMutedIndex,
                                                                           volume: true));
                        }
                    }

                    // Apply the timingpoint changes
                    TimingPointsChange.ApplyChanges(beatmapTo.BeatmapTiming, timingPointsChanges);
                }

                // Save the file
                editorTo.SaveFile();

                // Export the sample schema if there are samples
                if (sampleSchema.Count > 0)
                {
                    string exportFolder = MainWindow.ExportPath;

                    DirectoryInfo di = new DirectoryInfo(exportFolder);
                    foreach (FileInfo file in di.GetFiles())
                    {
                        file.Delete();
                    }

                    HitsoundExporter.ExportSampleSchema(sampleSchema, exportFolder);

                    System.Diagnostics.Process.Start(exportFolder);
                }

                // Update progressbar
                if (worker != null && worker.WorkerReportsProgress)
                {
                    worker.ReportProgress(++mapsDone * 100 / paths.Length);
                }
            }

            return("Done!");
        }
Esempio n. 25
0
        private string Run_Program(AutoFailDetectorVm args, BackgroundWorker worker, DoWorkEventArgs _)
        {
            var reader  = EditorReaderStuff.GetFullEditorReaderOrNot();
            var editor  = EditorReaderStuff.GetNewestVersionOrNot(args.Paths[0], reader);
            var beatmap = editor.Beatmap;

            // Get approach time and radius of the 50 score hit window
            var ar = args.ApproachRateOverride == -1
                ? editor.Beatmap.Difficulty["ApproachRate"].DoubleValue
                : args.ApproachRateOverride;
            var approachTime = (int)Beatmap.GetApproachTime(ar);

            var od = args.OverallDifficultyOverride == -1
                ? editor.Beatmap.Difficulty["OverallDifficulty"].DoubleValue
                : args.OverallDifficultyOverride;
            var window50 = (int)Math.Ceiling(200 - 10 * od);

            // Start time and end time
            var mapStartTime = (int)beatmap.GetMapStartTime();
            var mapEndTime   = (int)beatmap.GetMapEndTime();
            var autoFailTime = (int)beatmap.GetAutoFailCheckTime();

            // Detect auto-fail
            var autoFailDetector = new Classes.Tools.AutoFailDetector(beatmap.HitObjects,
                                                                      mapStartTime, mapEndTime, autoFailTime,
                                                                      approachTime, window50, args.PhysicsUpdateLeniency);

            var autoFail = autoFailDetector.DetectAutoFail();

            if (worker != null && worker.WorkerReportsProgress)
            {
                worker.ReportProgress(33);
            }

            // Fix auto-fail
            if (args.GetAutoFailFix)
            {
                var placedFix = autoFailDetector.AutoFailFixDialogue(args.AutoPlaceFix);

                if (placedFix)
                {
                    editor.SaveFile();
                }
            }

            if (worker != null && worker.WorkerReportsProgress)
            {
                worker.ReportProgress(67);
            }

            // Set the timeline lists
            _unloadingObjects          = args.ShowUnloadingObjects ? autoFailDetector.UnloadingObjects : new List <double>();
            _potentialUnloadingObjects = args.ShowPotentialUnloadingObjects ? autoFailDetector.PotentialUnloadingObjects : new List <double>();
            _potentialDisruptors       = args.ShowPotentialDisruptors ? autoFailDetector.Disruptors : new List <double>();

            // Set end time for the timeline
            _endTimeMonitor = mapEndTime;

            // Complete progressbar
            if (worker != null && worker.WorkerReportsProgress)
            {
                worker.ReportProgress(100);
            }

            // Do stuff
            RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, false, args.Quick));

            return(autoFail ? $"{autoFailDetector.UnloadingObjects.Count} unloading objects detected and {autoFailDetector.PotentialUnloadingObjects.Count} potential unloading objects detected!" :
                   autoFailDetector.PotentialUnloadingObjects.Count > 0 ? $"No auto-fail, but {autoFailDetector.PotentialUnloadingObjects.Count} potential unloading objects detected." :
                   "No auto-fail detected.");
        }
Esempio n. 26
0
        public static void ExportHitsounds(List <HitsoundEvent> hitsounds, string baseBeatmap, string exportFolder, string exportMapName, GameMode exportGameMode, bool useGreenlines, bool useStoryboard)
        {
            var     editor  = EditorReaderStuff.GetNewestVersionOrNot(baseBeatmap);
            Beatmap beatmap = editor.Beatmap;

            if (useStoryboard)
            {
                beatmap.StoryboardSoundSamples.Clear();
                foreach (var h in hitsounds.Where(h => !string.IsNullOrEmpty(h.Filename)))
                {
                    beatmap.StoryboardSoundSamples.Add(new StoryboardSoundSample(h.Time, 0, h.Filename, h.Volume * 100));
                }
            }
            else
            {
                // Make new timing points
                // Add red lines
                List <TimingPoint>        timingPoints        = beatmap.BeatmapTiming.GetAllRedlines();
                List <TimingPointsChange> timingPointsChanges = timingPoints.Select(tp =>
                                                                                    new TimingPointsChange(tp, mpb: true, meter: true, inherited: true, omitFirstBarLine: true))
                                                                .ToList();

                // Add hitsound stuff
                // Replace all hitobjects with the hitsounds
                beatmap.HitObjects.Clear();
                foreach (HitsoundEvent h in hitsounds)
                {
                    if (useGreenlines)
                    {
                        TimingPoint tp = beatmap.BeatmapTiming.GetTimingPointAtTime(h.Time + 5).Copy();
                        tp.Offset      = h.Time;
                        tp.SampleIndex = h.CustomIndex;
                        h.CustomIndex  = 0; // Set it to default value because it gets handled by greenlines now
                        tp.Volume      = Math.Round(tp.Volume * h.Volume);
                        h.Volume       = 0; // Set it to default value because it gets handled by greenlines now
                        timingPointsChanges.Add(new TimingPointsChange(tp, index: true, volume: true));
                    }

                    beatmap.HitObjects.Add(new HitObject(h.Pos, h.Time, 5, h.GetHitsounds(), h.SampleSet, h.Additions,
                                                         h.CustomIndex, h.Volume * 100, h.Filename));
                }

                // Replace the old timingpoints
                beatmap.BeatmapTiming.TimingPoints.Clear();
                TimingPointsChange.ApplyChanges(beatmap.BeatmapTiming, timingPointsChanges);
            }

            // Change version to hitsounds
            beatmap.General["StackLeniency"] = new TValue("0.0");
            beatmap.General["Mode"]          = new TValue(((int)exportGameMode).ToInvariant());
            beatmap.Metadata["Version"]      = new TValue(exportMapName);

            if (exportGameMode == GameMode.Mania)
            {
                // Count the number of distinct X positions
                int numXPositions = new HashSet <double>(hitsounds.Select(h => h.Pos.X)).Count;
                int numKeys       = MathHelper.Clamp(numXPositions, 1, 18);

                beatmap.Difficulty["CircleSize"] = new TValue(numKeys.ToInvariant());
            }
            else
            {
                beatmap.Difficulty["CircleSize"] = new TValue("4");
            }

            // Save the file to the export folder
            editor.SaveFile(Path.Combine(exportFolder, beatmap.GetFileName()));
        }
Esempio n. 27
0
        private string Merge_Sliders(Arguments arg, BackgroundWorker worker)
        {
            var slidersMerged = 0;

            var editorRead = EditorReaderStuff.TryGetFullEditorReader(out var reader);

            foreach (var path in arg.Paths)
            {
                var editor = EditorReaderStuff.GetBeatmapEditor(path, reader, editorRead, out var selected, out var editorActuallyRead);

                if (arg.SelectionMode == 0 && !editorActuallyRead)
                {
                    return(EditorReaderStuff.SelectedObjectsReadFailText);
                }

                var beatmap       = editor.Beatmap;
                var markedObjects = arg.SelectionMode == 0 ? selected :
                                    arg.SelectionMode == 1 ? beatmap.GetBookmarkedObjects() :
                                    beatmap.HitObjects;

                var mergeLast = false;
                for (var i = 0; i < markedObjects.Count - 1; i++)
                {
                    var ho1 = markedObjects[i];
                    var ho2 = markedObjects[i + 1];
                    if (ho1.IsSlider && ho2.IsSlider && (ho1.CurvePoints.Last() - ho2.Pos).Length <= arg.Leniency)
                    {
                        var sp1 = BezierConverter.ConvertToBezier(ho1.SliderPath).ControlPoints;
                        var sp2 = BezierConverter.ConvertToBezier(ho2.SliderPath).ControlPoints;

                        double extraLength = 0;
                        switch (arg.ConnectionMode)
                        {
                        case ConnectionMode.Move:
                            Move(sp2, sp1.Last() - sp2.First());
                            break;

                        case ConnectionMode.Linear:
                            sp1.Add(sp1.Last());
                            sp1.Add(sp2.First());
                            extraLength = (ho1.CurvePoints.Last() - ho2.Pos).Length;
                            break;
                        }

                        var mergedAnchors = sp1.Concat(sp2).ToList();
                        mergedAnchors.Round();

                        var linearLinear = arg.LinearOnLinear && IsLinearBezier(sp1) && IsLinearBezier(sp2);
                        if (linearLinear)
                        {
                            for (var j = 0; j < mergedAnchors.Count - 1; j++)
                            {
                                if (mergedAnchors[j] != mergedAnchors[j + 1])
                                {
                                    continue;
                                }
                                mergedAnchors.RemoveAt(j);
                                j--;
                            }
                        }

                        var mergedPath = new SliderPath(linearLinear ? PathType.Linear : PathType.Bezier, mergedAnchors.ToArray(),
                                                        ho1.PixelLength + ho2.PixelLength + extraLength);
                        ho1.SliderPath = mergedPath;

                        beatmap.HitObjects.Remove(ho2);
                        markedObjects.Remove(ho2);
                        i--;

                        slidersMerged++;
                        if (!mergeLast)
                        {
                            slidersMerged++;
                        }
                        mergeLast = true;
                    }
                    else if (ho1.IsSlider && ho2.IsCircle && (ho1.CurvePoints.Last() - ho2.Pos).Length <= arg.Leniency)
                    {
                        var sp1 = BezierConverter.ConvertToBezier(ho1.SliderPath).ControlPoints;

                        sp1.Add(sp1.Last());
                        sp1.Add(ho2.Pos);
                        var extraLength = (ho1.CurvePoints.Last() - ho2.Pos).Length;

                        var mergedAnchors = sp1;
                        mergedAnchors.Round();

                        var linearLinear = arg.LinearOnLinear && IsLinearBezier(sp1);
                        if (linearLinear)
                        {
                            for (var j = 0; j < mergedAnchors.Count - 1; j++)
                            {
                                if (mergedAnchors[j] != mergedAnchors[j + 1])
                                {
                                    continue;
                                }
                                mergedAnchors.RemoveAt(j);
                                j--;
                            }
                        }

                        var mergedPath = new SliderPath(linearLinear ? PathType.Linear : PathType.Bezier, mergedAnchors.ToArray(), ho1.PixelLength + extraLength);
                        ho1.SliderPath = mergedPath;

                        beatmap.HitObjects.Remove(ho2);
                        markedObjects.Remove(ho2);
                        i--;

                        slidersMerged++;
                        if (!mergeLast)
                        {
                            slidersMerged++;
                        }
                        mergeLast = true;
                    }
                    else if (ho1.IsCircle && ho2.IsSlider && (ho1.Pos - ho2.Pos).Length <= arg.Leniency)
                    {
                        var sp2 = BezierConverter.ConvertToBezier(ho2.SliderPath).ControlPoints;

                        sp2.Insert(0, sp2.First());
                        sp2.Insert(0, ho1.Pos);
                        var extraLength = (ho1.Pos - ho2.Pos).Length;

                        var mergedAnchors = sp2;
                        mergedAnchors.Round();

                        var linearLinear = arg.LinearOnLinear && IsLinearBezier(sp2);
                        if (linearLinear)
                        {
                            for (var j = 0; j < mergedAnchors.Count - 1; j++)
                            {
                                if (mergedAnchors[j] != mergedAnchors[j + 1])
                                {
                                    continue;
                                }
                                mergedAnchors.RemoveAt(j);
                                j--;
                            }
                        }

                        var mergedPath = new SliderPath(linearLinear ? PathType.Linear : PathType.Bezier, mergedAnchors.ToArray(), ho2.PixelLength + extraLength);
                        ho2.SliderPath = mergedPath;

                        beatmap.HitObjects.Remove(ho1);
                        markedObjects.Remove(ho1);
                        i--;

                        slidersMerged++;
                        if (!mergeLast)
                        {
                            slidersMerged++;
                        }
                        mergeLast = true;
                    }
                    else if (ho1.IsCircle && ho2.IsCircle && (ho1.Pos - ho2.Pos).Length <= arg.Leniency)
                    {
                        var mergedAnchors = new List <Vector2> {
                            ho1.Pos, ho2.Pos
                        };

                        var mergedPath = new SliderPath(arg.LinearOnLinear ? PathType.Linear : PathType.Bezier, mergedAnchors.ToArray(), (ho1.Pos - ho2.Pos).Length);
                        ho1.SliderPath    = mergedPath;
                        ho1.IsCircle      = false;
                        ho1.IsSlider      = true;
                        ho1.Repeat        = 1;
                        ho1.EdgeHitsounds = new List <int> {
                            ho1.GetHitsounds(), ho2.GetHitsounds()
                        };
                        ho1.EdgeSampleSets = new List <SampleSet> {
                            ho1.SampleSet, ho2.SampleSet
                        };
                        ho1.EdgeAdditionSets = new List <SampleSet> {
                            ho1.AdditionSet, ho2.AdditionSet
                        };

                        beatmap.HitObjects.Remove(ho2);
                        markedObjects.Remove(ho2);
                        i--;

                        slidersMerged++;
                        if (!mergeLast)
                        {
                            slidersMerged++;
                        }
                        mergeLast = true;
                    }
                    else
                    {
                        mergeLast = false;
                    }

                    if (worker != null && worker.WorkerReportsProgress)
                    {
                        worker.ReportProgress(i / markedObjects.Count);
                    }
                }

                // Save the file
                editor.SaveFile();
            }

            // Complete progressbar
            if (worker != null && worker.WorkerReportsProgress)
            {
                worker.ReportProgress(100);
            }

            // Do stuff
            if (arg.Quick)
            {
                RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, editorRead));
            }

            // Make an accurate message
            var message = "";

            if (Math.Abs(slidersMerged) == 1)
            {
                message += "Successfully merged " + slidersMerged + " slider!";
            }
            else
            {
                message += "Successfully merged " + slidersMerged + " sliders!";
            }
            return(arg.Quick ? "" : message);
        }
Esempio n. 28
0
        private string Complete_Sliders(SliderCompletionatorVm arg, BackgroundWorker worker, DoWorkEventArgs _)
        {
            int slidersCompleted = 0;

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot(out var editorReaderException1);

            if (arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected && editorReaderException1 != null)
            {
                throw new Exception("Could not fetch selected hit objects.", editorReaderException1);
            }

            foreach (string path in arg.Paths)
            {
                var editor = EditorReaderStuff.GetNewestVersionOrNot(path, reader, out var selected, out var editorReaderException2);

                if (arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected && editorReaderException2 != null)
                {
                    throw new Exception("Could not fetch selected hit objects.", editorReaderException2);
                }

                Beatmap          beatmap       = editor.Beatmap;
                Timing           timing        = beatmap.BeatmapTiming;
                List <HitObject> markedObjects = arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Selected ? selected :
                                                 arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Bookmarked ? beatmap.GetBookmarkedObjects() :
                                                 arg.ImportModeSetting == SliderCompletionatorVm.ImportMode.Time ? beatmap.QueryTimeCode(arg.TimeCode).ToList() :
                                                 beatmap.HitObjects;

                for (int i = 0; i < markedObjects.Count; i++)
                {
                    HitObject ho = markedObjects[i];
                    if (ho.IsSlider)
                    {
                        double oldSpatialLength = ho.PixelLength;
                        double newSpatialLength = arg.SpatialLength != -1 ? ho.GetSliderPath(fullLength: true).Distance *arg.SpatialLength : oldSpatialLength;

                        double oldTemporalLength = timing.CalculateSliderTemporalLength(ho.Time, ho.PixelLength);
                        double newTemporalLength = arg.TemporalLength != -1 ? timing.GetMpBAtTime(ho.Time) * arg.TemporalLength : oldTemporalLength;

                        double oldSv = timing.GetSvAtTime(ho.Time);
                        double newSv = oldSv / ((newSpatialLength / oldSpatialLength) / (newTemporalLength / oldTemporalLength));

                        if (double.IsNaN(newSv))
                        {
                            throw new Exception("Encountered NaN slider velocity. Make sure none of the inputs are zero.");
                        }

                        ho.SliderVelocity = newSv;
                        ho.PixelLength    = newSpatialLength;

                        // Scale anchors to completion
                        if (arg.MoveAnchors)
                        {
                            ho.SetAllCurvePoints(SliderPathUtil.MoveAnchorsToLength(
                                                     ho.GetAllCurvePoints(), ho.SliderType, ho.PixelLength, out var pathType));
                            ho.SliderType = pathType;
                        }

                        slidersCompleted++;
                    }
                    if (worker != null && worker.WorkerReportsProgress)
                    {
                        worker.ReportProgress(i / markedObjects.Count);
                    }
                }

                // Reconstruct SliderVelocity
                List <TimingPointsChange> timingPointsChanges = new List <TimingPointsChange>();
                // Add Hitobject stuff
                foreach (HitObject ho in beatmap.HitObjects)
                {
                    if (ho.IsSlider) // SliderVelocity changes
                    {
                        TimingPoint tp = ho.TimingPoint.Copy();
                        tp.Offset = ho.Time;
                        tp.MpB    = ho.SliderVelocity;
                        timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true));
                    }
                }

                // Add the new SliderVelocity changes
                TimingPointsChange.ApplyChanges(timing, timingPointsChanges);

                // Save the file
                editor.SaveFile();
            }

            // Complete progressbar
            if (worker != null && worker.WorkerReportsProgress)
            {
                worker.ReportProgress(100);
            }

            // Do stuff
            if (arg.Quick)
            {
                RunFinished?.Invoke(this, new RunToolCompletedEventArgs(true, reader != null));
            }

            // Make an accurate message
            string message = "";

            if (Math.Abs(slidersCompleted) == 1)
            {
                message += "Successfully completed " + slidersCompleted + " slider!";
            }
            else
            {
                message += "Successfully completed " + slidersCompleted + " sliders!";
            }
            return(arg.Quick ? "" : message);
        }
 private static void QuickBetterSave()
 {
     EditorReaderStuff.BetterSave();
 }
        private static void SmartQuickRun()
        {
            try
            {
                if (!SettingsManager.Settings.SmartQuickRunEnabled)
                {
                    QuickRunCurrentTool(); return;
                }

                var reader = EditorReaderStuff.GetFullEditorReader();

                var       so   = reader.hitObjects.Count(o => o.IsSelected);
                IQuickRun tool = null;

                if (System.Windows.Application.Current.Dispatcher == null)
                {
                    return;
                }

                System.Windows.Application.Current.Dispatcher.Invoke(() => {
                    if (so == 0)
                    {
                        if (SettingsManager.Settings.NoneQuickRunTool == "<Current Tool>")
                        {
                            QuickRunCurrentTool(); return;
                        }
                        if (!(MainWindow.AppWindow.Views.GetView(SettingsManager.Settings.NoneQuickRunTool) is IQuickRun noneTool))
                        {
                            return;
                        }

                        tool = noneTool;
                    }
                    else if (so == 1)
                    {
                        if (SettingsManager.Settings.SingleQuickRunTool == "<Current Tool>")
                        {
                            QuickRunCurrentTool(); return;
                        }
                        if (!(MainWindow.AppWindow.Views.GetView(SettingsManager.Settings.SingleQuickRunTool) is IQuickRun singleTool))
                        {
                            return;
                        }

                        tool = singleTool;
                    }
                    else if (so > 1)
                    {
                        if (SettingsManager.Settings.MultipleQuickRunTool == "<Current Tool>")
                        {
                            QuickRunCurrentTool(); return;
                        }
                        if (!(MainWindow.AppWindow.Views.GetView(SettingsManager.Settings.MultipleQuickRunTool) is IQuickRun multiTool))
                        {
                            return;
                        }

                        tool = multiTool;
                    }

                    if (tool == null)
                    {
                        return;
                    }

                    tool.RunFinished -= Reload;
                    tool.RunFinished += Reload;
                    tool.QuickRun();
                });
            }
            catch (Exception ex)
            {
                ex.Show();
            }
        }