diff --git a/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs index 80f6ce717..645536528 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Beatmaps/Formats/KaraokeLegacyBeatmapDecoderTest.cs @@ -107,7 +107,7 @@ public void TestDecodeTranslate() Assert.IsTrue(translates != null); // Check translate count - Assert.AreEqual(translates.Count(), 2); + Assert.AreEqual(translates.Length, 2); // All lyric should have two translates Assert.AreEqual(lyrics[0].Translates.Count, 2); diff --git a/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricEditorScreen.cs b/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricEditorScreen.cs index 421f45a34..8d6a97d46 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricEditorScreen.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneLyricEditorScreen.cs @@ -9,6 +9,7 @@ using osu.Game.Overlays; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Karaoke.Beatmaps.Formats; +using osu.Game.Rulesets.Karaoke.Edit.Import; using osu.Game.Rulesets.Karaoke.Edit.LyricEditor; using osu.Game.Rulesets.Karaoke.Tests.Beatmaps; using osu.Game.Rulesets.Karaoke.Tests.Resources; @@ -28,6 +29,8 @@ public class TestSceneLyricEditorScreen : EditorClockTestScene private LyricEditorScreen screen; + private ImportManager importManager; + public TestSceneLyricEditorScreen() { // It's a tricky to let osu! to read karaoke testing beatmap @@ -54,10 +57,12 @@ private void load() base.Content.AddRange(new Drawable[] { Content, - dialogOverlay = new DialogOverlay() + dialogOverlay = new DialogOverlay(), + importManager = new ImportManager() }); Dependencies.Cache(dialogOverlay); + Dependencies.Cache(importManager); } [SetUp] diff --git a/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneManageLanguagesDialog.cs b/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneManageLanguagesDialog.cs index d3e06e35e..952fa69cc 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneManageLanguagesDialog.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Edit/TestSceneManageLanguagesDialog.cs @@ -8,6 +8,7 @@ using osu.Framework.Testing; using osu.Game.Overlays; using osu.Game.Rulesets.Karaoke.Beatmaps; +using osu.Game.Rulesets.Karaoke.Edit.Translate; using osu.Game.Rulesets.Karaoke.Edit.Translate.Components; using osu.Game.Rulesets.Karaoke.Tests.Beatmaps; using osu.Game.Screens.Edit; diff --git a/osu.Game.Rulesets.Karaoke.Tests/Mods/KaraokeModPerfectTestScene.cs b/osu.Game.Rulesets.Karaoke.Tests/Mods/KaraokeModPerfectTestScene.cs index 71e105d2f..2f5b763b9 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Mods/KaraokeModPerfectTestScene.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Mods/KaraokeModPerfectTestScene.cs @@ -10,7 +10,7 @@ public abstract class KaraokeModPerfectTestScene : ModPerfectTestScene { protected override Ruleset CreatePlayerRuleset() => new KaraokeRuleset(); - public KaraokeModPerfectTestScene(ModPerfect mod) + protected KaraokeModPerfectTestScene(ModPerfect mod) : base(mod) { } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs index ef530fcd5..77e835e5d 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs @@ -255,7 +255,7 @@ private void processTranslate(Beatmap beatmap, IEnumerable translateLine value = translate.Split('=').LastOrDefault() }).GroupBy(x => x.key, y => y.value).ToList(); - for (int i = 0; i < translates.Count(); i++) + for (int i = 0; i < translates.Count; i++) { var id = i + 1; var singleLanguage = translates[i]; @@ -263,7 +263,7 @@ private void processTranslate(Beatmap beatmap, IEnumerable translateLine var key = singleLanguage.Key; var values = singleLanguage.ToList(); - var size = Math.Min(lyrics.Count(), singleLanguage.Count()); + var size = Math.Min(lyrics.Count, singleLanguage.Count()); for (int j = 0; j < size; j++) { diff --git a/osu.Game.Rulesets.Karaoke/Edit/Import/ImportLyricDialog.cs b/osu.Game.Rulesets.Karaoke/Edit/Import/ImportLyricDialog.cs new file mode 100644 index 000000000..e31b3c618 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Import/ImportLyricDialog.cs @@ -0,0 +1,86 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; +using osu.Game.Overlays; +using osu.Game.Overlays.Dialog; +using System; +using System.IO; +using osu.Game.Rulesets.Karaoke.Graphics.Overlays.Dialog; + +namespace osu.Game.Rulesets.Karaoke.Edit.Import +{ + public class ImportLyricDialog : PopupDialog + { + [Resolved] + private ImportManager importManager { get; set; } + + [Resolved] + private DialogOverlay dialogOverlay { get; set; } + + public ImportLyricDialog(FileInfo info, Action resetAction = null) + { + BodyText = "Import lyric file will clean-up all exist lyric."; + + Icon = FontAwesome.Regular.TrashAlt; + HeaderText = @"Confirm import lyric file?"; + Buttons = new PopupDialogButton[] + { + new PopupDialogOkButton + { + Text = @"Yes. Go for it.", + Action = () => + { + var success = processImport(info); + resetAction?.Invoke(success); + } + }, + new PopupDialogCancelButton + { + Text = @"No! Abort mission!", + }, + }; + } + + private bool processImport(FileInfo info) + { + try + { + importManager.ImportLrcFile(info); + dialogOverlay.Push(new OkPopupDialog + { + Icon = FontAwesome.Regular.CheckCircle, + HeaderText = @"Import success", + BodyText = "Lyrics has been imported." + }); + return true; + } + catch (Exception ex) + { + switch (ex) + { + case FileNotFoundException fileNotFoundException: + dialogOverlay.Push(new OkPopupDialog + { + Icon = FontAwesome.Regular.QuestionCircle, + HeaderText = @"File not found", + BodyText = fileNotFoundException.Message, + }); + break; + + case FileLoadException loadException: + dialogOverlay.Push(new OkPopupDialog + { + Icon = FontAwesome.Regular.QuestionCircle, + HeaderText = @"File not found", + BodyText = loadException.Message, + }); + break; + } + + return false; + } + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Import/ImportManager.cs b/osu.Game.Rulesets.Karaoke/Edit/Import/ImportManager.cs new file mode 100644 index 000000000..8361e7d8d --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Import/ImportManager.cs @@ -0,0 +1,74 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Karaoke.Beatmaps.Formats; +using osu.Game.Screens.Edit; +using System.IO; +using System.Linq; + +namespace osu.Game.Rulesets.Karaoke.Edit.Import +{ + public class ImportManager : Component + { + public static string[] LyricFotmatExtensions { get; } = { ".lrc", ".kar" }; + public static string[] NicokaraSkinFotmatExtensions { get; } = { ".nkmproj" }; + + private const string backup_lrc_name = "backup.lrc"; + + [Resolved] + private EditorBeatmap editorBeatmap { get; set; } + + [Resolved] + private IBindable beatmap { get; set; } + + public void ImportLrcFile(FileInfo info) + { + if (!info.Exists) + throw new FileNotFoundException("Lyric file does not found!"); + + var isFormatMatch = LyricFotmatExtensions.Contains(info.Extension); + if (!isFormatMatch) + throw new FileLoadException("Only .lrc or .kar karaoke file is supported now"); + + var set = beatmap.Value.BeatmapSetInfo; + var oldFile = set.Files?.FirstOrDefault(f => f.Filename == backup_lrc_name); + + using (var stream = info.OpenRead()) + { + // todo : make a backup if has new lyric file. + /* + if (oldFile != null) + beatmaps.ReplaceFile(set, oldFile, stream, backup_lrc_name); + else + beatmaps.AddFile(set, stream, backup_lrc_name); + */ + + // Import and replace all the file. + using (var reader = new IO.LineBufferedReader(stream)) + { + var decoder = new LrcDecoder(); + var lrcBeatmap = decoder.Decode(reader); + + // todo : remove all notes and lyric + // or just clear all beatmap because not really sure is singer should be removed also? + + // then re-add the lyric. + } + } + } + + public void ImportNicokaraSkinFile(FileInfo info) + { + if (!info.Exists) + throw new FileNotFoundException("Nicokara file does not found!"); + + var isFormatMatch = NicokaraSkinFotmatExtensions.Contains(info.Extension); + if (isFormatMatch) + throw new FileLoadException("Nicokara's skin extension should be .nkmproj"); + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs index 56842c9b9..ee40d965a 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutManager.cs @@ -37,6 +37,7 @@ public class LayoutManager : Component private void load() { var layoutLookups = source.GetConfig>(KaraokeIndexLookup.Layout)?.Value; + foreach (var layoutLookup in layoutLookups) { var lookup = new KaraokeSkinLookup(KaraokeSkinConfiguration.LyricLayout, layoutLookup.Key); @@ -49,6 +50,7 @@ private void load() EditLayout.Value = Layouts.FirstOrDefault(); var skinLookups = source.GetConfig>(KaraokeIndexLookup.Style)?.Value; + foreach (var skinLookup in skinLookups) { PreviewFontSelections.Add(skinLookup.Key, skinLookup.Value); diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs index 0458f2b8a..40f29ad5f 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutPreview.cs @@ -72,7 +72,7 @@ private void load(LayoutManager manager) { manager.PreviewLyric.BindValueChanged(e => { - if(e.NewValue != null) + if (e.NewValue != null) Child = new PreviewDrawableLyric(e.NewValue); }, true); @@ -94,7 +94,7 @@ public class PreviewDrawableLyric : DrawableLyric private KaraokeLayout layout; public PreviewDrawableLyric(Lyric hitObject) - : base(hitObject) + : base(hitObject) { } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutScreen.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutScreen.cs index 89ecf394a..b6240726b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutScreen.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutScreen.cs @@ -23,7 +23,7 @@ public class LayoutScreen : EditorScreen protected readonly LayoutManager LayoutManager; public LayoutScreen() - : base(EditorScreenMode.SongSetup) + : base(EditorScreenMode.SongSetup) { ColourProvider = new OverlayColourProvider(OverlayColourScheme.Green); Content.Add(LayoutManager = new LayoutManager()); diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutSection.cs index 2b71a9a73..2c2611965 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutSection.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/LayoutSection.cs @@ -26,7 +26,7 @@ internal abstract class LayoutSection : Container protected abstract string Title { get; } - public LayoutSection() + protected LayoutSection() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs index 314714241..50eb8c14a 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Layout/PreviewSection.cs @@ -5,8 +5,6 @@ using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; -using osu.Framework.Graphics.UserInterface; -using osu.Game.Graphics.UserInterface; using osu.Game.IO; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Karaoke.Beatmaps.Formats; @@ -64,6 +62,7 @@ private void load(LayoutManager manager) Height = 9 }; break; + case PreviewRatio.LegacyScreen: manager.PreviewScreenRatio.Value = new DisplayRatio { @@ -91,44 +90,46 @@ private Lyric getLyricSampleBySelection(PreviewSample previewSample) { case PreviewSample.SampeSmall: return createDefaultLyric("@カラオケ", - new[] - { - "@Ruby1=カ,か", - "@Ruby2=ラ,ら", - "@Ruby3=オ,お", - "@Ruby4=ケ,け" - }, - new[] - { - "@Romaji1=カ,ka", - "@Romaji2=ラ,ra", - "@Romaji3=オ,o", - "@Romaji4=ケ,ke" - } - , "karaoke"); + new[] + { + "@Ruby1=カ,か", + "@Ruby2=ラ,ら", + "@Ruby3=オ,お", + "@Ruby4=ケ,け" + }, + new[] + { + "@Romaji1=カ,ka", + "@Romaji2=ラ,ra", + "@Romaji3=オ,o", + "@Romaji4=ケ,ke" + } + , "karaoke"); case PreviewSample.SampleMedium: return createDefaultLyric("@[00:18:58]た[00:18:81]だ[00:19:36]風[00:20:09]に[00:20:29]揺[00:20:49]ら[00:20:68]れ[00:20:89]て[00:20:93]", - new[] - { - "@Ruby1=風,かぜ", - "@Ruby2=揺,ゆ" - }, - new[] - { - "@Romaji1=た,ta", - "@Romaji2=だ,da", - "@Romaji3=風,kaze", - "@Romaji4=に,ni", - "@Romaji5=揺,yu", - "@Romaji6=ら,ra", - "@Romaji7=れ,re", - "@Romaji8=て,te" - } - , "karaoke"); + new[] + { + "@Ruby1=風,かぜ", + "@Ruby2=揺,ゆ" + }, + new[] + { + "@Romaji1=た,ta", + "@Romaji2=だ,da", + "@Romaji3=風,kaze", + "@Romaji4=に,ni", + "@Romaji5=揺,yu", + "@Romaji6=ら,ra", + "@Romaji7=れ,re", + "@Romaji8=て,te" + } + , "karaoke"); + case PreviewSample.SampleLarge: return createDefaultLyric("@灰色(いろ)(いろ)の景色(いろ)(いろ)さえ色づき始める", - Array.Empty(), Array.Empty(), "karaoke"); + Array.Empty(), Array.Empty(), "karaoke"); + default: return null; } @@ -209,7 +210,7 @@ private class StyleDropdown : SettingsDropdown> private class StyleDropdownControl : DropdownControl { protected override string GenerateItemText(KeyValuePair item) - => item.Value ?? $"Style{item.Key}"; + => item.Value ?? $"Style{item.Key}"; } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/ImportLyricDialog.cs b/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/ImportLyricDialog.cs deleted file mode 100644 index af8d6f1b8..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/ImportLyricDialog.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Graphics.Sprites; -using osu.Game.Overlays.Dialog; -using System; - -namespace osu.Game.Rulesets.Karaoke.Edit.LyricEditor -{ - public class ImportLyricDialog : PopupDialog - { - public ImportLyricDialog(Action resetAction) - { - BodyText = "Import lyric file will clean-up all exist lyric."; - - Icon = FontAwesome.Regular.TrashAlt; - HeaderText = @"Confirm import lyric file?"; - Buttons = new PopupDialogButton[] - { - new PopupDialogOkButton - { - Text = @"Yes. Go for it.", - Action = resetAction - }, - new PopupDialogCancelButton - { - Text = @"No! Abort mission!", - }, - }; - } - } -} diff --git a/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/LyricEditorScreen.cs b/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/LyricEditorScreen.cs index a33477500..be151ca91 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/LyricEditorScreen.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/LyricEditor/LyricEditorScreen.cs @@ -9,8 +9,7 @@ using osu.Game.Database; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays; -using osu.Game.Overlays.Dialog; -using osu.Game.Rulesets.Karaoke.Beatmaps.Formats; +using osu.Game.Rulesets.Karaoke.Edit.Import; using osu.Game.Rulesets.Karaoke.Edit.Timelines; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Objects; @@ -26,15 +25,11 @@ namespace osu.Game.Rulesets.Karaoke.Edit.LyricEditor { public class LyricEditorScreen : EditorScreenWithTimeline, ICanAcceptFiles { - private const string backup_lrc_name = "backup.lrc"; - private KaraokeLyricEditorSkin skin; private FillFlowContainer