From 5597711949c30a9699c4ab3957c0d98e6ff2212c Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sun, 30 Apr 2023 22:24:21 +0800 Subject: [PATCH 1/3] Apply file-scope namespace into the main project. --- .../BaseHitObjectPropertyChangeHandlerTest.cs | 2 +- .../ImportBeatmapChangeHandlerTest.cs | 2 +- .../Editor/Checks/BaseCheckTest.cs | 2 +- .../CheckBeatmapAvailableTranslatesTest.cs | 2 +- .../Editor/Checks/CheckLyricLanguageTest.cs | 2 +- .../Editor/Checks/CheckLyricRomajiTagTest.cs | 2 +- .../Editor/Checks/CheckLyricRubyTagTest.cs | 2 +- .../Editor/Checks/CheckLyricSingerTest.cs | 2 +- .../Editor/Checks/CheckLyricTextTest.cs | 2 +- .../Editor/Checks/CheckLyricTimeTagTest.cs | 2 +- .../Editor/Checks/CheckLyricTimeTest.cs | 2 +- .../Editor/Checks/CheckLyricTranslateTest.cs | 2 +- .../Editor/Checks/CheckNoteTextTest.cs | 2 +- .../Editor/Checks/HitObjectCheckTest.cs | 2 +- .../TimeTags/Ja/JaTimeTagGeneratorTest.cs | 2 +- .../Formats/KaraokeJsonBeatmapDecoder.cs | 63 +- .../Formats/KaraokeJsonBeatmapEncoder.cs | 15 +- .../Formats/KaraokeLegacyBeatmapDecoder.cs | 407 +++++----- .../Formats/KaraokeLegacyBeatmapEncoder.cs | 105 ++- .../Beatmaps/Formats/LrcDecoder.cs | 95 ++- .../Beatmaps/Formats/LrcEncoder.cs | 111 ++- .../Beatmaps/Formats/LyricTextEncoder.cs | 15 +- .../IKaraokeBeatmapResourcesProvider.cs | 9 +- .../Beatmaps/KaraokeBeatmap.cs | 101 ++- .../Beatmaps/KaraokeBeatmapConverter.cs | 47 +- .../Beatmaps/KaraokeBeatmapExtension.cs | 33 +- .../Beatmaps/KaraokeBeatmapProcessor.cs | 81 +- .../KaraokeBeatmapResourcesProvider.cs | 67 +- .../Beatmaps/Metadatas/Singer.cs | 163 ++-- .../Beatmaps/Metadatas/SingerState.cs | 97 ++- .../Beatmaps/Metadatas/Types/ISinger.cs | 11 +- .../Bindables/BindableClassWithCurrent.cs | 23 +- .../Bindables/BindableCultureInfo.cs | 65 +- .../Bindables/BindableFontUsage.cs | 117 ++- .../KaraokeRulesetConfigManager.cs | 277 ++++--- .../KaraokeRulesetEditCheckerConfigManager.cs | 35 +- .../KaraokeRulesetEditConfigManager.cs | 33 +- ...araokeRulesetEditGeneratorConfigManager.cs | 183 +++-- .../KaraokeRulesetLyricEditorConfigManager.cs | 131 ++-- .../Configuration/KaraokeSessionStatics.cs | 123 ++- .../Difficulty/KaraokeDifficultyAttributes.cs | 71 +- .../Difficulty/KaraokeDifficultyCalculator.cs | 129 ++-- .../KaraokePerformanceAttributes.cs | 31 +- .../KaraokePerformanceCalculator.cs | 187 +++-- .../KaraokeDifficultyHitObject.cs | 15 +- .../Difficulty/Skills/Strain.cs | 111 ++- .../Blueprints/KaraokeSelectionBlueprint.cs | 15 +- .../Lyrics/LyricSelectionBlueprint.cs | 11 +- .../Notes/Components/EditBodyPiece.cs | 29 +- .../Notes/NoteSelectionBlueprint.cs | 95 ++- .../BeatmapListPropertyChangeHandler.cs | 119 ++- .../Beatmaps/BeatmapLanguagesChangeHandler.cs | 37 +- .../Beatmaps/BeatmapSingersChangeHandler.cs | 155 ++-- .../IBeatmapLanguagesChangeHandler.cs | 15 +- .../Beatmaps/IBeatmapSingersChangeHandler.cs | 19 +- .../ChangeHandlers/HitObjectChangeHandler.cs | 237 +++--- .../HitObjectPropertyChangeHandler.cs | 41 +- .../ChangeHandlers/HitObjectsChangeHandler.cs | 7 +- .../IImportBeatmapChangeHandler.cs | 9 +- .../Edit/ChangeHandlers/ILockChangeHandler.cs | 11 +- .../ImportBeatmapChangeHandler.cs | 37 +- .../Edit/ChangeHandlers/LockChangeHandler.cs | 41 +- .../Lyrics/ILyricLanguageChangeHandler.cs | 9 +- .../Lyrics/ILyricListPropertyChangeHandler.cs | 15 +- .../Lyrics/ILyricPropertyChangeHandler.cs | 7 +- .../Lyrics/ILyricReferenceChangeHandler.cs | 15 +- .../Lyrics/ILyricRomajiTagsChangeHandler.cs | 7 +- .../Lyrics/ILyricRubyTagsChangeHandler.cs | 7 +- .../Lyrics/ILyricSingerChangeHandler.cs | 9 +- .../Lyrics/ILyricTextChangeHandler.cs | 11 +- .../Lyrics/ILyricTextTagsChangeHandler.cs | 13 +- .../Lyrics/ILyricTimeTagsChangeHandler.cs | 41 +- .../Lyrics/ILyricTranslateChangeHandler.cs | 9 +- .../Lyrics/ILyricsChangeHandler.cs | 23 +- .../Lyrics/LyricLanguageChangeHandler.cs | 67 +- .../Lyrics/LyricPropertyChangeHandler.cs | 171 +++-- .../Lyrics/LyricReferenceChangeHandler.cs | 151 ++-- .../Lyrics/LyricRomajiTagsChangeHandler.cs | 61 +- .../Lyrics/LyricRubyTagsChangeHandler.cs | 61 +- .../Lyrics/LyricSingerChangeHandler.cs | 91 ++- .../Lyrics/LyricTextChangeHandler.cs | 51 +- .../Lyrics/LyricTextTagsChangeHandler.cs | 185 +++-- .../Lyrics/LyricTimeTagsChangeHandler.cs | 425 ++++++----- .../Lyrics/LyricTranslateChangeHandler.cs | 43 +- .../Lyrics/LyricsChangeHandler.cs | 235 +++--- .../Notes/INotePropertyChangeHandler.cs | 15 +- .../Notes/INotesChangeHandler.cs | 13 +- .../Notes/NotePropertyChangeHandler.cs | 95 ++- .../Notes/NotesChangeHandler.cs | 73 +- .../Checks/CheckBeatmapAvailableTranslates.cs | 123 ++- .../Edit/Checks/CheckHitObjectProperty.cs | 25 +- .../Edit/Checks/CheckLyricLanguage.cs | 39 +- .../Edit/Checks/CheckLyricReferenceLyric.cs | 107 ++- .../Edit/Checks/CheckLyricRomajiTag.cs | 81 +- .../Edit/Checks/CheckLyricRubyTag.cs | 81 +- .../Edit/Checks/CheckLyricSinger.cs | 39 +- .../Edit/Checks/CheckLyricText.cs | 39 +- .../Edit/Checks/CheckLyricTextTag.cs | 67 +- .../Edit/Checks/CheckLyricTime.cs | 85 +-- .../Edit/Checks/CheckLyricTimeTag.cs | 169 ++-- .../Edit/Checks/CheckLyricTranslate.cs | 45 +- .../Edit/Checks/CheckNoteReferenceLyric.cs | 189 +++-- .../Edit/Checks/CheckNoteText.cs | 63 +- .../Edit/Checks/Issues/LyricIssue.cs | 19 +- .../Edit/Checks/Issues/LyricRomajiTagIssue.cs | 17 +- .../Edit/Checks/Issues/LyricRubyTagIssue.cs | 17 +- .../Edit/Checks/Issues/LyricTimeTagIssue.cs | 19 +- .../Edit/Checks/Issues/NoteIssue.cs | 17 +- .../Edit/Components/Containers/Section.cs | 57 +- .../ContextMenu/LyricLockContextMenu.cs | 29 +- .../ContextMenu/SingerContextMenu.cs | 53 +- .../Edit/Components/Cursor/LayoutToolTip.cs | 49 +- .../Edit/Components/Cursor/TimeTagTooltip.cs | 133 ++-- .../Edit/Components/Menus/EnumMenu.cs | 65 +- .../Components/Menus/KaraokeEditorMenu.cs | 19 +- .../Components/Menus/KaraokeSkinEditorMenu.cs | 19 +- .../Components/Menus/NoteEditorPreviewMenu.cs | 51 +- .../Sprites/DrawableLayoutPreview.cs | 177 +++-- .../Components/Sprites/DrawableTextIndex.cs | 31 +- .../UserInterfaceV2/NoteEditPopover.cs | 159 ++-- .../Edit/DrawableKaraokeEditorRuleset.cs | 59 +- .../Edit/EditorNotePlayfield.cs | 121 ++- .../Edit/Export/ExportLyricManager.cs | 223 +++--- .../Beatmaps/BeatmapPropertyDetector.cs | 23 +- .../Beatmaps/BeatmapPropertyGenerator.cs | 23 +- .../Edit/Generator/GeneratorConfig.cs | 7 +- .../Lyrics/Language/LanguageDetector.cs | 53 +- .../Lyrics/Language/LanguageDetectorConfig.cs | 11 +- .../Lyrics/LyricGeneratorSelector.cs | 77 +- .../Generator/Lyrics/LyricPropertyDetector.cs | 23 +- .../Lyrics/LyricPropertyGenerator.cs | 23 +- .../Generator/Lyrics/Notes/NoteGenerator.cs | 93 ++- .../Lyrics/Notes/NoteGeneratorConfig.cs | 7 +- .../ReferenceLyric/ReferenceLyricDetector.cs | 97 ++- .../ReferenceLyricDetectorConfig.cs | 11 +- .../RomajiTags/Ja/JaRomajiTagGenerator.cs | 149 ++-- .../Ja/JaRomajiTagGeneratorConfig.cs | 11 +- .../Lyrics/RomajiTags/RomajiTagGenerator.cs | 25 +- .../RomajiTags/RomajiTagGeneratorConfig.cs | 7 +- .../RomajiTags/RomajiTagGeneratorSelector.cs | 15 +- .../Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs | 107 ++- .../RubyTags/Ja/JaRubyTagGeneratorConfig.cs | 27 +- .../Lyrics/RubyTags/RubyTagGenerator.cs | 25 +- .../Lyrics/RubyTags/RubyTagGeneratorConfig.cs | 7 +- .../RubyTags/RubyTagGeneratorSelector.cs | 15 +- .../Lyrics/TimeTags/Ja/JaTimeTagGenerator.cs | 197 +++-- .../TimeTags/Ja/JaTimeTagGeneratorConfig.cs | 101 ++- .../Lyrics/TimeTags/TimeTagGenerator.cs | 67 +- .../Lyrics/TimeTags/TimeTagGeneratorConfig.cs | 63 +- .../TimeTags/TimeTagGeneratorSelector.cs | 17 +- .../Lyrics/TimeTags/Zh/ZhTimeTagGenerator.cs | 27 +- .../TimeTags/Zh/ZhTimeTagGeneratorConfig.cs | 7 +- .../Edit/KaraokeBeatmapVerifier.cs | 45 +- .../Edit/KaraokeBlueprintContainer.cs | 29 +- .../Edit/KaraokeEditorPlayfield.cs | 11 +- .../Edit/KaraokeHitObjectComposer.cs | 233 +++--- .../Edit/KaraokeSelectionHandler.cs | 181 +++-- .../Setup/Components/LabelledSingerList.cs | 27 +- .../Edit/Setup/Components/SingerDisplay.cs | 165 ++-- .../Edit/Setup/Components/SingerList.cs | 253 +++--- .../Edit/Setup/KaraokeSetupSection.cs | 77 +- .../Edit/Utils/EditorBeatmapUtils.cs | 25 +- .../Edit/Utils/HitObjectWritableUtils.cs | 305 ++++---- .../Edit/Utils/LockStateUtils.cs | 11 +- .../Edit/Utils/ValueChangedEventUtils.cs | 27 +- .../Utils/ZoomableScrollContainerUtils.cs | 11 +- .../Extensions/EnumerableExtensions.cs | 97 ++- .../Extensions/ListExtensions.cs | 15 +- .../Extensions/OsuGameExtensions.cs | 43 +- .../Extensions/RegexExtensions.cs | 15 +- .../TrickyCompositeDrawableExtension.cs | 33 +- .../Extensions/TypeExtensions.cs | 39 +- .../Graphics/Containers/MessageContainer.cs | 81 +- .../OrderRearrangeableListContainer.cs | 107 ++- .../Graphics/Cursor/BackgroundToolTip.cs | 77 +- .../Graphics/Cursor/LyricToolTip.cs | 33 +- .../Graphics/Cursor/SingerToolTip.cs | 223 +++--- .../Graphics/Overlays/Dialog/OkPopupDialog.cs | 21 +- .../Graphics/Shapes/CornerBackground.cs | 15 +- .../Graphics/Shapes/RightTriangle.cs | 145 ++-- .../Sprites/DrawableCircleSingerAvatar.cs | 45 +- .../Sprites/DrawableKaraokeSpriteText.cs | 177 +++-- .../Sprites/DrawableLyricSpriteText.cs | 57 +- .../Graphics/Sprites/DrawableSingerAvatar.cs | 75 +- .../Graphics/Sprites/KaraokeIcon.cs | 25 +- .../Graphics/UserInterface/CircleCheckbox.cs | 147 ++-- .../MicrophoneSoundVisualizer.cs | 627 ++++++++------- .../RearrangeableTextFlowListContainer.cs | 183 +++-- .../Graphics/UserInterface/SingerDisplay.cs | 213 +++--- .../Graphics/UserInterfaceV2/FontSelector.cs | 575 +++++++------- .../UserInterfaceV2/LabelledColourSelector.cs | 139 ++-- .../UserInterfaceV2/LabelledHueSelector.cs | 121 ++- .../UserInterfaceV2/LabelledImageSelector.cs | 15 +- .../LabelledRealTimeSliderBar.cs | 13 +- .../UserInterfaceV2/LanguageSelector.cs | 145 ++-- .../IO/Archives/CachedFontArchiveReader.cs | 85 +-- .../Converters/ColourConverter.cs | 27 +- .../Converters/CultureInfoConverter.cs | 29 +- .../Converters/DictionaryConverter.cs | 49 +- .../Converters/FontUsageConverter.cs | 99 ++- .../Converters/GenericTypeConverter.cs | 103 ++- .../Converters/KaraokeSkinElementConverter.cs | 51 +- .../Converters/LyricConverter.cs | 109 ++- .../ReferenceLyricPropertyConfigConverter.cs | 17 +- .../Converters/RomajiTagConverter.cs | 55 +- .../Converters/RomajiTagsConverter.cs | 11 +- .../Converters/RubyTagConverter.cs | 57 +- .../Converters/RubyTagsConverter.cs | 11 +- .../Converters/ShaderConverter.cs | 49 +- .../Converters/SortableJsonConverter.cs | 41 +- .../Converters/TimeTagConverter.cs | 51 +- .../Converters/TimeTagsConverter.cs | 11 +- .../Serialization/Converters/ToneConverter.cs | 37 +- .../Converters/TranslatesConverter.cs | 7 +- .../KaraokeJsonSerializableExtensions.cs | 41 +- .../SkinJsonSerializableExtensions.cs | 25 +- .../WritablePropertiesOnlyResolver.cs | 21 +- .../IO/Stores/FntGlyphStore.cs | 15 +- .../IO/Stores/KaraokeLocalFontStore.cs | 95 ++- .../IO/Stores/TtfGlyphStore.cs | 269 ++++--- .../Judgements/KaraokeJudgement.cs | 7 +- .../Judgements/KaraokeJudgementResult.cs | 11 +- .../Judgements/KaraokeLyricJudgement.cs | 11 +- .../Judgements/KaraokeNoteJudgement.cs | 35 +- .../KaraokeControlInputManager.cs | 85 +-- .../KaraokeEditInputManager.cs | 137 ++-- .../KaraokeInputManager.cs | 201 +++-- osu.Game.Rulesets.Karaoke/KaraokeRuleset.cs | 489 ++++++------ .../KaraokeSkinComponentLookup.cs | 17 +- .../KaraokeSkinComponents.cs | 17 +- .../Localisation/ChangelogStrings.cs | 19 +- .../Localisation/CommonStrings.cs | 19 +- .../KaraokeSettingsSubsectionStrings.cs | 171 +++-- .../Mods/IApplicableToMicrophone.cs | 9 +- .../Mods/IApplicableToSettingHUDOverlay.cs | 17 +- .../Mods/KaraokeModAutoplay.cs | 51 +- .../Mods/KaraokeModAutoplayBySinger.cs | 49 +- .../Mods/KaraokeModDisableNote.cs | 29 +- .../Mods/KaraokeModFlashlight.cs | 165 ++-- .../Mods/KaraokeModHiddenNote.cs | 99 ++- .../Mods/KaraokeModNoFail.cs | 7 +- .../Mods/KaraokeModPerfect.cs | 7 +- .../Mods/KaraokeModPractice.cs | 59 +- .../Mods/KaraokeModSnow.cs | 187 +++-- .../Mods/KaraokeModSuddenDeath.cs | 7 +- .../Mods/KaraokeModWindowsUpdate.cs | 149 ++-- osu.Game.Rulesets.Karaoke/Objects/BarLine.cs | 19 +- .../Objects/Drawables/DrawableBarLine.cs | 197 +++-- .../Drawables/DrawableKaraokeHitObject.cs | 59 +- .../DrawableKaraokeScrollingHitObject.cs | 145 ++-- .../Objects/Drawables/DrawableLyric.cs | 325 ++++---- .../Objects/Drawables/DrawableNote.cs | 291 ++++--- .../Objects/KaraokeHitObject.cs | 11 +- .../Objects/LegacyProperties.cs | 13 +- osu.Game.Rulesets.Karaoke/Objects/Lyric.cs | 329 ++++---- .../Objects/Lyric_Binding.cs | 507 ++++++------ osu.Game.Rulesets.Karaoke/Objects/Note.cs | 211 +++-- .../IReferenceLyricPropertyConfig.cs | 11 +- .../Properties/ReferenceLyricConfig.cs | 29 +- .../Objects/Properties/SyncLyricConfig.cs | 89 ++- .../Objects/RomajiTag.cs | 99 ++- osu.Game.Rulesets.Karaoke/Objects/RubyTag.cs | 99 ++- osu.Game.Rulesets.Karaoke/Objects/TimeTag.cs | 73 +- osu.Game.Rulesets.Karaoke/Objects/Title.cs | 21 +- .../Objects/TitlePart.cs | 13 +- osu.Game.Rulesets.Karaoke/Objects/Tone.cs | 119 ++- .../Objects/Types/IHasLock.cs | 27 +- .../Objects/Types/IHasOrder.cs | 9 +- .../Objects/Types/IHasPrimaryKey.cs | 9 +- .../Objects/Types/IHasSingers.cs | 9 +- .../Objects/Types/IHasText.cs | 9 +- .../Objects/Types/ITextTag.cs | 27 +- .../Requests/Responses/APIChangelogBuild.cs | 127 ++-- .../Requests/Responses/APIChangelogSidebar.cs | 11 +- .../Changelog/ChangeLogMarkdownContainer.cs | 255 ++++--- .../Overlays/Changelog/ChangelogBuild.cs | 123 ++- .../Overlays/Changelog/ChangelogContent.cs | 27 +- .../Overlays/Changelog/ChangelogHeader.cs | 77 +- .../Overlays/Changelog/ChangelogListing.cs | 85 +-- .../Changelog/ChangelogSingleBuild.cs | 133 ++-- .../Changelog/Sidebar/ChangelogSection.cs | 185 +++-- .../Changelog/Sidebar/ChangelogSidebar.cs | 159 ++-- .../Overlays/Changelog/Sidebar/YearsPanel.cs | 155 ++-- .../Overlays/KaraokeChangelogOverlay.cs | 365 +++++---- .../Replays/KaraokeAutoGenerator.cs | 51 +- .../Replays/KaraokeAutoGeneratorBySinger.cs | 133 ++-- .../KaraokeFramedReplayInputHandler.cs | 37 +- .../Replays/KaraokeReplayFrame.cs | 79 +- .../Scoring/KaraokeHitWindows.cs | 7 +- .../Scoring/KaraokeLyricHitWindows.cs | 27 +- .../Scoring/KaraokeNoteHitWindows.cs | 31 +- .../Scoring/KaraokeScoreProcessor.cs | 11 +- .../Beatmaps/BeatmapEditorRoundedScreen.cs | 69 +- .../Edit/Beatmaps/BeatmapEditorScreen.cs | 39 +- .../Menus/AutoFocusToEditLyricMenu.cs | 103 ++- .../Components/Menus/GeneratorConfigMenu.cs | 11 +- .../Components/Menus/ImportLyricMenu.cs | 23 +- .../Components/Menus/LockStateMenu.cs | 21 +- .../Components/Menus/LyricEditorModeMenu.cs | 37 +- .../Menus/LyricEditorPreferLayoutMenu.cs | 11 +- .../Menus/LyricEditorTextSizeMenu.cs | 59 +- .../LanguageSelectorPopover.cs | 33 +- .../UserInterfaceV2/LyricSelector.cs | 169 ++-- .../Screens/Edit/Beatmaps/ILyricsProvider.cs | 9 +- .../Edit/Beatmaps/KaraokeBeatmapEditor.cs | 159 ++-- .../KaraokeBeatmapEditorScreenMode.cs | 23 +- .../Lyrics/BindableBlueprintContainer.cs | 145 ++-- .../Algorithms/CaretPositionAlgorithm.cs | 113 ++- .../ClickingCaretPositionAlgorithm.cs | 75 +- .../CuttingCaretPositionAlgorithm.cs | 19 +- .../Algorithms/ICaretPositionAlgorithm.cs | 17 +- .../IIndexCaretPositionAlgorithm.cs | 17 +- .../Algorithms/IndexCaretPositionAlgorithm.cs | 85 +-- .../Algorithms/MovingTimeTagCaretMode.cs | 31 +- .../NavigateCaretPositionAlgorithm.cs | 87 ++- .../Algorithms/TextCaretPositionAlgorithm.cs | 193 +++-- .../TimeTagCaretPositionAlgorithm.cs | 259 ++++--- .../TimeTagIndexCaretPositionAlgorithm.cs | 249 +++--- .../TypingCaretPositionAlgorithm.cs | 19 +- .../Lyrics/CaretPosition/CaretGenerateType.cs | 11 +- .../CaretPosition/ClickingCaretPosition.cs | 19 +- .../CaretPosition/CuttingCaretPosition.cs | 23 +- .../Lyrics/CaretPosition/ICaretPosition.cs | 11 +- .../CaretPosition/IIndexCaretPosition.cs | 7 +- .../CaretPosition/ITextTagCaretPosition.cs | 7 +- .../CaretPosition/NavigateCaretPosition.cs | 19 +- .../CaretPosition/TimeTagCaretPosition.cs | 23 +- .../TimeTagIndexCaretPosition.cs | 23 +- .../CaretPosition/TypingCaretPosition.cs | 23 +- .../Edit/Beatmaps/Lyrics/ClipboardToast.cs | 43 +- .../Lyrics/Components/Lyrics/BaseLayer.cs | 25 +- .../Components/Lyrics/BlueprintLayer.cs | 85 +-- .../Blueprints/RomajiBlueprintContainer.cs | 69 +- .../Blueprints/RomajiTagSelectionBlueprint.cs | 53 +- .../Blueprints/RubyBlueprintContainer.cs | 69 +- .../Blueprints/RubyTagSelectionBlueprint.cs | 53 +- .../Blueprints/TextTagBlueprintContainer.cs | 199 +++-- .../Blueprints/TextTagSelectionBlueprint.cs | 137 ++-- .../Blueprints/TimeTagBlueprintContainer.cs | 83 +- .../Blueprints/TimeTagSelectionBlueprint.cs | 61 +- .../Lyrics/Components/Lyrics/CaretLayer.cs | 143 ++-- .../Components/Lyrics/Carets/DrawableCaret.cs | 59 +- .../Lyrics/Carets/DrawableCaretType.cs | 11 +- .../Lyrics/Carets/DrawableLyricInputCaret.cs | 297 ++++---- .../Carets/DrawableLyricSplitterCaret.cs | 141 ++-- .../Lyrics/Carets/DrawableLyricTextCaret.cs | 31 +- .../Lyrics/Carets/DrawableTimeTagEditCaret.cs | 63 +- .../Carets/DrawableTimeTagRecordCaret.cs | 79 +- .../Lyrics/Components/DrawableTimeTag.cs | 59 +- .../Lyrics/Components/Lyrics/EditableLyric.cs | 73 +- .../Components/Lyrics/IEditableLyricState.cs | 9 +- .../Lyrics/InteractableKaraokeSpriteText.cs | 293 ++++--- .../Components/Lyrics/InteractableLyric.cs | 239 +++--- .../Lyrics/Components/Lyrics/LyricLayer.cs | 35 +- .../Lyrics/Components/Lyrics/TimeTagLayer.cs | 55 +- .../Lyrics/Components/Lyrics/ViewOnlyLyric.cs | 23 +- .../BottomEditor/AdjustTimeTagBottomEditor.cs | 21 +- .../AdjustTimeTagBlueprintContainer.cs | 227 +++--- .../AdjustTimeTagScrollContainer.cs | 123 ++- .../AdjustTimeTagSelectionBlueprint.cs | 243 +++--- .../AdjustTimeTags/CurrentTimeMarker.cs | 73 +- .../TimeTagOrderedSelectionContainer.cs | 61 +- .../Compose/BottomEditor/BaseBottomEditor.cs | 83 +- .../Compose/BottomEditor/NoteBottomEditor.cs | 21 +- .../Compose/BottomEditor/Notes/NoteEditor.cs | 189 +++-- .../Notes/NoteEditorBlueprintContainer.cs | 41 +- .../Notes/NoteEditorSelectionBlueprint.cs | 123 ++- .../RecordingTimeTagBottomEditor.cs | 21 +- .../RecordingTimeTags/CentreMarker.cs | 41 +- .../RecordingTimeTags/RecordingTimeTagPart.cs | 315 ++++---- .../RecordingTimeTagScrollContainer.cs | 281 ++++--- .../BottomEditor/TimeTagScrollContainer.cs | 223 +++--- .../Beatmaps/Lyrics/Compose/LyricComposer.cs | 533 +++++++------ .../Beatmaps/Lyrics/Compose/LyricEditor.cs | 71 +- .../Edit/Beatmaps/Lyrics/Compose/Panel.cs | 197 +++-- .../Beatmaps/Lyrics/Compose/PanelDirection.cs | 11 +- .../Lyrics/Compose/Panels/InvalidPanel.cs | 23 +- .../Lyrics/Compose/Panels/PropertyPanel.cs | 19 +- .../Lyrics/Compose/SpecialActionToolbar.cs | 227 +++--- .../Lyrics/Compose/Toolbar/ActionButton.cs | 45 +- .../Carets/MoveToCaretPositionButton.cs | 47 +- .../Toolbar/Carets/MoveToFirstIndexButton.cs | 17 +- .../Toolbar/Carets/MoveToLastIndexButton.cs | 17 +- .../Toolbar/Carets/MoveToNextIndexButton.cs | 17 +- .../Toolbar/Carets/MoveToNextLyricButton.cs | 17 +- .../Carets/MoveToPreviousIndexButton.cs | 17 +- .../Carets/MoveToPreviousLyricButton.cs | 17 +- .../Lyrics/Compose/Toolbar/KeyActionButton.cs | 33 +- .../Toolbar/LyricEditorConfigButton.cs | 33 +- .../Panels/ToggleInvalidInfoPanelButton.cs | 11 +- .../Panels/TogglePropertyPanelButton.cs | 11 +- .../Toolbar/Playback/PlaybackSwitchButton.cs | 145 ++-- .../Lyrics/Compose/Toolbar/Separator.cs | 37 +- .../TimeTags/ClearAllTimeTagTimeButton.cs | 23 +- .../TimeTags/ClearTimeTagTimeButton.cs | 37 +- .../Toolbar/TimeTags/CreateTimeTagButton.cs | 37 +- .../Toolbar/TimeTags/RemoveTimeTagButton.cs | 37 +- .../Toolbar/TimeTags/SetTimeTagTimeButton.cs | 45 +- .../Lyrics/Compose/Toolbar/ToggleButton.cs | 47 +- .../Lyrics/Compose/Toolbar/ToolbarButton.cs | 83 +- .../Toolbar/View/AdjustFontSizeButton.cs | 117 ++- .../Edit/Beatmaps/Lyrics/DeleteLyricDialog.cs | 37 +- .../Edit/Beatmaps/Lyrics/IIssueNavigator.cs | 9 +- .../Beatmaps/Lyrics/ILyricEditorClipboard.cs | 13 +- .../Edit/Beatmaps/Lyrics/ILyricEditorState.cs | 41 +- .../Edit/Beatmaps/Lyrics/IssueNavigator.cs | 177 +++-- .../Edit/Beatmaps/Lyrics/LyricEditor.cs | 719 +++++++++--------- .../Beatmaps/Lyrics/LyricEditorClipboard.cs | 607 ++++++++------- .../Lyrics/LyricEditorColourProvider.cs | 97 ++- .../Edit/Beatmaps/Lyrics/LyricEditorLayout.cs | 13 +- .../Edit/Beatmaps/Lyrics/LyricEditorMode.cs | 99 ++- .../Edit/Beatmaps/Lyrics/LyricEditorScreen.cs | 213 +++--- .../Edit/Beatmaps/Lyrics/LyricEditorSkin.cs | 127 ++-- .../Lyrics/LyricList/ApplySelectingArea.cs | 347 +++++---- .../Lyrics/LyricList/BaseLyricList.cs | 185 +++-- .../Lyrics/LyricList/DetailLyricList.cs | 71 +- .../LyricList/DrawableDetailLyricList.cs | 37 +- .../LyricList/DrawableDetailLyricListItem.cs | 17 +- .../Lyrics/LyricList/DrawableLyricList.cs | 125 ++- .../Lyrics/LyricList/DrawableLyricListItem.cs | 53 +- .../LyricList/DrawablePreviewLyricList.cs | 71 +- .../LyricList/DrawablePreviewLyricListItem.cs | 17 +- .../Lyrics/LyricList/PreviewLyricList.cs | 35 +- .../LyricList/Rows/CreateNewLyricDetailRow.cs | 57 +- .../Rows/CreateNewLyricPreviewRow.cs | 55 +- .../Lyrics/LyricList/Rows/DetailRow.cs | 77 +- .../LyricList/Rows/EditLyricDetailRow.cs | 45 +- .../LyricList/Rows/EditLyricPreviewRow.cs | 45 +- .../LyricList/Rows/Info/Badge/LanguageInfo.cs | 63 +- .../Rows/Info/Badge/ReferenceLyricInfo.cs | 71 +- .../LyricList/Rows/Info/Badge/SingerInfo.cs | 45 +- .../LyricList/Rows/Info/Badge/SubInfo.cs | 85 +-- .../LyricList/Rows/Info/Badge/TimeTagInfo.cs | 41 +- .../Rows/Info/FixedInfo/InvalidInfo.cs | 131 ++-- .../LyricList/Rows/Info/FixedInfo/LockInfo.cs | 117 ++- .../Rows/Info/FixedInfo/OrderInfo.cs | 31 +- .../Lyrics/LyricList/Rows/Info/InfoControl.cs | 369 +++++---- .../Lyrics/LyricList/Rows/PreviewRow.cs | 83 +- .../Beatmaps/Lyrics/LyricList/Rows/Row.cs | 363 +++++---- .../Beatmaps/Lyrics/OsuColourExtensions.cs | 27 +- .../Components/BlockSectionWrapper.cs | 197 +++-- ...LyricEditorDescriptionTextFlowContainer.cs | 19 +- .../Components/Markdown/SwitchMoteText.cs | 61 +- .../LabelledObjectFieldSwitchButton.cs | 171 +++-- .../Settings/LabelledObjectFieldTextBox.cs | 183 +++-- .../Language/AssignLanguageSubsection.cs | 75 +- .../LanguageAutoGenerateSubsection.cs | 41 +- .../Language/LanguageEditModeSection.cs | 81 +- .../Language/LanguageEditModeSpecialAction.cs | 11 +- .../Settings/Language/LanguageIssueSection.cs | 87 ++- .../LanguageSwitchSpecialActionSection.cs | 45 +- .../Lyrics/Settings/LanguageSettings.cs | 55 +- .../LyricEditorAutoGenerateSubsection.cs | 43 +- .../Settings/LyricEditorEditModeSection.cs | 65 +- .../Settings/LyricEditorIssueSection.cs | 81 +- .../Lyrics/Settings/LyricEditorSettings.cs | 21 +- .../Lyrics/Settings/LyricPropertySection.cs | 161 ++-- .../Beatmaps/Lyrics/Settings/NoteSettings.cs | 69 +- .../Notes/NoteAutoGenerateSubsection.cs | 51 +- .../Settings/Notes/NoteClearSubsection.cs | 31 +- .../Settings/Notes/NoteConfigSection.cs | 33 +- .../Settings/Notes/NoteEditModeSection.cs | 89 ++- .../Notes/NoteEditModeSpecialAction.cs | 13 +- .../Settings/Notes/NoteEditPropertyMode.cs | 13 +- .../Notes/NoteEditPropertyModeSection.cs | 29 +- .../Settings/Notes/NoteEditPropertySection.cs | 247 +++--- .../Lyrics/Settings/Notes/NoteIssueSection.cs | 89 ++- .../Notes/NoteSwitchSpecialActionSection.cs | 51 +- .../LabelledReferenceLyricSelector.cs | 217 +++--- .../ReferenceLyricAutoGenerateSection.cs | 37 +- .../Reference/ReferenceLyricConfigSection.cs | 247 +++--- .../Reference/ReferenceLyricSection.cs | 85 +-- .../Lyrics/Settings/ReferenceSettings.cs | 59 +- .../Lyrics/Settings/RomajiTagSettings.cs | 57 +- .../Components/CreateNewTextTagButton.cs | 207 +++-- .../Components/LabelledTextTagTextBox.cs | 421 +++++----- .../RomajiTagAutoGenerateSection.cs | 37 +- .../RubyRomaji/RomajiTagEditModeSection.cs | 121 ++- .../RubyRomaji/RomajiTagEditSection.cs | 131 ++-- .../RubyRomaji/RomajiTagIssueSection.cs | 23 +- .../RubyRomaji/RubyTagAutoGenerateSection.cs | 37 +- .../RubyRomaji/RubyTagEditModeSection.cs | 121 ++- .../Settings/RubyRomaji/RubyTagEditSection.cs | 131 ++-- .../RubyRomaji/RubyTagIssueSection.cs | 23 +- .../RubyRomaji/TextTagAutoGenerateSection.cs | 33 +- .../RubyRomaji/TextTagEditModeSection.cs | 15 +- .../Settings/RubyRomaji/TextTagEditSection.cs | 67 +- .../RubyRomaji/TextTagIssueSection.cs | 87 ++- .../Lyrics/Settings/RubyTagSettings.cs | 57 +- .../Lyrics/Settings/SelectLyricButton.cs | 123 ++- .../Lyrics/Settings/SettingsDirection.cs | 23 +- .../Lyrics/Settings/SingerSettings.cs | 19 +- .../Settings/Singers/SingerEditSection.cs | 217 +++--- .../Lyrics/Settings/SpecialActionSection.cs | 71 +- .../Lyrics/Settings/TextTagSettings.cs | 15 +- .../Texting/TextingDeleteSubsection.cs | 21 +- .../Texting/TextingEditModeSection.cs | 89 ++- .../Texting/TextingEditModeSpecialAction.cs | 13 +- .../TextingSwitchSpecialActionSection.cs | 53 +- .../Lyrics/Settings/TextingSettings.cs | 65 +- .../Lyrics/Settings/TimeTagSettings.cs | 73 +- .../Components/LabelledOpacityAdjustment.cs | 123 ++- .../TimeTags/CreateTimeTagActionReceiver.cs | 141 ++-- .../TimeTags/RecordTimeTagActionReceiver.cs | 67 +- .../TimeTags/TimeTagAdjustConfigSection.cs | 57 +- .../TimeTags/TimeTagAutoGenerateSection.cs | 65 +- .../TimeTags/TimeTagCreateConfigSection.cs | 37 +- .../TimeTags/TimeTagCreateConfigSubsection.cs | 257 ++++--- .../TimeTags/TimeTagEditModeSection.cs | 105 ++- .../Settings/TimeTags/TimeTagIssueSection.cs | 119 ++- .../TimeTags/TimeTagRecordingConfigSection.cs | 93 ++- .../Lyrics/States/CreateTimeTagEditMode.cs | 11 +- .../Lyrics/States/ILyricCaretState.cs | 37 +- .../Lyrics/States/ILyricSelectionState.cs | 29 +- .../Beatmaps/Lyrics/States/LyricCaretState.cs | 533 +++++++------ .../States/LyricEditorSelectingAction.cs | 11 +- .../Lyrics/States/LyricSelectionState.cs | 153 ++-- .../Lyrics/States/Modes/EditNoteModeState.cs | 49 +- .../States/Modes/EditRomajiModeState.cs | 27 +- .../Lyrics/States/Modes/EditRubyModeState.cs | 27 +- .../Lyrics/States/Modes/IEditNoteModeState.cs | 9 +- .../States/Modes/IEditRomajiModeState.cs | 7 +- .../Lyrics/States/Modes/IEditRubyModeState.cs | 7 +- .../States/Modes/IHasBlueprintSelection.cs | 11 +- .../Lyrics/States/Modes/IHasEditModeState.cs | 13 +- .../Lyrics/States/Modes/IHasSpecialAction.cs | 9 +- .../Lyrics/States/Modes/ILanguageModeState.cs | 7 +- .../Lyrics/States/Modes/ITextingModeState.cs | 7 +- .../Lyrics/States/Modes/ITimeTagModeState.cs | 11 +- .../Lyrics/States/Modes/LanguageEditMode.cs | 11 +- .../Lyrics/States/Modes/LanguageModeState.cs | 17 +- .../Modes/ModeStateWithBlueprintContainer.cs | 139 ++-- .../Lyrics/States/Modes/NoteEditMode.cs | 13 +- .../Lyrics/States/Modes/RomajiTagEditMode.cs | 13 +- .../Lyrics/States/Modes/RubyTagEditMode.cs | 13 +- .../Lyrics/States/Modes/TextingEditMode.cs | 13 +- .../Lyrics/States/Modes/TextingModeState.cs | 17 +- .../Lyrics/States/Modes/TimeTagEditMode.cs | 13 +- .../Lyrics/States/Modes/TimeTagModeState.cs | 51 +- .../Lyrics/States/MovingCaretAction.cs | 23 +- .../Screens/Edit/Beatmaps/LyricsProvider.cs | 77 +- .../Beatmaps/Singers/DeleteSingerDialog.cs | 37 +- .../Beatmaps/Singers/Detail/AvatarSection.cs | 27 +- .../Singers/Detail/EditSingerSection.cs | 7 +- .../Singers/Detail/MetadataSection.cs | 65 +- .../Singers/Detail/SingerEditPopover.cs | 37 +- .../ISingerScreenScrollingInfoProvider.cs | 11 +- .../Singers/Rows/Components/SingerAvatar.cs | 127 ++-- .../LyricTimelineSelectionBlueprint.cs | 41 +- .../SingerLyricEditorBlueprintContainer.cs | 81 +- .../Timeline/SingerLyricTimeline.cs | 91 ++- .../Rows/CreateNewLyricPlacementRow.cs | 49 +- .../Singers/Rows/DefaultLyricPlacementRow.cs | 101 ++- .../Singers/Rows/LyricPlacementRow.cs | 81 +- .../Singers/Rows/SingerLyricPlacementRow.cs | 243 +++--- .../Beatmaps/Singers/SingerEditSection.cs | 61 +- .../Singers/SingerRearrangeableList.cs | 53 +- .../Singers/SingerRearrangeableListItem.cs | 85 +-- .../Edit/Beatmaps/Singers/SingerScreen.cs | 131 ++-- .../Components/CreateNewLanguageButton.cs | 53 +- .../Translate/Components/LanguageDropdown.cs | 11 +- .../Components/LyricTranslateTextBox.cs | 103 ++- .../Components/RemoveLanguageButton.cs | 49 +- .../Components/TranslateLyricSpriteText.cs | 19 +- .../Translate/DeleteLanguagePopupDialog.cs | 37 +- .../Translate/ITranslateInfoProvider.cs | 9 +- .../Translate/TranslateEditSection.cs | 365 +++++---- .../Beatmaps/Translate/TranslateScreen.cs | 73 +- .../Containers/BindableScrollContainer.cs | 141 ++-- .../Edit/Components/Issues/IssuesToolTip.cs | 73 +- .../Components/Markdown/DescriptionFormat.cs | 27 +- .../Edit/Components/Markdown/InputKeyText.cs | 173 +++-- .../Menus/GenericScreenSelectionTabControl.cs | 105 ++- .../UserInterface/DeleteIconButton.cs | 49 +- .../Screens/Edit/EditorSection.cs | 19 +- .../Screens/Edit/GenericEditor.cs | 321 ++++---- .../Screens/Edit/GenericEditorScreen.cs | 43 +- .../AssignLanguageNavigation.cs | 65 +- .../AssignLanguageStepScreen.cs | 97 ++- .../UseLanguageDetectorPopupDialog.cs | 37 +- .../DragFile/Components/DrawableDragFile.cs | 159 ++-- .../Lyrics/DragFile/DragFileStepScreen.cs | 295 ++++--- .../Lyrics/DragFile/ImportLyricDialog.cs | 39 +- .../Lyrics/EditLyric/EditLyricNavigation.cs | 109 ++- .../Lyrics/EditLyric/EditLyricStepScreen.cs | 55 +- .../GenerateRubyRomajiNavigation.cs | 83 +- .../GenerateRubyRomajiStepScreen.cs | 109 ++- .../UseAutoGenerateRomajiPopupDialog.cs | 37 +- .../UseAutoGenerateRubyPopupDialog.cs | 37 +- .../AlreadyContainTimeTagPopupDialog.cs | 27 +- .../GenerateTimeTagNavigation.cs | 71 +- .../GenerateTimeTagStepScreen.cs | 93 ++- .../UseAutoGenerateTimeTagPopupDialog.cs | 37 +- .../Screens/Edit/Import/Lyrics/Header.cs | 257 ++++--- .../Import/Lyrics/IImportStateResolver.cs | 11 +- .../Import/Lyrics/ILyricImporterStepScreen.cs | 17 +- .../Edit/Import/Lyrics/ImportLyricManager.cs | 79 +- .../Edit/Import/Lyrics/LyricImporter.cs | 223 +++--- .../Edit/Import/Lyrics/LyricImporterStep.cs | 19 +- .../Import/Lyrics/LyricImporterStepScreen.cs | 127 ++-- .../LyricImporterStepScreenWithLyricEditor.cs | 135 ++-- ...yricImporterStepScreenWithTopNavigation.cs | 43 +- .../Lyrics/LyricImporterSubScreenStack.cs | 119 ++- .../Edit/Import/Lyrics/RollBackPopupDialog.cs | 37 +- .../Import/Lyrics/RollBackResetPopupDialog.cs | 37 +- .../Lyrics/Success/SuccessStepScreen.cs | 25 +- .../Edit/Import/Lyrics/TopNavigation.cs | 283 ++++--- .../Screens/Settings/Header.cs | 223 +++--- .../Screens/Settings/KaraokeSettings.cs | 197 +++-- .../Settings/KaraokeSettingsColourProvider.cs | 37 +- .../Screens/Settings/KaraokeSettingsPanel.cs | 207 +++-- .../Settings/KaraokeSettingsSection.cs | 45 +- .../Settings/KaraokeSettingsSubsection.cs | 25 +- .../Screens/Settings/KaraokeVersionManager.cs | 123 ++- .../Settings/Previews/DefaultPreview.cs | 93 ++- .../Previews/Gameplay/LyricPreview.cs | 201 +++-- .../Previews/Gameplay/NotePlayfieldPreview.cs | 137 ++-- .../Previews/Gameplay/ShowCursorPreview.cs | 79 +- .../Previews/Graphics/ManageFontPreview.cs | 473 ++++++------ .../Previews/Input/MicrophoneDevicePreview.cs | 61 +- .../Previews/SettingsSubsectionPreview.cs | 141 ++-- .../Previews/UnderConstructionPreview.cs | 107 ++- .../Settings/Sections/ConfigSection.cs | 31 +- .../Sections/Gameplay/GeneralSettings.cs | 29 +- .../Sections/Gameplay/LyricSettings.cs | 39 +- .../Sections/Gameplay/NoteSettings.cs | 57 +- .../Sections/Gameplay/ScoringSettings.cs | 87 ++- .../Sections/Gameplay/TranslateSettings.cs | 41 +- .../Sections/Graphics/LyricFontSettings.cs | 107 ++- .../Sections/Graphics/ManageFontSettings.cs | 41 +- .../Sections/Graphics/NoteFontSettings.cs | 39 +- .../Sections/Graphics/TransparentSettings.cs | 45 +- .../Sections/Input/MicrophoneSettings.cs | 29 +- .../Settings/Sections/ScoringSection.cs | 27 +- .../Screens/Settings/Sections/StyleSection.cs | 31 +- .../Screens/Settings/SettingsFont.cs | 227 +++--- .../Screens/Settings/SettingsLanguage.cs | 63 +- .../SettingsMicrophoneDeviceDropdown.cs | 33 +- .../Screens/Skin/Config/ConfigScreen.cs | 43 +- .../Screens/Skin/Config/IntervalSection.cs | 111 ++- .../Screens/Skin/Config/LyricConfigSection.cs | 7 +- .../Skin/Config/LyricFontInfoManager.cs | 45 +- .../Screens/Skin/Config/PositionSection.cs | 47 +- .../Screens/Skin/Config/RubyRomajiSection.cs | 115 ++- .../Screens/Skin/KaraokeSkinEditor.cs | 45 +- .../Screens/Skin/KaraokeSkinEditorScreen.cs | 169 ++-- .../Skin/KaraokeSkinEditorScreenMode.cs | 19 +- .../Screens/Skin/Style/LyricColorSection.cs | 59 +- .../Screens/Skin/Style/LyricFontSection.cs | 95 ++- .../Screens/Skin/Style/LyricShadowSection.cs | 71 +- .../Screens/Skin/Style/LyricStylePreview.cs | 127 ++-- .../Screens/Skin/Style/NoteColorSection.cs | 41 +- .../Screens/Skin/Style/NoteFontSection.cs | 41 +- .../Screens/Skin/Style/NoteStylePreview.cs | 127 ++-- .../Screens/Skin/Style/StyleManager.cs | 43 +- .../Screens/Skin/Style/StyleScreen.cs | 101 ++- .../Screens/Skin/Style/StyleSection.cs | 7 +- .../Argon/KaraokeArgonSkinTransformer.cs | 11 +- .../Skinning/Default/DefaultBodyPiece.cs | 117 ++- .../Skinning/Default/DefaultLyricPiece.cs | 21 +- .../Default/KaraokeDefaultSkinTransformer.cs | 91 ++- .../Skinning/Elements/ElementType.cs | 15 +- .../Skinning/Elements/IKaraokeSkinElement.cs | 13 +- .../Elements/InvalidDrawableTypeException.cs | 11 +- .../Skinning/Elements/LayoutGroup.cs | 11 +- .../Skinning/Elements/LyricFontInfo.cs | 257 ++++--- .../Skinning/Elements/LyricLayout.cs | 71 +- .../Skinning/Elements/LyricStyle.cs | 99 ++- .../Skinning/Elements/NoteStyle.cs | 67 +- .../Skinning/Fonts/BitmapFontCompressor.cs | 229 +++--- .../Fonts/BitmapFontImageGenerator.cs | 103 ++- .../Skinning/Fonts/FontInfo.cs | 61 +- .../Skinning/Fonts/FontManager.cs | 369 +++++---- .../InternalSkinStorageResourceProvider.cs | 27 +- .../Skinning/KaraokeBeatmapSkin.cs | 155 ++-- .../Skinning/KaraokeIndexLookup.cs | 19 +- .../Skinning/KaraokeSkin.cs | 227 +++--- .../KaraokeSkinConfigurationLookup.cs | 75 +- .../Skinning/KaraokeSkinLookup.cs | 67 +- .../Legacy/KaraokeClassicSkinTransformer.cs | 11 +- .../Legacy/KaraokeLegacySkinTransformer.cs | 91 ++- .../Skinning/Legacy/LegacyColumnBackground.cs | 143 ++-- .../Skinning/Legacy/LegacyHitExplosion.cs | 95 ++- .../Skinning/Legacy/LegacyJudgementLine.cs | 145 ++-- .../Legacy/LegacyKaraokeColumnElement.cs | 15 +- .../Skinning/Legacy/LegacyKaraokeElement.cs | 33 +- .../Skinning/Legacy/LegacyNotePiece.cs | 365 +++++---- .../Skinning/Legacy/LegacyStageBackground.cs | 53 +- .../Skinning/Tools/SkinConverterTool.cs | 73 +- .../KaraokeTrianglesSkinTransformer.cs | 11 +- .../Statistics/BeatmapInfoGraph.cs | 91 ++- .../Statistics/BeatmapMetadataGraph.cs | 297 ++++---- .../Statistics/NotScorableGraph.cs | 41 +- .../Statistics/ScoringResultGraph.cs | 359 +++++---- osu.Game.Rulesets.Karaoke/Timing/StopClock.cs | 29 +- .../UI/Components/CenterLine.cs | 31 +- .../UI/Components/DefaultColumnBackground.cs | 39 +- .../UI/Components/DefaultJudgementLine.cs | 69 +- .../RealTimeScoringVisualization.cs | 109 ++- .../Components/ReplayScoringVisualization.cs | 83 +- .../UI/Components/ScoringMarker.cs | 39 +- .../UI/Components/ScoringStatus.cs | 297 ++++---- .../UI/Components/VoiceVisualization.cs | 285 ++++--- .../UI/DefaultHitExplosion.cs | 207 +++-- .../UI/DrawableKaraokeRuleset.cs | 105 ++- .../UI/DrawableNoteJudgement.cs | 79 +- .../UI/HUD/BindableNumberExtension.cs | 25 +- .../UI/HUD/GeneralSettingOverlay.cs | 213 +++--- .../UI/HUD/ISettingHUDOverlay.cs | 11 +- .../UI/HUD/PracticeOverlay.cs | 43 +- .../UI/HUD/SettingButton.cs | 17 +- .../UI/HUD/SettingButtonsDisplay.cs | 115 ++- .../UI/HUD/SettingOverlay.cs | 221 +++--- .../UI/HUD/SettingOverlayContainer.cs | 107 ++- .../UI/KaraokePlayfield.cs | 277 ++++--- .../UI/KaraokePlayfieldAdjustmentContainer.cs | 75 +- .../UI/KaraokeReplayRecorder.cs | 23 +- .../UI/KaraokeScrollingDirection.cs | 11 +- .../UI/KaraokeSettingsSubsection.cs | 201 +++-- .../UI/LyricPlayfield.cs | 93 ++- osu.Game.Rulesets.Karaoke/UI/NotePlayfield.cs | 329 ++++---- .../ClickablePlayerSliderBar.cs | 137 ++-- .../UI/PlayerSettings/LyricsPreview.cs | 225 +++--- .../UI/PlayerSettings/PitchSettings.cs | 65 +- .../UI/PlayerSettings/PlaybackSettings.cs | 77 +- .../UI/PlayerSettings/PracticeSettings.cs | 101 ++- .../UI/PlayerSettings/RubyRomajiSettings.cs | 49 +- .../UI/PlayerSettings/TranslateSettings.cs | 87 ++- .../UI/Position/INotePositionInfo.cs | 11 +- .../UI/Position/NotePositionCalculator.cs | 57 +- .../UI/Position/NotePositionInfo.cs | 65 +- .../UI/Scrolling/ScrollingNotePlayfield.cs | 225 +++--- .../Utils/AssemblyUtils.cs | 19 +- .../Utils/BindablesUtils.cs | 53 +- osu.Game.Rulesets.Karaoke/Utils/CharUtils.cs | 93 ++- .../Utils/CultureInfoUtils.cs | 43 +- osu.Game.Rulesets.Karaoke/Utils/EnumUtils.cs | 19 +- .../Utils/FontUsageUtils.cs | 11 +- osu.Game.Rulesets.Karaoke/Utils/FontUtils.cs | 83 +- .../Utils/JpStringUtils.cs | 27 +- osu.Game.Rulesets.Karaoke/Utils/LyricUtils.cs | 449 ++++++----- .../Utils/LyricsUtils.cs | 207 +++-- osu.Game.Rulesets.Karaoke/Utils/NoteUtils.cs | 27 +- osu.Game.Rulesets.Karaoke/Utils/NotesUtils.cs | 57 +- osu.Game.Rulesets.Karaoke/Utils/OrderUtils.cs | 273 ++++--- .../Utils/RectangleFUtils.cs | 25 +- .../Utils/SingerUtils.cs | 35 +- .../Utils/TextIndexUtils.cs | 109 ++- .../Utils/TextTagUtils.cs | 143 ++-- .../Utils/TextTagsUtils.cs | 167 ++-- .../Utils/TimeTagUtils.cs | 53 +- .../Utils/TimeTagsUtils.cs | 509 +++++++------ osu.Game.Rulesets.Karaoke/Utils/TypeUtils.cs | 19 +- .../Utils/VersionUtils.cs | 41 +- 754 files changed, 31941 insertions(+), 32680 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/BaseHitObjectPropertyChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/BaseHitObjectPropertyChangeHandlerTest.cs index 00df866e1..726202751 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/BaseHitObjectPropertyChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/BaseHitObjectPropertyChangeHandlerTest.cs @@ -14,4 +14,4 @@ protected void TriggerHandlerChangedWithChangeForbiddenException(Action.ChangeForbiddenException>(c); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/ImportBeatmapChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/ImportBeatmapChangeHandlerTest.cs index e7d5ae8a2..5fdbd99dd 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/ImportBeatmapChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/ImportBeatmapChangeHandlerTest.cs @@ -43,4 +43,4 @@ public void TestImport() Assert.AreEqual(2, karaokeBeatmap.HitObjects.Count); }); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/BaseCheckTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/BaseCheckTest.cs index 09f738c16..d5909d05c 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/BaseCheckTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/BaseCheckTest.cs @@ -52,4 +52,4 @@ protected IEnumerable Run(BeatmapVerifierContext context) { return check.Run(context); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckBeatmapAvailableTranslatesTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckBeatmapAvailableTranslatesTest.cs index 21aaa7323..e2e066443 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckBeatmapAvailableTranslatesTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckBeatmapAvailableTranslatesTest.cs @@ -126,4 +126,4 @@ private static IBeatmap createTestingBeatmap(List? translateLanguag private static BeatmapVerifierContext getContext(IBeatmap beatmap) => new(beatmap, new TestWorkingBeatmap(beatmap)); -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricLanguageTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricLanguageTest.cs index 4b53e7769..36bff726e 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricLanguageTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricLanguageTest.cs @@ -34,4 +34,4 @@ public void TestCheckNotFillLanguage(string? language) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRomajiTagTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRomajiTagTest.cs index 7f3234a24..29de23279 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRomajiTagTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRomajiTagTest.cs @@ -64,4 +64,4 @@ public void TestCheckRomajiEmptyText(string text, string[] romajies) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRubyTagTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRubyTagTest.cs index 1e84a10ed..02f811e91 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRubyTagTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricRubyTagTest.cs @@ -64,4 +64,4 @@ public void TestCheckRubyEmptyText(string text, string[] rubies) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricSingerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricSingerTest.cs index af902096b..358b21cbd 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricSingerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricSingerTest.cs @@ -35,4 +35,4 @@ public void TestCheckNoSinger(int[] singers) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTextTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTextTest.cs index dcc67bf92..17b3f03f6 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTextTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTextTest.cs @@ -38,4 +38,4 @@ public void TestCheckNoText(string text) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTagTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTagTest.cs index 8d1d01048..2784dbd0c 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTagTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTagTest.cs @@ -100,4 +100,4 @@ public void TestCheckEmptyTime(string text, string[] timeTags) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTest.cs index f23c78940..ed48721e9 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTimeTest.cs @@ -47,4 +47,4 @@ public void TestCheckEndTimeInvalid(string lyricText, string[] timeTags) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTranslateTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTranslateTest.cs index 9cd837d4d..ce7f44f9a 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTranslateTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckLyricTranslateTest.cs @@ -45,4 +45,4 @@ public void TestCheckTranslationNoText(string text) AssertNotOk(lyric); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckNoteTextTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckNoteTextTest.cs index 5c5383f59..aaf712653 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckNoteTextTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/CheckNoteTextTest.cs @@ -51,4 +51,4 @@ public void TestCheckNoRubyText(string? rubyText) AssertNotOk(note); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/HitObjectCheckTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/HitObjectCheckTest.cs index b2519d922..0bc2cec6e 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/HitObjectCheckTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Checks/HitObjectCheckTest.cs @@ -43,4 +43,4 @@ private BeatmapVerifierContext getContext(IEnumerable hitObjects) return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap)); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorTest.cs index 1fae22268..f8f79dcb6 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorTest.cs @@ -163,4 +163,4 @@ public void TestGenerateWithRubyLyric() }; CheckGenerateResult(lyric, expectedTimeTags, config); } -} \ No newline at end of file +} diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapDecoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapDecoder.cs index e058f4227..52c572a31 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapDecoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapDecoder.cs @@ -12,49 +12,48 @@ using osu.Game.IO.Serialization; using osu.Game.Rulesets.Karaoke.IO.Serialization; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats; + +public class KaraokeJsonBeatmapDecoder : JsonBeatmapDecoder { - public class KaraokeJsonBeatmapDecoder : JsonBeatmapDecoder + public new static void Register() { - public new static void Register() - { - AddDecoder("// karaoke json file format v", m => new KaraokeJsonBeatmapDecoder()); + AddDecoder("// karaoke json file format v", m => new KaraokeJsonBeatmapDecoder()); - // use this weird way to let all the fall-back beatmap(include karaoke beatmap) become karaoke beatmap. - SetFallbackDecoder(() => new KaraokeJsonBeatmapDecoder()); - } - - protected override void ParseStreamInto(LineBufferedReader stream, Beatmap output) - { - var globalSetting = KaraokeJsonSerializableExtensions.CreateGlobalSettings(); - globalSetting.ContractResolver = new KaraokeBeatmapContractResolver(); + // use this weird way to let all the fall-back beatmap(include karaoke beatmap) become karaoke beatmap. + SetFallbackDecoder(() => new KaraokeJsonBeatmapDecoder()); + } - // create id if object is by reference. - globalSetting.PreserveReferencesHandling = PreserveReferencesHandling.Objects; + protected override void ParseStreamInto(LineBufferedReader stream, Beatmap output) + { + var globalSetting = KaraokeJsonSerializableExtensions.CreateGlobalSettings(); + globalSetting.ContractResolver = new KaraokeBeatmapContractResolver(); - // should not let json decoder to read this line. - if (stream.PeekLine()?.Contains("// karaoke json file format v") ?? false) - { - stream.ReadLine(); - } + // create id if object is by reference. + globalSetting.PreserveReferencesHandling = PreserveReferencesHandling.Objects; - // equal to stream.ReadToEnd().DeserializeInto(output); in the base class. - JsonConvert.PopulateObject(stream.ReadToEnd(), output, globalSetting); + // should not let json decoder to read this line. + if (stream.PeekLine()?.Contains("// karaoke json file format v") ?? false) + { + stream.ReadLine(); } - private class KaraokeBeatmapContractResolver : SnakeCaseKeyContractResolver - { - protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) - { - var props = base.CreateProperties(type, memberSerialization); + // equal to stream.ReadToEnd().DeserializeInto(output); in the base class. + JsonConvert.PopulateObject(stream.ReadToEnd(), output, globalSetting); + } - if (type == typeof(BeatmapInfo)) - { - return props.Where(p => p.PropertyName != "ruleset_id").ToList(); - } + private class KaraokeBeatmapContractResolver : SnakeCaseKeyContractResolver + { + protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) + { + var props = base.CreateProperties(type, memberSerialization); - return props; + if (type == typeof(BeatmapInfo)) + { + return props.Where(p => p.PropertyName != "ruleset_id").ToList(); } + + return props; } } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapEncoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapEncoder.cs index 25098b504..8f51a301a 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapEncoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeJsonBeatmapEncoder.cs @@ -5,15 +5,14 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Karaoke.IO.Serialization; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats; + +public class KaraokeJsonBeatmapEncoder { - public class KaraokeJsonBeatmapEncoder + public string Encode(Beatmap output) { - public string Encode(Beatmap output) - { - var globalSetting = KaraokeJsonSerializableExtensions.CreateGlobalSettings(); - string json = JsonConvert.SerializeObject(output, globalSetting); - return "// karaoke json file format v1" + '\n' + json; - } + var globalSetting = KaraokeJsonSerializableExtensions.CreateGlobalSettings(); + string json = JsonConvert.SerializeObject(output, globalSetting); + return "// karaoke json file format v1" + '\n' + json; } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs index adf8a1355..f70e90b33 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapDecoder.cs @@ -12,269 +12,268 @@ using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats; + +public class KaraokeLegacyBeatmapDecoder : LegacyBeatmapDecoder { - public class KaraokeLegacyBeatmapDecoder : LegacyBeatmapDecoder + public new const int LATEST_VERSION = 1; + + public new static void Register() + { + AddDecoder(@"karaoke file format v", m => new KaraokeLegacyBeatmapDecoder(Parsing.ParseInt(m.Split('v').Last()))); + + // use this weird way to let all the fall-back beatmap(include karaoke beatmap) become karaoke beatmap. + SetFallbackDecoder(() => new KaraokeLegacyBeatmapDecoder()); + } + + public KaraokeLegacyBeatmapDecoder(int version = LATEST_VERSION) + : base(version) { - public new const int LATEST_VERSION = 1; + } + + private readonly IList lrcLines = new List(); + private readonly IList noteLines = new List(); + private readonly IList translates = new List(); - public new static void Register() + protected override void ParseLine(Beatmap beatmap, Section section, string line) + { + if (section != Section.HitObjects) { - AddDecoder(@"karaoke file format v", m => new KaraokeLegacyBeatmapDecoder(Parsing.ParseInt(m.Split('v').Last()))); + // should not let base.ParseLine read the line like "Mode: 111" + if (line.StartsWith("Mode", StringComparison.Ordinal)) + { + beatmap.BeatmapInfo.Ruleset = new KaraokeRuleset().RulesetInfo; + return; + } - // use this weird way to let all the fall-back beatmap(include karaoke beatmap) become karaoke beatmap. - SetFallbackDecoder(() => new KaraokeLegacyBeatmapDecoder()); + base.ParseLine(beatmap, section, line); + return; } - public KaraokeLegacyBeatmapDecoder(int version = LATEST_VERSION) - : base(version) + if (line.ToLower().StartsWith("@ruby", StringComparison.Ordinal) || line.ToLower().StartsWith("@romaji", StringComparison.Ordinal)) { + // lrc queue + lrcLines.Add(line); } - - private readonly IList lrcLines = new List(); - private readonly IList noteLines = new List(); - private readonly IList translates = new List(); - - protected override void ParseLine(Beatmap beatmap, Section section, string line) + else if (line.ToLower().StartsWith("@note", StringComparison.Ordinal)) + { + // add tone line queue + noteLines.Add(line); + } + else if (line.ToLower().StartsWith("@tr", StringComparison.Ordinal)) + { + // add translate queue + translates.Add(line); + } + else if (line.StartsWith("@", StringComparison.Ordinal)) { - if (section != Section.HitObjects) + // Remove @ in time tag and add into lrc queue + lrcLines.Add(line[1..]); + } + else if (line.ToLower() == "end") + { + // Start processing file + using (var stream = new MemoryStream()) + using (var writer = new StreamWriter(stream)) + using (var reader = new LineBufferedReader(stream)) { - // should not let base.ParseLine read the line like "Mode: 111" - if (line.StartsWith("Mode", StringComparison.Ordinal)) - { - beatmap.BeatmapInfo.Ruleset = new KaraokeRuleset().RulesetInfo; - return; - } + // Create stream + writer.Write(string.Join("\n", lrcLines)); + writer.Flush(); + stream.Position = 0; - base.ParseLine(beatmap, section, line); - return; - } + // Create lec decoder + var decoder = new LrcDecoder(); + var lrcBeatmap = decoder.Decode(reader); - if (line.ToLower().StartsWith("@ruby", StringComparison.Ordinal) || line.ToLower().StartsWith("@romaji", StringComparison.Ordinal)) - { - // lrc queue - lrcLines.Add(line); - } - else if (line.ToLower().StartsWith("@note", StringComparison.Ordinal)) - { - // add tone line queue - noteLines.Add(line); - } - else if (line.ToLower().StartsWith("@tr", StringComparison.Ordinal)) - { - // add translate queue - translates.Add(line); + // Apply hitobjects + beatmap.HitObjects = lrcBeatmap.HitObjects; } - else if (line.StartsWith("@", StringComparison.Ordinal)) - { - // Remove @ in time tag and add into lrc queue - lrcLines.Add(line[1..]); - } - else if (line.ToLower() == "end") - { - // Start processing file - using (var stream = new MemoryStream()) - using (var writer = new StreamWriter(stream)) - using (var reader = new LineBufferedReader(stream)) - { - // Create stream - writer.Write(string.Join("\n", lrcLines)); - writer.Flush(); - stream.Position = 0; - // Create lec decoder - var decoder = new LrcDecoder(); - var lrcBeatmap = decoder.Decode(reader); + processNotes(beatmap, noteLines); + processTranslate(beatmap, translates); + } + } + + private void processNotes(Beatmap beatmap, IList lines) + { + var noteGenerator = new NoteGenerator(new NoteGeneratorConfig()); - // Apply hitobjects - beatmap.HitObjects = lrcBeatmap.HitObjects; - } + // Remove all karaoke note + beatmap.HitObjects.RemoveAll(x => x is Note); - processNotes(beatmap, noteLines); - processTranslate(beatmap, translates); - } - } + var lyrics = beatmap.HitObjects.OfType().ToList(); - private void processNotes(Beatmap beatmap, IList lines) + for (int l = 0; l < lyrics.Count; l++) { - var noteGenerator = new NoteGenerator(new NoteGeneratorConfig()); + var lyric = lyrics[l]; + string? line = lines.ElementAtOrDefault(l)?.Split('=').Last(); - // Remove all karaoke note - beatmap.HitObjects.RemoveAll(x => x is Note); + // Create default note if not exist + if (string.IsNullOrEmpty(line)) + { + beatmap.HitObjects.AddRange(noteGenerator.Generate(lyric)); + continue; + } - var lyrics = beatmap.HitObjects.OfType().ToList(); + string[] notes = line.Split(','); + var defaultNotes = noteGenerator.Generate(lyric).ToList(); + int minNoteNumber = Math.Min(notes.Length, defaultNotes.Count); - for (int l = 0; l < lyrics.Count; l++) + // Process each note + for (int i = 0; i < minNoteNumber; i++) { - var lyric = lyrics[l]; - string? line = lines.ElementAtOrDefault(l)?.Split('=').Last(); + string note = notes[i]; + var defaultNote = defaultNotes[i]; - // Create default note if not exist - if (string.IsNullOrEmpty(line)) + // Support multi note in one time tag, format like ([1;0.5;か]|1#|...) + if (!note.StartsWith("(", StringComparison.Ordinal) || !note.EndsWith(")", StringComparison.Ordinal)) { - beatmap.HitObjects.AddRange(noteGenerator.Generate(lyric)); - continue; + // Process and add note + applyNote(defaultNote, note); + beatmap.HitObjects.Add(defaultNote); } - - string[] notes = line.Split(','); - var defaultNotes = noteGenerator.Generate(lyric).ToList(); - int minNoteNumber = Math.Min(notes.Length, defaultNotes.Count); - - // Process each note - for (int i = 0; i < minNoteNumber; i++) + else { - string note = notes[i]; - var defaultNote = defaultNotes[i]; + float startPercentage = 0; + string[] rubyNotes = note.Replace("(", string.Empty).Replace(")", string.Empty).Split('|'); - // Support multi note in one time tag, format like ([1;0.5;か]|1#|...) - if (!note.StartsWith("(", StringComparison.Ordinal) || !note.EndsWith(")", StringComparison.Ordinal)) + for (int j = 0; j < rubyNotes.Length; j++) { - // Process and add note - applyNote(defaultNote, note); - beatmap.HitObjects.Add(defaultNote); - } - else - { - float startPercentage = 0; - string[] rubyNotes = note.Replace("(", string.Empty).Replace(")", string.Empty).Split('|'); + string rubyNote = rubyNotes[j]; - for (int j = 0; j < rubyNotes.Length; j++) - { - string rubyNote = rubyNotes[j]; - - string tone; - float percentage = (float)Math.Round((float)1 / rubyNotes.Length, 2, MidpointRounding.AwayFromZero); - string? ruby = defaultNote.RubyText?.ElementAtOrDefault(j).ToString(); - - // Format like [1;0.5;か] - if (note.StartsWith("[", StringComparison.Ordinal) && note.EndsWith("]", StringComparison.Ordinal)) - { - string[] rubyNoteProperty = note.Replace("[", string.Empty).Replace("]", string.Empty).Split(';'); - - // Copy tome property - tone = rubyNoteProperty[0]; - - // Copy percentage property - if (rubyNoteProperty.Length >= 2) - float.TryParse(rubyNoteProperty[1], out percentage); - - // Copy text property - if (rubyNoteProperty.Length >= 3) - ruby = rubyNoteProperty[2]; - } - else - { - tone = rubyNote; - } - - // Split note and apply them - var splitDefaultNote = SliceNote(defaultNote, startPercentage, percentage); - startPercentage += percentage; - if (!string.IsNullOrEmpty(ruby)) - splitDefaultNote.Text = ruby; - - // Process and add note - applyNote(splitDefaultNote, tone); - beatmap.HitObjects.Add(splitDefaultNote); - } - } - } - } + string tone; + float percentage = (float)Math.Round((float)1 / rubyNotes.Length, 2, MidpointRounding.AwayFromZero); + string? ruby = defaultNote.RubyText?.ElementAtOrDefault(j).ToString(); - static void applyNote(Note note, string noteStr, string? ruby = null, double? duration = null) - { - if (noteStr == "-") - note.Display = false; - else - { - note.Display = true; - note.Tone = convertTone(noteStr); - } + // Format like [1;0.5;か] + if (note.StartsWith("[", StringComparison.Ordinal) && note.EndsWith("]", StringComparison.Ordinal)) + { + string[] rubyNoteProperty = note.Replace("[", string.Empty).Replace("]", string.Empty).Split(';'); - if (!string.IsNullOrEmpty(ruby)) - note.Text = ruby; + // Copy tome property + tone = rubyNoteProperty[0]; - if (duration != null) - note.Duration = duration.Value; + // Copy percentage property + if (rubyNoteProperty.Length >= 2) + float.TryParse(rubyNoteProperty[1], out percentage); - //Support format : 1 1. 1.5 1+ 1# - static Tone convertTone(string tone) - { - bool half = false; + // Copy text property + if (rubyNoteProperty.Length >= 3) + ruby = rubyNoteProperty[2]; + } + else + { + tone = rubyNote; + } - if (tone.Contains('.') || tone.Contains('#')) - { - half = true; + // Split note and apply them + var splitDefaultNote = SliceNote(defaultNote, startPercentage, percentage); + startPercentage += percentage; + if (!string.IsNullOrEmpty(ruby)) + splitDefaultNote.Text = ruby; - // only get digit part - tone = tone.Split('.').FirstOrDefault()?.Split('#').FirstOrDefault() ?? string.Empty; + // Process and add note + applyNote(splitDefaultNote, tone); + beatmap.HitObjects.Add(splitDefaultNote); } - - if (!int.TryParse(tone, out int scale)) - throw new InvalidCastException($"{tone} does not support in {nameof(KaraokeLegacyBeatmapDecoder)}"); - - return new Tone - { - Scale = scale, - Half = half - }; } } } - private void processTranslate(Beatmap beatmap, IEnumerable translateLines) + static void applyNote(Note note, string noteStr, string? ruby = null, double? duration = null) { - var availableTranslates = new List(); - - var lyrics = beatmap.HitObjects.OfType().ToList(); - var translations = translateLines.Select(translate => new + if (noteStr == "-") + note.Display = false; + else { - key = translate.Split('=').FirstOrDefault()?.Split('[').LastOrDefault()?.Split(']').FirstOrDefault(), - value = translate.Split('=').LastOrDefault() ?? string.Empty - }).GroupBy(x => x.key, y => y.value).ToList(); + note.Display = true; + note.Tone = convertTone(noteStr); + } - foreach (var translation in translations) - { - // get culture and translate - string? languageCode = translation.Key; - if (string.IsNullOrEmpty(languageCode)) - continue; + if (!string.IsNullOrEmpty(ruby)) + note.Text = ruby; - var cultureInfo = new CultureInfo(languageCode); - var values = translation.ToList(); + if (duration != null) + note.Duration = duration.Value; - int size = Math.Min(lyrics.Count, translation.Count()); + //Support format : 1 1. 1.5 1+ 1# + static Tone convertTone(string tone) + { + bool half = false; - for (int j = 0; j < size; j++) + if (tone.Contains('.') || tone.Contains('#')) { - lyrics[j].Translates.Add(cultureInfo, values[j]); + half = true; + + // only get digit part + tone = tone.Split('.').FirstOrDefault()?.Split('#').FirstOrDefault() ?? string.Empty; } - availableTranslates.Add(cultureInfo); + if (!int.TryParse(tone, out int scale)) + throw new InvalidCastException($"{tone} does not support in {nameof(KaraokeLegacyBeatmapDecoder)}"); + + return new Tone + { + Scale = scale, + Half = half + }; } + } + } + + private void processTranslate(Beatmap beatmap, IEnumerable translateLines) + { + var availableTranslates = new List(); + + var lyrics = beatmap.HitObjects.OfType().ToList(); + var translations = translateLines.Select(translate => new + { + key = translate.Split('=').FirstOrDefault()?.Split('[').LastOrDefault()?.Split(']').FirstOrDefault(), + value = translate.Split('=').LastOrDefault() ?? string.Empty + }).GroupBy(x => x.key, y => y.value).ToList(); + + foreach (var translation in translations) + { + // get culture and translate + string? languageCode = translation.Key; + if (string.IsNullOrEmpty(languageCode)) + continue; - var dictionary = new LegacyProperties + var cultureInfo = new CultureInfo(languageCode); + var values = translation.ToList(); + + int size = Math.Min(lyrics.Count, translation.Count()); + + for (int j = 0; j < size; j++) { - AvailableTranslates = availableTranslates - }; + lyrics[j].Translates.Add(cultureInfo, values[j]); + } - beatmap.HitObjects.Add(dictionary); + availableTranslates.Add(cultureInfo); } - internal static Note SliceNote(Note note, double startPercentage, double durationPercentage) + var dictionary = new LegacyProperties { - if (startPercentage < 0 || startPercentage + durationPercentage > 1) - throw new ArgumentOutOfRangeException($"{nameof(Note)} cannot assign split range of start from {startPercentage} and duration {durationPercentage}"); + AvailableTranslates = availableTranslates + }; - double durationFromStartTime = note.Duration * startPercentage; - double secondNoteDuration = note.Duration * (1 - startPercentage - durationPercentage); + beatmap.HitObjects.Add(dictionary); + } - // todo: there's no need to create the new note. - var newNote = note.DeepClone(); - newNote.StartTimeOffset = note.StartTimeOffset + durationFromStartTime; - newNote.EndTimeOffset = note.EndTimeOffset - secondNoteDuration; + internal static Note SliceNote(Note note, double startPercentage, double durationPercentage) + { + if (startPercentage < 0 || startPercentage + durationPercentage > 1) + throw new ArgumentOutOfRangeException($"{nameof(Note)} cannot assign split range of start from {startPercentage} and duration {durationPercentage}"); - return newNote; - } + double durationFromStartTime = note.Duration * startPercentage; + double secondNoteDuration = note.Duration * (1 - startPercentage - durationPercentage); + + // todo: there's no need to create the new note. + var newNote = note.DeepClone(); + newNote.StartTimeOffset = note.StartTimeOffset + durationFromStartTime; + newNote.EndTimeOffset = note.EndTimeOffset - secondNoteDuration; + + return newNote; } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs index 4123dda28..0605d9694 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/KaraokeLegacyBeatmapEncoder.cs @@ -7,77 +7,76 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats; + +public class KaraokeLegacyBeatmapEncoder { - public class KaraokeLegacyBeatmapEncoder + public string Encode(Beatmap output) { - public string Encode(Beatmap output) + var lrcEncoder = new LrcEncoder(); + var results = new List { - var lrcEncoder = new LrcEncoder(); - var results = new List - { - lrcEncoder.Encode(output), - string.Join("\n", encodeNote(output)), - string.Join("\n", encodeTranslate(output)), - }; + lrcEncoder.Encode(output), + string.Join("\n", encodeNote(output)), + string.Join("\n", encodeTranslate(output)), + }; - return string.Join("\n\n", results.Where(x => !string.IsNullOrEmpty(x))); - } + return string.Join("\n\n", results.Where(x => !string.IsNullOrEmpty(x))); + } - private IEnumerable encodeNote(Beatmap output) + private IEnumerable encodeNote(Beatmap output) + { + var notes = output.HitObjects.OfType().ToList(); + var lyrics = output.HitObjects.OfType().ToList(); + return notes.GroupBy(x => x.ReferenceLyric).Select(g => { - var notes = output.HitObjects.OfType().ToList(); - var lyrics = output.HitObjects.OfType().ToList(); - return notes.GroupBy(x => x.ReferenceLyric).Select(g => - { - var lyric = g.Key; - if (lyric == null) - throw new ArgumentNullException(); + var lyric = g.Key; + if (lyric == null) + throw new ArgumentNullException(); - // Get note group - var noteGroup = g.ToList().GroupBy(n => n.ReferenceTimeTagIndex); + // Get note group + var noteGroup = g.ToList().GroupBy(n => n.ReferenceTimeTagIndex); - // Convert to group format - string noteGroupStr = string.Join(",", noteGroup.Select(x => - { - if (x.Count() == 1) - return convertNote(x.First()); + // Convert to group format + string noteGroupStr = string.Join(",", noteGroup.Select(x => + { + if (x.Count() == 1) + return convertNote(x.First()); - return "(" + string.Join("|", x.Select(convertNote)) + ")"; - })); + return "(" + string.Join("|", x.Select(convertNote)) + ")"; + })); - return $"note{lyrics.IndexOf(lyric) + 1}={noteGroupStr}"; - }).ToList(); + return $"note{lyrics.IndexOf(lyric) + 1}={noteGroupStr}"; + }).ToList(); - // Convert single note - static string convertNote(Note note) - { - if (!note.Display) - return "-"; + // Convert single note + static string convertNote(Note note) + { + if (!note.Display) + return "-"; - // TODO : Fill if customize ruby and percentage - return convertTone(note.Tone); + // TODO : Fill if customize ruby and percentage + return convertTone(note.Tone); - // Convert tone to string - static string convertTone(Tone tone) => tone.Scale + (tone.Half ? "#" : string.Empty); - } + // Convert tone to string + static string convertTone(Tone tone) => tone.Scale + (tone.Half ? "#" : string.Empty); } + } - private IEnumerable encodeTranslate(Beatmap output) - { - if (!output.AnyTranslate()) - yield break; + private IEnumerable encodeTranslate(Beatmap output) + { + if (!output.AnyTranslate()) + yield break; - var lyrics = output.HitObjects.OfType().ToList(); - var availableTranslates = output.AvailableTranslates(); + var lyrics = output.HitObjects.OfType().ToList(); + var availableTranslates = output.AvailableTranslates(); - foreach (var translate in availableTranslates) + foreach (var translate in availableTranslates) + { + foreach (var lyric in lyrics) { - foreach (var lyric in lyrics) - { - string translateString = lyric.Translates.TryGetValue(translate, out string? value) ? value : string.Empty; - yield return $"@tr[{translate.Name}]={translateString}"; - } + string translateString = lyric.Translates.TryGetValue(translate, out string? value) ? value : string.Empty; + yield return $"@tr[{translate.Name}]={translateString}"; } } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs index 06bbcf226..66de27adc 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcDecoder.cs @@ -12,65 +12,64 @@ using Lyric = osu.Game.Rulesets.Karaoke.Objects.Lyric; using RubyTag = osu.Game.Rulesets.Karaoke.Objects.RubyTag; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats; + +public class LrcDecoder : Decoder { - public class LrcDecoder : Decoder + public static void Register() { - public static void Register() - { - // Lrc decoder looks like [mm:ss:__] - AddDecoder("[", _ => new LrcDecoder()); - } - - protected override void ParseStreamInto(LineBufferedReader stream, Beatmap output) - { - // Clear all hitobjects - output.HitObjects.Clear(); - - string lyricText = stream.ReadToEnd(); - var result = new LrcParser.Parser.Lrc.LrcParser().Decode(lyricText); + // Lrc decoder looks like [mm:ss:__] + AddDecoder("[", _ => new LrcDecoder()); + } - foreach (var lrcLyric in result.Lyrics) - { - var lrcTimeTags = lrcLyric.TimeTags.Select(convertTimeTag).ToArray(); - var lrcRubies = lrcLyric.RubyTags.Select(convertRubyTag).ToArray(); - var lrcRubyTimeTags = lrcLyric.RubyTags.Select(convertTimeTagsFromRubyTags).SelectMany(x => x).ToArray(); + protected override void ParseStreamInto(LineBufferedReader stream, Beatmap output) + { + // Clear all hitobjects + output.HitObjects.Clear(); - var lyric = new Lyric - { - ID = output.HitObjects.Count, // id is star from zero. - Order = output.HitObjects.Count + 1, // should create default order. - Text = lrcLyric.Text, - TimeTags = TimeTagsUtils.Sort(lrcTimeTags.Concat(lrcRubyTimeTags)), - RubyTags = lrcRubies - }; - output.HitObjects.Add(lyric); - } + string lyricText = stream.ReadToEnd(); + var result = new LrcParser.Parser.Lrc.LrcParser().Decode(lyricText); - static TimeTag convertTimeTag(KeyValuePair timeTag) - => new(convertTextIndex(timeTag.Key), timeTag.Value); + foreach (var lrcLyric in result.Lyrics) + { + var lrcTimeTags = lrcLyric.TimeTags.Select(convertTimeTag).ToArray(); + var lrcRubies = lrcLyric.RubyTags.Select(convertRubyTag).ToArray(); + var lrcRubyTimeTags = lrcLyric.RubyTags.Select(convertTimeTagsFromRubyTags).SelectMany(x => x).ToArray(); - static Framework.Graphics.Sprites.TextIndex convertTextIndex(TextIndex textIndex) + var lyric = new Lyric { - int index = textIndex.Index; - var state = textIndex.State == IndexState.Start ? Framework.Graphics.Sprites.TextIndex.IndexState.Start : Framework.Graphics.Sprites.TextIndex.IndexState.End; + ID = output.HitObjects.Count, // id is star from zero. + Order = output.HitObjects.Count + 1, // should create default order. + Text = lrcLyric.Text, + TimeTags = TimeTagsUtils.Sort(lrcTimeTags.Concat(lrcRubyTimeTags)), + RubyTags = lrcRubies + }; + output.HitObjects.Add(lyric); + } + + static TimeTag convertTimeTag(KeyValuePair timeTag) + => new(convertTextIndex(timeTag.Key), timeTag.Value); - return new Framework.Graphics.Sprites.TextIndex(index, state); - } + static Framework.Graphics.Sprites.TextIndex convertTextIndex(TextIndex textIndex) + { + int index = textIndex.Index; + var state = textIndex.State == IndexState.Start ? Framework.Graphics.Sprites.TextIndex.IndexState.Start : Framework.Graphics.Sprites.TextIndex.IndexState.End; - static RubyTag convertRubyTag(LrcParser.Model.RubyTag rubyTag) - => new() - { - Text = rubyTag.Text, - StartIndex = rubyTag.StartIndex, - EndIndex = rubyTag.EndIndex - }; + return new Framework.Graphics.Sprites.TextIndex(index, state); + } - static TimeTag[] convertTimeTagsFromRubyTags(LrcParser.Model.RubyTag rubyTag) + static RubyTag convertRubyTag(LrcParser.Model.RubyTag rubyTag) + => new() { - int startIndex = rubyTag.StartIndex; - return rubyTag.TimeTags.Select(x => convertTimeTag(new KeyValuePair(new TextIndex(startIndex), x.Value))).ToArray(); - } + Text = rubyTag.Text, + StartIndex = rubyTag.StartIndex, + EndIndex = rubyTag.EndIndex + }; + + static TimeTag[] convertTimeTagsFromRubyTags(LrcParser.Model.RubyTag rubyTag) + { + int startIndex = rubyTag.StartIndex; + return rubyTag.TimeTags.Select(x => convertTimeTag(new KeyValuePair(new TextIndex(startIndex), x.Value))).ToArray(); } } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcEncoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcEncoder.cs index ed2fc9a5b..345ac150c 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcEncoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LrcEncoder.cs @@ -12,72 +12,71 @@ using RubyTag = LrcParser.Model.RubyTag; using TextIndex = osu.Framework.Graphics.Sprites.TextIndex; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats; + +public class LrcEncoder { - public class LrcEncoder + public string Encode(Beatmap output) { - public string Encode(Beatmap output) + // Note : save to lyric will lost some tags with no value. + var song = new Song { - // Note : save to lyric will lost some tags with no value. - var song = new Song - { - Lyrics = output.HitObjects.OfType().Select(encodeLyric).ToList(), - }; - string encodeResult = new LrcParser.Parser.Lrc.LrcParser().Encode(song); - return encodeResult; - - static LrcParser.Model.Lyric encodeLyric(Lyric lyric) => - new() - { - Text = lyric.Text, - TimeTags = convertTimeTag(lyric.TimeTags), - RubyTags = convertRubyTag(lyric.RubyTags) - }; + Lyrics = output.HitObjects.OfType().Select(encodeLyric).ToList(), + }; + string encodeResult = new LrcParser.Parser.Lrc.LrcParser().Encode(song); + return encodeResult; - static SortedDictionary convertTimeTag(IList timeTags) + static LrcParser.Model.Lyric encodeLyric(Lyric lyric) => + new() { - // Note : save to lyric will lost some tags with duplicated index. - var timeTagDictionary = ToDictionary(timeTags).ToDictionary(k => convertTextIndex(k.Key), v => (int?)v.Value); - return new SortedDictionary(timeTagDictionary); - } - - static LrcParser.Model.TextIndex convertTextIndex(TextIndex textIndex) - { - int index = textIndex.Index; - var state = textIndex.State == TextIndex.IndexState.Start ? IndexState.Start : IndexState.End; - - return new LrcParser.Model.TextIndex(index, state); - } + Text = lyric.Text, + TimeTags = convertTimeTag(lyric.TimeTags), + RubyTags = convertRubyTag(lyric.RubyTags) + }; - static List convertRubyTag(IEnumerable rubyTags) - => rubyTags.Select(x => new RubyTag - { - Text = x.Text, - StartIndex = x.StartIndex, - EndIndex = x.EndIndex - }).ToList(); + static SortedDictionary convertTimeTag(IList timeTags) + { + // Note : save to lyric will lost some tags with duplicated index. + var timeTagDictionary = ToDictionary(timeTags).ToDictionary(k => convertTextIndex(k.Key), v => (int?)v.Value); + return new SortedDictionary(timeTagDictionary); } - /// - /// Convert list of time tag to dictionary. - /// - /// Time tags - /// Should auto-fix or not - /// Fix way - /// Fix way - /// Time tags with dictionary format. - internal static IReadOnlyDictionary ToDictionary(IList timeTags, bool applyFix = true, GroupCheck other = GroupCheck.Asc, - SelfCheck self = SelfCheck.BasedOnStart) + static LrcParser.Model.TextIndex convertTextIndex(TextIndex textIndex) { - // sorted value - var sortedTimeTags = applyFix ? TimeTagsUtils.FixOverlapping(timeTags, other, self) : TimeTagsUtils.Sort(timeTags); + int index = textIndex.Index; + var state = textIndex.State == TextIndex.IndexState.Start ? IndexState.Start : IndexState.End; - // convert to dictionary, will get start's smallest time and end's largest time. - return sortedTimeTags.Where(x => x.Time != null).GroupBy(x => x.Index) - .Select(x => TextIndexUtils.GetValueByState(x.Key, x.FirstOrDefault(), x.LastOrDefault())) - .ToDictionary( - k => k?.Index ?? throw new ArgumentNullException(nameof(k)), - v => v?.Time ?? throw new ArgumentNullException(nameof(v))); + return new LrcParser.Model.TextIndex(index, state); } + + static List convertRubyTag(IEnumerable rubyTags) + => rubyTags.Select(x => new RubyTag + { + Text = x.Text, + StartIndex = x.StartIndex, + EndIndex = x.EndIndex + }).ToList(); + } + + /// + /// Convert list of time tag to dictionary. + /// + /// Time tags + /// Should auto-fix or not + /// Fix way + /// Fix way + /// Time tags with dictionary format. + internal static IReadOnlyDictionary ToDictionary(IList timeTags, bool applyFix = true, GroupCheck other = GroupCheck.Asc, + SelfCheck self = SelfCheck.BasedOnStart) + { + // sorted value + var sortedTimeTags = applyFix ? TimeTagsUtils.FixOverlapping(timeTags, other, self) : TimeTagsUtils.Sort(timeTags); + + // convert to dictionary, will get start's smallest time and end's largest time. + return sortedTimeTags.Where(x => x.Time != null).GroupBy(x => x.Index) + .Select(x => TextIndexUtils.GetValueByState(x.Key, x.FirstOrDefault(), x.LastOrDefault())) + .ToDictionary( + k => k?.Index ?? throw new ArgumentNullException(nameof(k)), + v => v?.Time ?? throw new ArgumentNullException(nameof(v))); } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LyricTextEncoder.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LyricTextEncoder.cs index 67dab920d..4ad6c2960 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LyricTextEncoder.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Formats/LyricTextEncoder.cs @@ -5,15 +5,14 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Formats; + +public class LyricTextEncoder { - public class LyricTextEncoder + public string Encode(IBeatmap output) { - public string Encode(IBeatmap output) - { - var lyrics = output.HitObjects.OfType(); - var lyricTexts = lyrics.Select(x => x.Text).Where(x => !string.IsNullOrWhiteSpace(x)); - return string.Join('\n', lyricTexts); - } + var lyrics = output.HitObjects.OfType(); + var lyricTexts = lyrics.Select(x => x.Text).Where(x => !string.IsNullOrWhiteSpace(x)); + return string.Join('\n', lyricTexts); } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/IKaraokeBeatmapResourcesProvider.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/IKaraokeBeatmapResourcesProvider.cs index b2af611a9..b91afbef1 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/IKaraokeBeatmapResourcesProvider.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/IKaraokeBeatmapResourcesProvider.cs @@ -4,10 +4,9 @@ using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; -namespace osu.Game.Rulesets.Karaoke.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Beatmaps; + +public interface IKaraokeBeatmapResourcesProvider { - public interface IKaraokeBeatmapResourcesProvider - { - Texture? GetSingerAvatar(ISinger singer); - } + Texture? GetSingerAvatar(ISinger singer); } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmap.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmap.cs index 54a0c5e1a..3bce5a303 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmap.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmap.cs @@ -11,70 +11,69 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Stages; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Beatmaps; + +public class KaraokeBeatmap : Beatmap { - public class KaraokeBeatmap : Beatmap - { - public IList AvailableTranslates { get; set; } = new List(); + public IList AvailableTranslates { get; set; } = new List(); - public SingerInfo SingerInfo { get; set; } = new(); + public SingerInfo SingerInfo { get; set; } = new(); - public PageInfo PageInfo { get; set; } = new(); + public PageInfo PageInfo { get; set; } = new(); - public IList StageInfos { get; set; } = new List(); + public IList StageInfos { get; set; } = new List(); - /// - /// This property will not be null after is called. - /// - [JsonIgnore] - public StageInfo? CurrentStageInfo { get; set; } + /// + /// This property will not be null after is called. + /// + [JsonIgnore] + public StageInfo? CurrentStageInfo { get; set; } - public NoteInfo NoteInfo { get; set; } = new(); + public NoteInfo NoteInfo { get; set; } = new(); - public bool Scorable { get; set; } + public bool Scorable { get; set; } - public override IEnumerable GetStatistics() - { - int singers = SingerInfo.GetAllSingers().Count(); - int lyrics = HitObjects.Count(s => s is Lyric); + public override IEnumerable GetStatistics() + { + int singers = SingerInfo.GetAllSingers().Count(); + int lyrics = HitObjects.Count(s => s is Lyric); - var defaultStatistic = new List + var defaultStatistic = new List + { + new() + { + Name = @"Singer", + Content = singers.ToString(), + CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.User } + }, + new() { - new() - { - Name = @"Singer", - Content = singers.ToString(), - CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.User } - }, - new() - { - Name = @"Lyric", - Content = lyrics.ToString(), - CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.AlignLeft } - }, - }; + Name = @"Lyric", + Content = lyrics.ToString(), + CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.AlignLeft } + }, + }; - if (Scorable) + if (Scorable) + { + int notes = HitObjects.Count(s => s is Note { Display: true }); + defaultStatistic.Add(new BeatmapStatistic { - int notes = HitObjects.Count(s => s is Note { Display: true }); - defaultStatistic.Add(new BeatmapStatistic - { - Name = @"Note", - Content = notes.ToString(), - CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.Music } - }); - } - else + Name = @"Note", + Content = notes.ToString(), + CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.Music } + }); + } + else + { + defaultStatistic.Add(new BeatmapStatistic { - defaultStatistic.Add(new BeatmapStatistic - { - Name = @"This beatmap is not scorable.", - Content = @"This beatmap is not scorable.", - CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.Times } - }); - } - - return defaultStatistic.ToArray(); + Name = @"This beatmap is not scorable.", + Content = @"This beatmap is not scorable.", + CreateIcon = () => new SpriteIcon { Icon = FontAwesome.Solid.Times } + }); } + + return defaultStatistic.ToArray(); } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapConverter.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapConverter.cs index c73fe47a6..0e6b20262 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapConverter.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapConverter.cs @@ -9,39 +9,38 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Objects; -namespace osu.Game.Rulesets.Karaoke.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Beatmaps; + +public class KaraokeBeatmapConverter : BeatmapConverter { - public class KaraokeBeatmapConverter : BeatmapConverter + public KaraokeBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) + : base(beatmap, ruleset) { - public KaraokeBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) - : base(beatmap, ruleset) - { - } + } - public override bool CanConvert() => Beatmap.HitObjects.All(h => h is KaraokeHitObject); + public override bool CanConvert() => Beatmap.HitObjects.All(h => h is KaraokeHitObject); - protected override Beatmap ConvertBeatmap(IBeatmap original, CancellationToken cancellationToken) - { - var beatmap = base.ConvertBeatmap(original, cancellationToken); + protected override Beatmap ConvertBeatmap(IBeatmap original, CancellationToken cancellationToken) + { + var beatmap = base.ConvertBeatmap(original, cancellationToken); - // Apply property created from legacy decoder - var propertyDictionary = beatmap.HitObjects.OfType().FirstOrDefault(); + // Apply property created from legacy decoder + var propertyDictionary = beatmap.HitObjects.OfType().FirstOrDefault(); - if (propertyDictionary == null) - return beatmap; + if (propertyDictionary == null) + return beatmap; - if (beatmap is not KaraokeBeatmap karaokeBeatmap) - throw new InvalidCastException(nameof(beatmap)); + if (beatmap is not KaraokeBeatmap karaokeBeatmap) + throw new InvalidCastException(nameof(beatmap)); - karaokeBeatmap.AvailableTranslates = propertyDictionary.AvailableTranslates; - beatmap.HitObjects.Remove(propertyDictionary); + karaokeBeatmap.AvailableTranslates = propertyDictionary.AvailableTranslates; + beatmap.HitObjects.Remove(propertyDictionary); - return beatmap; - } + return beatmap; + } - protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap, CancellationToken cancellationToken) - => throw new NotImplementedException(); + protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap, CancellationToken cancellationToken) + => throw new NotImplementedException(); - protected override Beatmap CreateBeatmap() => new KaraokeBeatmap(); - } + protected override Beatmap CreateBeatmap() => new KaraokeBeatmap(); } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapExtension.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapExtension.cs index 24b3beaee..f17ae952f 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapExtension.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapExtension.cs @@ -6,29 +6,28 @@ using System.Linq; using osu.Game.Beatmaps; -namespace osu.Game.Rulesets.Karaoke.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Beatmaps; + +public static class KaraokeBeatmapExtension { - public static class KaraokeBeatmapExtension + public static bool IsScorable(this IBeatmap beatmap) { - public static bool IsScorable(this IBeatmap beatmap) + if (beatmap is not KaraokeBeatmap karaokeBeatmap) { - if (beatmap is not KaraokeBeatmap karaokeBeatmap) - { - // we should throw invalidate exception here but it will cause test case failed. - // because beatmap in the working beatmap in test case not always be karaoke beatmap class. - return false; - } - - return karaokeBeatmap.Scorable; + // we should throw invalidate exception here but it will cause test case failed. + // because beatmap in the working beatmap in test case not always be karaoke beatmap class. + return false; } - public static IList AvailableTranslates(this IBeatmap beatmap) => (beatmap as KaraokeBeatmap)?.AvailableTranslates ?? new List(); + return karaokeBeatmap.Scorable; + } - public static bool AnyTranslate(this IBeatmap beatmap) => beatmap.AvailableTranslates().Any(); + public static IList AvailableTranslates(this IBeatmap beatmap) => (beatmap as KaraokeBeatmap)?.AvailableTranslates ?? new List(); - public static float PitchToScale(this IBeatmap beatmap, float pitch) - { - return pitch / 20 - 7; - } + public static bool AnyTranslate(this IBeatmap beatmap) => beatmap.AvailableTranslates().Any(); + + public static float PitchToScale(this IBeatmap beatmap, float pitch) + { + return pitch / 20 - 7; } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs index c95c39813..00050ec56 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapProcessor.cs @@ -11,59 +11,58 @@ using osu.Game.Rulesets.Karaoke.Objects.Types; using osu.Game.Rulesets.Karaoke.Objects.Workings; -namespace osu.Game.Rulesets.Karaoke.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Beatmaps; + +public class KaraokeBeatmapProcessor : BeatmapProcessor { - public class KaraokeBeatmapProcessor : BeatmapProcessor - { - public new KaraokeBeatmap Beatmap => (KaraokeBeatmap)base.Beatmap; + public new KaraokeBeatmap Beatmap => (KaraokeBeatmap)base.Beatmap; - public KaraokeBeatmapProcessor(IBeatmap beatmap) - : base(beatmap) - { - } + public KaraokeBeatmapProcessor(IBeatmap beatmap) + : base(beatmap) + { + } - public override void PreProcess() - { - applyStage(Beatmap); + public override void PreProcess() + { + applyStage(Beatmap); - base.PreProcess(); - applyInvalidProperty(Beatmap); - } + base.PreProcess(); + applyInvalidProperty(Beatmap); + } - private void applyStage(KaraokeBeatmap beatmap) + private void applyStage(KaraokeBeatmap beatmap) + { + // current stage info will be null if not select any mod or first load. + // trying to load the first stage or create a default one. + if (beatmap.CurrentStageInfo == null) { - // current stage info will be null if not select any mod or first load. - // trying to load the first stage or create a default one. - if (beatmap.CurrentStageInfo == null) - { - beatmap.CurrentStageInfo = getWorkingStage() ?? createDefaultWorkingStage(); + beatmap.CurrentStageInfo = getWorkingStage() ?? createDefaultWorkingStage(); - // should invalidate the working property here because the stage info is changed. - beatmap.HitObjects.OfType().ForEach(x => - { - x.InvalidateWorkingProperty(LyricWorkingProperty.Timing); - x.InvalidateWorkingProperty(LyricWorkingProperty.EffectApplier); - }); - beatmap.HitObjects.OfType().ForEach(x => x.InvalidateWorkingProperty(NoteWorkingProperty.EffectApplier)); - } + // should invalidate the working property here because the stage info is changed. + beatmap.HitObjects.OfType().ForEach(x => + { + x.InvalidateWorkingProperty(LyricWorkingProperty.Timing); + x.InvalidateWorkingProperty(LyricWorkingProperty.EffectApplier); + }); + beatmap.HitObjects.OfType().ForEach(x => x.InvalidateWorkingProperty(NoteWorkingProperty.EffectApplier)); + } - if (beatmap.CurrentStageInfo is IHasCalculatedProperty calculatedProperty) - calculatedProperty.ValidateCalculatedProperty(beatmap); + if (beatmap.CurrentStageInfo is IHasCalculatedProperty calculatedProperty) + calculatedProperty.ValidateCalculatedProperty(beatmap); - StageInfo? getWorkingStage() - => Beatmap.StageInfos.FirstOrDefault(); + StageInfo? getWorkingStage() + => Beatmap.StageInfos.FirstOrDefault(); - StageInfo createDefaultWorkingStage() => new PreviewStageInfo(); - } + StageInfo createDefaultWorkingStage() => new PreviewStageInfo(); + } - private void applyInvalidProperty(KaraokeBeatmap beatmap) + private void applyInvalidProperty(KaraokeBeatmap beatmap) + { + // should convert to array here because validate the working property might change the start-time and the end time. + // which will cause got the wrong item in the array. + foreach (var hitObject in beatmap.HitObjects.OfType().ToArray()) { - // should convert to array here because validate the working property might change the start-time and the end time. - // which will cause got the wrong item in the array. - foreach (var hitObject in beatmap.HitObjects.OfType().ToArray()) - { - hitObject.ValidateWorkingProperty(beatmap); - } + hitObject.ValidateWorkingProperty(beatmap); } } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapResourcesProvider.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapResourcesProvider.cs index 508e87351..50ef13720 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapResourcesProvider.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/KaraokeBeatmapResourcesProvider.cs @@ -13,41 +13,40 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; -namespace osu.Game.Rulesets.Karaoke.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Beatmaps; + +public partial class KaraokeBeatmapResourcesProvider : Component, IKaraokeBeatmapResourcesProvider { - public partial class KaraokeBeatmapResourcesProvider : Component, IKaraokeBeatmapResourcesProvider + [Resolved] + private BeatmapManager beatmapManager { get; set; } + + [Resolved] + private IBindable working { get; set; } + + public Texture GetSingerAvatar(ISinger singer) + { + var provider = getBeatmapResourceProvider(); + if (provider == null) + return null; + + if (singer is not Singer s) + return null; + + var beatmapSetInfo = working.Value.BeatmapSetInfo; + if (beatmapSetInfo == null) + return null; + + string path = beatmapSetInfo.GetPathForFile($"assets/singers/{s.AvatarFile}"); + return provider.LargeTextureStore.Get(path); + } + + private IBeatmapResourceProvider getBeatmapResourceProvider() { - [Resolved] - private BeatmapManager beatmapManager { get; set; } - - [Resolved] - private IBindable working { get; set; } - - public Texture GetSingerAvatar(ISinger singer) - { - var provider = getBeatmapResourceProvider(); - if (provider == null) - return null; - - if (singer is not Singer s) - return null; - - var beatmapSetInfo = working.Value.BeatmapSetInfo; - if (beatmapSetInfo == null) - return null; - - string path = beatmapSetInfo.GetPathForFile($"assets/singers/{s.AvatarFile}"); - return provider.LargeTextureStore.Get(path); - } - - private IBeatmapResourceProvider getBeatmapResourceProvider() - { - // todo : use better way to get the resource provider. - var prop = typeof(BeatmapManager).GetField("workingBeatmapCache", BindingFlags.Instance | BindingFlags.NonPublic); - if (prop == null) - throw new ArgumentNullException(); - - return prop.GetValue(beatmapManager) as WorkingBeatmapCache; - } + // todo : use better way to get the resource provider. + var prop = typeof(BeatmapManager).GetField("workingBeatmapCache", BindingFlags.Instance | BindingFlags.NonPublic); + if (prop == null) + throw new ArgumentNullException(); + + return prop.GetValue(beatmapManager) as WorkingBeatmapCache; } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Singer.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Singer.cs index 69f69b1c6..4b619eb88 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Singer.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Singer.cs @@ -5,89 +5,88 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; + +public class Singer : ISinger { - public class Singer : ISinger + public Singer() + { + } + + public Singer(int id) + { + ID = id; + } + + public int ID { get; protected set; } + + [JsonIgnore] + public readonly Bindable OrderBindable = new(); + + /// + /// Order + /// + public int Order + { + get => OrderBindable.Value; + set => OrderBindable.Value = value; + } + + [JsonIgnore] + public readonly Bindable AvatarFileBindable = new(); + + public string AvatarFile + { + get => AvatarFileBindable.Value; + set => AvatarFileBindable.Value = value; + } + + [JsonIgnore] + public Bindable HueBindable = new BindableFloat + { + MinValue = 0, + MaxValue = 1 + }; + + public float Hue + { + get => HueBindable.Value; + set => HueBindable.Value = value; + } + + [JsonIgnore] + public readonly Bindable NameBindable = new(); + + public string Name + { + get => NameBindable.Value; + set => NameBindable.Value = value; + } + + [JsonIgnore] + public readonly Bindable RomajiNameBindable = new(); + + public string RomajiName + { + get => RomajiNameBindable.Value; + set => RomajiNameBindable.Value = value; + } + + [JsonIgnore] + public readonly Bindable EnglishNameBindable = new(); + + public string EnglishName + { + get => EnglishNameBindable.Value; + set => EnglishNameBindable.Value = value; + } + + [JsonIgnore] + public readonly Bindable DescriptionBindable = new(); + + public string Description { - public Singer() - { - } - - public Singer(int id) - { - ID = id; - } - - public int ID { get; protected set; } - - [JsonIgnore] - public readonly Bindable OrderBindable = new(); - - /// - /// Order - /// - public int Order - { - get => OrderBindable.Value; - set => OrderBindable.Value = value; - } - - [JsonIgnore] - public readonly Bindable AvatarFileBindable = new(); - - public string AvatarFile - { - get => AvatarFileBindable.Value; - set => AvatarFileBindable.Value = value; - } - - [JsonIgnore] - public Bindable HueBindable = new BindableFloat - { - MinValue = 0, - MaxValue = 1 - }; - - public float Hue - { - get => HueBindable.Value; - set => HueBindable.Value = value; - } - - [JsonIgnore] - public readonly Bindable NameBindable = new(); - - public string Name - { - get => NameBindable.Value; - set => NameBindable.Value = value; - } - - [JsonIgnore] - public readonly Bindable RomajiNameBindable = new(); - - public string RomajiName - { - get => RomajiNameBindable.Value; - set => RomajiNameBindable.Value = value; - } - - [JsonIgnore] - public readonly Bindable EnglishNameBindable = new(); - - public string EnglishName - { - get => EnglishNameBindable.Value; - set => EnglishNameBindable.Value = value; - } - - [JsonIgnore] - public readonly Bindable DescriptionBindable = new(); - - public string Description - { - get => DescriptionBindable.Value; - set => DescriptionBindable.Value = value; - } + get => DescriptionBindable.Value; + set => DescriptionBindable.Value = value; } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/SingerState.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/SingerState.cs index 79d9a963b..583319590 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/SingerState.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/SingerState.cs @@ -5,56 +5,55 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; + +public class SingerState : ISinger { - public class SingerState : ISinger + public SingerState() + { + } + + public SingerState(int id, int mainSingerId) + { + ID = id; + MainSingerId = mainSingerId; + } + + public int ID { get; protected set; } + + public int MainSingerId { get; protected set; } + + [JsonIgnore] + public readonly Bindable OrderBindable = new(); + + /// + /// Order + /// + public int Order + { + get => OrderBindable.Value; + set => OrderBindable.Value = value; + } + + [JsonIgnore] + public Bindable HueBindable = new BindableFloat + { + MinValue = 0, + MaxValue = 1 + }; + + public float Hue + { + get => HueBindable.Value; + set => HueBindable.Value = value; + } + + [JsonIgnore] + public readonly Bindable DescriptionBindable = new(); + + public string Description { - public SingerState() - { - } - - public SingerState(int id, int mainSingerId) - { - ID = id; - MainSingerId = mainSingerId; - } - - public int ID { get; protected set; } - - public int MainSingerId { get; protected set; } - - [JsonIgnore] - public readonly Bindable OrderBindable = new(); - - /// - /// Order - /// - public int Order - { - get => OrderBindable.Value; - set => OrderBindable.Value = value; - } - - [JsonIgnore] - public Bindable HueBindable = new BindableFloat - { - MinValue = 0, - MaxValue = 1 - }; - - public float Hue - { - get => HueBindable.Value; - set => HueBindable.Value = value; - } - - [JsonIgnore] - public readonly Bindable DescriptionBindable = new(); - - public string Description - { - get => DescriptionBindable.Value; - set => DescriptionBindable.Value = value; - } + get => DescriptionBindable.Value; + set => DescriptionBindable.Value = value; } } diff --git a/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Types/ISinger.cs b/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Types/ISinger.cs index 47f375997..16646ab7b 100644 --- a/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Types/ISinger.cs +++ b/osu.Game.Rulesets.Karaoke/Beatmaps/Metadatas/Types/ISinger.cs @@ -3,12 +3,11 @@ using osu.Game.Rulesets.Karaoke.Objects.Types; -namespace osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types +namespace osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; + +public interface ISinger : IHasOrder { - public interface ISinger : IHasOrder - { - int ID { get; } + int ID { get; } - float Hue { get; } - } + float Hue { get; } } diff --git a/osu.Game.Rulesets.Karaoke/Bindables/BindableClassWithCurrent.cs b/osu.Game.Rulesets.Karaoke/Bindables/BindableClassWithCurrent.cs index 8334e3157..0618045a7 100644 --- a/osu.Game.Rulesets.Karaoke/Bindables/BindableClassWithCurrent.cs +++ b/osu.Game.Rulesets.Karaoke/Bindables/BindableClassWithCurrent.cs @@ -3,19 +3,18 @@ using osu.Framework.Bindables; -namespace osu.Game.Rulesets.Karaoke.Bindables +namespace osu.Game.Rulesets.Karaoke.Bindables; + +public class BindableClassWithCurrent : BindableWithCurrent where T : class { - public class BindableClassWithCurrent : BindableWithCurrent where T : class + /// + /// Raise and once, without any changes actually occurring. + /// This does not propagate to any outward bound bindables. + /// + public void TriggerOtherChange() { - /// - /// Raise and once, without any changes actually occurring. - /// This does not propagate to any outward bound bindables. - /// - public void TriggerOtherChange() - { - // will trigger other bindable - TriggerValueChange(Value, this); - TriggerDisabledChange(this, false); - } + // will trigger other bindable + TriggerValueChange(Value, this); + TriggerDisabledChange(this, false); } } diff --git a/osu.Game.Rulesets.Karaoke/Bindables/BindableCultureInfo.cs b/osu.Game.Rulesets.Karaoke/Bindables/BindableCultureInfo.cs index 4be103e91..a64bdcf23 100644 --- a/osu.Game.Rulesets.Karaoke/Bindables/BindableCultureInfo.cs +++ b/osu.Game.Rulesets.Karaoke/Bindables/BindableCultureInfo.cs @@ -6,46 +6,45 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Bindables +namespace osu.Game.Rulesets.Karaoke.Bindables; + +public class BindableCultureInfo : Bindable { - public class BindableCultureInfo : Bindable + public BindableCultureInfo(CultureInfo? value = default) + : base(value) { - public BindableCultureInfo(CultureInfo? value = default) - : base(value) + } + + public override void Parse(object? input) + { + if (input == null) { + Value = null; + return; } - public override void Parse(object? input) + switch (input) { - if (input == null) - { - Value = null; - return; - } - - switch (input) - { - case string str: - Value = CultureInfoUtils.CreateLoadCultureInfoByCode(str); - break; - - case int lcid: - Value = CultureInfoUtils.CreateLoadCultureInfoById(lcid); - break; - - case CultureInfo cultureInfo: - Value = cultureInfo; - break; - - default: - base.Parse(input); - break; - } - } + case string str: + Value = CultureInfoUtils.CreateLoadCultureInfoByCode(str); + break; - protected override Bindable CreateInstance() => new BindableCultureInfo(); + case int lcid: + Value = CultureInfoUtils.CreateLoadCultureInfoById(lcid); + break; - public override string ToString(string format, IFormatProvider formatProvider) - => Value != null ? CultureInfoUtils.GetSaveCultureInfoCode(Value) : string.Empty; + case CultureInfo cultureInfo: + Value = cultureInfo; + break; + + default: + base.Parse(input); + break; + } } + + protected override Bindable CreateInstance() => new BindableCultureInfo(); + + public override string ToString(string format, IFormatProvider formatProvider) + => Value != null ? CultureInfoUtils.GetSaveCultureInfoCode(Value) : string.Empty; } diff --git a/osu.Game.Rulesets.Karaoke/Bindables/BindableFontUsage.cs b/osu.Game.Rulesets.Karaoke/Bindables/BindableFontUsage.cs index 798d41075..360f3a557 100644 --- a/osu.Game.Rulesets.Karaoke/Bindables/BindableFontUsage.cs +++ b/osu.Game.Rulesets.Karaoke/Bindables/BindableFontUsage.cs @@ -8,79 +8,78 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Extensions; -namespace osu.Game.Rulesets.Karaoke.Bindables +namespace osu.Game.Rulesets.Karaoke.Bindables; + +public class BindableFontUsage : Bindable { - public class BindableFontUsage : Bindable + public BindableFontUsage(FontUsage value = default) + : base(value) { - public BindableFontUsage(FontUsage value = default) - : base(value) - { - MinFontSize = DefaultMinFontSize; - MaxFontSize = DefaultMaxFontSize; - } + MinFontSize = DefaultMinFontSize; + MaxFontSize = DefaultMaxFontSize; + } - public float MinFontSize { get; set; } - public float MaxFontSize { get; set; } + public float MinFontSize { get; set; } + public float MaxFontSize { get; set; } - protected float DefaultMinFontSize => 0; + protected float DefaultMinFontSize => 0; - protected float DefaultMaxFontSize => 200; + protected float DefaultMaxFontSize => 200; - public override FontUsage Value - { - get => base.Value; - set => base.Value = value.With(size: Math.Clamp(value.Size, MinFontSize, MaxFontSize)); - } + public override FontUsage Value + { + get => base.Value; + set => base.Value = value.With(size: Math.Clamp(value.Size, MinFontSize, MaxFontSize)); + } - public override void BindTo(Bindable them) + public override void BindTo(Bindable them) + { + if (them is BindableFontUsage other) { - if (them is BindableFontUsage other) - { - MinFontSize = Math.Max(MinFontSize, other.MinFontSize); - MaxFontSize = Math.Min(MaxFontSize, other.MaxFontSize); - } - - base.BindTo(them); + MinFontSize = Math.Max(MinFontSize, other.MinFontSize); + MaxFontSize = Math.Min(MaxFontSize, other.MaxFontSize); } - public override void Parse(object input) + base.BindTo(them); + } + + public override void Parse(object input) + { + if (input is not string str || string.IsNullOrEmpty(str)) { - if (input is not string str || string.IsNullOrEmpty(str)) - { - Value = default; - return; - } + Value = default; + return; + } - // because FontUsage.ToString() will have "," symbol. - str = str.Replace(",", string.Empty); - var regex = new Regex(@"\b(?font|family|weight|size|italics|fixedWidth)(?[=]+)(?("".*"")|(\S*))", RegexOptions.Compiled | RegexOptions.IgnoreCase); - var dictionary = regex.Matches(str).ToDictionary(k => k.GetGroupValue("key"), v => v.GetGroupValue("value")); + // because FontUsage.ToString() will have "," symbol. + str = str.Replace(",", string.Empty); + var regex = new Regex(@"\b(?font|family|weight|size|italics|fixedWidth)(?[=]+)(?("".*"")|(\S*))", RegexOptions.Compiled | RegexOptions.IgnoreCase); + var dictionary = regex.Matches(str).ToDictionary(k => k.GetGroupValue("key"), v => v.GetGroupValue("value")); - if (dictionary.ContainsKey("Font")) - { - string font = dictionary["Font"]; - string? family = font.Contains('-') ? font.Split('-').FirstOrDefault() : font; - string? weight = font.Contains('-') ? font.Split('-').LastOrDefault() : string.Empty; - float size = float.Parse(dictionary["Size"]); - bool italics = dictionary["Italics"].ToLower() == "true"; - bool fixedWidth = dictionary["FixedWidth"].ToLower() == "true"; - Value = new FontUsage(family, size, weight, italics, fixedWidth); - } - else - { - string family = dictionary["family"]; - string weight = dictionary["weight"]; - float size = float.Parse(dictionary["size"]); - bool italics = dictionary["italics"].ToLower() == "true"; - bool fixedWidth = dictionary["fixedWidth"].ToLower() == "true"; - Value = new FontUsage(family, size, weight, italics, fixedWidth); - } + if (dictionary.ContainsKey("Font")) + { + string font = dictionary["Font"]; + string? family = font.Contains('-') ? font.Split('-').FirstOrDefault() : font; + string? weight = font.Contains('-') ? font.Split('-').LastOrDefault() : string.Empty; + float size = float.Parse(dictionary["Size"]); + bool italics = dictionary["Italics"].ToLower() == "true"; + bool fixedWidth = dictionary["FixedWidth"].ToLower() == "true"; + Value = new FontUsage(family, size, weight, italics, fixedWidth); } + else + { + string family = dictionary["family"]; + string weight = dictionary["weight"]; + float size = float.Parse(dictionary["size"]); + bool italics = dictionary["italics"].ToLower() == "true"; + bool fixedWidth = dictionary["fixedWidth"].ToLower() == "true"; + Value = new FontUsage(family, size, weight, italics, fixedWidth); + } + } - protected override Bindable CreateInstance() => new BindableFontUsage(); + protected override Bindable CreateInstance() => new BindableFontUsage(); - // IDK why not being called in here while saving. - public override string ToString(string format, IFormatProvider formatProvider) - => $"family={Value.Family} weight={Value.Weight} size={Value.Size} italics={Value.Italics} fixedWidth={Value.FixedWidth}"; - } + // IDK why not being called in here while saving. + public override string ToString(string format, IFormatProvider formatProvider) + => $"family={Value.Family} weight={Value.Weight} size={Value.Size} italics={Value.Italics} fixedWidth={Value.FixedWidth}"; } diff --git a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetConfigManager.cs b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetConfigManager.cs index a0a10de65..a9fb134ef 100644 --- a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetConfigManager.cs @@ -12,163 +12,162 @@ using osu.Game.Rulesets.Karaoke.UI; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Configuration +namespace osu.Game.Rulesets.Karaoke.Configuration; + +public class KaraokeRulesetConfigManager : RulesetConfigManager { - public class KaraokeRulesetConfigManager : RulesetConfigManager + public KaraokeRulesetConfigManager(SettingsStore? settings, RulesetInfo ruleset, int? variant = null) + : base(settings, ruleset, variant) { - public KaraokeRulesetConfigManager(SettingsStore? settings, RulesetInfo ruleset, int? variant = null) - : base(settings, ruleset, variant) - { - } - - protected override void InitialiseDefaults() - { - base.InitialiseDefaults(); - - // Visual - SetDefault(KaraokeRulesetSetting.ScrollTime, 5000.0, 1000.0, 10000.0, 100.0); - SetDefault(KaraokeRulesetSetting.ScrollDirection, KaraokeScrollingDirection.Left); - SetDefault(KaraokeRulesetSetting.DisplayNoteRubyText, false); - SetDefault(KaraokeRulesetSetting.ShowCursor, true); - SetDefault(KaraokeRulesetSetting.NoteAlpha, 1, 0.2, 1, 0.01); - SetDefault(KaraokeRulesetSetting.LyricAlpha, 1, 0.2, 1, 0.01); - - // Translate - SetDefault(KaraokeRulesetSetting.UseTranslate, true); - SetDefault(KaraokeRulesetSetting.PreferLanguage, new CultureInfo("en-US")); - - SetDefault(KaraokeRulesetSetting.DisplayRuby, true); - SetDefault(KaraokeRulesetSetting.DisplayRomaji, true); - - // Pitch - SetDefault(KaraokeRulesetSetting.OverridePitchAtGameplay, false); - SetDefault(KaraokeRulesetSetting.Pitch, 0, -10, 10); - SetDefault(KaraokeRulesetSetting.OverrideVocalPitchAtGameplay, false); - SetDefault(KaraokeRulesetSetting.VocalPitch, 0, -10, 10); - SetDefault(KaraokeRulesetSetting.OverrideScoringPitchAtGameplay, false); - SetDefault(KaraokeRulesetSetting.ScoringPitch, 0, -10, 10); - - // Playback - SetDefault(KaraokeRulesetSetting.OverridePlaybackSpeedAtGameplay, false); - SetDefault(KaraokeRulesetSetting.PlaybackSpeed, 0, -10, 10); - - // Practice - SetDefault(KaraokeRulesetSetting.PracticePreemptTime, 3000.0, 0.0, 5000.0, 100.0); - - // Device - SetDefault(KaraokeRulesetSetting.MicrophoneDevice, string.Empty); - - // Font - SetDefault(KaraokeRulesetSetting.MainFont, new FontUsage("Torus", 48, "Bold"), 48f, 48f); - SetDefault(KaraokeRulesetSetting.RubyFont, new FontUsage("Torus", 20, "Bold"), 8f, 48f); - SetDefault(KaraokeRulesetSetting.RubyMargin, 5, 0, 20); - SetDefault(KaraokeRulesetSetting.RomajiFont, new FontUsage("Torus", 20, "Bold"), 8f, 48f); - SetDefault(KaraokeRulesetSetting.RomajiMargin, 0, 0, 20); - SetDefault(KaraokeRulesetSetting.ForceUseDefaultFont, false); - SetDefault(KaraokeRulesetSetting.TranslateFont, new FontUsage("Torus", 18, "Bold"), 10f, 48f); - SetDefault(KaraokeRulesetSetting.ForceUseDefaultTranslateFont, false); - SetDefault(KaraokeRulesetSetting.NoteFont, new FontUsage("Torus", 12, "Bold"), 10f, 32f); - SetDefault(KaraokeRulesetSetting.ForceUseDefaultNoteFont, false); - } - - protected override void AddBindable(KaraokeRulesetSetting lookup, Bindable bindable) - { - switch (lookup) - { - case KaraokeRulesetSetting.PreferLanguage: - // todo : need to hve a default value here because it will cause error if object is null while saving. - base.AddBindable(lookup, new BindableCultureInfo(bindable.Value as CultureInfo)); - break; - - case KaraokeRulesetSetting.MainFont: - case KaraokeRulesetSetting.RubyFont: - case KaraokeRulesetSetting.RomajiFont: - case KaraokeRulesetSetting.TranslateFont: - case KaraokeRulesetSetting.NoteFont: - base.AddBindable(lookup, new BindableFontUsage(TypeUtils.ChangeType(bindable.Value))); - break; - - default: - base.AddBindable(lookup, bindable); - break; - } - } - - protected BindableFontUsage SetDefault(KaraokeRulesetSetting setting, FontUsage fontUsage, float? minFontSize = null, float? maxFontSize = null) - { - base.SetDefault(setting, fontUsage); - - // Should not use base.setDefault's value because it will return Bindable, not BindableFontUsage - var bindable = GetOriginalBindable(setting); - if (bindable is not BindableFontUsage bindableFontUsage) - throw new InvalidCastException(nameof(bindable)); - - // Assign size restriction in here. - if (minFontSize.HasValue) bindableFontUsage.MinFontSize = minFontSize.Value; - if (maxFontSize.HasValue) bindableFontUsage.MaxFontSize = maxFontSize.Value; - - return bindableFontUsage; - } - - public override TrackedSettings CreateTrackedSettings() => new() - { - new TrackedSetting(KaraokeRulesetSetting.ScrollTime, v => new SettingDescription(v, "Scroll Time", $"{v}ms")), - new TrackedSetting(KaraokeRulesetSetting.DisplayNoteRubyText, b => new SettingDescription(b, "Toggle display", b ? "Show" : "Hide")), - new TrackedSetting(KaraokeRulesetSetting.ShowCursor, b => new SettingDescription(b, "Cursor display", b ? "Show" : "Hide")), - new TrackedSetting(KaraokeRulesetSetting.UseTranslate, b => new SettingDescription(b, "Display translate", b ? "Show" : "Hide")), - new TrackedSetting(KaraokeRulesetSetting.PreferLanguage, c => new SettingDescription(c, "Translate language", CultureInfoUtils.GetLanguageDisplayText(c))), - new TrackedSetting(KaraokeRulesetSetting.DisplayRuby, b => new SettingDescription(b, "Display ruby", b ? "Show" : "Hide")), - new TrackedSetting(KaraokeRulesetSetting.DisplayRomaji, b => new SettingDescription(b, "Display romaji", b ? "Show" : "Hide")), - new TrackedSetting(KaraokeRulesetSetting.MicrophoneDevice, d => new SettingDescription(d, "Change to the new microphone device", d)), - }; } - public enum KaraokeRulesetSetting + protected override void InitialiseDefaults() { + base.InitialiseDefaults(); + // Visual - ScrollTime, - ScrollDirection, - DisplayNoteRubyText, - ShowCursor, - NoteAlpha, - LyricAlpha, + SetDefault(KaraokeRulesetSetting.ScrollTime, 5000.0, 1000.0, 10000.0, 100.0); + SetDefault(KaraokeRulesetSetting.ScrollDirection, KaraokeScrollingDirection.Left); + SetDefault(KaraokeRulesetSetting.DisplayNoteRubyText, false); + SetDefault(KaraokeRulesetSetting.ShowCursor, true); + SetDefault(KaraokeRulesetSetting.NoteAlpha, 1, 0.2, 1, 0.01); + SetDefault(KaraokeRulesetSetting.LyricAlpha, 1, 0.2, 1, 0.01); // Translate - UseTranslate, - PreferLanguage, + SetDefault(KaraokeRulesetSetting.UseTranslate, true); + SetDefault(KaraokeRulesetSetting.PreferLanguage, new CultureInfo("en-US")); - // Ruby/Romaji - DisplayRuby, - DisplayRomaji, + SetDefault(KaraokeRulesetSetting.DisplayRuby, true); + SetDefault(KaraokeRulesetSetting.DisplayRomaji, true); // Pitch - OverridePitchAtGameplay, - Pitch, - OverrideVocalPitchAtGameplay, - VocalPitch, - OverrideScoringPitchAtGameplay, - ScoringPitch, + SetDefault(KaraokeRulesetSetting.OverridePitchAtGameplay, false); + SetDefault(KaraokeRulesetSetting.Pitch, 0, -10, 10); + SetDefault(KaraokeRulesetSetting.OverrideVocalPitchAtGameplay, false); + SetDefault(KaraokeRulesetSetting.VocalPitch, 0, -10, 10); + SetDefault(KaraokeRulesetSetting.OverrideScoringPitchAtGameplay, false); + SetDefault(KaraokeRulesetSetting.ScoringPitch, 0, -10, 10); // Playback - OverridePlaybackSpeedAtGameplay, - PlaybackSpeed, + SetDefault(KaraokeRulesetSetting.OverridePlaybackSpeedAtGameplay, false); + SetDefault(KaraokeRulesetSetting.PlaybackSpeed, 0, -10, 10); // Practice - PracticePreemptTime, + SetDefault(KaraokeRulesetSetting.PracticePreemptTime, 3000.0, 0.0, 5000.0, 100.0); // Device - MicrophoneDevice, + SetDefault(KaraokeRulesetSetting.MicrophoneDevice, string.Empty); // Font - MainFont, - RubyFont, - RubyMargin, - RomajiFont, - RomajiMargin, - ForceUseDefaultFont, - TranslateFont, - ForceUseDefaultTranslateFont, - NoteFont, - ForceUseDefaultNoteFont, + SetDefault(KaraokeRulesetSetting.MainFont, new FontUsage("Torus", 48, "Bold"), 48f, 48f); + SetDefault(KaraokeRulesetSetting.RubyFont, new FontUsage("Torus", 20, "Bold"), 8f, 48f); + SetDefault(KaraokeRulesetSetting.RubyMargin, 5, 0, 20); + SetDefault(KaraokeRulesetSetting.RomajiFont, new FontUsage("Torus", 20, "Bold"), 8f, 48f); + SetDefault(KaraokeRulesetSetting.RomajiMargin, 0, 0, 20); + SetDefault(KaraokeRulesetSetting.ForceUseDefaultFont, false); + SetDefault(KaraokeRulesetSetting.TranslateFont, new FontUsage("Torus", 18, "Bold"), 10f, 48f); + SetDefault(KaraokeRulesetSetting.ForceUseDefaultTranslateFont, false); + SetDefault(KaraokeRulesetSetting.NoteFont, new FontUsage("Torus", 12, "Bold"), 10f, 32f); + SetDefault(KaraokeRulesetSetting.ForceUseDefaultNoteFont, false); } + + protected override void AddBindable(KaraokeRulesetSetting lookup, Bindable bindable) + { + switch (lookup) + { + case KaraokeRulesetSetting.PreferLanguage: + // todo : need to hve a default value here because it will cause error if object is null while saving. + base.AddBindable(lookup, new BindableCultureInfo(bindable.Value as CultureInfo)); + break; + + case KaraokeRulesetSetting.MainFont: + case KaraokeRulesetSetting.RubyFont: + case KaraokeRulesetSetting.RomajiFont: + case KaraokeRulesetSetting.TranslateFont: + case KaraokeRulesetSetting.NoteFont: + base.AddBindable(lookup, new BindableFontUsage(TypeUtils.ChangeType(bindable.Value))); + break; + + default: + base.AddBindable(lookup, bindable); + break; + } + } + + protected BindableFontUsage SetDefault(KaraokeRulesetSetting setting, FontUsage fontUsage, float? minFontSize = null, float? maxFontSize = null) + { + base.SetDefault(setting, fontUsage); + + // Should not use base.setDefault's value because it will return Bindable, not BindableFontUsage + var bindable = GetOriginalBindable(setting); + if (bindable is not BindableFontUsage bindableFontUsage) + throw new InvalidCastException(nameof(bindable)); + + // Assign size restriction in here. + if (minFontSize.HasValue) bindableFontUsage.MinFontSize = minFontSize.Value; + if (maxFontSize.HasValue) bindableFontUsage.MaxFontSize = maxFontSize.Value; + + return bindableFontUsage; + } + + public override TrackedSettings CreateTrackedSettings() => new() + { + new TrackedSetting(KaraokeRulesetSetting.ScrollTime, v => new SettingDescription(v, "Scroll Time", $"{v}ms")), + new TrackedSetting(KaraokeRulesetSetting.DisplayNoteRubyText, b => new SettingDescription(b, "Toggle display", b ? "Show" : "Hide")), + new TrackedSetting(KaraokeRulesetSetting.ShowCursor, b => new SettingDescription(b, "Cursor display", b ? "Show" : "Hide")), + new TrackedSetting(KaraokeRulesetSetting.UseTranslate, b => new SettingDescription(b, "Display translate", b ? "Show" : "Hide")), + new TrackedSetting(KaraokeRulesetSetting.PreferLanguage, c => new SettingDescription(c, "Translate language", CultureInfoUtils.GetLanguageDisplayText(c))), + new TrackedSetting(KaraokeRulesetSetting.DisplayRuby, b => new SettingDescription(b, "Display ruby", b ? "Show" : "Hide")), + new TrackedSetting(KaraokeRulesetSetting.DisplayRomaji, b => new SettingDescription(b, "Display romaji", b ? "Show" : "Hide")), + new TrackedSetting(KaraokeRulesetSetting.MicrophoneDevice, d => new SettingDescription(d, "Change to the new microphone device", d)), + }; +} + +public enum KaraokeRulesetSetting +{ + // Visual + ScrollTime, + ScrollDirection, + DisplayNoteRubyText, + ShowCursor, + NoteAlpha, + LyricAlpha, + + // Translate + UseTranslate, + PreferLanguage, + + // Ruby/Romaji + DisplayRuby, + DisplayRomaji, + + // Pitch + OverridePitchAtGameplay, + Pitch, + OverrideVocalPitchAtGameplay, + VocalPitch, + OverrideScoringPitchAtGameplay, + ScoringPitch, + + // Playback + OverridePlaybackSpeedAtGameplay, + PlaybackSpeed, + + // Practice + PracticePreemptTime, + + // Device + MicrophoneDevice, + + // Font + MainFont, + RubyFont, + RubyMargin, + RomajiFont, + RomajiMargin, + ForceUseDefaultFont, + TranslateFont, + ForceUseDefaultTranslateFont, + NoteFont, + ForceUseDefaultNoteFont, } diff --git a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditCheckerConfigManager.cs b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditCheckerConfigManager.cs index 8213b9131..cfcba5caa 100644 --- a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditCheckerConfigManager.cs +++ b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditCheckerConfigManager.cs @@ -4,27 +4,26 @@ using osu.Game.Configuration; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Configuration +namespace osu.Game.Rulesets.Karaoke.Configuration; + +public class KaraokeRulesetEditCheckerConfigManager : InMemoryConfigManager { - public class KaraokeRulesetEditCheckerConfigManager : InMemoryConfigManager + protected override void InitialiseDefaults() { - protected override void InitialiseDefaults() - { - base.InitialiseDefaults(); + base.InitialiseDefaults(); - // Lyric - SetDefault(KaraokeRulesetEditCheckerSetting.LyricRubyPositionSorting, TextTagsUtils.Sorting.Asc); - SetDefault(KaraokeRulesetEditCheckerSetting.LyricRomajiPositionSorting, TextTagsUtils.Sorting.Asc); - SetDefault(KaraokeRulesetEditCheckerSetting.LyricTimeTagTimeSelfCheck, SelfCheck.BasedOnStart); - SetDefault(KaraokeRulesetEditCheckerSetting.LyricTimeTagTimeGroupCheck, GroupCheck.Asc); - } + // Lyric + SetDefault(KaraokeRulesetEditCheckerSetting.LyricRubyPositionSorting, TextTagsUtils.Sorting.Asc); + SetDefault(KaraokeRulesetEditCheckerSetting.LyricRomajiPositionSorting, TextTagsUtils.Sorting.Asc); + SetDefault(KaraokeRulesetEditCheckerSetting.LyricTimeTagTimeSelfCheck, SelfCheck.BasedOnStart); + SetDefault(KaraokeRulesetEditCheckerSetting.LyricTimeTagTimeGroupCheck, GroupCheck.Asc); } +} - public enum KaraokeRulesetEditCheckerSetting - { - LyricRubyPositionSorting, - LyricRomajiPositionSorting, - LyricTimeTagTimeSelfCheck, - LyricTimeTagTimeGroupCheck - } +public enum KaraokeRulesetEditCheckerSetting +{ + LyricRubyPositionSorting, + LyricRomajiPositionSorting, + LyricTimeTagTimeSelfCheck, + LyricTimeTagTimeGroupCheck } diff --git a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditConfigManager.cs b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditConfigManager.cs index b218d02eb..4dd13599e 100644 --- a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditConfigManager.cs +++ b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditConfigManager.cs @@ -3,26 +3,25 @@ using osu.Game.Configuration; -namespace osu.Game.Rulesets.Karaoke.Configuration +namespace osu.Game.Rulesets.Karaoke.Configuration; + +public class KaraokeRulesetEditConfigManager : InMemoryConfigManager { - public class KaraokeRulesetEditConfigManager : InMemoryConfigManager + protected override void InitialiseDefaults() { - protected override void InitialiseDefaults() - { - base.InitialiseDefaults(); - - // Note editor - SetDefault(KaraokeRulesetEditSetting.DisplayRuby, true); - SetDefault(KaraokeRulesetEditSetting.DisplayRomaji, true); - SetDefault(KaraokeRulesetEditSetting.DisplayTranslate, true); - } - } + base.InitialiseDefaults(); - public enum KaraokeRulesetEditSetting - { // Note editor - DisplayRuby, - DisplayRomaji, - DisplayTranslate, + SetDefault(KaraokeRulesetEditSetting.DisplayRuby, true); + SetDefault(KaraokeRulesetEditSetting.DisplayRomaji, true); + SetDefault(KaraokeRulesetEditSetting.DisplayTranslate, true); } } + +public enum KaraokeRulesetEditSetting +{ + // Note editor + DisplayRuby, + DisplayRomaji, + DisplayTranslate, +} diff --git a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditGeneratorConfigManager.cs b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditGeneratorConfigManager.cs index 9ede46c91..28d6486e6 100644 --- a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditGeneratorConfigManager.cs +++ b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetEditGeneratorConfigManager.cs @@ -17,122 +17,121 @@ using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Ja; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Zh; -namespace osu.Game.Rulesets.Karaoke.Configuration +namespace osu.Game.Rulesets.Karaoke.Configuration; + +public class KaraokeRulesetEditGeneratorConfigManager : InMemoryConfigManager { - public class KaraokeRulesetEditGeneratorConfigManager : InMemoryConfigManager + protected override void InitialiseDefaults() { - protected override void InitialiseDefaults() - { - base.InitialiseDefaults(); + base.InitialiseDefaults(); - // Beatmap page - SetDefault(); + // Beatmap page + SetDefault(); - // Classic stage. - SetDefault(); - SetDefault(); - SetDefault(); + // Classic stage. + SetDefault(); + SetDefault(); + SetDefault(); - // Preview stage. - SetDefault(); + // Preview stage. + SetDefault(); - // Language detection - SetDefault(); + // Language detection + SetDefault(); - // Language detection - SetDefault(); + // Language detection + SetDefault(); - // Note generator - SetDefault(); + // Note generator + SetDefault(); - // Romaji generator - SetDefault(); + // Romaji generator + SetDefault(); - // Ruby generator - SetDefault(); + // Ruby generator + SetDefault(); - // Time tag generator - SetDefault(); - SetDefault(); - } + // Time tag generator + SetDefault(); + SetDefault(); + } - protected void SetDefault() where T : GeneratorConfig, new() - { - var defaultValue = CreateDefaultConfig(); - var setting = GetSettingByType(); - - SetDefault(setting, defaultValue); - } - - protected static T CreateDefaultConfig() where T : GeneratorConfig, new() => new(); - - protected static KaraokeRulesetEditGeneratorSetting GetSettingByType() => - typeof(TValue) switch - { - Type t when t == typeof(PageGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.BeatmapPageGeneratorConfig, - Type t when t == typeof(ClassicLyricLayoutCategoryGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ClassicLyricLayoutCategoryGeneratorConfig, - Type t when t == typeof(ClassicLyricTimingInfoGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ClassicLyricTimingInfoGeneratorConfig, - Type t when t == typeof(ClassicStageInfoGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ClassicStageInfoGeneratorConfig, - Type t when t == typeof(PreviewStageInfoGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.PreviewStageInfoGeneratorConfig, - Type t when t == typeof(ReferenceLyricDetectorConfig) => KaraokeRulesetEditGeneratorSetting.ReferenceLyricDetectorConfig, - Type t when t == typeof(LanguageDetectorConfig) => KaraokeRulesetEditGeneratorSetting.LanguageDetectorConfig, - Type t when t == typeof(NoteGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.NoteGeneratorConfig, - Type t when t == typeof(JaRomajiTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.JaRomajiTagGeneratorConfig, - Type t when t == typeof(JaRubyTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.JaRubyTagGeneratorConfig, - Type t when t == typeof(JaTimeTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.JaTimeTagGeneratorConfig, - Type t when t == typeof(ZhTimeTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ZhTimeTagGeneratorConfig, - _ => throw new NotSupportedException() - }; - - public TValue Get() where TValue : GeneratorConfig, new() - { - var lookup = GetSettingByType(); - return Get(lookup); - } + protected void SetDefault() where T : GeneratorConfig, new() + { + var defaultValue = CreateDefaultConfig(); + var setting = GetSettingByType(); - public GeneratorConfig GetGeneratorConfig(KaraokeRulesetEditGeneratorSetting lookup) - { - if (!ConfigStore.TryGetValue(lookup, out IBindable? obj)) - throw new KeyNotFoundException(); + SetDefault(setting, defaultValue); + } - var prop = obj.GetType().GetProperty("Value"); - if (prop?.GetValue(obj) is not GeneratorConfig generatorConfig) - throw new InvalidCastException(); + protected static T CreateDefaultConfig() where T : GeneratorConfig, new() => new(); - return generatorConfig; - } + protected static KaraokeRulesetEditGeneratorSetting GetSettingByType() => + typeof(TValue) switch + { + Type t when t == typeof(PageGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.BeatmapPageGeneratorConfig, + Type t when t == typeof(ClassicLyricLayoutCategoryGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ClassicLyricLayoutCategoryGeneratorConfig, + Type t when t == typeof(ClassicLyricTimingInfoGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ClassicLyricTimingInfoGeneratorConfig, + Type t when t == typeof(ClassicStageInfoGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ClassicStageInfoGeneratorConfig, + Type t when t == typeof(PreviewStageInfoGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.PreviewStageInfoGeneratorConfig, + Type t when t == typeof(ReferenceLyricDetectorConfig) => KaraokeRulesetEditGeneratorSetting.ReferenceLyricDetectorConfig, + Type t when t == typeof(LanguageDetectorConfig) => KaraokeRulesetEditGeneratorSetting.LanguageDetectorConfig, + Type t when t == typeof(NoteGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.NoteGeneratorConfig, + Type t when t == typeof(JaRomajiTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.JaRomajiTagGeneratorConfig, + Type t when t == typeof(JaRubyTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.JaRubyTagGeneratorConfig, + Type t when t == typeof(JaTimeTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.JaTimeTagGeneratorConfig, + Type t when t == typeof(ZhTimeTagGeneratorConfig) => KaraokeRulesetEditGeneratorSetting.ZhTimeTagGeneratorConfig, + _ => throw new NotSupportedException() + }; + + public TValue Get() where TValue : GeneratorConfig, new() + { + var lookup = GetSettingByType(); + return Get(lookup); } - public enum KaraokeRulesetEditGeneratorSetting + public GeneratorConfig GetGeneratorConfig(KaraokeRulesetEditGeneratorSetting lookup) { - // Beatmap - BeatmapPageGeneratorConfig, + if (!ConfigStore.TryGetValue(lookup, out IBindable? obj)) + throw new KeyNotFoundException(); - // Classic stage. - ClassicLyricLayoutCategoryGeneratorConfig, - ClassicLyricTimingInfoGeneratorConfig, - ClassicStageInfoGeneratorConfig, + var prop = obj.GetType().GetProperty("Value"); + if (prop?.GetValue(obj) is not GeneratorConfig generatorConfig) + throw new InvalidCastException(); - // Preview stage. - PreviewStageInfoGeneratorConfig, + return generatorConfig; + } +} - // Reference lyric detection. - ReferenceLyricDetectorConfig, +public enum KaraokeRulesetEditGeneratorSetting +{ + // Beatmap + BeatmapPageGeneratorConfig, - // Language detection - LanguageDetectorConfig, + // Classic stage. + ClassicLyricLayoutCategoryGeneratorConfig, + ClassicLyricTimingInfoGeneratorConfig, + ClassicStageInfoGeneratorConfig, - // Note generator - NoteGeneratorConfig, + // Preview stage. + PreviewStageInfoGeneratorConfig, - // Romaji generator - JaRomajiTagGeneratorConfig, + // Reference lyric detection. + ReferenceLyricDetectorConfig, - // Ruby generator - JaRubyTagGeneratorConfig, + // Language detection + LanguageDetectorConfig, - // Time tag generator - JaTimeTagGeneratorConfig, - ZhTimeTagGeneratorConfig - } + // Note generator + NoteGeneratorConfig, + + // Romaji generator + JaRomajiTagGeneratorConfig, + + // Ruby generator + JaRubyTagGeneratorConfig, + + // Time tag generator + JaTimeTagGeneratorConfig, + ZhTimeTagGeneratorConfig } diff --git a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetLyricEditorConfigManager.cs b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetLyricEditorConfigManager.cs index ae20940a0..4e339fefb 100644 --- a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetLyricEditorConfigManager.cs +++ b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeRulesetLyricEditorConfigManager.cs @@ -9,83 +9,82 @@ using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.States; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Configuration +namespace osu.Game.Rulesets.Karaoke.Configuration; + +public class KaraokeRulesetLyricEditorConfigManager : InMemoryConfigManager { - public class KaraokeRulesetLyricEditorConfigManager : InMemoryConfigManager + protected override void InitialiseDefaults() { - protected override void InitialiseDefaults() - { - base.InitialiseDefaults(); - - // General - SetDefault(KaraokeRulesetLyricEditorSetting.LyricEditorPreferLayout, LyricEditorLayout.Preview); - SetDefault(KaraokeRulesetLyricEditorSetting.LyricEditorFontSize, FontUtils.DEFAULT_FONT_SIZE); - SetDefault(KaraokeRulesetLyricEditorSetting.AutoFocusToEditLyric, true); - SetDefault(KaraokeRulesetLyricEditorSetting.AutoFocusToEditLyricSkipRows, 1, 0, 4); - SetDefault(KaraokeRulesetLyricEditorSetting.ClickToLockLyricState, LockState.Partial); - - // Composer - SetDefault(KaraokeRulesetLyricEditorSetting.ShowPropertyPanelInComposer, true); - SetDefault(KaraokeRulesetLyricEditorSetting.ShowInvalidInfoInComposer, true); - SetDefault(KaraokeRulesetLyricEditorSetting.FontSizeInComposer, FontUtils.DEFAULT_FONT_SIZE_IN_COMPOSER); - - // Create time-tag. - SetDefault(KaraokeRulesetLyricEditorSetting.CreateTimeTagEditMode, CreateTimeTagEditMode.Create); - SetDefault(KaraokeRulesetLyricEditorSetting.CreateTimeTagMovingCaretMode, MovingTimeTagCaretMode.None); - - // Recording - SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagMovingCaretMode, MovingTimeTagCaretMode.None); - SetDefault(KaraokeRulesetLyricEditorSetting.RecordingAutoMoveToNextTimeTag, true); - SetDefault(KaraokeRulesetLyricEditorSetting.RecordingChangeTimeWhileMovingTheCaret, true); - SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagShowWaveform, true); - SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagWaveformOpacity, 0.5f, 0, 1, 0.01f); - SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagShowTick, true); - SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagTickOpacity, 0.5f, 0, 1, 0.01f); + base.InitialiseDefaults(); - // Adjust - SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagShowWaveform, true); - SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagWaveformOpacity, 0.5f, 0, 1, 0.01f); - SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagShowTick, true); - SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagTickOpacity, 0.5f, 0, 1, 0.01f); - } - - /// - /// Binds a local bindable with a configuration-backed bindable. - /// - public void BindWith(KaraokeRulesetLyricEditorSetting lookup, IBindable bindable) => bindable.BindTo(GetOriginalBindable(lookup)); - } - - public enum KaraokeRulesetLyricEditorSetting - { // General - LyricEditorPreferLayout, - LyricEditorFontSize, - AutoFocusToEditLyric, - AutoFocusToEditLyricSkipRows, - ClickToLockLyricState, + SetDefault(KaraokeRulesetLyricEditorSetting.LyricEditorPreferLayout, LyricEditorLayout.Preview); + SetDefault(KaraokeRulesetLyricEditorSetting.LyricEditorFontSize, FontUtils.DEFAULT_FONT_SIZE); + SetDefault(KaraokeRulesetLyricEditorSetting.AutoFocusToEditLyric, true); + SetDefault(KaraokeRulesetLyricEditorSetting.AutoFocusToEditLyricSkipRows, 1, 0, 4); + SetDefault(KaraokeRulesetLyricEditorSetting.ClickToLockLyricState, LockState.Partial); // Composer - ShowPropertyPanelInComposer, - ShowInvalidInfoInComposer, - FontSizeInComposer, + SetDefault(KaraokeRulesetLyricEditorSetting.ShowPropertyPanelInComposer, true); + SetDefault(KaraokeRulesetLyricEditorSetting.ShowInvalidInfoInComposer, true); + SetDefault(KaraokeRulesetLyricEditorSetting.FontSizeInComposer, FontUtils.DEFAULT_FONT_SIZE_IN_COMPOSER); // Create time-tag. - CreateTimeTagEditMode, - CreateTimeTagMovingCaretMode, + SetDefault(KaraokeRulesetLyricEditorSetting.CreateTimeTagEditMode, CreateTimeTagEditMode.Create); + SetDefault(KaraokeRulesetLyricEditorSetting.CreateTimeTagMovingCaretMode, MovingTimeTagCaretMode.None); // Recording - RecordingTimeTagMovingCaretMode, - RecordingAutoMoveToNextTimeTag, - RecordingChangeTimeWhileMovingTheCaret, - RecordingTimeTagShowWaveform, - RecordingTimeTagWaveformOpacity, - RecordingTimeTagShowTick, - RecordingTimeTagTickOpacity, + SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagMovingCaretMode, MovingTimeTagCaretMode.None); + SetDefault(KaraokeRulesetLyricEditorSetting.RecordingAutoMoveToNextTimeTag, true); + SetDefault(KaraokeRulesetLyricEditorSetting.RecordingChangeTimeWhileMovingTheCaret, true); + SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagShowWaveform, true); + SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagWaveformOpacity, 0.5f, 0, 1, 0.01f); + SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagShowTick, true); + SetDefault(KaraokeRulesetLyricEditorSetting.RecordingTimeTagTickOpacity, 0.5f, 0, 1, 0.01f); // Adjust - AdjustTimeTagShowWaveform, - AdjustTimeTagWaveformOpacity, - AdjustTimeTagShowTick, - AdjustTimeTagTickOpacity, + SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagShowWaveform, true); + SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagWaveformOpacity, 0.5f, 0, 1, 0.01f); + SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagShowTick, true); + SetDefault(KaraokeRulesetLyricEditorSetting.AdjustTimeTagTickOpacity, 0.5f, 0, 1, 0.01f); } + + /// + /// Binds a local bindable with a configuration-backed bindable. + /// + public void BindWith(KaraokeRulesetLyricEditorSetting lookup, IBindable bindable) => bindable.BindTo(GetOriginalBindable(lookup)); +} + +public enum KaraokeRulesetLyricEditorSetting +{ + // General + LyricEditorPreferLayout, + LyricEditorFontSize, + AutoFocusToEditLyric, + AutoFocusToEditLyricSkipRows, + ClickToLockLyricState, + + // Composer + ShowPropertyPanelInComposer, + ShowInvalidInfoInComposer, + FontSizeInComposer, + + // Create time-tag. + CreateTimeTagEditMode, + CreateTimeTagMovingCaretMode, + + // Recording + RecordingTimeTagMovingCaretMode, + RecordingAutoMoveToNextTimeTag, + RecordingChangeTimeWhileMovingTheCaret, + RecordingTimeTagShowWaveform, + RecordingTimeTagWaveformOpacity, + RecordingTimeTagShowTick, + RecordingTimeTagTickOpacity, + + // Adjust + AdjustTimeTagShowWaveform, + AdjustTimeTagWaveformOpacity, + AdjustTimeTagShowTick, + AdjustTimeTagTickOpacity, } diff --git a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeSessionStatics.cs b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeSessionStatics.cs index 05ee7acb1..4c8ecda95 100644 --- a/osu.Game.Rulesets.Karaoke/Configuration/KaraokeSessionStatics.cs +++ b/osu.Game.Rulesets.Karaoke/Configuration/KaraokeSessionStatics.cs @@ -11,79 +11,78 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.UI.Components; -namespace osu.Game.Rulesets.Karaoke.Configuration +namespace osu.Game.Rulesets.Karaoke.Configuration; + +public class KaraokeSessionStatics : InMemoryConfigManager { - public class KaraokeSessionStatics : InMemoryConfigManager - { - private readonly KaraokeRulesetConfigManager rulesetConfigManager; - - public KaraokeSessionStatics(KaraokeRulesetConfigManager config, IBeatmap? beatmap) - { - rulesetConfigManager = config; - - // Translate - bool useTranslate = getValue(KaraokeRulesetSetting.UseTranslate); - var preferLanguage = getValue(KaraokeRulesetSetting.PreferLanguage); - var availableTranslate = beatmap?.AvailableTranslates(); - var selectedLanguage = availableTranslate?.FirstOrDefault(t => EqualityComparer.Default.Equals(t, preferLanguage)) ?? availableTranslate?.FirstOrDefault(); - SetDefault(KaraokeRulesetSession.UseTranslate, useTranslate); - SetDefault(KaraokeRulesetSession.PreferLanguage, selectedLanguage); - - bool displayRuby = getValue(KaraokeRulesetSetting.DisplayRuby); - bool displayRomaji = getValue(KaraokeRulesetSetting.DisplayRomaji); - SetDefault(KaraokeRulesetSession.DisplayRuby, displayRuby); - SetDefault(KaraokeRulesetSession.DisplayRomaji, displayRomaji); - - // Pitch - bool overridePitch = getValue(KaraokeRulesetSetting.OverridePitchAtGameplay); - int pitchValue = getValue(KaraokeRulesetSetting.Pitch); - SetDefault(KaraokeRulesetSession.Pitch, overridePitch ? pitchValue : 0, -10, 10); - - bool overrideVocalPitch = getValue(KaraokeRulesetSetting.OverrideVocalPitchAtGameplay); - int vocalPitchValue = getValue(KaraokeRulesetSetting.VocalPitch); - SetDefault(KaraokeRulesetSession.VocalPitch, overrideVocalPitch ? vocalPitchValue : 0, -10, 10); - - bool overrideScoringPitch = getValue(KaraokeRulesetSetting.OverrideScoringPitchAtGameplay); - int scoringPitchValue = getValue(KaraokeRulesetSetting.ScoringPitch); - SetDefault(KaraokeRulesetSession.ScoringPitch, overrideScoringPitch ? scoringPitchValue : 0, -8, 8); - - // Playback - bool overridePlaybackSpeed = getValue(KaraokeRulesetSetting.OverridePlaybackSpeedAtGameplay); - int playbackSpeedValue = getValue(KaraokeRulesetSetting.PlaybackSpeed); - SetDefault(KaraokeRulesetSession.PlaybackSpeed, overridePlaybackSpeed ? playbackSpeedValue : 0, -10, 10); - - // Practice - SetDefault(KaraokeRulesetSession.SingingLyrics, Array.Empty()); - - // Scoring status - SetDefault(KaraokeRulesetSession.ScoringStatus, ScoringStatusMode.NotInitialized); - } - - private T getValue(KaraokeRulesetSetting setting) => rulesetConfigManager.Get(setting); - } + private readonly KaraokeRulesetConfigManager rulesetConfigManager; - public enum KaraokeRulesetSession + public KaraokeSessionStatics(KaraokeRulesetConfigManager config, IBeatmap? beatmap) { - // Translate - UseTranslate, - PreferLanguage, + rulesetConfigManager = config; - // Ruby/Romaji - DisplayRuby, - DisplayRomaji, + // Translate + bool useTranslate = getValue(KaraokeRulesetSetting.UseTranslate); + var preferLanguage = getValue(KaraokeRulesetSetting.PreferLanguage); + var availableTranslate = beatmap?.AvailableTranslates(); + var selectedLanguage = availableTranslate?.FirstOrDefault(t => EqualityComparer.Default.Equals(t, preferLanguage)) ?? availableTranslate?.FirstOrDefault(); + SetDefault(KaraokeRulesetSession.UseTranslate, useTranslate); + SetDefault(KaraokeRulesetSession.PreferLanguage, selectedLanguage); + + bool displayRuby = getValue(KaraokeRulesetSetting.DisplayRuby); + bool displayRomaji = getValue(KaraokeRulesetSetting.DisplayRomaji); + SetDefault(KaraokeRulesetSession.DisplayRuby, displayRuby); + SetDefault(KaraokeRulesetSession.DisplayRomaji, displayRomaji); // Pitch - Pitch, - VocalPitch, - ScoringPitch, + bool overridePitch = getValue(KaraokeRulesetSetting.OverridePitchAtGameplay); + int pitchValue = getValue(KaraokeRulesetSetting.Pitch); + SetDefault(KaraokeRulesetSession.Pitch, overridePitch ? pitchValue : 0, -10, 10); + + bool overrideVocalPitch = getValue(KaraokeRulesetSetting.OverrideVocalPitchAtGameplay); + int vocalPitchValue = getValue(KaraokeRulesetSetting.VocalPitch); + SetDefault(KaraokeRulesetSession.VocalPitch, overrideVocalPitch ? vocalPitchValue : 0, -10, 10); + + bool overrideScoringPitch = getValue(KaraokeRulesetSetting.OverrideScoringPitchAtGameplay); + int scoringPitchValue = getValue(KaraokeRulesetSetting.ScoringPitch); + SetDefault(KaraokeRulesetSession.ScoringPitch, overrideScoringPitch ? scoringPitchValue : 0, -8, 8); // Playback - PlaybackSpeed, + bool overridePlaybackSpeed = getValue(KaraokeRulesetSetting.OverridePlaybackSpeedAtGameplay); + int playbackSpeedValue = getValue(KaraokeRulesetSetting.PlaybackSpeed); + SetDefault(KaraokeRulesetSession.PlaybackSpeed, overridePlaybackSpeed ? playbackSpeedValue : 0, -10, 10); // Practice - SingingLyrics, + SetDefault(KaraokeRulesetSession.SingingLyrics, Array.Empty()); // Scoring status - ScoringStatus, + SetDefault(KaraokeRulesetSession.ScoringStatus, ScoringStatusMode.NotInitialized); } + + private T getValue(KaraokeRulesetSetting setting) => rulesetConfigManager.Get(setting); +} + +public enum KaraokeRulesetSession +{ + // Translate + UseTranslate, + PreferLanguage, + + // Ruby/Romaji + DisplayRuby, + DisplayRomaji, + + // Pitch + Pitch, + VocalPitch, + ScoringPitch, + + // Playback + PlaybackSpeed, + + // Practice + SingingLyrics, + + // Scoring status + ScoringStatus, } diff --git a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyAttributes.cs b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyAttributes.cs index 671923145..2eb1aaf2e 100644 --- a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyAttributes.cs +++ b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyAttributes.cs @@ -6,43 +6,42 @@ using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; -namespace osu.Game.Rulesets.Karaoke.Difficulty +namespace osu.Game.Rulesets.Karaoke.Difficulty; + +public class KaraokeDifficultyAttributes : DifficultyAttributes { - public class KaraokeDifficultyAttributes : DifficultyAttributes + /// + /// The hit window for a GREAT hit inclusive of rate-adjusting mods (DT/HT/etc). + /// + /// + /// Rate-adjusting mods do not affect the hit window at all in osu-stable. + /// + [JsonProperty("great_hit_window")] + public double GreatHitWindow { get; set; } + + /// + /// The score multiplier applied via score-reducing mods. + /// + [JsonProperty("score_multiplier")] + public double ScoreMultiplier { get; set; } + + public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() + { + foreach (var v in base.ToDatabaseAttributes()) + yield return v; + + // Todo: osu!mania doesn't output MaxCombo attribute for some reason. + yield return (ATTRIB_ID_DIFFICULTY, StarRating); + yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); + yield return (ATTRIB_ID_SCORE_MULTIPLIER, ScoreMultiplier); + } + + public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) { - /// - /// The hit window for a GREAT hit inclusive of rate-adjusting mods (DT/HT/etc). - /// - /// - /// Rate-adjusting mods do not affect the hit window at all in osu-stable. - /// - [JsonProperty("great_hit_window")] - public double GreatHitWindow { get; set; } - - /// - /// The score multiplier applied via score-reducing mods. - /// - [JsonProperty("score_multiplier")] - public double ScoreMultiplier { get; set; } - - public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes() - { - foreach (var v in base.ToDatabaseAttributes()) - yield return v; - - // Todo: osu!mania doesn't output MaxCombo attribute for some reason. - yield return (ATTRIB_ID_DIFFICULTY, StarRating); - yield return (ATTRIB_ID_GREAT_HIT_WINDOW, GreatHitWindow); - yield return (ATTRIB_ID_SCORE_MULTIPLIER, ScoreMultiplier); - } - - public override void FromDatabaseAttributes(IReadOnlyDictionary values, IBeatmapOnlineInfo onlineInfo) - { - base.FromDatabaseAttributes(values, onlineInfo); - - StarRating = values[ATTRIB_ID_DIFFICULTY]; - GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW]; - ScoreMultiplier = values[ATTRIB_ID_SCORE_MULTIPLIER]; - } + base.FromDatabaseAttributes(values, onlineInfo); + + StarRating = values[ATTRIB_ID_DIFFICULTY]; + GreatHitWindow = values[ATTRIB_ID_GREAT_HIT_WINDOW]; + ScoreMultiplier = values[ATTRIB_ID_SCORE_MULTIPLIER]; } } diff --git a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyCalculator.cs b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyCalculator.cs index 265392052..75daf79f7 100644 --- a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokeDifficultyCalculator.cs @@ -16,89 +16,88 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Mods; -namespace osu.Game.Rulesets.Karaoke.Difficulty +namespace osu.Game.Rulesets.Karaoke.Difficulty; + +public class KaraokeDifficultyCalculator : DifficultyCalculator { - public class KaraokeDifficultyCalculator : DifficultyCalculator + private const double star_scaling_factor = 0.018; + + private readonly bool isForCurrentRuleset; + private readonly double originalOverallDifficulty; + + public KaraokeDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap) + : base(ruleset, beatmap) { - private const double star_scaling_factor = 0.018; + isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.MatchesOnlineID(ruleset); + originalOverallDifficulty = beatmap.BeatmapInfo.Difficulty.OverallDifficulty; + } - private readonly bool isForCurrentRuleset; - private readonly double originalOverallDifficulty; + protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) + { + if (beatmap.HitObjects.Count == 0) + return new KaraokeDifficultyAttributes { Mods = mods }; - public KaraokeDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap) - : base(ruleset, beatmap) + return new KaraokeDifficultyAttributes { - isForCurrentRuleset = beatmap.BeatmapInfo.Ruleset.MatchesOnlineID(ruleset); - originalOverallDifficulty = beatmap.BeatmapInfo.Difficulty.OverallDifficulty; - } + StarRating = skills[0].DifficultyValue() * star_scaling_factor, + Mods = mods, + // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future + GreatHitWindow = (int)Math.Ceiling(getHitWindow300(mods) / clockRate), + MaxCombo = beatmap.HitObjects.Sum(h => h is Note ? 2 : 1), + }; + } - protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) - { - if (beatmap.HitObjects.Count == 0) - return new KaraokeDifficultyAttributes { Mods = mods }; - - return new KaraokeDifficultyAttributes - { - StarRating = skills[0].DifficultyValue() * star_scaling_factor, - Mods = mods, - // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future - GreatHitWindow = (int)Math.Ceiling(getHitWindow300(mods) / clockRate), - MaxCombo = beatmap.HitObjects.Sum(h => h is Note ? 2 : 1), - }; - } + protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) + { + var sortedObjects = beatmap.HitObjects.OfType().ToArray(); - protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) - { - var sortedObjects = beatmap.HitObjects.OfType().ToArray(); + // todo : might have a sort. + // LegacySortHelper.Sort(sortedObjects, Comparer.Create((a, b) => (int)Math.Round(a.StartTime) - (int)Math.Round(b.StartTime))); - // todo : might have a sort. - // LegacySortHelper.Sort(sortedObjects, Comparer.Create((a, b) => (int)Math.Round(a.StartTime) - (int)Math.Round(b.StartTime))); + var objects = new List(); - var objects = new List(); + for (int i = 1; i < sortedObjects.Length; i++) + objects.Add(new KaraokeDifficultyHitObject(sortedObjects[i], sortedObjects[i - 1], clockRate, objects, objects.Count)); - for (int i = 1; i < sortedObjects.Length; i++) - objects.Add(new KaraokeDifficultyHitObject(sortedObjects[i], sortedObjects[i - 1], clockRate, objects, objects.Count)); + return objects; + } - return objects; - } + // Sorting is done in CreateDifficultyHitObjects, since the full list of hitobjects is required. + protected override IEnumerable SortObjects(IEnumerable input) => input; - // Sorting is done in CreateDifficultyHitObjects, since the full list of hitobjects is required. - protected override IEnumerable SortObjects(IEnumerable input) => input; + protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[] + { + new Strain(mods, ((KaraokeBeatmap)beatmap).NoteInfo) + }; - protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => new Skill[] + protected override Mod[] DifficultyAdjustmentMods => + new Mod[] { - new Strain(mods, ((KaraokeBeatmap)beatmap).NoteInfo) + new KaraokeModDisableNote(), + new KaraokeModHiddenNote(), }; - protected override Mod[] DifficultyAdjustmentMods => - new Mod[] - { - new KaraokeModDisableNote(), - new KaraokeModHiddenNote(), - }; + private int getHitWindow300(Mod[] mods) + { + if (isForCurrentRuleset) + { + double od = Math.Min(10.0, Math.Max(0, 10.0 - originalOverallDifficulty)); + return applyModAdjustments(34 + 3 * od, mods); + } + + if (Math.Round(originalOverallDifficulty) > 4) + return applyModAdjustments(34, mods); - private int getHitWindow300(Mod[] mods) + return applyModAdjustments(47, mods); + + static int applyModAdjustments(double value, Mod[] mods) { - if (isForCurrentRuleset) - { - double od = Math.Min(10.0, Math.Max(0, 10.0 - originalOverallDifficulty)); - return applyModAdjustments(34 + 3 * od, mods); - } - - if (Math.Round(originalOverallDifficulty) > 4) - return applyModAdjustments(34, mods); - - return applyModAdjustments(47, mods); - - static int applyModAdjustments(double value, Mod[] mods) - { - if (mods.Any(m => m is KaraokeModDisableNote)) - value /= 1.4; - else if (mods.Any(m => m is KaraokeModHiddenNote)) - value *= 1.4; - - return (int)value; - } + if (mods.Any(m => m is KaraokeModDisableNote)) + value /= 1.4; + else if (mods.Any(m => m is KaraokeModHiddenNote)) + value *= 1.4; + + return (int)value; } } } diff --git a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceAttributes.cs b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceAttributes.cs index 84388cff9..7471d5ee0 100644 --- a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceAttributes.cs +++ b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceAttributes.cs @@ -5,26 +5,25 @@ using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; -namespace osu.Game.Rulesets.Karaoke.Difficulty +namespace osu.Game.Rulesets.Karaoke.Difficulty; + +public class KaraokePerformanceAttributes : PerformanceAttributes { - public class KaraokePerformanceAttributes : PerformanceAttributes - { - [JsonProperty("difficulty")] - public double Difficulty { get; set; } + [JsonProperty("difficulty")] + public double Difficulty { get; set; } - [JsonProperty("accuracy")] - public double Accuracy { get; set; } + [JsonProperty("accuracy")] + public double Accuracy { get; set; } - [JsonProperty("scaled_score")] - public double ScaledScore { get; set; } + [JsonProperty("scaled_score")] + public double ScaledScore { get; set; } - public override IEnumerable GetAttributesForDisplay() - { - foreach (var attribute in base.GetAttributesForDisplay()) - yield return attribute; + public override IEnumerable GetAttributesForDisplay() + { + foreach (var attribute in base.GetAttributesForDisplay()) + yield return attribute; - yield return new PerformanceDisplayAttribute(nameof(Difficulty), "Difficulty", Difficulty); - yield return new PerformanceDisplayAttribute(nameof(Accuracy), "Accuracy", Accuracy); - } + yield return new PerformanceDisplayAttribute(nameof(Difficulty), "Difficulty", Difficulty); + yield return new PerformanceDisplayAttribute(nameof(Accuracy), "Accuracy", Accuracy); } } diff --git a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceCalculator.cs b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceCalculator.cs index c2147f603..513ffef1a 100644 --- a/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceCalculator.cs +++ b/osu.Game.Rulesets.Karaoke/Difficulty/KaraokePerformanceCalculator.cs @@ -9,119 +9,118 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; -namespace osu.Game.Rulesets.Karaoke.Difficulty +namespace osu.Game.Rulesets.Karaoke.Difficulty; + +public class KaraokePerformanceCalculator : PerformanceCalculator { - public class KaraokePerformanceCalculator : PerformanceCalculator + // Score after being scaled by non-difficulty-increasing mods + private double scaledScore; + + private int countPerfect; + private int countGreat; + private int countGood; + private int countOk; + private int countMeh; + private int countMiss; + + public KaraokePerformanceCalculator() + : base(new KaraokeRuleset()) { - // Score after being scaled by non-difficulty-increasing mods - private double scaledScore; - - private int countPerfect; - private int countGreat; - private int countGood; - private int countOk; - private int countMeh; - private int countMiss; - - public KaraokePerformanceCalculator() - : base(new KaraokeRuleset()) - { - } + } - protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + { + var karaokeAttributes = (KaraokeDifficultyAttributes)attributes; + + scaledScore = score.TotalScore; + countPerfect = score.Statistics.GetValueOrDefault(HitResult.Perfect); + countGreat = score.Statistics.GetValueOrDefault(HitResult.Great); + countGood = score.Statistics.GetValueOrDefault(HitResult.Good); + countOk = score.Statistics.GetValueOrDefault(HitResult.Ok); + countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh); + countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss); + + if (karaokeAttributes.ScoreMultiplier > 0) { - var karaokeAttributes = (KaraokeDifficultyAttributes)attributes; - - scaledScore = score.TotalScore; - countPerfect = score.Statistics.GetValueOrDefault(HitResult.Perfect); - countGreat = score.Statistics.GetValueOrDefault(HitResult.Great); - countGood = score.Statistics.GetValueOrDefault(HitResult.Good); - countOk = score.Statistics.GetValueOrDefault(HitResult.Ok); - countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh); - countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss); - - if (karaokeAttributes.ScoreMultiplier > 0) - { - // Scale score up, so it's comparable to other keymods - scaledScore *= 1.0 / karaokeAttributes.ScoreMultiplier; - } - - // Arbitrary initial value for scaling pp in order to standardize distributions across game modes. - // The specific number has no intrinsic meaning and can be adjusted as needed. - double multiplier = 0.8; - - if (score.Mods.Any(m => m is ModNoFail)) - multiplier *= 0.9; - if (score.Mods.Any(m => m is ModEasy)) - multiplier *= 0.5; - - double difficultyValue = computeDifficultyValue(karaokeAttributes); - double accValue = computeAccuracyValue(difficultyValue, karaokeAttributes); - double totalValue = - Math.Pow( - Math.Pow(difficultyValue, 1.1) + - Math.Pow(accValue, 1.1), 1.0 / 1.1 - ) * multiplier; - - return new KaraokePerformanceAttributes - { - Difficulty = difficultyValue, - Accuracy = accValue, - ScaledScore = scaledScore, - Total = totalValue - }; + // Scale score up, so it's comparable to other keymods + scaledScore *= 1.0 / karaokeAttributes.ScoreMultiplier; } - private double computeDifficultyValue(KaraokeDifficultyAttributes attributes) + // Arbitrary initial value for scaling pp in order to standardize distributions across game modes. + // The specific number has no intrinsic meaning and can be adjusted as needed. + double multiplier = 0.8; + + if (score.Mods.Any(m => m is ModNoFail)) + multiplier *= 0.9; + if (score.Mods.Any(m => m is ModEasy)) + multiplier *= 0.5; + + double difficultyValue = computeDifficultyValue(karaokeAttributes); + double accValue = computeAccuracyValue(difficultyValue, karaokeAttributes); + double totalValue = + Math.Pow( + Math.Pow(difficultyValue, 1.1) + + Math.Pow(accValue, 1.1), 1.0 / 1.1 + ) * multiplier; + + return new KaraokePerformanceAttributes { - double difficultyValue = Math.Pow(5 * Math.Max(1, attributes.StarRating / 0.2) - 4.0, 2.2) / 135.0; + Difficulty = difficultyValue, + Accuracy = accValue, + ScaledScore = scaledScore, + Total = totalValue + }; + } - difficultyValue *= 1.0 + 0.1 * Math.Min(1.0, totalHits / 1500.0); + private double computeDifficultyValue(KaraokeDifficultyAttributes attributes) + { + double difficultyValue = Math.Pow(5 * Math.Max(1, attributes.StarRating / 0.2) - 4.0, 2.2) / 135.0; - switch (scaledScore) - { - case <= 500000: - difficultyValue = 0; - break; + difficultyValue *= 1.0 + 0.1 * Math.Min(1.0, totalHits / 1500.0); - case <= 600000: - difficultyValue *= (scaledScore - 500000) / 100000 * 0.3; - break; + switch (scaledScore) + { + case <= 500000: + difficultyValue = 0; + break; - case <= 700000: - difficultyValue *= 0.3 + (scaledScore - 600000) / 100000 * 0.25; - break; + case <= 600000: + difficultyValue *= (scaledScore - 500000) / 100000 * 0.3; + break; - case <= 800000: - difficultyValue *= 0.55 + (scaledScore - 700000) / 100000 * 0.20; - break; + case <= 700000: + difficultyValue *= 0.3 + (scaledScore - 600000) / 100000 * 0.25; + break; - case <= 900000: - difficultyValue *= 0.75 + (scaledScore - 800000) / 100000 * 0.15; - break; + case <= 800000: + difficultyValue *= 0.55 + (scaledScore - 700000) / 100000 * 0.20; + break; - default: - difficultyValue *= 0.90 + (scaledScore - 900000) / 100000 * 0.1; - break; - } + case <= 900000: + difficultyValue *= 0.75 + (scaledScore - 800000) / 100000 * 0.15; + break; - return difficultyValue; + default: + difficultyValue *= 0.90 + (scaledScore - 900000) / 100000 * 0.1; + break; } - private double computeAccuracyValue(double difficultyValue, KaraokeDifficultyAttributes attributes) - { - if (attributes.GreatHitWindow <= 0) - return 0; + return difficultyValue; + } - // Lots of arbitrary values from testing. - // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution - double accuracyValue = Math.Max(0.0, 0.2 - (attributes.GreatHitWindow - 34) * 0.006667) - * difficultyValue - * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); + private double computeAccuracyValue(double difficultyValue, KaraokeDifficultyAttributes attributes) + { + if (attributes.GreatHitWindow <= 0) + return 0; - return accuracyValue; - } + // Lots of arbitrary values from testing. + // Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution + double accuracyValue = Math.Max(0.0, 0.2 - (attributes.GreatHitWindow - 34) * 0.006667) + * difficultyValue + * Math.Pow(Math.Max(0.0, scaledScore - 960000) / 40000, 1.1); - private double totalHits => countPerfect + countOk + countGreat + countGood + countMeh + countMiss; + return accuracyValue; } + + private double totalHits => countPerfect + countOk + countGreat + countGood + countMeh + countMiss; } diff --git a/osu.Game.Rulesets.Karaoke/Difficulty/Preprocessing/KaraokeDifficultyHitObject.cs b/osu.Game.Rulesets.Karaoke/Difficulty/Preprocessing/KaraokeDifficultyHitObject.cs index b8b9e2806..06387f157 100644 --- a/osu.Game.Rulesets.Karaoke/Difficulty/Preprocessing/KaraokeDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Karaoke/Difficulty/Preprocessing/KaraokeDifficultyHitObject.cs @@ -6,15 +6,14 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Objects; -namespace osu.Game.Rulesets.Karaoke.Difficulty.Preprocessing +namespace osu.Game.Rulesets.Karaoke.Difficulty.Preprocessing; + +public class KaraokeDifficultyHitObject : DifficultyHitObject { - public class KaraokeDifficultyHitObject : DifficultyHitObject - { - public new Note BaseObject => (Note)base.BaseObject; + public new Note BaseObject => (Note)base.BaseObject; - public KaraokeDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, List objects, int index) - : base(hitObject, lastObject, clockRate, objects, index) - { - } + public KaraokeDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, List objects, int index) + : base(hitObject, lastObject, clockRate, objects, index) + { } } diff --git a/osu.Game.Rulesets.Karaoke/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Karaoke/Difficulty/Skills/Strain.cs index a3f5b8556..835ea78ac 100644 --- a/osu.Game.Rulesets.Karaoke/Difficulty/Skills/Strain.cs +++ b/osu.Game.Rulesets.Karaoke/Difficulty/Skills/Strain.cs @@ -10,79 +10,78 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Mods; -namespace osu.Game.Rulesets.Karaoke.Difficulty.Skills +namespace osu.Game.Rulesets.Karaoke.Difficulty.Skills; + +public class Strain : StrainDecaySkill { - public class Strain : StrainDecaySkill - { - private const double individual_decay_base = 0.125; - private const double overall_decay_base = 0.30; + private const double individual_decay_base = 0.125; + private const double overall_decay_base = 0.30; - protected override double SkillMultiplier => 1; - protected override double StrainDecayBase => 1; + protected override double SkillMultiplier => 1; + protected override double StrainDecayBase => 1; - private readonly double[] holdEndTimes; - private readonly double[] individualStrains; + private readonly double[] holdEndTimes; + private readonly double[] individualStrains; - private double individualStrain; - private double overallStrain; + private double individualStrain; + private double overallStrain; - public Strain(Mod[] mods, NoteInfo noteInfo) - : base(mods) - { - int totalColumns = noteInfo.Columns; + public Strain(Mod[] mods, NoteInfo noteInfo) + : base(mods) + { + int totalColumns = noteInfo.Columns; - holdEndTimes = new double[totalColumns * 2 - 1]; - individualStrains = new double[totalColumns * 2 - 1]; - overallStrain = 1; - } + holdEndTimes = new double[totalColumns * 2 - 1]; + individualStrains = new double[totalColumns * 2 - 1]; + overallStrain = 1; + } - protected override double StrainValueOf(DifficultyHitObject current) - { - var maniaCurrent = (KaraokeDifficultyHitObject)current; - double endTime = maniaCurrent.EndTime; - int column = getColumnIndex(maniaCurrent.BaseObject.Tone); + protected override double StrainValueOf(DifficultyHitObject current) + { + var maniaCurrent = (KaraokeDifficultyHitObject)current; + double endTime = maniaCurrent.EndTime; + int column = getColumnIndex(maniaCurrent.BaseObject.Tone); - double holdFactor = 1.0; // Factor to all additional strains in case something else is held - double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly + double holdFactor = 1.0; // Factor to all additional strains in case something else is held + double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly - // Fill up the holdEndTimes array - for (int i = 0; i < holdEndTimes.Length; ++i) - { - // If there is at least one other overlapping end or note, then we get an addition, buuuuuut... - if (Precision.DefinitelyBigger(holdEndTimes[i], maniaCurrent.StartTime, 1) && Precision.DefinitelyBigger(endTime, holdEndTimes[i], 1)) - holdAddition = 1.0; + // Fill up the holdEndTimes array + for (int i = 0; i < holdEndTimes.Length; ++i) + { + // If there is at least one other overlapping end or note, then we get an addition, buuuuuut... + if (Precision.DefinitelyBigger(holdEndTimes[i], maniaCurrent.StartTime, 1) && Precision.DefinitelyBigger(endTime, holdEndTimes[i], 1)) + holdAddition = 1.0; - // ... this addition only is valid if there is _no_ other note with the same ending. Releasing multiple notes at the same time is just as easy as releasing 1 - if (Precision.AlmostEquals(endTime, holdEndTimes[i], 1)) - holdAddition = 0; + // ... this addition only is valid if there is _no_ other note with the same ending. Releasing multiple notes at the same time is just as easy as releasing 1 + if (Precision.AlmostEquals(endTime, holdEndTimes[i], 1)) + holdAddition = 0; - // We give a slight bonus to everything if something is held meanwhile - if (Precision.DefinitelyBigger(holdEndTimes[i], endTime, 1)) - holdFactor = 1.25; + // We give a slight bonus to everything if something is held meanwhile + if (Precision.DefinitelyBigger(holdEndTimes[i], endTime, 1)) + holdFactor = 1.25; - // Decay individual strains - individualStrains[i] = applyDecay(individualStrains[i], current.DeltaTime, individual_decay_base); - } + // Decay individual strains + individualStrains[i] = applyDecay(individualStrains[i], current.DeltaTime, individual_decay_base); + } - holdEndTimes[column] = endTime; + holdEndTimes[column] = endTime; - // Increase individual strain in own column - individualStrains[column] += 2.0 * holdFactor; - individualStrain = individualStrains[column]; + // Increase individual strain in own column + individualStrains[column] += 2.0 * holdFactor; + individualStrain = individualStrains[column]; - overallStrain = applyDecay(overallStrain, current.DeltaTime, overall_decay_base) + (1 + holdAddition) * holdFactor; + overallStrain = applyDecay(overallStrain, current.DeltaTime, overall_decay_base) + (1 + holdAddition) * holdFactor; - return individualStrain + overallStrain - CurrentStrain; + return individualStrain + overallStrain - CurrentStrain; - // todo : implementation. - static int getColumnIndex(Tone tone) => 0; - } + // todo : implementation. + static int getColumnIndex(Tone tone) => 0; + } - protected override double CalculateInitialStrain(double offset, DifficultyHitObject current) - => applyDecay(individualStrain, offset - current.Previous(0).StartTime, individual_decay_base) - + applyDecay(overallStrain, offset - current.Previous(0).StartTime, overall_decay_base); + protected override double CalculateInitialStrain(double offset, DifficultyHitObject current) + => applyDecay(individualStrain, offset - current.Previous(0).StartTime, individual_decay_base) + + applyDecay(overallStrain, offset - current.Previous(0).StartTime, overall_decay_base); - private double applyDecay(double value, double deltaTime, double decayBase) - => value * Math.Pow(decayBase, deltaTime / 1000); - } + private double applyDecay(double value, double deltaTime, double decayBase) + => value * Math.Pow(decayBase, deltaTime / 1000); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/KaraokeSelectionBlueprint.cs b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/KaraokeSelectionBlueprint.cs index cf7a717cc..f6d2b0277 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/KaraokeSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/KaraokeSelectionBlueprint.cs @@ -7,15 +7,14 @@ using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints +namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints; + +public partial class KaraokeSelectionBlueprint : HitObjectSelectionBlueprint + where T : KaraokeHitObject { - public partial class KaraokeSelectionBlueprint : HitObjectSelectionBlueprint - where T : KaraokeHitObject + protected KaraokeSelectionBlueprint(T hitObject) + : base(hitObject) { - protected KaraokeSelectionBlueprint(T hitObject) - : base(hitObject) - { - RelativeSizeAxes = Axes.None; - } + RelativeSizeAxes = Axes.None; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Lyrics/LyricSelectionBlueprint.cs b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Lyrics/LyricSelectionBlueprint.cs index c681079f7..8ad0faf64 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Lyrics/LyricSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Lyrics/LyricSelectionBlueprint.cs @@ -5,13 +5,12 @@ using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints.Lyrics; + +public partial class LyricSelectionBlueprint : KaraokeSelectionBlueprint { - public partial class LyricSelectionBlueprint : KaraokeSelectionBlueprint + public LyricSelectionBlueprint(Lyric lyric) + : base(lyric) { - public LyricSelectionBlueprint(Lyric lyric) - : base(lyric) - { - } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/Components/EditBodyPiece.cs b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/Components/EditBodyPiece.cs index fe8caa311..58a8800c3 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/Components/EditBodyPiece.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/Components/EditBodyPiece.cs @@ -10,23 +10,22 @@ using osu.Game.Graphics; using osu.Game.Rulesets.Karaoke.Skinning.Default; -namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints.Notes.Components +namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints.Notes.Components; + +public partial class EditBodyPiece : Container { - public partial class EditBodyPiece : Container + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - [BackgroundDependencyLoader] - private void load(OsuColour colours) + Masking = true; + BorderColour = colours.Yellow; + BorderThickness = 2; + CornerRadius = DefaultBodyPiece.CORNER_RADIUS; + Child = new Box { - Masking = true; - BorderColour = colours.Yellow; - BorderThickness = 2; - CornerRadius = DefaultBodyPiece.CORNER_RADIUS; - Child = new Box - { - RelativeSizeAxes = Axes.Both, - AlwaysPresent = true, - Alpha = 0 - }; - } + RelativeSizeAxes = Axes.Both, + AlwaysPresent = true, + Alpha = 0 + }; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/NoteSelectionBlueprint.cs b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/NoteSelectionBlueprint.cs index e0df3219a..22b746eeb 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/NoteSelectionBlueprint.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Blueprints/Notes/NoteSelectionBlueprint.cs @@ -20,70 +20,69 @@ using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints.Notes +namespace osu.Game.Rulesets.Karaoke.Edit.Blueprints.Notes; + +public partial class NoteSelectionBlueprint : KaraokeSelectionBlueprint, IHasPopover { - public partial class NoteSelectionBlueprint : KaraokeSelectionBlueprint, IHasPopover - { - [Resolved] - private INotesChangeHandler notesChangeHandler { get; set; } + [Resolved] + private INotesChangeHandler notesChangeHandler { get; set; } - [Resolved] - private INotePropertyChangeHandler notePropertyChangeHandler { get; set; } + [Resolved] + private INotePropertyChangeHandler notePropertyChangeHandler { get; set; } - [Resolved] - private Playfield playfield { get; set; } + [Resolved] + private Playfield playfield { get; set; } - [Resolved] - private IScrollingInfo scrollingInfo { get; set; } + [Resolved] + private IScrollingInfo scrollingInfo { get; set; } - [Resolved] - private INotePositionInfo notePositionInfo { get; set; } + [Resolved] + private INotePositionInfo notePositionInfo { get; set; } - [Resolved] - private EditorBeatmap beatmap { get; set; } + [Resolved] + private EditorBeatmap beatmap { get; set; } - protected ScrollingHitObjectContainer HitObjectContainer => ((KaraokePlayfield)playfield).NotePlayfield.HitObjectContainer; + protected ScrollingHitObjectContainer HitObjectContainer => ((KaraokePlayfield)playfield).NotePlayfield.HitObjectContainer; - public NoteSelectionBlueprint(Note note) - : base(note) + public NoteSelectionBlueprint(Note note) + : base(note) + { + AddInternal(new EditBodyPiece { - AddInternal(new EditBodyPiece - { - RelativeSizeAxes = Axes.Both - }); - } + RelativeSizeAxes = Axes.Both + }); + } - protected override void Update() - { - base.Update(); + protected override void Update() + { + base.Update(); - var anchor = scrollingInfo.Direction.Value == ScrollingDirection.Left ? Anchor.CentreLeft : Anchor.CentreRight; - Anchor = Origin = anchor; + var anchor = scrollingInfo.Direction.Value == ScrollingDirection.Left ? Anchor.CentreLeft : Anchor.CentreRight; + Anchor = Origin = anchor; - Position = Parent.ToLocalSpace(HitObjectContainer.ScreenSpacePositionAtTime(HitObject.StartTime)) - AnchorPosition; - Y += notePositionInfo.Calculator.YPositionAt(HitObject.Tone); + Position = Parent.ToLocalSpace(HitObjectContainer.ScreenSpacePositionAtTime(HitObject.StartTime)) - AnchorPosition; + Y += notePositionInfo.Calculator.YPositionAt(HitObject.Tone); - Width = HitObjectContainer.LengthAtTime(HitObject.StartTime, HitObject.EndTime); - Height = notePositionInfo.Calculator.ColumnHeight; - } + Width = HitObjectContainer.LengthAtTime(HitObject.StartTime, HitObject.EndTime); + Height = notePositionInfo.Calculator.ColumnHeight; + } - public override MenuItem[] ContextMenuItems => new MenuItem[] - { - new OsuMenuItem(HitObject.Display ? "Hide" : "Show", HitObject.Display ? MenuItemType.Destructive : MenuItemType.Standard, - () => notePropertyChangeHandler.ChangeDisplayState(!HitObject.Display)), - new OsuMenuItem("Split", MenuItemType.Destructive, () => notesChangeHandler.Split()), - }; + public override MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem(HitObject.Display ? "Hide" : "Show", HitObject.Display ? MenuItemType.Destructive : MenuItemType.Standard, + () => notePropertyChangeHandler.ChangeDisplayState(!HitObject.Display)), + new OsuMenuItem("Split", MenuItemType.Destructive, () => notesChangeHandler.Split()), + }; - public Popover GetPopover() => new NoteEditPopover(HitObject); + public Popover GetPopover() => new NoteEditPopover(HitObject); - protected override bool OnClick(ClickEvent e) - { - // should only select current note before open the popover because note change handler will change property in all selected notes. - beatmap.SelectedHitObjects.Clear(); - beatmap.SelectedHitObjects.Add(HitObject); + protected override bool OnClick(ClickEvent e) + { + // should only select current note before open the popover because note change handler will change property in all selected notes. + beatmap.SelectedHitObjects.Clear(); + beatmap.SelectedHitObjects.Add(HitObject); - this.ShowPopover(); - return base.OnClick(e); - } + this.ShowPopover(); + return base.OnClick(e); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/BeatmapListPropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/BeatmapListPropertyChangeHandler.cs index d3db8b674..95f185687 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/BeatmapListPropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/BeatmapListPropertyChangeHandler.cs @@ -13,83 +13,82 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +// todo: not a good design because eventually karaoke beatmap will not have the the field with list type. +// it should be wrap into class (e.g. localizationInfo) with list of translate inside. +// so guess this class will be removed eventually. +public abstract partial class BeatmapListPropertyChangeHandler : Component { - // todo: not a good design because eventually karaoke beatmap will not have the the field with list type. - // it should be wrap into class (e.g. localizationInfo) with list of translate inside. - // so guess this class will be removed eventually. - public abstract partial class BeatmapListPropertyChangeHandler : Component - { - [Resolved, AllowNull] - private EditorBeatmap beatmap { get; set; } + [Resolved, AllowNull] + private EditorBeatmap beatmap { get; set; } - private KaraokeBeatmap karaokeBeatmap => EditorBeatmapUtils.GetPlayableBeatmap(beatmap); + private KaraokeBeatmap karaokeBeatmap => EditorBeatmapUtils.GetPlayableBeatmap(beatmap); - protected IEnumerable Lyrics => karaokeBeatmap.HitObjects.OfType(); + protected IEnumerable Lyrics => karaokeBeatmap.HitObjects.OfType(); - // todo: should be interface. - protected BindableList Items = new(); + // todo: should be interface. + protected BindableList Items = new(); - [BackgroundDependencyLoader] - private void load() - { - Items.AddRange(GetItemsFromBeatmap(karaokeBeatmap)); + [BackgroundDependencyLoader] + private void load() + { + Items.AddRange(GetItemsFromBeatmap(karaokeBeatmap)); - // todo: find a better way to handle only beatmap property changed. - beatmap.TransactionEnded += syncItemsFromBeatmap; + // todo: find a better way to handle only beatmap property changed. + beatmap.TransactionEnded += syncItemsFromBeatmap; - syncItemsFromBeatmap(); + syncItemsFromBeatmap(); - void syncItemsFromBeatmap() - { - var items = GetItemsFromBeatmap(karaokeBeatmap); + void syncItemsFromBeatmap() + { + var items = GetItemsFromBeatmap(karaokeBeatmap); - if (Items.SequenceEqual(items)) - return; + if (Items.SequenceEqual(items)) + return; - Items.AddRange(items.Except(Items)); - Items.RemoveAll(x => !items.Contains(x)); - } + Items.AddRange(items.Except(Items)); + Items.RemoveAll(x => !items.Contains(x)); } + } - protected void PerformObjectChanged(TItem item, Action? action) - { - // should call change from editor beatmap because there's only way to trigger transaction ended. - beatmap.BeginChange(); - action?.Invoke(item); - beatmap.EndChange(); - } + protected void PerformObjectChanged(TItem item, Action? action) + { + // should call change from editor beatmap because there's only way to trigger transaction ended. + beatmap.BeginChange(); + action?.Invoke(item); + beatmap.EndChange(); + } - protected abstract IList GetItemsFromBeatmap(KaraokeBeatmap beatmap); + protected abstract IList GetItemsFromBeatmap(KaraokeBeatmap beatmap); - public void Add(TItem item) - { - var items = GetItemsFromBeatmap(karaokeBeatmap); - if (items.Contains(item)) - throw new InvalidOperationException(nameof(item)); - - PerformObjectChanged(item, i => - { - items.Add(i); - OnItemAdded(i); - }); - } + public void Add(TItem item) + { + var items = GetItemsFromBeatmap(karaokeBeatmap); + if (items.Contains(item)) + throw new InvalidOperationException(nameof(item)); - public void Remove(TItem item) + PerformObjectChanged(item, i => { - var items = GetItemsFromBeatmap(karaokeBeatmap); - if (!items.Contains(item)) - throw new InvalidOperationException($"{nameof(item)} is not in the list"); - - PerformObjectChanged(item, i => - { - items.Remove(i); - OnItemRemoved(i); - }); - } + items.Add(i); + OnItemAdded(i); + }); + } - protected abstract void OnItemAdded(TItem item); + public void Remove(TItem item) + { + var items = GetItemsFromBeatmap(karaokeBeatmap); + if (!items.Contains(item)) + throw new InvalidOperationException($"{nameof(item)} is not in the list"); - protected abstract void OnItemRemoved(TItem item); + PerformObjectChanged(item, i => + { + items.Remove(i); + OnItemRemoved(i); + }); } + + protected abstract void OnItemAdded(TItem item); + + protected abstract void OnItemRemoved(TItem item); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapLanguagesChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapLanguagesChangeHandler.cs index 55f6d4b3c..e565d9b53 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapLanguagesChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapLanguagesChangeHandler.cs @@ -7,30 +7,29 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Karaoke.Beatmaps; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; + +public partial class BeatmapLanguagesChangeHandler : BeatmapListPropertyChangeHandler, IBeatmapLanguagesChangeHandler { - public partial class BeatmapLanguagesChangeHandler : BeatmapListPropertyChangeHandler, IBeatmapLanguagesChangeHandler - { - public IBindableList Languages => Items; + public IBindableList Languages => Items; - protected override IList GetItemsFromBeatmap(KaraokeBeatmap beatmap) - => beatmap.AvailableTranslates; + protected override IList GetItemsFromBeatmap(KaraokeBeatmap beatmap) + => beatmap.AvailableTranslates; - protected override void OnItemAdded(CultureInfo item) - { - // there's no need to do anything. - } + protected override void OnItemAdded(CultureInfo item) + { + // there's no need to do anything. + } - protected override void OnItemRemoved(CultureInfo item) + protected override void OnItemRemoved(CultureInfo item) + { + // Delete from lyric also. + foreach (var lyric in Lyrics.Where(lyric => lyric.Translates.ContainsKey(item))) { - // Delete from lyric also. - foreach (var lyric in Lyrics.Where(lyric => lyric.Translates.ContainsKey(item))) - { - lyric.Translates.Remove(item); - } + lyric.Translates.Remove(item); } - - public bool IsLanguageContainsTranslate(CultureInfo cultureInfo) - => Lyrics.Any(x => x.Translates.ContainsKey(cultureInfo)); } + + public bool IsLanguageContainsTranslate(CultureInfo cultureInfo) + => Lyrics.Any(x => x.Translates.ContainsKey(cultureInfo)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapSingersChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapSingersChangeHandler.cs index f9c188828..74892e152 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapSingersChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/BeatmapSingersChangeHandler.cs @@ -12,110 +12,109 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; + +public partial class BeatmapSingersChangeHandler : BeatmapPropertyChangeHandler, IBeatmapSingersChangeHandler { - public partial class BeatmapSingersChangeHandler : BeatmapPropertyChangeHandler, IBeatmapSingersChangeHandler - { - [Resolved] - private BeatmapManager? beatmapManager { get; set; } + [Resolved] + private BeatmapManager? beatmapManager { get; set; } - [Resolved] - private IBindable? working { get; set; } + [Resolved] + private IBindable? working { get; set; } - private SingerInfo singerInfo => KaraokeBeatmap.SingerInfo; + private SingerInfo singerInfo => KaraokeBeatmap.SingerInfo; - public BindableList Singers => singerInfo.Singers; + public BindableList Singers => singerInfo.Singers; - public void ChangeOrder(ISinger singer, int newIndex) + public void ChangeOrder(ISinger singer, int newIndex) + { + performSingerChanged(singer, s => { - performSingerChanged(singer, s => + int oldOrder = s.Order; + int newOrder = newIndex + 1; // order is start from 1 + OrderUtils.ChangeOrder(Singers.ToArray(), oldOrder, newOrder, (switchSinger, oldOrder, newOrder) => { - int oldOrder = s.Order; - int newOrder = newIndex + 1; // order is start from 1 - OrderUtils.ChangeOrder(Singers.ToArray(), oldOrder, newOrder, (switchSinger, oldOrder, newOrder) => - { - // todo : not really sure should call update? - }); + // todo : not really sure should call update? }); - } - - public bool ChangeSingerAvatar(Singer singer, FileInfo fileInfo) - { - if (beatmapManager == null || working == null) - return false; - - if (!fileInfo.Exists) - throw new FileNotFoundException(); + }); + } - // note: follow the same logic in the ResourcesSection.ChangeBackgroundImage - var set = working.Value.BeatmapSetInfo; + public bool ChangeSingerAvatar(Singer singer, FileInfo fileInfo) + { + if (beatmapManager == null || working == null) + return false; - // todo: we might re-format the new file name, like give it a hash name for prevent duplicated file name with other singer. - string newFileName = fileInfo.Name; + if (!fileInfo.Exists) + throw new FileNotFoundException(); - using (var stream = fileInfo.OpenRead()) - { - // in the future we probably want to check if this is being used elsewhere (other difficulties?) - var oldFile = set.Files.FirstOrDefault(f => f.Filename == singer.AvatarFile); - if (oldFile != null) - beatmapManager.DeleteFile(set, oldFile); + // note: follow the same logic in the ResourcesSection.ChangeBackgroundImage + var set = working.Value.BeatmapSetInfo; - beatmapManager.AddFile(set, stream, $"assets/singers/{newFileName}"); - } + // todo: we might re-format the new file name, like give it a hash name for prevent duplicated file name with other singer. + string newFileName = fileInfo.Name; - performSingerChanged(singer, s => - { - // Write-back the file name. - s.AvatarFile = newFileName; - }); + using (var stream = fileInfo.OpenRead()) + { + // in the future we probably want to check if this is being used elsewhere (other difficulties?) + var oldFile = set.Files.FirstOrDefault(f => f.Filename == singer.AvatarFile); + if (oldFile != null) + beatmapManager.DeleteFile(set, oldFile); - return true; + beatmapManager.AddFile(set, stream, $"assets/singers/{newFileName}"); } - public Singer Add() + performSingerChanged(singer, s => { - var newSinger = singerInfo.AddSinger(s => - { - s.Order = getMaxSingerOrder() + 1; - s.Name = "New singer"; - }); - return newSinger; + // Write-back the file name. + s.AvatarFile = newFileName; + }); - int getMaxSingerOrder() - => OrderUtils.GetMaxOrderNumber(singerInfo.GetAllSingers()); - } + return true; + } - public void Remove(Singer singer) + public Singer Add() + { + var newSinger = singerInfo.AddSinger(s => { - singerInfo.RemoveSinger(singer); + s.Order = getMaxSingerOrder() + 1; + s.Name = "New singer"; + }); + return newSinger; - // Should re-sort the order - OrderUtils.ShiftingOrder(singerInfo.GetAllSingers().Where(x => x.Order > singer.Order), -1); + int getMaxSingerOrder() + => OrderUtils.GetMaxOrderNumber(singerInfo.GetAllSingers()); + } - // should clear removed singer ids in singer editor. - Lyrics.ForEach(x => - { - x.SingerIds.Remove(singer.ID); - }); - } + public void Remove(Singer singer) + { + singerInfo.RemoveSinger(singer); - private void performSingerInfoChanged(Action action) + // Should re-sort the order + OrderUtils.ShiftingOrder(singerInfo.GetAllSingers().Where(x => x.Order > singer.Order), -1); + + // should clear removed singer ids in singer editor. + Lyrics.ForEach(x => { - PerformBeatmapChanged(beatmap => - { - action(beatmap.SingerInfo); - }); - } + x.SingerIds.Remove(singer.ID); + }); + } - private void performSingerChanged(TSinger singer, Action action) where TSinger : ISinger + private void performSingerInfoChanged(Action action) + { + PerformBeatmapChanged(beatmap => { - performSingerInfoChanged(singerInfo => - { - if (!singerInfo.Singers.Contains(singer)) - throw new InvalidOperationException("Singer should be in the beatmap"); + action(beatmap.SingerInfo); + }); + } - action(singer); - }); - } + private void performSingerChanged(TSinger singer, Action action) where TSinger : ISinger + { + performSingerInfoChanged(singerInfo => + { + if (!singerInfo.Singers.Contains(singer)) + throw new InvalidOperationException("Singer should be in the beatmap"); + + action(singer); + }); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapLanguagesChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapLanguagesChangeHandler.cs index 83ead89d4..7161dd320 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapLanguagesChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapLanguagesChangeHandler.cs @@ -4,16 +4,15 @@ using System.Globalization; using osu.Framework.Bindables; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; + +public interface IBeatmapLanguagesChangeHandler { - public interface IBeatmapLanguagesChangeHandler - { - IBindableList Languages { get; } + IBindableList Languages { get; } - void Add(CultureInfo culture); + void Add(CultureInfo culture); - void Remove(CultureInfo culture); + void Remove(CultureInfo culture); - bool IsLanguageContainsTranslate(CultureInfo cultureInfo); - } + bool IsLanguageContainsTranslate(CultureInfo cultureInfo); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapSingersChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapSingersChangeHandler.cs index 8f11f1ffa..9f313238f 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapSingersChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Beatmaps/IBeatmapSingersChangeHandler.cs @@ -6,19 +6,18 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Beatmaps; + +public interface IBeatmapSingersChangeHandler { - public interface IBeatmapSingersChangeHandler - { - // todo: should use IBindableList eventually, but cannot do that because it's bind to selection item. - BindableList Singers { get; } + // todo: should use IBindableList eventually, but cannot do that because it's bind to selection item. + BindableList Singers { get; } - void ChangeOrder(ISinger singer, int newIndex); + void ChangeOrder(ISinger singer, int newIndex); - bool ChangeSingerAvatar(Singer singer, FileInfo fileInfo); + bool ChangeSingerAvatar(Singer singer, FileInfo fileInfo); - Singer Add(); + Singer Add(); - void Remove(Singer singer); - } + void Remove(Singer singer); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectChangeHandler.cs index f1e82a63b..c1ebd46cf 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectChangeHandler.cs @@ -14,163 +14,162 @@ using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +public abstract partial class HitObjectChangeHandler : Component where THitObject : HitObject { - public abstract partial class HitObjectChangeHandler : Component where THitObject : HitObject - { - private readonly Cached changingCache = new(); + private readonly Cached changingCache = new(); - private bool triggerBeatmapSave = true; + private bool triggerBeatmapSave = true; - [Resolved, AllowNull] - private EditorBeatmap beatmap { get; set; } + [Resolved, AllowNull] + private EditorBeatmap beatmap { get; set; } - protected IEnumerable HitObjects => beatmap.HitObjects.OfType(); + protected IEnumerable HitObjects => beatmap.HitObjects.OfType(); - protected HitObjectChangeHandler() - { - changingCache.Validate(); - } + protected HitObjectChangeHandler() + { + changingCache.Validate(); + } - protected void CheckExactlySelectedOneHitObject() - { - if (beatmap.SelectedHitObjects.OfType().Count() != 1) - throw new InvalidOperationException($"Should be exactly one {nameof(THitObject)} being selected."); - } + protected void CheckExactlySelectedOneHitObject() + { + if (beatmap.SelectedHitObjects.OfType().Count() != 1) + throw new InvalidOperationException($"Should be exactly one {nameof(THitObject)} being selected."); + } - // Can remove this method after as TransactionalCommitComponent injection for all rulesets(means customized ruleset is able to save/load beatmap). - // we can use changeHandler.TransactionActive to check if there's any active transaction. - // e.g. : changeHandler is TransactionalCommitComponent transactionalCommitComponent && !transactionalCommitComponent.TransactionActive - protected void NotTriggerSaveStateOnThisChange() - { - triggerBeatmapSave = false; - } + // Can remove this method after as TransactionalCommitComponent injection for all rulesets(means customized ruleset is able to save/load beatmap). + // we can use changeHandler.TransactionActive to check if there's any active transaction. + // e.g. : changeHandler is TransactionalCommitComponent transactionalCommitComponent && !transactionalCommitComponent.TransactionActive + protected void NotTriggerSaveStateOnThisChange() + { + triggerBeatmapSave = false; + } - protected virtual void PerformOnSelection(Action action) - => PerformOnSelection(action); + protected virtual void PerformOnSelection(Action action) + => PerformOnSelection(action); - protected void PerformOnSelection(Action action) where T : HitObject - { - if (!changingCache.IsValid) - throw new NotSupportedException("Cannot trigger the change while applying another change."); + protected void PerformOnSelection(Action action) where T : HitObject + { + if (!changingCache.IsValid) + throw new NotSupportedException("Cannot trigger the change while applying another change."); - if (beatmap.SelectedHitObjects.Count == 0) - throw new NotSupportedException($"Should contain at least one selected {nameof(THitObject)}"); + if (beatmap.SelectedHitObjects.Count == 0) + throw new NotSupportedException($"Should contain at least one selected {nameof(THitObject)}"); - changingCache.Invalidate(); + changingCache.Invalidate(); - try + try + { + // todo: follow-up the discussion in the https://github.com/karaoke-dev/karaoke/pull/1669 after support the change handler for customized ruleset. + if (triggerBeatmapSave) { - // todo: follow-up the discussion in the https://github.com/karaoke-dev/karaoke/pull/1669 after support the change handler for customized ruleset. - if (triggerBeatmapSave) - { - // should trigger the UpdateState() in the editor beatmap only if there's no active state. - beatmap.PerformOnSelection(h => - { - if (h is T tHitObject) - action(tHitObject); - }); - } - else + // should trigger the UpdateState() in the editor beatmap only if there's no active state. + beatmap.PerformOnSelection(h => { - // Just update the object property if already in the changing state. - // e.g. dragging. - beatmap.SelectedHitObjects.ForEach(h => - { - if (h is T tHitObject) - action(tHitObject); - }); - } - } - catch - { - // We should make sure that editor beatmap will end the change if still changing. - // will goes to here if have exception in the change handler. - if (beatmap.TransactionActive) - beatmap.EndChange(); - - throw; + if (h is T tHitObject) + action(tHitObject); + }); } - finally + else { - changingCache.Validate(); - triggerBeatmapSave = true; + // Just update the object property if already in the changing state. + // e.g. dragging. + beatmap.SelectedHitObjects.ForEach(h => + { + if (h is T tHitObject) + action(tHitObject); + }); } } + catch + { + // We should make sure that editor beatmap will end the change if still changing. + // will goes to here if have exception in the change handler. + if (beatmap.TransactionActive) + beatmap.EndChange(); - protected void AddRange(IEnumerable hitObjects) where T : HitObject => hitObjects.ForEach(Add); - - protected virtual void Add(T hitObject) where T : HitObject + throw; + } + finally { - bool containsInBeatmap = HitObjects.Any(x => x == hitObject); - if (containsInBeatmap) - throw new InvalidOperationException("Seems this hit object is already in the beatmap."); + changingCache.Validate(); + triggerBeatmapSave = true; + } + } - if (isCreateObjectLocked(hitObject)) - throw new AddOrRemoveForbiddenException(); + protected void AddRange(IEnumerable hitObjects) where T : HitObject => hitObjects.ForEach(Add); - beatmap.Add(hitObject); - } + protected virtual void Add(T hitObject) where T : HitObject + { + bool containsInBeatmap = HitObjects.Any(x => x == hitObject); + if (containsInBeatmap) + throw new InvalidOperationException("Seems this hit object is already in the beatmap."); - protected virtual void Insert(int index, T hitObject) where T : HitObject - { - bool containsInBeatmap = HitObjects.Any(x => x == hitObject); - if (containsInBeatmap) - throw new InvalidOperationException("Seems this hit object is already in the beatmap."); + if (isCreateObjectLocked(hitObject)) + throw new AddOrRemoveForbiddenException(); - if (isCreateObjectLocked(hitObject)) - throw new AddOrRemoveForbiddenException(); + beatmap.Add(hitObject); + } - beatmap.Insert(index, hitObject); - } + protected virtual void Insert(int index, T hitObject) where T : HitObject + { + bool containsInBeatmap = HitObjects.Any(x => x == hitObject); + if (containsInBeatmap) + throw new InvalidOperationException("Seems this hit object is already in the beatmap."); - protected void RemoveRange(IEnumerable hitObjects) where T : HitObject => hitObjects.ForEach(Remove); + if (isCreateObjectLocked(hitObject)) + throw new AddOrRemoveForbiddenException(); - protected void Remove(T hitObject) where T : HitObject - { - if (isRemoveObjectLocked(hitObject)) - throw new AddOrRemoveForbiddenException(); + beatmap.Insert(index, hitObject); + } - beatmap.Remove(hitObject); - } + protected void RemoveRange(IEnumerable hitObjects) where T : HitObject => hitObjects.ForEach(Remove); + + protected void Remove(T hitObject) where T : HitObject + { + if (isRemoveObjectLocked(hitObject)) + throw new AddOrRemoveForbiddenException(); - private bool isCreateObjectLocked(T hitObject) + beatmap.Remove(hitObject); + } + + private bool isCreateObjectLocked(T hitObject) + { + return hitObject switch { - return hitObject switch - { - Lyric => false, - Note note => note.ReferenceLyric != null && HitObjectWritableUtils.IsCreateOrRemoveNoteLocked(note.ReferenceLyric), - _ => throw new InvalidCastException() - }; - } + Lyric => false, + Note note => note.ReferenceLyric != null && HitObjectWritableUtils.IsCreateOrRemoveNoteLocked(note.ReferenceLyric), + _ => throw new InvalidCastException() + }; + } - private bool isRemoveObjectLocked(T hitObject) + private bool isRemoveObjectLocked(T hitObject) + { + switch (hitObject) { - switch (hitObject) - { - case Lyric lyric: - bool hasReferenceLyric = EditorBeatmapUtils.GetAllReferenceLyrics(beatmap, lyric).Any(); - return hasReferenceLyric || HitObjectWritableUtils.IsRemoveLyricLocked(lyric); + case Lyric lyric: + bool hasReferenceLyric = EditorBeatmapUtils.GetAllReferenceLyrics(beatmap, lyric).Any(); + return hasReferenceLyric || HitObjectWritableUtils.IsRemoveLyricLocked(lyric); - case Note note: - return note.ReferenceLyric != null && HitObjectWritableUtils.IsCreateOrRemoveNoteLocked(note.ReferenceLyric); + case Note note: + return note.ReferenceLyric != null && HitObjectWritableUtils.IsCreateOrRemoveNoteLocked(note.ReferenceLyric); - default: - throw new InvalidCastException(); - } + default: + throw new InvalidCastException(); } + } - protected void TriggerHitObjectUpdate(T hitObject) where T : HitObject - { - beatmap.Update(hitObject); - } + protected void TriggerHitObjectUpdate(T hitObject) where T : HitObject + { + beatmap.Update(hitObject); + } - public class AddOrRemoveForbiddenException : Exception + public class AddOrRemoveForbiddenException : Exception + { + public AddOrRemoveForbiddenException() + : base("Should not add or remove the hit-object.") { - public AddOrRemoveForbiddenException() - : base("Should not add or remove the hit-object.") - { - } } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectPropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectPropertyChangeHandler.cs index 3dd6e83be..544e2ccfd 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectPropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectPropertyChangeHandler.cs @@ -8,34 +8,33 @@ using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +public abstract partial class HitObjectPropertyChangeHandler : HitObjectChangeHandler, IHitObjectPropertyChangeHandler + where THitObject : HitObject { - public abstract partial class HitObjectPropertyChangeHandler : HitObjectChangeHandler, IHitObjectPropertyChangeHandler - where THitObject : HitObject - { - [Resolved, AllowNull] - private EditorBeatmap beatmap { get; set; } + [Resolved, AllowNull] + private EditorBeatmap beatmap { get; set; } - protected sealed override void PerformOnSelection(Action action) - { - // note: should not check lyric in the perform on selection because it will let change handler in lazer broken. - if (beatmap.SelectedHitObjects.OfType().Any(IsWritePropertyLocked)) - throw new ChangeForbiddenException(); + protected sealed override void PerformOnSelection(Action action) + { + // note: should not check lyric in the perform on selection because it will let change handler in lazer broken. + if (beatmap.SelectedHitObjects.OfType().Any(IsWritePropertyLocked)) + throw new ChangeForbiddenException(); - base.PerformOnSelection(action); - } + base.PerformOnSelection(action); + } - protected abstract bool IsWritePropertyLocked(THitObject hitObject); + protected abstract bool IsWritePropertyLocked(THitObject hitObject); - public virtual bool IsSelectionsLocked() - => beatmap.SelectedHitObjects.OfType().Any(IsWritePropertyLocked); + public virtual bool IsSelectionsLocked() + => beatmap.SelectedHitObjects.OfType().Any(IsWritePropertyLocked); - public class ChangeForbiddenException : InvalidOperationException + public class ChangeForbiddenException : InvalidOperationException + { + public ChangeForbiddenException() + : base("This property might be locked or it's a reference property.") { - public ChangeForbiddenException() - : base("This property might be locked or it's a reference property.") - { - } } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectsChangeHandler.cs index a491e8571..85aa6579a 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/HitObjectsChangeHandler.cs @@ -3,9 +3,8 @@ using osu.Game.Rulesets.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +public abstract partial class HitObjectsChangeHandler : HitObjectChangeHandler where THitObject : HitObject { - public abstract partial class HitObjectsChangeHandler : HitObjectChangeHandler where THitObject : HitObject - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/IImportBeatmapChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/IImportBeatmapChangeHandler.cs index d8ee6858a..cda32c47f 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/IImportBeatmapChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/IImportBeatmapChangeHandler.cs @@ -3,10 +3,9 @@ using osu.Game.Beatmaps; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +public interface IImportBeatmapChangeHandler { - public interface IImportBeatmapChangeHandler - { - void Import(IBeatmap newBeatmap); - } + void Import(IBeatmap newBeatmap); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ILockChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ILockChangeHandler.cs index e0eb26be7..9f012c140 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ILockChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ILockChangeHandler.cs @@ -3,12 +3,11 @@ using osu.Game.Rulesets.Karaoke.Objects.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +public interface ILockChangeHandler : IHitObjectPropertyChangeHandler { - public interface ILockChangeHandler : IHitObjectPropertyChangeHandler - { - void Lock(LockState lockState); + void Lock(LockState lockState); - void Unlock(); - } + void Unlock(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ImportBeatmapChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ImportBeatmapChangeHandler.cs index c8c0c9fee..786e2c1de 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ImportBeatmapChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/ImportBeatmapChangeHandler.cs @@ -11,34 +11,33 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +public partial class ImportBeatmapChangeHandler : Component, IImportBeatmapChangeHandler { - public partial class ImportBeatmapChangeHandler : Component, IImportBeatmapChangeHandler - { - [Resolved, AllowNull] - private EditorBeatmap beatmap { get; set; } + [Resolved, AllowNull] + private EditorBeatmap beatmap { get; set; } - private KaraokeBeatmap karaokeBeatmap => EditorBeatmapUtils.GetPlayableBeatmap(beatmap); + private KaraokeBeatmap karaokeBeatmap => EditorBeatmapUtils.GetPlayableBeatmap(beatmap); - public void Import(IBeatmap newBeatmap) - { - beatmap.BeginChange(); + public void Import(IBeatmap newBeatmap) + { + beatmap.BeginChange(); - beatmap.Clear(); + beatmap.Clear(); - var lyrics = newBeatmap.HitObjects.OfType().ToArray(); + var lyrics = newBeatmap.HitObjects.OfType().ToArray(); - if (lyrics.Any()) + if (lyrics.Any()) + { + for (int i = 0; i < lyrics.Length; i++) { - for (int i = 0; i < lyrics.Length; i++) - { - lyrics[i].ID = i; - } - - beatmap.AddRange(lyrics); + lyrics[i].ID = i; } - beatmap.EndChange(); + beatmap.AddRange(lyrics); } + + beatmap.EndChange(); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/LockChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/LockChangeHandler.cs index a5579a177..bdb170d94 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/LockChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/LockChangeHandler.cs @@ -6,32 +6,31 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers; + +public partial class LockChangeHandler : HitObjectPropertyChangeHandler, ILockChangeHandler { - public partial class LockChangeHandler : HitObjectPropertyChangeHandler, ILockChangeHandler + public void Lock(LockState lockState) { - public void Lock(LockState lockState) + PerformOnSelection(h => { - PerformOnSelection(h => - { - if (h is IHasLock hasLock) - hasLock.Lock = lockState; - }); - } + if (h is IHasLock hasLock) + hasLock.Lock = lockState; + }); + } - public void Unlock() - { - Lock(LockState.None); - } + public void Unlock() + { + Lock(LockState.None); + } - protected sealed override bool IsWritePropertyLocked(KaraokeHitObject hitObject) + protected sealed override bool IsWritePropertyLocked(KaraokeHitObject hitObject) + { + return hitObject switch { - return hitObject switch - { - Lyric lyric => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Lock)), - Note note => HitObjectWritableUtils.IsWriteNotePropertyLocked(note, nameof(Lyric.Lock)), - _ => throw new NotSupportedException() - }; - } + Lyric lyric => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Lock)), + Note note => HitObjectWritableUtils.IsWriteNotePropertyLocked(note, nameof(Lyric.Lock)), + _ => throw new NotSupportedException() + }; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs index cd994921c..04dcb4dab 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricLanguageChangeHandler.cs @@ -3,10 +3,9 @@ using System.Globalization; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricLanguageChangeHandler : ILyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler { - public interface ILyricLanguageChangeHandler : ILyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler - { - void SetLanguage(CultureInfo? language); - } + void SetLanguage(CultureInfo? language); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricListPropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricListPropertyChangeHandler.cs index 2473855c9..724a38296 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricListPropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricListPropertyChangeHandler.cs @@ -3,16 +3,15 @@ using System.Collections.Generic; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricListPropertyChangeHandler : ILyricPropertyChangeHandler { - public interface ILyricListPropertyChangeHandler : ILyricPropertyChangeHandler - { - void Add(TItem item); + void Add(TItem item); - void AddRange(IEnumerable items); + void AddRange(IEnumerable items); - void Remove(TItem item); + void Remove(TItem item); - void RemoveRange(IEnumerable items); - } + void RemoveRange(IEnumerable items); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyChangeHandler.cs index 04fff2013..4fecd49ef 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricPropertyChangeHandler.cs @@ -1,9 +1,8 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricPropertyChangeHandler : IHitObjectPropertyChangeHandler { - public interface ILyricPropertyChangeHandler : IHitObjectPropertyChangeHandler - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs index 6abc4d9ee..976ce038a 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricReferenceChangeHandler.cs @@ -5,16 +5,15 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Properties; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricReferenceChangeHandler : ILyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler { - public interface ILyricReferenceChangeHandler : ILyricPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler - { - void UpdateReferenceLyric(Lyric? referenceLyric); + void UpdateReferenceLyric(Lyric? referenceLyric); - void SwitchToReferenceLyricConfig(); + void SwitchToReferenceLyricConfig(); - void SwitchToSyncLyricConfig(); + void SwitchToSyncLyricConfig(); - void AdjustLyricConfig(Action action) where TConfig : IReferenceLyricPropertyConfig; - } + void AdjustLyricConfig(Action action) where TConfig : IReferenceLyricPropertyConfig; } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs index 18528be5d..ef6d38780 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRomajiTagsChangeHandler.cs @@ -3,9 +3,8 @@ using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricRomajiTagsChangeHandler : ILyricTextTagsChangeHandler, ILyricPropertyAutoGenerateChangeHandler { - public interface ILyricRomajiTagsChangeHandler : ILyricTextTagsChangeHandler, ILyricPropertyAutoGenerateChangeHandler - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs index 51c763a67..014098f70 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricRubyTagsChangeHandler.cs @@ -3,9 +3,8 @@ using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricRubyTagsChangeHandler : ILyricTextTagsChangeHandler, ILyricPropertyAutoGenerateChangeHandler { - public interface ILyricRubyTagsChangeHandler : ILyricTextTagsChangeHandler, ILyricPropertyAutoGenerateChangeHandler - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricSingerChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricSingerChangeHandler.cs index 7da638597..fbfbdb200 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricSingerChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricSingerChangeHandler.cs @@ -3,10 +3,9 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricSingerChangeHandler : ILyricListPropertyChangeHandler { - public interface ILyricSingerChangeHandler : ILyricListPropertyChangeHandler - { - void Clear(); - } + void Clear(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextChangeHandler.cs index b1f16567f..1617d5161 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextChangeHandler.cs @@ -1,12 +1,11 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricTextChangeHandler : ILyricPropertyChangeHandler { - public interface ILyricTextChangeHandler : ILyricPropertyChangeHandler - { - void InsertText(int index, string text); + void InsertText(int index, string text); - void DeleteLyricText(int index); - } + void DeleteLyricText(int index); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextTagsChangeHandler.cs index ab8beed23..3c341004e 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTextTagsChangeHandler.cs @@ -4,14 +4,13 @@ using System.Collections.Generic; using osu.Game.Rulesets.Karaoke.Objects.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricTextTagsChangeHandler : ILyricListPropertyChangeHandler where TTextTag : ITextTag { - public interface ILyricTextTagsChangeHandler : ILyricListPropertyChangeHandler where TTextTag : ITextTag - { - void SetIndex(TTextTag textTag, int? startIndex, int? endIndex); + void SetIndex(TTextTag textTag, int? startIndex, int? endIndex); - void ShiftingIndex(IEnumerable textTags, int offset); + void ShiftingIndex(IEnumerable textTags, int offset); - void SetText(TTextTag textTag, string text); - } + void SetText(TTextTag textTag, string text); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs index 900725380..36dc94176 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTimeTagsChangeHandler.cs @@ -5,36 +5,35 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricTimeTagsChangeHandler : ILyricListPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler { - public interface ILyricTimeTagsChangeHandler : ILyricListPropertyChangeHandler, ILyricPropertyAutoGenerateChangeHandler - { - void SetTimeTagTime(TimeTag timeTag, double time); + void SetTimeTagTime(TimeTag timeTag, double time); - void ShiftingTimeTagTime(IEnumerable timeTags, double offset); + void ShiftingTimeTagTime(IEnumerable timeTags, double offset); - void ClearTimeTagTime(TimeTag timeTag); + void ClearTimeTagTime(TimeTag timeTag); - void ClearAllTimeTagTime(); + void ClearAllTimeTagTime(); - void AddByPosition(TextIndex index); + void AddByPosition(TextIndex index); - void RemoveByPosition(TextIndex index); + void RemoveByPosition(TextIndex index); - TimeTag Shifting(TimeTag timeTag, ShiftingDirection direction, ShiftingType type); - } + TimeTag Shifting(TimeTag timeTag, ShiftingDirection direction, ShiftingType type); +} - public enum ShiftingDirection - { - Left, +public enum ShiftingDirection +{ + Left, - Right - } + Right +} - public enum ShiftingType - { - State, +public enum ShiftingType +{ + State, - Index, - } + Index, } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTranslateChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTranslateChangeHandler.cs index 14d6e638c..b4164b66d 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTranslateChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricTranslateChangeHandler.cs @@ -3,10 +3,9 @@ using System.Globalization; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricTranslateChangeHandler : ILyricPropertyChangeHandler { - public interface ILyricTranslateChangeHandler : ILyricPropertyChangeHandler - { - void UpdateTranslate(CultureInfo cultureInfo, string translate); - } + void UpdateTranslate(CultureInfo cultureInfo, string translate); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricsChangeHandler.cs index 3e2eb65a7..5af75e475 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/ILyricsChangeHandler.cs @@ -4,24 +4,23 @@ using System.Collections.Generic; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public interface ILyricsChangeHandler { - public interface ILyricsChangeHandler - { - void Split(int index); + void Split(int index); - void Combine(); + void Combine(); - void CreateAtPosition(); + void CreateAtPosition(); - void CreateAtLast(); + void CreateAtLast(); - void AddBelowToSelection(Lyric newLyric); + void AddBelowToSelection(Lyric newLyric); - void AddRangeBelowToSelection(IEnumerable newLyrics); + void AddRangeBelowToSelection(IEnumerable newLyrics); - void Remove(); + void Remove(); - void ChangeOrder(int newOrder); - } + void ChangeOrder(int newOrder); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs index e6045ad3b..9ab9d6535 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricLanguageChangeHandler.cs @@ -8,49 +8,48 @@ using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricLanguageChangeHandler : LyricPropertyChangeHandler, ILyricLanguageChangeHandler { - public partial class LyricLanguageChangeHandler : LyricPropertyChangeHandler, ILyricLanguageChangeHandler + #region Auto-Generate + + public bool CanGenerate() { - #region Auto-Generate + var detector = GetDetector(); + return CanDetect(detector); + } - public bool CanGenerate() - { - var detector = GetDetector(); - return CanDetect(detector); - } + public IDictionary GetGeneratorNotSupportedLyrics() + { + var detector = GetDetector(); + return GetInvalidMessageFromDetector(detector); + } - public IDictionary GetGeneratorNotSupportedLyrics() - { - var detector = GetDetector(); - return GetInvalidMessageFromDetector(detector); - } + public void AutoGenerate() + { + var detector = GetDetector(); - public void AutoGenerate() + PerformOnSelection(lyric => { - var detector = GetDetector(); - - PerformOnSelection(lyric => - { - var detectedLanguage = detector.Detect(lyric); - lyric.Language = detectedLanguage; - }); - } + var detectedLanguage = detector.Detect(lyric); + lyric.Language = detectedLanguage; + }); + } - #endregion + #endregion - public void SetLanguage(CultureInfo? language) + public void SetLanguage(CultureInfo? language) + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - if (EqualityComparer.Default.Equals(language, lyric.Language)) - return; - - lyric.Language = language; - }); - } + if (EqualityComparer.Default.Equals(language, lyric.Language)) + return; - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Language)); + lyric.Language = language; + }); } + + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Language)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs index 591a2ba82..643fc3750 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricPropertyChangeHandler.cs @@ -11,93 +11,92 @@ using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public abstract partial class LyricPropertyChangeHandler : HitObjectPropertyChangeHandler, ILyricPropertyChangeHandler { - public abstract partial class LyricPropertyChangeHandler : HitObjectPropertyChangeHandler, ILyricPropertyChangeHandler + #region Auto-Generate + + [Resolved] + private KaraokeRulesetEditGeneratorConfigManager? generatorConfigManager { get; set; } + + protected LyricPropertyDetector GetDetector() + where TConfig : GeneratorConfig, new() + { + // using reflection to get the detector. + var config = getGeneratorConfig(); + var detectorType = getChildType(typeof(LyricPropertyDetector<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); + var detector = Activator.CreateInstance(detectorType, config) as LyricPropertyDetector; + return detector ?? throw new InvalidOperationException(); + } + + protected LyricPropertyDetector GetDetector(IEnumerable lyrics) + where TConfig : GeneratorConfig, new() + { + // using reflection to get the detector. + var config = getGeneratorConfig(); + var detectorType = getChildType(typeof(LyricPropertyDetector<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); + var detector = Activator.CreateInstance(detectorType, lyrics, config) as LyricPropertyDetector; + return detector ?? throw new InvalidOperationException(); + } + + protected LyricPropertyGenerator GetGenerator() + where TConfig : GeneratorConfig, new() { - #region Auto-Generate - - [Resolved] - private KaraokeRulesetEditGeneratorConfigManager? generatorConfigManager { get; set; } - - protected LyricPropertyDetector GetDetector() - where TConfig : GeneratorConfig, new() - { - // using reflection to get the detector. - var config = getGeneratorConfig(); - var detectorType = getChildType(typeof(LyricPropertyDetector<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); - var detector = Activator.CreateInstance(detectorType, config) as LyricPropertyDetector; - return detector ?? throw new InvalidOperationException(); - } - - protected LyricPropertyDetector GetDetector(IEnumerable lyrics) - where TConfig : GeneratorConfig, new() - { - // using reflection to get the detector. - var config = getGeneratorConfig(); - var detectorType = getChildType(typeof(LyricPropertyDetector<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); - var detector = Activator.CreateInstance(detectorType, lyrics, config) as LyricPropertyDetector; - return detector ?? throw new InvalidOperationException(); - } - - protected LyricPropertyGenerator GetGenerator() - where TConfig : GeneratorConfig, new() - { - // using reflection to get the generator. - var config = getGeneratorConfig(); - var generatorType = getChildType(typeof(LyricPropertyGenerator<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); - var generator = Activator.CreateInstance(generatorType, config) as LyricPropertyGenerator; - return generator ?? throw new InvalidOperationException(); - } - - protected LyricGeneratorSelector GetSelector() - where TBaseConfig : GeneratorConfig - { - // using reflection to get the selector. - var selectorType = getChildType(typeof(LyricGeneratorSelector<,>).MakeGenericType(typeof(TProperty), typeof(TBaseConfig))); - var selector = Activator.CreateInstance(selectorType, generatorConfigManager) as LyricGeneratorSelector; - return selector ?? throw new InvalidOperationException(); - } - - private Type getChildType(Type type) - { - // should get the assembly that the has the class GeneratorConfig. - var assembly = typeof(GeneratorConfig).Assembly; - return assembly.GetTypes() - .Single(x => type.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); - } - - private TConfig getGeneratorConfig() - where TConfig : GeneratorConfig, new() - { - if (generatorConfigManager == null) - throw new InvalidOperationException(); - - return generatorConfigManager.Get(); - } - - protected bool CanDetect(PropertyDetector detector) - => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(detector.CanDetect); - - protected bool CanGenerate(PropertyGenerator generator) - => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(generator.CanGenerate); - - protected IDictionary GetInvalidMessageFromDetector(PropertyDetector detector) - => HitObjects.Select(x => new KeyValuePair(x, detector.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) - .Where(x => x.Value != null) - .ToDictionary(k => k.Key, v => v.Value!.Value); - - protected IDictionary GetInvalidMessageFromGenerator(PropertyGenerator generator) - => HitObjects.Select(x => new KeyValuePair(x, generator.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) - .Where(x => x.Value != null) - .ToDictionary(k => k.Key, v => v.Value!.Value); - - private LocalisableString? getReferenceLyricInvalidMessage(Lyric lyric) - { - bool locked = IsWritePropertyLocked(lyric); - return locked ? "Cannot modify property because has reference lyric." : default(LocalisableString?); - } - - #endregion + // using reflection to get the generator. + var config = getGeneratorConfig(); + var generatorType = getChildType(typeof(LyricPropertyGenerator<,>).MakeGenericType(typeof(TProperty), typeof(TConfig))); + var generator = Activator.CreateInstance(generatorType, config) as LyricPropertyGenerator; + return generator ?? throw new InvalidOperationException(); } + + protected LyricGeneratorSelector GetSelector() + where TBaseConfig : GeneratorConfig + { + // using reflection to get the selector. + var selectorType = getChildType(typeof(LyricGeneratorSelector<,>).MakeGenericType(typeof(TProperty), typeof(TBaseConfig))); + var selector = Activator.CreateInstance(selectorType, generatorConfigManager) as LyricGeneratorSelector; + return selector ?? throw new InvalidOperationException(); + } + + private Type getChildType(Type type) + { + // should get the assembly that the has the class GeneratorConfig. + var assembly = typeof(GeneratorConfig).Assembly; + return assembly.GetTypes() + .Single(x => type.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); + } + + private TConfig getGeneratorConfig() + where TConfig : GeneratorConfig, new() + { + if (generatorConfigManager == null) + throw new InvalidOperationException(); + + return generatorConfigManager.Get(); + } + + protected bool CanDetect(PropertyDetector detector) + => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(detector.CanDetect); + + protected bool CanGenerate(PropertyGenerator generator) + => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(generator.CanGenerate); + + protected IDictionary GetInvalidMessageFromDetector(PropertyDetector detector) + => HitObjects.Select(x => new KeyValuePair(x, detector.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) + .Where(x => x.Value != null) + .ToDictionary(k => k.Key, v => v.Value!.Value); + + protected IDictionary GetInvalidMessageFromGenerator(PropertyGenerator generator) + => HitObjects.Select(x => new KeyValuePair(x, generator.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) + .Where(x => x.Value != null) + .ToDictionary(k => k.Key, v => v.Value!.Value); + + private LocalisableString? getReferenceLyricInvalidMessage(Lyric lyric) + { + bool locked = IsWritePropertyLocked(lyric); + return locked ? "Cannot modify property because has reference lyric." : default(LocalisableString?); + } + + #endregion } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs index 149ca28de..0d6b91eec 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricReferenceChangeHandler.cs @@ -10,106 +10,105 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Properties; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricReferenceChangeHandler : LyricPropertyChangeHandler, ILyricReferenceChangeHandler { - public partial class LyricReferenceChangeHandler : LyricPropertyChangeHandler, ILyricReferenceChangeHandler + #region Auto-Generate + + public bool CanGenerate() { - #region Auto-Generate + var detector = GetDetector(HitObjects); + return CanDetect(detector); + } - public bool CanGenerate() - { - var detector = GetDetector(HitObjects); - return CanDetect(detector); - } + public IDictionary GetGeneratorNotSupportedLyrics() + { + var detector = GetDetector(HitObjects); + return GetInvalidMessageFromDetector(detector); + } - public IDictionary GetGeneratorNotSupportedLyrics() - { - var detector = GetDetector(HitObjects); - return GetInvalidMessageFromDetector(detector); - } + public void AutoGenerate() + { + var detector = GetDetector(HitObjects); - public void AutoGenerate() + PerformOnSelection(lyric => { - var detector = GetDetector(HitObjects); + var referencedLyric = detector.Detect(lyric); + lyric.ReferenceLyricId = referencedLyric?.ID; - PerformOnSelection(lyric => - { - var referencedLyric = detector.Detect(lyric); - lyric.ReferenceLyricId = referencedLyric?.ID; + // technically this property should be assigned by beatmap processor, but should be OK to assign here for testing purpose. + lyric.ReferenceLyric = referencedLyric; - // technically this property should be assigned by beatmap processor, but should be OK to assign here for testing purpose. - lyric.ReferenceLyric = referencedLyric; + if (lyric.ReferenceLyricId != null && lyric.ReferenceLyricConfig is not SyncLyricConfig) + lyric.ReferenceLyricConfig = new SyncLyricConfig(); + }); + } - if (lyric.ReferenceLyricId != null && lyric.ReferenceLyricConfig is not SyncLyricConfig) - lyric.ReferenceLyricConfig = new SyncLyricConfig(); - }); - } + #endregion - #endregion + public void UpdateReferenceLyric(Lyric? referenceLyric) + { + if (referenceLyric != null && !HitObjects.Contains(referenceLyric)) + throw new InvalidOperationException($"{nameof(referenceLyric)} should in the beatmap."); - public void UpdateReferenceLyric(Lyric? referenceLyric) + PerformOnSelection(lyric => { - if (referenceLyric != null && !HitObjects.Contains(referenceLyric)) - throw new InvalidOperationException($"{nameof(referenceLyric)} should in the beatmap."); + if (referenceLyric == lyric) + throw new InvalidOperationException($"{nameof(referenceLyric)} should not be the same instance as {nameof(lyric)}"); - PerformOnSelection(lyric => - { - if (referenceLyric == lyric) - throw new InvalidOperationException($"{nameof(referenceLyric)} should not be the same instance as {nameof(lyric)}"); - - if (referenceLyric?.ReferenceLyric != null) - throw new InvalidOperationException($"{nameof(referenceLyric)} should not contains another reference lyric."); + if (referenceLyric?.ReferenceLyric != null) + throw new InvalidOperationException($"{nameof(referenceLyric)} should not contains another reference lyric."); - lyric.ReferenceLyricId = referenceLyric?.ID; + lyric.ReferenceLyricId = referenceLyric?.ID; - if (lyric.ReferenceLyricId == null) - { - lyric.ReferenceLyricConfig = null; - } - else if (lyric.ReferenceLyricConfig == null) - { - // todo: not really sure should use sync config if lyric text are similar. - lyric.ReferenceLyricConfig = new ReferenceLyricConfig(); - } + if (lyric.ReferenceLyricId == null) + { + lyric.ReferenceLyricConfig = null; + } + else if (lyric.ReferenceLyricConfig == null) + { + // todo: not really sure should use sync config if lyric text are similar. + lyric.ReferenceLyricConfig = new ReferenceLyricConfig(); + } - TriggerHitObjectUpdate(lyric); - }); - } + TriggerHitObjectUpdate(lyric); + }); + } - public void SwitchToReferenceLyricConfig() + public void SwitchToReferenceLyricConfig() + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - if (lyric.ReferenceLyric == null) - throw new InvalidOperationException($"{nameof(lyric)} must have reference lyric."); + if (lyric.ReferenceLyric == null) + throw new InvalidOperationException($"{nameof(lyric)} must have reference lyric."); - lyric.ReferenceLyricConfig = new ReferenceLyricConfig(); - }); - } + lyric.ReferenceLyricConfig = new ReferenceLyricConfig(); + }); + } - public void SwitchToSyncLyricConfig() + public void SwitchToSyncLyricConfig() + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - if (lyric.ReferenceLyric == null) - throw new InvalidOperationException($"{nameof(lyric)} must have reference lyric."); + if (lyric.ReferenceLyric == null) + throw new InvalidOperationException($"{nameof(lyric)} must have reference lyric."); - lyric.ReferenceLyricConfig = new SyncLyricConfig(); - }); - } + lyric.ReferenceLyricConfig = new SyncLyricConfig(); + }); + } - public void AdjustLyricConfig(Action action) where TConfig : IReferenceLyricPropertyConfig + public void AdjustLyricConfig(Action action) where TConfig : IReferenceLyricPropertyConfig + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - if (lyric.ReferenceLyricConfig is not TConfig config) - throw new InvalidOperationException($"{nameof(config)} must be the type of ${typeof(TConfig)}."); - - action.Invoke(config); - }); - } + if (lyric.ReferenceLyricConfig is not TConfig config) + throw new InvalidOperationException($"{nameof(config)} must be the type of ${typeof(TConfig)}."); - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.ReferenceLyric), nameof(Lyric.ReferenceLyricConfig)); + action.Invoke(config); + }); } + + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.ReferenceLyric), nameof(Lyric.ReferenceLyricConfig)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs index 900d450ba..4e2da4483 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRomajiTagsChangeHandler.cs @@ -7,46 +7,45 @@ using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricRomajiTagsChangeHandler : LyricTextTagsChangeHandler, ILyricRomajiTagsChangeHandler { - public partial class LyricRomajiTagsChangeHandler : LyricTextTagsChangeHandler, ILyricRomajiTagsChangeHandler + #region Auto-Generate + + public bool CanGenerate() { - #region Auto-Generate + var generator = GetSelector(); + return CanGenerate(generator); + } - public bool CanGenerate() - { - var generator = GetSelector(); - return CanGenerate(generator); - } + public IDictionary GetGeneratorNotSupportedLyrics() + { + var generator = GetSelector(); + return GetInvalidMessageFromGenerator(generator); + } - public IDictionary GetGeneratorNotSupportedLyrics() - { - var generator = GetSelector(); - return GetInvalidMessageFromGenerator(generator); - } + public void AutoGenerate() + { + var generator = GetSelector(); - public void AutoGenerate() + PerformOnSelection(lyric => { - var generator = GetSelector(); - - PerformOnSelection(lyric => - { - lyric.RomajiTags = generator.Generate(lyric); - }); - } + lyric.RomajiTags = generator.Generate(lyric); + }); + } - #endregion + #endregion - protected override bool ContainsInLyric(Lyric lyric, RomajiTag textTag) - => lyric.RomajiTags.Contains(textTag); + protected override bool ContainsInLyric(Lyric lyric, RomajiTag textTag) + => lyric.RomajiTags.Contains(textTag); - protected override void AddToLyric(Lyric lyric, RomajiTag textTag) - => lyric.RomajiTags.Add(textTag); + protected override void AddToLyric(Lyric lyric, RomajiTag textTag) + => lyric.RomajiTags.Add(textTag); - protected override void RemoveFromLyric(Lyric lyric, RomajiTag textTag) - => lyric.RomajiTags.Remove(textTag); + protected override void RemoveFromLyric(Lyric lyric, RomajiTag textTag) + => lyric.RomajiTags.Remove(textTag); - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.RomajiTags)); - } + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.RomajiTags)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs index e255d142f..445984b1c 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricRubyTagsChangeHandler.cs @@ -7,46 +7,45 @@ using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricRubyTagsChangeHandler : LyricTextTagsChangeHandler, ILyricRubyTagsChangeHandler { - public partial class LyricRubyTagsChangeHandler : LyricTextTagsChangeHandler, ILyricRubyTagsChangeHandler + #region Auto-Generate + + public bool CanGenerate() { - #region Auto-Generate + var generator = GetSelector(); + return CanGenerate(generator); + } - public bool CanGenerate() - { - var generator = GetSelector(); - return CanGenerate(generator); - } + public IDictionary GetGeneratorNotSupportedLyrics() + { + var generator = GetSelector(); + return GetInvalidMessageFromGenerator(generator); + } - public IDictionary GetGeneratorNotSupportedLyrics() - { - var generator = GetSelector(); - return GetInvalidMessageFromGenerator(generator); - } + public void AutoGenerate() + { + var generator = GetSelector(); - public void AutoGenerate() + PerformOnSelection(lyric => { - var generator = GetSelector(); - - PerformOnSelection(lyric => - { - lyric.RubyTags = generator.Generate(lyric); - }); - } + lyric.RubyTags = generator.Generate(lyric); + }); + } - #endregion + #endregion - protected override bool ContainsInLyric(Lyric lyric, RubyTag textTag) - => lyric.RubyTags.Contains(textTag); + protected override bool ContainsInLyric(Lyric lyric, RubyTag textTag) + => lyric.RubyTags.Contains(textTag); - protected override void AddToLyric(Lyric lyric, RubyTag textTag) - => lyric.RubyTags.Add(textTag); + protected override void AddToLyric(Lyric lyric, RubyTag textTag) + => lyric.RubyTags.Add(textTag); - protected override void RemoveFromLyric(Lyric lyric, RubyTag textTag) - => lyric.RubyTags.Remove(textTag); + protected override void RemoveFromLyric(Lyric lyric, RubyTag textTag) + => lyric.RubyTags.Remove(textTag); - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.RubyTags)); - } + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.RubyTags)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricSingerChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricSingerChangeHandler.cs index d6ff0a3ed..a19854994 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricSingerChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricSingerChangeHandler.cs @@ -7,69 +7,68 @@ using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricSingerChangeHandler : LyricPropertyChangeHandler, ILyricSingerChangeHandler { - public partial class LyricSingerChangeHandler : LyricPropertyChangeHandler, ILyricSingerChangeHandler + public void Add(ISinger singer) { - public void Add(ISinger singer) + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - lyric.SingerIds.Add(singer.ID); + lyric.SingerIds.Add(singer.ID); - TriggerHitObjectUpdate(lyric); - }); - } + TriggerHitObjectUpdate(lyric); + }); + } - public void AddRange(IEnumerable singers) + public void AddRange(IEnumerable singers) + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => + // should convert to array because enumerable might change while deleting. + foreach (var singer in singers.ToArray()) { - // should convert to array because enumerable might change while deleting. - foreach (var singer in singers.ToArray()) - { - lyric.SingerIds.Add(singer.ID); - } + lyric.SingerIds.Add(singer.ID); + } - TriggerHitObjectUpdate(lyric); - }); - } + TriggerHitObjectUpdate(lyric); + }); + } - public void Remove(ISinger singer) + public void Remove(ISinger singer) + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - lyric.SingerIds.Remove(singer.ID); + lyric.SingerIds.Remove(singer.ID); - TriggerHitObjectUpdate(lyric); - }); - } + TriggerHitObjectUpdate(lyric); + }); + } - public void RemoveRange(IEnumerable singers) + public void RemoveRange(IEnumerable singers) + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => + // should convert to array because enumerable might change while deleting. + foreach (var singer in singers.ToArray()) { - // should convert to array because enumerable might change while deleting. - foreach (var singer in singers.ToArray()) - { - lyric.SingerIds.Remove(singer.ID); - } + lyric.SingerIds.Remove(singer.ID); + } - TriggerHitObjectUpdate(lyric); - }); - } + TriggerHitObjectUpdate(lyric); + }); + } - public void Clear() + public void Clear() + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - lyric.SingerIds.Clear(); + lyric.SingerIds.Clear(); - TriggerHitObjectUpdate(lyric); - }); - } - - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.SingerIds)); + TriggerHitObjectUpdate(lyric); + }); } + + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.SingerIds)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextChangeHandler.cs index 9e15894d8..100cbe213 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextChangeHandler.cs @@ -6,40 +6,39 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricTextChangeHandler : LyricPropertyChangeHandler, ILyricTextChangeHandler { - public partial class LyricTextChangeHandler : LyricPropertyChangeHandler, ILyricTextChangeHandler + public void InsertText(int index, string text) { - public void InsertText(int index, string text) - { - CheckExactlySelectedOneHitObject(); + CheckExactlySelectedOneHitObject(); - PerformOnSelection(lyric => - { - LyricUtils.AddText(lyric, index, text); - }); - } - - public void DeleteLyricText(int index) + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + LyricUtils.AddText(lyric, index, text); + }); + } - PerformOnSelection(lyric => - { - LyricUtils.RemoveText(lyric, index - 1); + public void DeleteLyricText(int index) + { + CheckExactlySelectedOneHitObject(); - if (!string.IsNullOrEmpty(lyric.Text)) - return; + PerformOnSelection(lyric => + { + LyricUtils.RemoveText(lyric, index - 1); - if (HitObjectWritableUtils.IsRemoveLyricLocked(lyric)) - return; + if (!string.IsNullOrEmpty(lyric.Text)) + return; - OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyric.Order), -1); - Remove(lyric); - }); - } + if (HitObjectWritableUtils.IsRemoveLyricLocked(lyric)) + return; - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Text), nameof(Lyric.RubyTags), nameof(Lyric.RomajiTags), nameof(Lyric.TimeTags)); + OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyric.Order), -1); + Remove(lyric); + }); } + + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Text), nameof(Lyric.RubyTags), nameof(Lyric.RomajiTags), nameof(Lyric.TimeTags)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextTagsChangeHandler.cs index 663a5999c..a92a5ebc5 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTextTagsChangeHandler.cs @@ -8,135 +8,134 @@ using osu.Game.Rulesets.Karaoke.Objects.Types; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public abstract partial class LyricTextTagsChangeHandler : LyricPropertyChangeHandler, ILyricTextTagsChangeHandler where TTextTag : class, ITextTag, new() { - public abstract partial class LyricTextTagsChangeHandler : LyricPropertyChangeHandler, ILyricTextTagsChangeHandler where TTextTag : class, ITextTag, new() + public void Add(TTextTag textTag) { - public void Add(TTextTag textTag) + CheckExactlySelectedOneHitObject(); + + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + bool containsInLyric = ContainsInLyric(lyric, textTag); + if (containsInLyric) + throw new InvalidOperationException($"{nameof(textTag)} already in the lyric"); - PerformOnSelection(lyric => + AddToLyric(lyric, textTag); + }); + } + + public void AddRange(IEnumerable textTags) + { + CheckExactlySelectedOneHitObject(); + + PerformOnSelection(lyric => + { + // should convert to array because enumerable might change while deleting. + foreach (var textTag in textTags.ToArray()) { bool containsInLyric = ContainsInLyric(lyric, textTag); if (containsInLyric) throw new InvalidOperationException($"{nameof(textTag)} already in the lyric"); AddToLyric(lyric, textTag); - }); - } + } + }); + } - public void AddRange(IEnumerable textTags) - { - CheckExactlySelectedOneHitObject(); + public void Remove(TTextTag textTag) + { + CheckExactlySelectedOneHitObject(); - PerformOnSelection(lyric => - { - // should convert to array because enumerable might change while deleting. - foreach (var textTag in textTags.ToArray()) - { - bool containsInLyric = ContainsInLyric(lyric, textTag); - if (containsInLyric) - throw new InvalidOperationException($"{nameof(textTag)} already in the lyric"); - - AddToLyric(lyric, textTag); - } - }); - } - - public void Remove(TTextTag textTag) + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + bool containsInLyric = ContainsInLyric(lyric, textTag); + if (!containsInLyric) + throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); - PerformOnSelection(lyric => + RemoveFromLyric(lyric, textTag); + }); + } + + public void RemoveRange(IEnumerable textTags) + { + CheckExactlySelectedOneHitObject(); + + PerformOnSelection(lyric => + { + // should convert to array because enumerable might change while deleting. + foreach (var textTag in textTags.ToArray()) { bool containsInLyric = ContainsInLyric(lyric, textTag); if (!containsInLyric) throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); RemoveFromLyric(lyric, textTag); - }); - } + } + }); + } - public void RemoveRange(IEnumerable textTags) - { - CheckExactlySelectedOneHitObject(); + public void SetIndex(TTextTag textTag, int? startIndex, int? endIndex) + { + CheckExactlySelectedOneHitObject(); - PerformOnSelection(lyric => - { - // should convert to array because enumerable might change while deleting. - foreach (var textTag in textTags.ToArray()) - { - bool containsInLyric = ContainsInLyric(lyric, textTag); - if (!containsInLyric) - throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); - - RemoveFromLyric(lyric, textTag); - } - }); - } - - public void SetIndex(TTextTag textTag, int? startIndex, int? endIndex) + // note: it's ok not sort the text tag by index. + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + bool containsInLyric = ContainsInLyric(lyric, textTag); + if (!containsInLyric) + throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); - // note: it's ok not sort the text tag by index. - PerformOnSelection(lyric => - { - bool containsInLyric = ContainsInLyric(lyric, textTag); - if (!containsInLyric) - throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); - - if (startIndex != null) - textTag.StartIndex = startIndex.Value; + if (startIndex != null) + textTag.StartIndex = startIndex.Value; - if (endIndex != null) - textTag.EndIndex = endIndex.Value; + if (endIndex != null) + textTag.EndIndex = endIndex.Value; - // after change the index, should check if index is valid. - if (TextTagUtils.OutOfRange(textTag, lyric.Text)) - throw new InvalidOperationException($"{nameof(startIndex)} or {nameof(endIndex)} is not valid"); - }); - } + // after change the index, should check if index is valid. + if (TextTagUtils.OutOfRange(textTag, lyric.Text)) + throw new InvalidOperationException($"{nameof(startIndex)} or {nameof(endIndex)} is not valid"); + }); + } - public void ShiftingIndex(IEnumerable textTags, int offset) - { - CheckExactlySelectedOneHitObject(); + public void ShiftingIndex(IEnumerable textTags, int offset) + { + CheckExactlySelectedOneHitObject(); - // note: it's ok not sort the text tag by index. - PerformOnSelection(lyric => - { - foreach (var textTag in textTags) - { - bool containsInLyric = ContainsInLyric(lyric, textTag); - if (!containsInLyric) - throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); - - (int startIndex, int endIndex) = TextTagUtils.GetShiftingIndex(textTag, lyric.Text, offset); - textTag.StartIndex = startIndex; - textTag.EndIndex = endIndex; - } - }); - } - - public void SetText(TTextTag textTag, string text) + // note: it's ok not sort the text tag by index. + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); - - PerformOnSelection(lyric => + foreach (var textTag in textTags) { bool containsInLyric = ContainsInLyric(lyric, textTag); if (!containsInLyric) throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); - textTag.Text = text; - }); - } + (int startIndex, int endIndex) = TextTagUtils.GetShiftingIndex(textTag, lyric.Text, offset); + textTag.StartIndex = startIndex; + textTag.EndIndex = endIndex; + } + }); + } - protected abstract bool ContainsInLyric(Lyric lyric, TTextTag textTag); + public void SetText(TTextTag textTag, string text) + { + CheckExactlySelectedOneHitObject(); - protected abstract void AddToLyric(Lyric lyric, TTextTag textTag); + PerformOnSelection(lyric => + { + bool containsInLyric = ContainsInLyric(lyric, textTag); + if (!containsInLyric) + throw new InvalidOperationException($"{nameof(textTag)} is not in the lyric"); - protected abstract void RemoveFromLyric(Lyric lyric, TTextTag textTag); + textTag.Text = text; + }); } + + protected abstract bool ContainsInLyric(Lyric lyric, TTextTag textTag); + + protected abstract void AddToLyric(Lyric lyric, TTextTag textTag); + + protected abstract void RemoveFromLyric(Lyric lyric, TTextTag textTag); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs index c8323071f..aa1eaa6b9 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTimeTagsChangeHandler.cs @@ -11,289 +11,288 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricTimeTagsChangeHandler : LyricPropertyChangeHandler, ILyricTimeTagsChangeHandler { - public partial class LyricTimeTagsChangeHandler : LyricPropertyChangeHandler, ILyricTimeTagsChangeHandler + #region Auto-Generate + + public bool CanGenerate() { - #region Auto-Generate + var generator = GetSelector(); + return CanGenerate(generator); + } - public bool CanGenerate() - { - var generator = GetSelector(); - return CanGenerate(generator); - } + public IDictionary GetGeneratorNotSupportedLyrics() + { + var generator = GetSelector(); + return GetInvalidMessageFromGenerator(generator); + } - public IDictionary GetGeneratorNotSupportedLyrics() - { - var generator = GetSelector(); - return GetInvalidMessageFromGenerator(generator); - } + public void AutoGenerate() + { + var generator = GetSelector(); - public void AutoGenerate() + PerformOnSelection(lyric => { - var generator = GetSelector(); + lyric.TimeTags = generator.Generate(lyric); + }); + } - PerformOnSelection(lyric => - { - lyric.TimeTags = generator.Generate(lyric); - }); - } + #endregion - #endregion + public void SetTimeTagTime(TimeTag timeTag, double time) + { + CheckExactlySelectedOneHitObject(); - public void SetTimeTagTime(TimeTag timeTag, double time) + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + bool containsInLyric = lyric.TimeTags.Contains(timeTag); + if (!containsInLyric) + throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); + + timeTag.Time = time; + }); + } + + public void ShiftingTimeTagTime(IEnumerable timeTags, double offset) + { + CheckExactlySelectedOneHitObject(); + NotTriggerSaveStateOnThisChange(); - PerformOnSelection(lyric => + PerformOnSelection(lyric => + { + foreach (var timeTag in timeTags) { bool containsInLyric = lyric.TimeTags.Contains(timeTag); if (!containsInLyric) throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); - timeTag.Time = time; - }); - } + timeTag.Time += offset; + } + }); + } - public void ShiftingTimeTagTime(IEnumerable timeTags, double offset) - { - CheckExactlySelectedOneHitObject(); - NotTriggerSaveStateOnThisChange(); + public void ClearTimeTagTime(TimeTag timeTag) + { + CheckExactlySelectedOneHitObject(); - PerformOnSelection(lyric => - { - foreach (var timeTag in timeTags) - { - bool containsInLyric = lyric.TimeTags.Contains(timeTag); - if (!containsInLyric) - throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); + PerformOnSelection(lyric => + { + bool containsInLyric = lyric.TimeTags.Contains(timeTag); + if (!containsInLyric) + throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); - timeTag.Time += offset; - } - }); - } + timeTag.Time = null; + }); + } - public void ClearTimeTagTime(TimeTag timeTag) + public void ClearAllTimeTagTime() + { + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); - - PerformOnSelection(lyric => + foreach (var timeTag in lyric.TimeTags) { - bool containsInLyric = lyric.TimeTags.Contains(timeTag); - if (!containsInLyric) - throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); - timeTag.Time = null; - }); - } + } + }); + } - public void ClearAllTimeTagTime() - { - PerformOnSelection(lyric => - { - foreach (var timeTag in lyric.TimeTags) - { - timeTag.Time = null; - } - }); - } + public void Add(TimeTag timeTag) + { + CheckExactlySelectedOneHitObject(); - public void Add(TimeTag timeTag) + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + bool containsInLyric = lyric.TimeTags.Contains(timeTag); + if (containsInLyric) + throw new InvalidOperationException($"{nameof(timeTag)} already in the lyric"); - PerformOnSelection(lyric => + insertTimeTag(lyric, timeTag, InsertDirection.End); + }); + } + + public void AddRange(IEnumerable timeTags) + { + CheckExactlySelectedOneHitObject(); + + PerformOnSelection(lyric => + { + // should convert to array because enumerable might change while deleting. + foreach (var timeTag in timeTags.ToArray()) { bool containsInLyric = lyric.TimeTags.Contains(timeTag); if (containsInLyric) throw new InvalidOperationException($"{nameof(timeTag)} already in the lyric"); insertTimeTag(lyric, timeTag, InsertDirection.End); - }); - } + } + }); + } - public void AddRange(IEnumerable timeTags) - { - CheckExactlySelectedOneHitObject(); + public void Remove(TimeTag timeTag) + { + CheckExactlySelectedOneHitObject(); - PerformOnSelection(lyric => - { - // should convert to array because enumerable might change while deleting. - foreach (var timeTag in timeTags.ToArray()) - { - bool containsInLyric = lyric.TimeTags.Contains(timeTag); - if (containsInLyric) - throw new InvalidOperationException($"{nameof(timeTag)} already in the lyric"); + PerformOnSelection(lyric => + { + // delete time tag from list + lyric.TimeTags.Remove(timeTag); + }); + } - insertTimeTag(lyric, timeTag, InsertDirection.End); - } - }); - } + public void RemoveRange(IEnumerable timeTags) + { + CheckExactlySelectedOneHitObject(); - public void Remove(TimeTag timeTag) + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); - - PerformOnSelection(lyric => + // should convert to array because enumerable might change while deleting. + foreach (var timeTag in timeTags.ToArray()) { - // delete time tag from list - lyric.TimeTags.Remove(timeTag); - }); - } + bool containsInLyric = lyric.TimeTags.Remove(timeTag); + if (!containsInLyric) + throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); + } + }); + } - public void RemoveRange(IEnumerable timeTags) + public void AddByPosition(TextIndex index) + { + CheckExactlySelectedOneHitObject(); + + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + insertTimeTag(lyric, new TimeTag(index), InsertDirection.End); + }); + } - PerformOnSelection(lyric => - { - // should convert to array because enumerable might change while deleting. - foreach (var timeTag in timeTags.ToArray()) - { - bool containsInLyric = lyric.TimeTags.Remove(timeTag); - if (!containsInLyric) - throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); - } - }); - } + public void RemoveByPosition(TextIndex index) + { + CheckExactlySelectedOneHitObject(); - public void AddByPosition(TextIndex index) + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + var matchedTimeTags = lyric.TimeTags.Where(x => x.Index == index).ToList(); + if (!matchedTimeTags.Any()) + return; - PerformOnSelection(lyric => - { - insertTimeTag(lyric, new TimeTag(index), InsertDirection.End); - }); - } + var removedTimeTag = matchedTimeTags.MinBy(x => x.Time ?? double.MinValue); + if (removedTimeTag != null) + lyric.TimeTags.Remove(removedTimeTag); + }); + } - public void RemoveByPosition(TextIndex index) - { - CheckExactlySelectedOneHitObject(); + public TimeTag Shifting(TimeTag timeTag, ShiftingDirection direction, ShiftingType type) + { + CheckExactlySelectedOneHitObject(); - PerformOnSelection(lyric => - { - var matchedTimeTags = lyric.TimeTags.Where(x => x.Index == index).ToList(); - if (!matchedTimeTags.Any()) - return; - - var removedTimeTag = matchedTimeTags.MinBy(x => x.Time ?? double.MinValue); - if (removedTimeTag != null) - lyric.TimeTags.Remove(removedTimeTag); - }); - } + TimeTag newTimeTag = null!; - public TimeTag Shifting(TimeTag timeTag, ShiftingDirection direction, ShiftingType type) + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + bool containsInLyric = lyric.TimeTags.Contains(timeTag); + if (!containsInLyric) + throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); - TimeTag newTimeTag = null!; + // remove the time-tag first. + lyric.TimeTags.Remove(timeTag); - PerformOnSelection(lyric => - { - bool containsInLyric = lyric.TimeTags.Contains(timeTag); - if (!containsInLyric) - throw new InvalidOperationException($"{nameof(timeTag)} is not in the lyric"); + // then, create a new one and insert into the list. + var newIndex = calculateNewIndex(lyric, timeTag.Index, direction, type); + double? newTime = timeTag.Time; + newTimeTag = new TimeTag(newIndex, newTime); - // remove the time-tag first. - lyric.TimeTags.Remove(timeTag); + switch (direction) + { + case ShiftingDirection.Left: + insertTimeTag(lyric, newTimeTag, InsertDirection.End); + break; - // then, create a new one and insert into the list. - var newIndex = calculateNewIndex(lyric, timeTag.Index, direction, type); - double? newTime = timeTag.Time; - newTimeTag = new TimeTag(newIndex, newTime); + case ShiftingDirection.Right: + insertTimeTag(lyric, newTimeTag, InsertDirection.Start); + break; - switch (direction) - { - case ShiftingDirection.Left: - insertTimeTag(lyric, newTimeTag, InsertDirection.End); - break; + default: + throw new InvalidOperationException(); + } + }); - case ShiftingDirection.Right: - insertTimeTag(lyric, newTimeTag, InsertDirection.Start); - break; + return newTimeTag; - default: - throw new InvalidOperationException(); - } - }); + static TextIndex calculateNewIndex(Lyric lyric, TextIndex originIndex, ShiftingDirection direction, ShiftingType type) + { + var newIndex = getNewIndex(originIndex, direction, type); + if (TextIndexUtils.OutOfRange(newIndex, lyric.Text)) + throw new ArgumentOutOfRangeException(); - return newTimeTag; + return newIndex; - static TextIndex calculateNewIndex(Lyric lyric, TextIndex originIndex, ShiftingDirection direction, ShiftingType type) - { - var newIndex = getNewIndex(originIndex, direction, type); - if (TextIndexUtils.OutOfRange(newIndex, lyric.Text)) - throw new ArgumentOutOfRangeException(); - - return newIndex; - - static TextIndex getNewIndex(TextIndex originIndex, ShiftingDirection direction, ShiftingType type) => - type switch - { - ShiftingType.Index => TextIndexUtils.ShiftingIndex(originIndex, direction == ShiftingDirection.Left ? -1 : 1), - ShiftingType.State => direction == ShiftingDirection.Left ? TextIndexUtils.GetPreviousIndex(originIndex) : TextIndexUtils.GetNextIndex(originIndex), - _ => throw new InvalidOperationException() - }; - } + static TextIndex getNewIndex(TextIndex originIndex, ShiftingDirection direction, ShiftingType type) => + type switch + { + ShiftingType.Index => TextIndexUtils.ShiftingIndex(originIndex, direction == ShiftingDirection.Left ? -1 : 1), + ShiftingType.State => direction == ShiftingDirection.Left ? TextIndexUtils.GetPreviousIndex(originIndex) : TextIndexUtils.GetNextIndex(originIndex), + _ => throw new InvalidOperationException() + }; } + } - private void insertTimeTag(Lyric lyric, TimeTag timeTag, InsertDirection direction) + private void insertTimeTag(Lyric lyric, TimeTag timeTag, InsertDirection direction) + { + var timeTags = lyric.TimeTags; + + // just add if there's no time-tag + if (lyric.TimeTags.Count == 0) { - var timeTags = lyric.TimeTags; + timeTags.Add(timeTag); + return; + } - // just add if there's no time-tag - if (lyric.TimeTags.Count == 0) + if (timeTags.All(x => x.Index < timeTag.Index)) + { + timeTags.Add(timeTag); + } + else if (timeTags.All(x => x.Index > timeTag.Index)) + { + timeTags.Insert(0, timeTag); + } + else + { + switch (direction) { - timeTags.Add(timeTag); - return; - } + case InsertDirection.Start: + { + var nextTimeTag = timeTags.FirstOrDefault(x => x.Index >= timeTag.Index) ?? timeTags.Last(); + int index = timeTags.IndexOf(nextTimeTag); + timeTags.Insert(index, timeTag); + break; + } - if (timeTags.All(x => x.Index < timeTag.Index)) - { - timeTags.Add(timeTag); - } - else if (timeTags.All(x => x.Index > timeTag.Index)) - { - timeTags.Insert(0, timeTag); - } - else - { - switch (direction) + case InsertDirection.End: { - case InsertDirection.Start: - { - var nextTimeTag = timeTags.FirstOrDefault(x => x.Index >= timeTag.Index) ?? timeTags.Last(); - int index = timeTags.IndexOf(nextTimeTag); - timeTags.Insert(index, timeTag); - break; - } - - case InsertDirection.End: - { - var previousTextTag = timeTags.Reverse().FirstOrDefault(x => x.Index <= timeTag.Index) ?? timeTags.First(); - int index = timeTags.IndexOf(previousTextTag) + 1; - timeTags.Insert(index, timeTag); - break; - } - - default: - throw new InvalidOperationException(); + var previousTextTag = timeTags.Reverse().FirstOrDefault(x => x.Index <= timeTag.Index) ?? timeTags.First(); + int index = timeTags.IndexOf(previousTextTag) + 1; + timeTags.Insert(index, timeTag); + break; } + + default: + throw new InvalidOperationException(); } } + } - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.TimeTags)); + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.TimeTags)); - /// - /// Insert direction if contains the time-tag with the same index. - /// - private enum InsertDirection - { - Start, + /// + /// Insert direction if contains the time-tag with the same index. + /// + private enum InsertDirection + { + Start, - End - } + End } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTranslateChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTranslateChangeHandler.cs index 0245edbca..17d0dea3b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTranslateChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricTranslateChangeHandler.cs @@ -6,31 +6,30 @@ using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricTranslateChangeHandler : LyricPropertyChangeHandler, ILyricTranslateChangeHandler { - public partial class LyricTranslateChangeHandler : LyricPropertyChangeHandler, ILyricTranslateChangeHandler + public void UpdateTranslate(CultureInfo cultureInfo, string translate) { - public void UpdateTranslate(CultureInfo cultureInfo, string translate) - { - CheckExactlySelectedOneHitObject(); + CheckExactlySelectedOneHitObject(); - PerformOnSelection(lyric => + PerformOnSelection(lyric => + { + // should not save translate if is null or empty or whitespace + if (string.IsNullOrWhiteSpace(translate)) { - // should not save translate if is null or empty or whitespace - if (string.IsNullOrWhiteSpace(translate)) - { - if (lyric.Translates.ContainsKey(cultureInfo)) - lyric.Translates.Remove(cultureInfo); - } - else - { - if (!lyric.Translates.TryAdd(cultureInfo, translate)) - lyric.Translates[cultureInfo] = translate; - } - }); - } - - protected override bool IsWritePropertyLocked(Lyric lyric) - => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Translates)); + if (lyric.Translates.ContainsKey(cultureInfo)) + lyric.Translates.Remove(cultureInfo); + } + else + { + if (!lyric.Translates.TryAdd(cultureInfo, translate)) + lyric.Translates[cultureInfo] = translate; + } + }); } + + protected override bool IsWritePropertyLocked(Lyric lyric) + => HitObjectWritableUtils.IsWriteLyricPropertyLocked(lyric, nameof(Lyric.Translates)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricsChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricsChangeHandler.cs index 36e160083..b3366b225 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricsChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricsChangeHandler.cs @@ -8,155 +8,154 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; + +public partial class LyricsChangeHandler : HitObjectsChangeHandler, ILyricsChangeHandler { - public partial class LyricsChangeHandler : HitObjectsChangeHandler, ILyricsChangeHandler + public void Split(int index) { - public void Split(int index) - { - CheckExactlySelectedOneHitObject(); - - PerformOnSelection(lyric => - { - // Shifting order that order is larger than current lyric. - int lyricOrder = lyric.Order; - OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyricOrder), 1); - - // Split lyric - var (firstLyric, secondLyric) = LyricsUtils.SplitLyric(lyric, index); - firstLyric.Order = lyric.Order; - firstLyric.ID = getId(); - secondLyric.Order = lyric.Order + 1; - secondLyric.ID = getId() + 1; - - // Add those tho lyric and remove old one. - Add(secondLyric); - Add(firstLyric); - Remove(lyric); - }); - } + CheckExactlySelectedOneHitObject(); - public void Combine() + PerformOnSelection(lyric => { - CheckExactlySelectedOneHitObject(); + // Shifting order that order is larger than current lyric. + int lyricOrder = lyric.Order; + OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyricOrder), 1); + + // Split lyric + var (firstLyric, secondLyric) = LyricsUtils.SplitLyric(lyric, index); + firstLyric.Order = lyric.Order; + firstLyric.ID = getId(); + secondLyric.Order = lyric.Order + 1; + secondLyric.ID = getId() + 1; + + // Add those tho lyric and remove old one. + Add(secondLyric); + Add(firstLyric); + Remove(lyric); + }); + } - PerformOnSelection(lyric => - { - var previousLyric = HitObjects.GetPrevious(lyric); - if (previousLyric == null) - throw new ArgumentNullException(nameof(previousLyric)); + public void Combine() + { + CheckExactlySelectedOneHitObject(); - // Shifting order that order is larger than current lyric. - int lyricOrder = previousLyric.Order; - OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyricOrder), -1); + PerformOnSelection(lyric => + { + var previousLyric = HitObjects.GetPrevious(lyric); + if (previousLyric == null) + throw new ArgumentNullException(nameof(previousLyric)); + + // Shifting order that order is larger than current lyric. + int lyricOrder = previousLyric.Order; + OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyricOrder), -1); + + var newLyric = LyricsUtils.CombineLyric(previousLyric, lyric); + newLyric.Order = lyricOrder; + + // Add created lyric and remove old two. + Add(newLyric); + Remove(previousLyric); + Remove(lyric); + }); + } - var newLyric = LyricsUtils.CombineLyric(previousLyric, lyric); - newLyric.Order = lyricOrder; + public void CreateAtPosition() + { + AddBelowToSelection(new Lyric + { + Text = "New lyric", + }); + } - // Add created lyric and remove old two. - Add(newLyric); - Remove(previousLyric); - Remove(lyric); - }); - } + public void CreateAtLast() + { + int order = OrderUtils.GetMaxOrderNumber(HitObjects.ToArray()); - public void CreateAtPosition() + // Add new lyric to target order. + Add(new Lyric { - AddBelowToSelection(new Lyric - { - Text = "New lyric", - }); - } + Text = "New lyric", + Order = order + 1, + }); + } - public void CreateAtLast() - { - int order = OrderUtils.GetMaxOrderNumber(HitObjects.ToArray()); + public void AddBelowToSelection(Lyric newLyric) + { + AddRangeBelowToSelection(new[] { newLyric }); + } - // Add new lyric to target order. - Add(new Lyric - { - Text = "New lyric", - Order = order + 1, - }); - } + public void AddRangeBelowToSelection(IEnumerable newLyrics) + { + CheckExactlySelectedOneHitObject(); - public void AddBelowToSelection(Lyric newLyric) + PerformOnSelection(lyric => { - AddRangeBelowToSelection(new[] { newLyric }); - } + int order = lyric.Order; - public void AddRangeBelowToSelection(IEnumerable newLyrics) - { - CheckExactlySelectedOneHitObject(); + // Shifting order that order is larger than current lyric. + OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > order), newLyrics.Count()); - PerformOnSelection(lyric => + foreach (var newLyric in newLyrics) { - int order = lyric.Order; - - // Shifting order that order is larger than current lyric. - OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > order), newLyrics.Count()); + newLyric.Order = ++order; + Add(newLyric); + } + }); + } - foreach (var newLyric in newLyrics) - { - newLyric.Order = ++order; - Add(newLyric); - } - }); - } + public void Remove() + { + PerformOnSelection(lyric => + { + // Shifting order that order is larger than current lyric. + OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyric.Order), -1); + Remove(lyric); + }); + } - public void Remove() + public void ChangeOrder(int newOrder) + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => + int oldOrder = lyric.Order; + OrderUtils.ChangeOrder(HitObjects.ToArray(), oldOrder, newOrder + 1, (switchSinger, oldOrder, newOrder) => { - // Shifting order that order is larger than current lyric. - OrderUtils.ShiftingOrder(HitObjects.Where(x => x.Order > lyric.Order), -1); - Remove(lyric); + // todo : not really sure should call update? }); - } + }); + } - public void ChangeOrder(int newOrder) + protected override void Add(T hitObject) + { + if (hitObject is Lyric lyric) { - PerformOnSelection(lyric => - { - int oldOrder = lyric.Order; - OrderUtils.ChangeOrder(HitObjects.ToArray(), oldOrder, newOrder + 1, (switchSinger, oldOrder, newOrder) => - { - // todo : not really sure should call update? - }); - }); + int index = getInsertIndex(lyric.Order); + Insert(index, lyric); } - - protected override void Add(T hitObject) + else { - if (hitObject is Lyric lyric) - { - int index = getInsertIndex(lyric.Order); - Insert(index, lyric); - } - else - { - base.Add(hitObject); - } + base.Add(hitObject); } + } - protected override void Insert(int index, T hitObject) + protected override void Insert(int index, T hitObject) + { + if (hitObject is Lyric lyric) { - if (hitObject is Lyric lyric) - { - lyric.ID = getId(); + lyric.ID = getId(); - base.Insert(index, lyric); - } - else - { - base.Add(hitObject); - } + base.Insert(index, lyric); } + else + { + base.Add(hitObject); + } + } - private int getInsertIndex(int order) - => HitObjects.ToList().FindIndex(x => x.Order == order - 1) + 1; + private int getInsertIndex(int order) + => HitObjects.ToList().FindIndex(x => x.Order == order - 1) + 1; - private int getId() - => HitObjects.Any() ? HitObjects.Max(x => x.ID) + 1 : 1; - } + private int getId() + => HitObjects.Any() ? HitObjects.Max(x => x.ID) + 1 : 1; } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotePropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotePropertyChangeHandler.cs index 373869683..016326e0a 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotePropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotePropertyChangeHandler.cs @@ -3,16 +3,15 @@ using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes; + +public interface INotePropertyChangeHandler : IHitObjectPropertyChangeHandler { - public interface INotePropertyChangeHandler : IHitObjectPropertyChangeHandler - { - void ChangeText(string text); + void ChangeText(string text); - void ChangeRubyText(string ruby); + void ChangeRubyText(string ruby); - void ChangeDisplayState(bool display); + void ChangeDisplayState(bool display); - void OffsetTone(Tone offset); - } + void OffsetTone(Tone offset); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotesChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotesChangeHandler.cs index ab792cc1f..f55dbb062 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotesChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/INotesChangeHandler.cs @@ -1,14 +1,13 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes; + +public interface INotesChangeHandler { - public interface INotesChangeHandler - { - void Split(float percentage = 0.5f); + void Split(float percentage = 0.5f); - void Combine(); + void Combine(); - void Clear(); - } + void Clear(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotePropertyChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotePropertyChangeHandler.cs index 93e64281e..ed8e37974 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotePropertyChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotePropertyChangeHandler.cs @@ -8,69 +8,68 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes; + +public partial class NotePropertyChangeHandler : HitObjectPropertyChangeHandler, INotePropertyChangeHandler { - public partial class NotePropertyChangeHandler : HitObjectPropertyChangeHandler, INotePropertyChangeHandler + [Resolved, AllowNull] + private EditorBeatmap beatmap { get; set; } + + public void ChangeText(string text) { - [Resolved, AllowNull] - private EditorBeatmap beatmap { get; set; } + CheckExactlySelectedOneHitObject(); - public void ChangeText(string text) + PerformOnSelection(note => { - CheckExactlySelectedOneHitObject(); + note.Text = text; + }); + } - PerformOnSelection(note => - { - note.Text = text; - }); - } + public void ChangeRubyText(string ruby) + { + CheckExactlySelectedOneHitObject(); - public void ChangeRubyText(string ruby) + PerformOnSelection(note => { - CheckExactlySelectedOneHitObject(); - - PerformOnSelection(note => - { - // Should change ruby text as null if remove all words. - note.RubyText = string.IsNullOrEmpty(ruby) ? null : ruby; - }); - } + // Should change ruby text as null if remove all words. + note.RubyText = string.IsNullOrEmpty(ruby) ? null : ruby; + }); + } - public void ChangeDisplayState(bool display) + public void ChangeDisplayState(bool display) + { + PerformOnSelection(note => { - PerformOnSelection(note => - { - note.Display = display; + note.Display = display; - // Move to center if note is not display - if (!note.Display) - note.Tone = new Tone(); - }); - } - - public void OffsetTone(Tone offset) - { - if (offset == default(Tone)) - throw new InvalidOperationException("Offset number should not be zero."); + // Move to center if note is not display + if (!note.Display) + note.Tone = new Tone(); + }); + } - var noteInfo = EditorBeatmapUtils.GetPlayableBeatmap(beatmap).NoteInfo; + public void OffsetTone(Tone offset) + { + if (offset == default(Tone)) + throw new InvalidOperationException("Offset number should not be zero."); - PerformOnSelection(note => - { - if (note.Tone >= noteInfo.MaxTone && offset > 0) - return; + var noteInfo = EditorBeatmapUtils.GetPlayableBeatmap(beatmap).NoteInfo; - if (note.Tone <= noteInfo.MinTone && offset < 0) - return; + PerformOnSelection(note => + { + if (note.Tone >= noteInfo.MaxTone && offset > 0) + return; - note.Tone += offset; + if (note.Tone <= noteInfo.MinTone && offset < 0) + return; - //Change all note to visible - note.Display = true; - }); - } + note.Tone += offset; - protected sealed override bool IsWritePropertyLocked(Note note) - => HitObjectWritableUtils.IsWriteNotePropertyLocked(note, nameof(Note.Text), nameof(Note.RubyText), nameof(Note.Display)); + //Change all note to visible + note.Display = true; + }); } + + protected sealed override bool IsWritePropertyLocked(Note note) + => HitObjectWritableUtils.IsWriteNotePropertyLocked(note, nameof(Note.Text), nameof(Note.RubyText), nameof(Note.Display)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotesChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotesChangeHandler.cs index dbfefb4c1..2b765dc91 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotesChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Notes/NotesChangeHandler.cs @@ -9,54 +9,53 @@ using osu.Game.Rulesets.Karaoke.Utils; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes +namespace osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Notes; + +public partial class NotesChangeHandler : HitObjectsChangeHandler, INotesChangeHandler { - public partial class NotesChangeHandler : HitObjectsChangeHandler, INotesChangeHandler + [Resolved, AllowNull] + private EditorBeatmap beatmap { get; set; } + + public void Split(float percentage = 0.5f) { - [Resolved, AllowNull] - private EditorBeatmap beatmap { get; set; } + CheckExactlySelectedOneHitObject(); - public void Split(float percentage = 0.5f) + PerformOnSelection(note => { - CheckExactlySelectedOneHitObject(); + var (firstNote, secondNote) = NotesUtils.SplitNote(note); + Add(firstNote); + Add(secondNote); + Remove(note); + }); + } - PerformOnSelection(note => - { - var (firstNote, secondNote) = NotesUtils.SplitNote(note); - Add(firstNote); - Add(secondNote); - Remove(note); - }); - } - - public void Combine() + public void Combine() + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - var notes = beatmap.SelectedHitObjects.OfType().Where(n => n.ReferenceLyric == lyric).ToList(); + var notes = beatmap.SelectedHitObjects.OfType().Where(n => n.ReferenceLyric == lyric).ToList(); - if (notes.Count < 2) - throw new InvalidOperationException($"Should have select at lest two {nameof(notes)}."); + if (notes.Count < 2) + throw new InvalidOperationException($"Should have select at lest two {nameof(notes)}."); - var combinedNote = NotesUtils.CombineNote(notes[0], notes[1]); + var combinedNote = NotesUtils.CombineNote(notes[0], notes[1]); - for (int i = 2; i < notes.Count; i++) - { - combinedNote = NotesUtils.CombineNote(notes[i - 1], notes[i]); - } + for (int i = 2; i < notes.Count; i++) + { + combinedNote = NotesUtils.CombineNote(notes[i - 1], notes[i]); + } - RemoveRange(notes); - Add(combinedNote); - }); - } + RemoveRange(notes); + Add(combinedNote); + }); + } - public void Clear() + public void Clear() + { + PerformOnSelection(lyric => { - PerformOnSelection(lyric => - { - var notes = beatmap.HitObjects.OfType().Where(n => n.ReferenceLyric == lyric).ToList(); - RemoveRange(notes); - }); - } + var notes = beatmap.HitObjects.OfType().Where(n => n.ReferenceLyric == lyric).ToList(); + RemoveRange(notes); + }); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckBeatmapAvailableTranslates.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckBeatmapAvailableTranslates.cs index 19cd2b359..674450d86 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckBeatmapAvailableTranslates.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckBeatmapAvailableTranslates.cs @@ -9,92 +9,91 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckBeatmapAvailableTranslates : CheckBeatmapProperty, Lyric> { - public class CheckBeatmapAvailableTranslates : CheckBeatmapProperty, Lyric> + protected override string Description => "Beatmap with invalid localization info."; + + public override IEnumerable PossibleTemplates => new IssueTemplate[] { - protected override string Description => "Beatmap with invalid localization info."; + new IssueTemplateMissingTranslate(this), + new IssueTemplateMissingPartialTranslate(this), + new IssueTemplateContainsNotListedLanguage(this) + }; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateMissingTranslate(this), - new IssueTemplateMissingPartialTranslate(this), - new IssueTemplateContainsNotListedLanguage(this) - }; + protected override IList GetPropertyFromBeatmap(KaraokeBeatmap karaokeBeatmap) + => karaokeBeatmap.AvailableTranslates; - protected override IList GetPropertyFromBeatmap(KaraokeBeatmap karaokeBeatmap) - => karaokeBeatmap.AvailableTranslates; + protected override IEnumerable CheckProperty(IList property) + { + // todo: maybe check duplicated languages? + yield break; + } - protected override IEnumerable CheckProperty(IList property) - { - // todo: maybe check duplicated languages? + protected override IEnumerable CheckHitObjects(IList property, IReadOnlyList hitObject) + { + if (hitObject.Count == 0) yield break; - } - protected override IEnumerable CheckHitObjects(IList property, IReadOnlyList hitObject) + // check if some translate is missing or empty. + foreach (var language in property) { - if (hitObject.Count == 0) - yield break; + var notTranslateLyrics = hitObject.Where(x => !x.Translates.ContainsKey(language) || string.IsNullOrWhiteSpace(x.Translates[language])).ToArray(); - // check if some translate is missing or empty. - foreach (var language in property) + if (notTranslateLyrics.Length == hitObject.Count) { - var notTranslateLyrics = hitObject.Where(x => !x.Translates.ContainsKey(language) || string.IsNullOrWhiteSpace(x.Translates[language])).ToArray(); - - if (notTranslateLyrics.Length == hitObject.Count) - { - yield return new IssueTemplateMissingTranslate(this).Create(notTranslateLyrics, language); - } - else if (notTranslateLyrics.Any()) - { - yield return new IssueTemplateMissingPartialTranslate(this).Create(notTranslateLyrics, language); - } + yield return new IssueTemplateMissingTranslate(this).Create(notTranslateLyrics, language); } - - // should check is lyric contains translate that is not listed in beatmap. - // if got this issue, then it's a bug. - var allTranslateLanguageInLyric = hitObject.SelectMany(x => x.Translates.Keys).Distinct(); - var languageNotListInBeatmap = allTranslateLanguageInLyric.Except(property); - - foreach (var language in languageNotListInBeatmap) + else if (notTranslateLyrics.Any()) { - var notTranslateLyrics = hitObject.Where(x => !x.Translates.ContainsKey(language)); - - yield return new IssueTemplateContainsNotListedLanguage(this).Create(notTranslateLyrics, language); + yield return new IssueTemplateMissingPartialTranslate(this).Create(notTranslateLyrics, language); } } - public class IssueTemplateMissingTranslate : IssueTemplate + // should check is lyric contains translate that is not listed in beatmap. + // if got this issue, then it's a bug. + var allTranslateLanguageInLyric = hitObject.SelectMany(x => x.Translates.Keys).Distinct(); + var languageNotListInBeatmap = allTranslateLanguageInLyric.Except(property); + + foreach (var language in languageNotListInBeatmap) { - public IssueTemplateMissingTranslate(ICheck check) - : base(check, IssueType.Problem, "There are no lyric translations for this language.") - { - } + var notTranslateLyrics = hitObject.Where(x => !x.Translates.ContainsKey(language)); - public Issue Create(IEnumerable hitObjects, CultureInfo cultureInfo) - => new(hitObjects, this, cultureInfo); + yield return new IssueTemplateContainsNotListedLanguage(this).Create(notTranslateLyrics, language); } + } - public class IssueTemplateMissingPartialTranslate : IssueTemplate + public class IssueTemplateMissingTranslate : IssueTemplate + { + public IssueTemplateMissingTranslate(ICheck check) + : base(check, IssueType.Problem, "There are no lyric translations for this language.") { - public IssueTemplateMissingPartialTranslate(ICheck check) - : base(check, IssueType.Problem, "Some lyrics in this language are missing translations.") - { - } - - public Issue Create(IEnumerable hitObjects, CultureInfo cultureInfo) - => new(hitObjects, this, cultureInfo); } - public class IssueTemplateContainsNotListedLanguage : IssueTemplate + public Issue Create(IEnumerable hitObjects, CultureInfo cultureInfo) + => new(hitObjects, this, cultureInfo); + } + + public class IssueTemplateMissingPartialTranslate : IssueTemplate + { + public IssueTemplateMissingPartialTranslate(ICheck check) + : base(check, IssueType.Problem, "Some lyrics in this language are missing translations.") { - public IssueTemplateContainsNotListedLanguage(ICheck check) - : base(check, IssueType.Problem, "Seems some translate language is not listed, plz contact developer to fix that bug.") - { - } + } + + public Issue Create(IEnumerable hitObjects, CultureInfo cultureInfo) + => new(hitObjects, this, cultureInfo); + } - public Issue Create(IEnumerable hitObjects, CultureInfo cultureInfo) - => new(hitObjects, this, cultureInfo); + public class IssueTemplateContainsNotListedLanguage : IssueTemplate + { + public IssueTemplateContainsNotListedLanguage(ICheck check) + : base(check, IssueType.Problem, "Seems some translate language is not listed, plz contact developer to fix that bug.") + { } + + public Issue Create(IEnumerable hitObjects, CultureInfo cultureInfo) + => new(hitObjects, this, cultureInfo); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckHitObjectProperty.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckHitObjectProperty.cs index fba646fb1..8f66be226 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckHitObjectProperty.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckHitObjectProperty.cs @@ -7,23 +7,22 @@ using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks -{ - public abstract class CheckHitObjectProperty : ICheck where THitObject : KaraokeHitObject - { - public CheckMetadata Metadata => new(CheckCategory.HitObjects, Description); +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; - protected abstract string Description { get; } +public abstract class CheckHitObjectProperty : ICheck where THitObject : KaraokeHitObject +{ + public CheckMetadata Metadata => new(CheckCategory.HitObjects, Description); - public abstract IEnumerable PossibleTemplates { get; } + protected abstract string Description { get; } - public virtual IEnumerable Run(BeatmapVerifierContext context) - { - var hitObjects = context.Beatmap.HitObjects.OfType(); + public abstract IEnumerable PossibleTemplates { get; } - return hitObjects.Select(Check).SelectMany(x => x); - } + public virtual IEnumerable Run(BeatmapVerifierContext context) + { + var hitObjects = context.Beatmap.HitObjects.OfType(); - protected abstract IEnumerable Check(THitObject hitObject); + return hitObjects.Select(Check).SelectMany(x => x); } + + protected abstract IEnumerable Check(THitObject hitObject); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricLanguage.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricLanguage.cs index ddb0e5b1a..21c7bf2da 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricLanguage.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricLanguage.cs @@ -6,32 +6,31 @@ using osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricLanguage : CheckHitObjectProperty { - public class CheckLyricLanguage : CheckHitObjectProperty + protected override string Description => "Lyric with invalid language."; + + public override IEnumerable PossibleTemplates => new IssueTemplate[] { - protected override string Description => "Lyric with invalid language."; + new IssueTemplateLyricNotFillLanguage(this), + }; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricNotFillLanguage(this), - }; + protected override IEnumerable Check(Lyric lyric) + { + if (lyric.Language == null) + yield return new IssueTemplateLyricNotFillLanguage(this).Create(lyric); + } - protected override IEnumerable Check(Lyric lyric) + public class IssueTemplateLyricNotFillLanguage : IssueTemplate + { + public IssueTemplateLyricNotFillLanguage(ICheck check) + : base(check, IssueType.Problem, "Lyric must have assign language.") { - if (lyric.Language == null) - yield return new IssueTemplateLyricNotFillLanguage(this).Create(lyric); } - public class IssueTemplateLyricNotFillLanguage : IssueTemplate - { - public IssueTemplateLyricNotFillLanguage(ICheck check) - : base(check, IssueType.Problem, "Lyric must have assign language.") - { - } - - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricReferenceLyric.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricReferenceLyric.cs index 49029770b..5d4e549b5 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricReferenceLyric.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricReferenceLyric.cs @@ -7,77 +7,76 @@ using osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricReferenceLyric : CheckHitObjectReferenceProperty { - public class CheckLyricReferenceLyric : CheckHitObjectReferenceProperty - { - protected override string Description => "Lyric with invalid reference lyric."; + protected override string Description => "Lyric with invalid reference lyric."; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricSelfReference(this), - new IssueTemplateLyricInvalidReferenceLyric(this), - new IssueTemplateLyricNullReferenceLyricConfig(this), - new IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric(this) - }; + public override IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateLyricSelfReference(this), + new IssueTemplateLyricInvalidReferenceLyric(this), + new IssueTemplateLyricNullReferenceLyricConfig(this), + new IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric(this) + }; - protected override IEnumerable CheckReferenceProperty(Lyric lyric, IEnumerable allAvailableReferencedHitObjects) - { - if (lyric.ReferenceLyric == lyric) - yield return new IssueTemplateLyricSelfReference(this).Create(lyric); + protected override IEnumerable CheckReferenceProperty(Lyric lyric, IEnumerable allAvailableReferencedHitObjects) + { + if (lyric.ReferenceLyric == lyric) + yield return new IssueTemplateLyricSelfReference(this).Create(lyric); - if (lyric.ReferenceLyric != null && !allAvailableReferencedHitObjects.Contains(lyric.ReferenceLyric)) - yield return new IssueTemplateLyricInvalidReferenceLyric(this).Create(lyric); + if (lyric.ReferenceLyric != null && !allAvailableReferencedHitObjects.Contains(lyric.ReferenceLyric)) + yield return new IssueTemplateLyricInvalidReferenceLyric(this).Create(lyric); - if (lyric.ReferenceLyric != null && lyric.ReferenceLyricConfig == null) - yield return new IssueTemplateLyricNullReferenceLyricConfig(this).Create(lyric); + if (lyric.ReferenceLyric != null && lyric.ReferenceLyricConfig == null) + yield return new IssueTemplateLyricNullReferenceLyricConfig(this).Create(lyric); - if (lyric.ReferenceLyric == null && lyric.ReferenceLyricConfig != null) - yield return new IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric(this).Create(lyric); - } + if (lyric.ReferenceLyric == null && lyric.ReferenceLyricConfig != null) + yield return new IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric(this).Create(lyric); + } - public class IssueTemplateLyricSelfReference : IssueTemplate + public class IssueTemplateLyricSelfReference : IssueTemplate + { + public IssueTemplateLyricSelfReference(ICheck check) + : base(check, IssueType.Error, "Lyric should not reference to itself.") { - public IssueTemplateLyricSelfReference(ICheck check) - : base(check, IssueType.Error, "Lyric should not reference to itself.") - { - } - - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); } - public class IssueTemplateLyricInvalidReferenceLyric : IssueTemplate - { - public IssueTemplateLyricInvalidReferenceLyric(ICheck check) - : base(check, IssueType.Error, "Reference lyric does not exist in the beatmap.") - { - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); + } - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); + public class IssueTemplateLyricInvalidReferenceLyric : IssueTemplate + { + public IssueTemplateLyricInvalidReferenceLyric(ICheck check) + : base(check, IssueType.Error, "Reference lyric does not exist in the beatmap.") + { } - public class IssueTemplateLyricNullReferenceLyricConfig : IssueTemplate - { - public IssueTemplateLyricNullReferenceLyricConfig(ICheck check) - : base(check, IssueType.Error, "Must have config if reference to another lyric.") - { - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); + } - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); + public class IssueTemplateLyricNullReferenceLyricConfig : IssueTemplate + { + public IssueTemplateLyricNullReferenceLyricConfig(ICheck check) + : base(check, IssueType.Error, "Must have config if reference to another lyric.") + { } - public class IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric : IssueTemplate - { - public IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric(ICheck check) - : base(check, IssueType.Error, "Should not have the reference lyric config if reference to another lyric.") - { - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); + } - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); + public class IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric : IssueTemplate + { + public IssueTemplateLyricHasReferenceLyricConfigIfNoReferenceLyric(ICheck check) + : base(check, IssueType.Error, "Should not have the reference lyric config if reference to another lyric.") + { } + + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRomajiTag.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRomajiTag.cs index c27e5fd3f..3bab23f7b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRomajiTag.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRomajiTag.cs @@ -7,65 +7,64 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricRomajiTag : CheckLyricTextTag { - public class CheckLyricRomajiTag : CheckLyricTextTag - { - protected override string Description => "Lyric with invalid romaji tag."; + protected override string Description => "Lyric with invalid romaji tag."; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricRomajiOutOfRange(this), - new IssueTemplateLyricRomajiOverlapping(this), - new IssueTemplateLyricRomajiEmptyText(this), - }; + public override IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateLyricRomajiOutOfRange(this), + new IssueTemplateLyricRomajiOverlapping(this), + new IssueTemplateLyricRomajiEmptyText(this), + }; - protected override IList GetTextTag(Lyric lyric) - => lyric.RomajiTags; + protected override IList GetTextTag(Lyric lyric) + => lyric.RomajiTags; - protected override TextTagsUtils.Sorting Sorting => TextTagsUtils.Sorting.Asc; + protected override TextTagsUtils.Sorting Sorting => TextTagsUtils.Sorting.Asc; - protected override Issue GetOutOfRangeIssue(Lyric lyric, RomajiTag textTag) - => new IssueTemplateLyricRomajiOutOfRange(this).Create(lyric, textTag); + protected override Issue GetOutOfRangeIssue(Lyric lyric, RomajiTag textTag) + => new IssueTemplateLyricRomajiOutOfRange(this).Create(lyric, textTag); - protected override Issue GetOverlappingIssue(Lyric lyric, RomajiTag textTag) - => new IssueTemplateLyricRomajiOverlapping(this).Create(lyric, textTag); + protected override Issue GetOverlappingIssue(Lyric lyric, RomajiTag textTag) + => new IssueTemplateLyricRomajiOverlapping(this).Create(lyric, textTag); - protected override Issue GetEmptyTextIssue(Lyric lyric, RomajiTag textTag) - => new IssueTemplateLyricRomajiEmptyText(this).Create(lyric, textTag); + protected override Issue GetEmptyTextIssue(Lyric lyric, RomajiTag textTag) + => new IssueTemplateLyricRomajiEmptyText(this).Create(lyric, textTag); - public abstract class IssueTemplateLyricRomaji : IssueTemplateLyricTextTag + public abstract class IssueTemplateLyricRomaji : IssueTemplateLyricTextTag + { + protected IssueTemplateLyricRomaji(ICheck check, IssueType type, string unformattedMessage) + : base(check, type, unformattedMessage) { - protected IssueTemplateLyricRomaji(ICheck check, IssueType type, string unformattedMessage) - : base(check, type, unformattedMessage) - { - } - - public Issue Create(Lyric lyric, RomajiTag textTag) => new LyricRomajiTagIssue(lyric, this, textTag); } - public class IssueTemplateLyricRomajiOutOfRange : IssueTemplateLyricRomaji + public Issue Create(Lyric lyric, RomajiTag textTag) => new LyricRomajiTagIssue(lyric, this, textTag); + } + + public class IssueTemplateLyricRomajiOutOfRange : IssueTemplateLyricRomaji + { + public IssueTemplateLyricRomajiOutOfRange(ICheck check) + : base(check, IssueType.Error, "Romaji tag index is out of range.") { - public IssueTemplateLyricRomajiOutOfRange(ICheck check) - : base(check, IssueType.Error, "Romaji tag index is out of range.") - { - } } + } - public class IssueTemplateLyricRomajiOverlapping : IssueTemplateLyricRomaji + public class IssueTemplateLyricRomajiOverlapping : IssueTemplateLyricRomaji + { + public IssueTemplateLyricRomajiOverlapping(ICheck check) + : base(check, IssueType.Problem, "Romaji tag index is overlapping to another romaji tag.") { - public IssueTemplateLyricRomajiOverlapping(ICheck check) - : base(check, IssueType.Problem, "Romaji tag index is overlapping to another romaji tag.") - { - } } + } - public class IssueTemplateLyricRomajiEmptyText : IssueTemplateLyricRomaji + public class IssueTemplateLyricRomajiEmptyText : IssueTemplateLyricRomaji + { + public IssueTemplateLyricRomajiEmptyText(ICheck check) + : base(check, IssueType.Problem, "Romaji tag's text should not be empty or white-space only.") { - public IssueTemplateLyricRomajiEmptyText(ICheck check) - : base(check, IssueType.Problem, "Romaji tag's text should not be empty or white-space only.") - { - } } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRubyTag.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRubyTag.cs index 11bbdde62..f5ce914c4 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRubyTag.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricRubyTag.cs @@ -7,65 +7,64 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricRubyTag : CheckLyricTextTag { - public class CheckLyricRubyTag : CheckLyricTextTag - { - protected override string Description => "Lyric with invalid ruby tag."; + protected override string Description => "Lyric with invalid ruby tag."; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricRubyOutOfRange(this), - new IssueTemplateLyricRubyOverlapping(this), - new IssueTemplateLyricRubyEmptyText(this), - }; + public override IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateLyricRubyOutOfRange(this), + new IssueTemplateLyricRubyOverlapping(this), + new IssueTemplateLyricRubyEmptyText(this), + }; - protected override IList GetTextTag(Lyric lyric) - => lyric.RubyTags; + protected override IList GetTextTag(Lyric lyric) + => lyric.RubyTags; - protected override TextTagsUtils.Sorting Sorting => TextTagsUtils.Sorting.Asc; + protected override TextTagsUtils.Sorting Sorting => TextTagsUtils.Sorting.Asc; - protected override Issue GetOutOfRangeIssue(Lyric lyric, RubyTag textTag) - => new IssueTemplateLyricRubyOutOfRange(this).Create(lyric, textTag); + protected override Issue GetOutOfRangeIssue(Lyric lyric, RubyTag textTag) + => new IssueTemplateLyricRubyOutOfRange(this).Create(lyric, textTag); - protected override Issue GetOverlappingIssue(Lyric lyric, RubyTag textTag) - => new IssueTemplateLyricRubyOverlapping(this).Create(lyric, textTag); + protected override Issue GetOverlappingIssue(Lyric lyric, RubyTag textTag) + => new IssueTemplateLyricRubyOverlapping(this).Create(lyric, textTag); - protected override Issue GetEmptyTextIssue(Lyric lyric, RubyTag textTag) - => new IssueTemplateLyricRubyEmptyText(this).Create(lyric, textTag); + protected override Issue GetEmptyTextIssue(Lyric lyric, RubyTag textTag) + => new IssueTemplateLyricRubyEmptyText(this).Create(lyric, textTag); - public abstract class IssueTemplateLyricRuby : IssueTemplateLyricTextTag + public abstract class IssueTemplateLyricRuby : IssueTemplateLyricTextTag + { + protected IssueTemplateLyricRuby(ICheck check, IssueType type, string unformattedMessage) + : base(check, type, unformattedMessage) { - protected IssueTemplateLyricRuby(ICheck check, IssueType type, string unformattedMessage) - : base(check, type, unformattedMessage) - { - } - - public Issue Create(Lyric lyric, RubyTag textTag) => new LyricRubyTagIssue(lyric, this, textTag, textTag); } - public class IssueTemplateLyricRubyOutOfRange : IssueTemplateLyricRuby + public Issue Create(Lyric lyric, RubyTag textTag) => new LyricRubyTagIssue(lyric, this, textTag, textTag); + } + + public class IssueTemplateLyricRubyOutOfRange : IssueTemplateLyricRuby + { + public IssueTemplateLyricRubyOutOfRange(ICheck check) + : base(check, IssueType.Error, "Ruby tag index is out of range.") { - public IssueTemplateLyricRubyOutOfRange(ICheck check) - : base(check, IssueType.Error, "Ruby tag index is out of range.") - { - } } + } - public class IssueTemplateLyricRubyOverlapping : IssueTemplateLyricRuby + public class IssueTemplateLyricRubyOverlapping : IssueTemplateLyricRuby + { + public IssueTemplateLyricRubyOverlapping(ICheck check) + : base(check, IssueType.Problem, "Ruby tag index is overlapping to another ruby tag.") { - public IssueTemplateLyricRubyOverlapping(ICheck check) - : base(check, IssueType.Problem, "Ruby tag index is overlapping to another ruby tag.") - { - } } + } - public class IssueTemplateLyricRubyEmptyText : IssueTemplateLyricRuby + public class IssueTemplateLyricRubyEmptyText : IssueTemplateLyricRuby + { + public IssueTemplateLyricRubyEmptyText(ICheck check) + : base(check, IssueType.Problem, "Ruby tag's text should not be empty or white-space only.") { - public IssueTemplateLyricRubyEmptyText(ICheck check) - : base(check, IssueType.Problem, "Ruby tag's text should not be empty or white-space only.") - { - } } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricSinger.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricSinger.cs index f79fd5284..08b145695 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricSinger.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricSinger.cs @@ -7,32 +7,31 @@ using osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricSinger : CheckHitObjectProperty { - public class CheckLyricSinger : CheckHitObjectProperty + protected override string Description => "Lyric with invalid singer."; + + public override IEnumerable PossibleTemplates => new IssueTemplate[] { - protected override string Description => "Lyric with invalid singer."; + new IssueTemplateLyricNoSinger(this), + }; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricNoSinger(this), - }; + protected override IEnumerable Check(Lyric lyric) + { + if (!lyric.SingerIds.Any()) + yield return new IssueTemplateLyricNoSinger(this).Create(lyric); + } - protected override IEnumerable Check(Lyric lyric) + public class IssueTemplateLyricNoSinger : IssueTemplate + { + public IssueTemplateLyricNoSinger(ICheck check) + : base(check, IssueType.Problem, "Lyric must have at least one singer.") { - if (!lyric.SingerIds.Any()) - yield return new IssueTemplateLyricNoSinger(this).Create(lyric); } - public class IssueTemplateLyricNoSinger : IssueTemplate - { - public IssueTemplateLyricNoSinger(ICheck check) - : base(check, IssueType.Problem, "Lyric must have at least one singer.") - { - } - - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricText.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricText.cs index 6773449b1..33f4f4d04 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricText.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricText.cs @@ -6,32 +6,31 @@ using osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricText : CheckHitObjectProperty { - public class CheckLyricText : CheckHitObjectProperty + protected override string Description => "Lyric with invalid text."; + + public override IEnumerable PossibleTemplates => new IssueTemplate[] { - protected override string Description => "Lyric with invalid text."; + new IssueTemplateLyricNoText(this), + }; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricNoText(this), - }; + protected override IEnumerable Check(Lyric lyric) + { + if (string.IsNullOrWhiteSpace(lyric.Text)) + yield return new IssueTemplateLyricNoText(this).Create(lyric); + } - protected override IEnumerable Check(Lyric lyric) + public class IssueTemplateLyricNoText : IssueTemplate + { + public IssueTemplateLyricNoText(ICheck check) + : base(check, IssueType.Problem, "Lyric's text should not be empty or white-space only.") { - if (string.IsNullOrWhiteSpace(lyric.Text)) - yield return new IssueTemplateLyricNoText(this).Create(lyric); } - public class IssueTemplateLyricNoText : IssueTemplate - { - public IssueTemplateLyricNoText(ICheck check) - : base(check, IssueType.Problem, "Lyric's text should not be empty or white-space only.") - { - } - - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTextTag.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTextTag.cs index 641bddbf4..f6d91e2cc 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTextTag.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTextTag.cs @@ -7,51 +7,50 @@ using osu.Game.Rulesets.Karaoke.Objects.Types; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public abstract class CheckLyricTextTag : CheckHitObjectProperty where TTextTag : ITextTag { - public abstract class CheckLyricTextTag : CheckHitObjectProperty where TTextTag : ITextTag + protected override IEnumerable Check(Lyric lyric) { - protected override IEnumerable Check(Lyric lyric) + string text = lyric.Text; + var textTags = GetTextTag(lyric); + + var outOfRangeTags = TextTagsUtils.FindOutOfRange(textTags, text); + var overlappingTags = TextTagsUtils.FindOverlapping(textTags, Sorting); + var emptyTextTags = TextTagsUtils.FindEmptyText(textTags); + + foreach (var textTag in outOfRangeTags) { - string text = lyric.Text; - var textTags = GetTextTag(lyric); - - var outOfRangeTags = TextTagsUtils.FindOutOfRange(textTags, text); - var overlappingTags = TextTagsUtils.FindOverlapping(textTags, Sorting); - var emptyTextTags = TextTagsUtils.FindEmptyText(textTags); - - foreach (var textTag in outOfRangeTags) - { - yield return GetOutOfRangeIssue(lyric, textTag); - } - - foreach (var textTag in overlappingTags) - { - yield return GetOverlappingIssue(lyric, textTag); - } - - foreach (var textTag in emptyTextTags) - { - yield return GetEmptyTextIssue(lyric, textTag); - } + yield return GetOutOfRangeIssue(lyric, textTag); } - protected abstract IList GetTextTag(Lyric lyric); + foreach (var textTag in overlappingTags) + { + yield return GetOverlappingIssue(lyric, textTag); + } - protected abstract TextTagsUtils.Sorting Sorting { get; } + foreach (var textTag in emptyTextTags) + { + yield return GetEmptyTextIssue(lyric, textTag); + } + } + + protected abstract IList GetTextTag(Lyric lyric); - protected abstract Issue GetOutOfRangeIssue(Lyric lyric, TTextTag textTag); + protected abstract TextTagsUtils.Sorting Sorting { get; } - protected abstract Issue GetOverlappingIssue(Lyric lyric, TTextTag textTag); + protected abstract Issue GetOutOfRangeIssue(Lyric lyric, TTextTag textTag); - protected abstract Issue GetEmptyTextIssue(Lyric lyric, TTextTag textTag); + protected abstract Issue GetOverlappingIssue(Lyric lyric, TTextTag textTag); - public abstract class IssueTemplateLyricTextTag : IssueTemplate + protected abstract Issue GetEmptyTextIssue(Lyric lyric, TTextTag textTag); + + public abstract class IssueTemplateLyricTextTag : IssueTemplate + { + protected IssueTemplateLyricTextTag(ICheck check, IssueType type, string unformattedMessage) + : base(check, type, unformattedMessage) { - protected IssueTemplateLyricTextTag(ICheck check, IssueType type, string unformattedMessage) - : base(check, type, unformattedMessage) - { - } } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTime.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTime.cs index 3758934ff..a763e6b84 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTime.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTime.cs @@ -7,62 +7,61 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricTime : CheckHitObjectProperty { - public class CheckLyricTime : CheckHitObjectProperty - { - protected override string Description => "Lyric with invalid time."; + protected override string Description => "Lyric with invalid time."; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricTimeOverlapping(this), - new IssueTemplateLyricStartTimeInvalid(this), - new IssueTemplateLyricEndTimeInvalid(this) - }; + public override IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateLyricTimeOverlapping(this), + new IssueTemplateLyricStartTimeInvalid(this), + new IssueTemplateLyricEndTimeInvalid(this) + }; - protected override IEnumerable Check(Lyric lyric) - { - if (LyricUtils.CheckIsTimeOverlapping(lyric)) - yield return new IssueTemplateLyricTimeOverlapping(this).Create(lyric); + protected override IEnumerable Check(Lyric lyric) + { + if (LyricUtils.CheckIsTimeOverlapping(lyric)) + yield return new IssueTemplateLyricTimeOverlapping(this).Create(lyric); - if (LyricUtils.CheckIsStartTimeInvalid(lyric)) - yield return new IssueTemplateLyricStartTimeInvalid(this).Create(lyric); + if (LyricUtils.CheckIsStartTimeInvalid(lyric)) + yield return new IssueTemplateLyricStartTimeInvalid(this).Create(lyric); - if (LyricUtils.CheckIsEndTimeInvalid(lyric)) - yield return new IssueTemplateLyricEndTimeInvalid(this).Create(lyric); - } + if (LyricUtils.CheckIsEndTimeInvalid(lyric)) + yield return new IssueTemplateLyricEndTimeInvalid(this).Create(lyric); + } - public class IssueTemplateLyricTimeOverlapping : IssueTemplate + public class IssueTemplateLyricTimeOverlapping : IssueTemplate + { + public IssueTemplateLyricTimeOverlapping(ICheck check) + : base(check, IssueType.Problem, "Lyric's start is larger than end-time.") { - public IssueTemplateLyricTimeOverlapping(ICheck check) - : base(check, IssueType.Problem, "Lyric's start is larger than end-time.") - { - } - - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); } - public class IssueTemplateLyricStartTimeInvalid : IssueTemplate - { - public IssueTemplateLyricStartTimeInvalid(ICheck check) - : base(check, IssueType.Problem, "Lyric's start time is larger than time-tag's time.") - { - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); + } - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); + public class IssueTemplateLyricStartTimeInvalid : IssueTemplate + { + public IssueTemplateLyricStartTimeInvalid(ICheck check) + : base(check, IssueType.Problem, "Lyric's start time is larger than time-tag's time.") + { } - public class IssueTemplateLyricEndTimeInvalid : IssueTemplate - { - public IssueTemplateLyricEndTimeInvalid(ICheck check) - : base(check, IssueType.Problem, "Lyric's end time is smaller than time-tag's time.") - { - } + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); + } - public Issue Create(Lyric lyric) - => new LyricIssue(lyric, this); + public class IssueTemplateLyricEndTimeInvalid : IssueTemplate + { + public IssueTemplateLyricEndTimeInvalid(ICheck check) + : base(check, IssueType.Problem, "Lyric's end time is smaller than time-tag's time.") + { } + + public Issue Create(Lyric lyric) + => new LyricIssue(lyric, this); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTimeTag.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTimeTag.cs index 6d07f9bd5..2c312b18c 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTimeTag.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTimeTag.cs @@ -8,123 +8,122 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricTimeTag : CheckHitObjectProperty { - public class CheckLyricTimeTag : CheckHitObjectProperty - { - protected override string Description => "Lyric with invalid time-tag."; + protected override string Description => "Lyric with invalid time-tag."; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricEmptyTimeTag(this), - new IssueTemplateLyricMissingFirstTimeTag(this), - new IssueTemplateLyricMissingLastTimeTag(this), - new IssueTemplateLyricTimeTagOutOfRange(this), - new IssueTemplateLyricTimeTagOverlapping(this), - new IssueTemplateLyricTimeTagEmptyTime(this), - }; - - protected override IEnumerable Check(Lyric lyric) + public override IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateLyricEmptyTimeTag(this), + new IssueTemplateLyricMissingFirstTimeTag(this), + new IssueTemplateLyricMissingLastTimeTag(this), + new IssueTemplateLyricTimeTagOutOfRange(this), + new IssueTemplateLyricTimeTagOverlapping(this), + new IssueTemplateLyricTimeTagEmptyTime(this), + }; + + protected override IEnumerable Check(Lyric lyric) + { + if (!lyric.TimeTags.Any()) { - if (!lyric.TimeTags.Any()) - { - yield return new IssueTemplateLyricEmptyTimeTag(this).Create(lyric); + yield return new IssueTemplateLyricEmptyTimeTag(this).Create(lyric); - yield break; - } - - if (!TimeTagsUtils.HasStartTimeTagInLyric(lyric.TimeTags, lyric.Text)) - yield return new IssueTemplateLyricMissingFirstTimeTag(this).Create(lyric); - - if (!TimeTagsUtils.HasEndTimeTagInLyric(lyric.TimeTags, lyric.Text)) - yield return new IssueTemplateLyricMissingLastTimeTag(this).Create(lyric); + yield break; + } - // todo: maybe config? - const GroupCheck group_check = GroupCheck.Asc; - const SelfCheck self_check = SelfCheck.BasedOnStart; + if (!TimeTagsUtils.HasStartTimeTagInLyric(lyric.TimeTags, lyric.Text)) + yield return new IssueTemplateLyricMissingFirstTimeTag(this).Create(lyric); - var outOfRangeTags = TimeTagsUtils.FindOutOfRange(lyric.TimeTags, lyric.Text); - var overlappingTimeTags = TimeTagsUtils.FindOverlapping(lyric.TimeTags, group_check, self_check).ToArray(); - var noTimeTimeTags = TimeTagsUtils.FindNoneTime(lyric.TimeTags); + if (!TimeTagsUtils.HasEndTimeTagInLyric(lyric.TimeTags, lyric.Text)) + yield return new IssueTemplateLyricMissingLastTimeTag(this).Create(lyric); - foreach (var textTag in outOfRangeTags) - { - yield return new IssueTemplateLyricTimeTagOutOfRange(this).Create(lyric, textTag); - } + // todo: maybe config? + const GroupCheck group_check = GroupCheck.Asc; + const SelfCheck self_check = SelfCheck.BasedOnStart; - foreach (var textTag in overlappingTimeTags) - { - yield return new IssueTemplateLyricTimeTagOverlapping(this).Create(lyric, textTag); - } + var outOfRangeTags = TimeTagsUtils.FindOutOfRange(lyric.TimeTags, lyric.Text); + var overlappingTimeTags = TimeTagsUtils.FindOverlapping(lyric.TimeTags, group_check, self_check).ToArray(); + var noTimeTimeTags = TimeTagsUtils.FindNoneTime(lyric.TimeTags); - foreach (var textTag in noTimeTimeTags) - { - yield return new IssueTemplateLyricTimeTagEmptyTime(this).Create(lyric, textTag); - } + foreach (var textTag in outOfRangeTags) + { + yield return new IssueTemplateLyricTimeTagOutOfRange(this).Create(lyric, textTag); } - public class IssueTemplateLyricEmptyTimeTag : IssueTemplate + foreach (var textTag in overlappingTimeTags) { - public IssueTemplateLyricEmptyTimeTag(ICheck check) - : base(check, IssueType.Problem, "This lyric has no time-tag.") - { - } - - public Issue Create(Lyric lyric) => new LyricIssue(lyric, this); + yield return new IssueTemplateLyricTimeTagOverlapping(this).Create(lyric, textTag); } - public class IssueTemplateLyricMissingFirstTimeTag : IssueTemplate + foreach (var textTag in noTimeTimeTags) { - public IssueTemplateLyricMissingFirstTimeTag(ICheck check) - : base(check, IssueType.Problem, "Missing first time-tag in the lyric.") - { - } - - public Issue Create(Lyric lyric) => new LyricIssue(lyric, this); + yield return new IssueTemplateLyricTimeTagEmptyTime(this).Create(lyric, textTag); } + } - public class IssueTemplateLyricMissingLastTimeTag : IssueTemplate + public class IssueTemplateLyricEmptyTimeTag : IssueTemplate + { + public IssueTemplateLyricEmptyTimeTag(ICheck check) + : base(check, IssueType.Problem, "This lyric has no time-tag.") { - public IssueTemplateLyricMissingLastTimeTag(ICheck check) - : base(check, IssueType.Problem, "Missing last time-tag in the lyric.") - { - } + } + + public Issue Create(Lyric lyric) => new LyricIssue(lyric, this); + } - public Issue Create(Lyric lyric) => new LyricIssue(lyric, this); + public class IssueTemplateLyricMissingFirstTimeTag : IssueTemplate + { + public IssueTemplateLyricMissingFirstTimeTag(ICheck check) + : base(check, IssueType.Problem, "Missing first time-tag in the lyric.") + { } - public abstract class IssueTemplateLyricTimeTag : IssueTemplate + public Issue Create(Lyric lyric) => new LyricIssue(lyric, this); + } + + public class IssueTemplateLyricMissingLastTimeTag : IssueTemplate + { + public IssueTemplateLyricMissingLastTimeTag(ICheck check) + : base(check, IssueType.Problem, "Missing last time-tag in the lyric.") { - protected IssueTemplateLyricTimeTag(ICheck check, IssueType type, string unformattedMessage) - : base(check, type, unformattedMessage) - { - } + } + + public Issue Create(Lyric lyric) => new LyricIssue(lyric, this); + } - public Issue Create(Lyric lyric, TimeTag timeTag) => new LyricTimeTagIssue(lyric, this, timeTag, timeTag); + public abstract class IssueTemplateLyricTimeTag : IssueTemplate + { + protected IssueTemplateLyricTimeTag(ICheck check, IssueType type, string unformattedMessage) + : base(check, type, unformattedMessage) + { } - public class IssueTemplateLyricTimeTagOutOfRange : IssueTemplateLyricTimeTag + public Issue Create(Lyric lyric, TimeTag timeTag) => new LyricTimeTagIssue(lyric, this, timeTag, timeTag); + } + + public class IssueTemplateLyricTimeTagOutOfRange : IssueTemplateLyricTimeTag + { + public IssueTemplateLyricTimeTagOutOfRange(ICheck check) + : base(check, IssueType.Problem, "Time-tag index is out of range.") { - public IssueTemplateLyricTimeTagOutOfRange(ICheck check) - : base(check, IssueType.Problem, "Time-tag index is out of range.") - { - } } + } - public class IssueTemplateLyricTimeTagOverlapping : IssueTemplateLyricTimeTag + public class IssueTemplateLyricTimeTagOverlapping : IssueTemplateLyricTimeTag + { + public IssueTemplateLyricTimeTagOverlapping(ICheck check) + : base(check, IssueType.Problem, "Time-tag index is overlapping to another time-tag.") { - public IssueTemplateLyricTimeTagOverlapping(ICheck check) - : base(check, IssueType.Problem, "Time-tag index is overlapping to another time-tag.") - { - } } + } - public class IssueTemplateLyricTimeTagEmptyTime : IssueTemplateLyricTimeTag + public class IssueTemplateLyricTimeTagEmptyTime : IssueTemplateLyricTimeTag + { + public IssueTemplateLyricTimeTagEmptyTime(ICheck check) + : base(check, IssueType.Problem, "Time-tag has no time.") { - public IssueTemplateLyricTimeTagEmptyTime(ICheck check) - : base(check, IssueType.Problem, "Time-tag has no time.") - { - } } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTranslate.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTranslate.cs index ee802ec19..06ed363c0 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTranslate.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckLyricTranslate.cs @@ -7,37 +7,36 @@ using osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckLyricTranslate : CheckHitObjectProperty { - public class CheckLyricTranslate : CheckHitObjectProperty + protected override string Description => "Lyric with invalid translations."; + + public override IEnumerable PossibleTemplates => new IssueTemplate[] { - protected override string Description => "Lyric with invalid translations."; + new IssueTemplateLyricTranslationNoText(this), + }; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateLyricTranslationNoText(this), - }; + protected override IEnumerable Check(Lyric lyric) + { + var translates = lyric.Translates; - protected override IEnumerable Check(Lyric lyric) + foreach ((var language, string translate) in translates) { - var translates = lyric.Translates; - - foreach ((var language, string translate) in translates) - { - if (string.IsNullOrWhiteSpace(translate)) - yield return new IssueTemplateLyricTranslationNoText(this).Create(lyric, language); - } + if (string.IsNullOrWhiteSpace(translate)) + yield return new IssueTemplateLyricTranslationNoText(this).Create(lyric, language); } + } - public class IssueTemplateLyricTranslationNoText : IssueTemplate + public class IssueTemplateLyricTranslationNoText : IssueTemplate + { + public IssueTemplateLyricTranslationNoText(ICheck check) + : base(check, IssueType.Problem, "Translation in the lyric should not by empty or white-space only.") { - public IssueTemplateLyricTranslationNoText(ICheck check) - : base(check, IssueType.Problem, "Translation in the lyric should not by empty or white-space only.") - { - } - - public Issue Create(Lyric lyric, CultureInfo language) - => new LyricIssue(lyric, this, language); } + + public Issue Create(Lyric lyric, CultureInfo language) + => new LyricIssue(lyric, this, language); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteReferenceLyric.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteReferenceLyric.cs index 7f6b03b42..c8320e8f6 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteReferenceLyric.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteReferenceLyric.cs @@ -7,133 +7,132 @@ using osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckNoteReferenceLyric : CheckHitObjectReferenceProperty { - public class CheckNoteReferenceLyric : CheckHitObjectReferenceProperty - { - protected override string Description => "Note with invalid reference lyric."; + protected override string Description => "Note with invalid reference lyric."; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateNoteNullReferenceLyric(this), - new IssueTemplateNoteInvalidReferenceLyric(this), - new IssueTemplateNoteMissingReferenceTimeTag(this), - new IssueTemplateNoteMissingStartReferenceTimeTag(this), - new IssueTemplateNoteStartReferenceTimeTagMissingTime(this), - new IssueTemplateNoteMissingEndReferenceTimeTag(this), - new IssueTemplateNoteEndReferenceTimeTagMissingTime(this), - }; - - protected override IEnumerable CheckReferenceProperty(Note note, IEnumerable allAvailableReferencedHitObjects) + public override IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateNoteNullReferenceLyric(this), + new IssueTemplateNoteInvalidReferenceLyric(this), + new IssueTemplateNoteMissingReferenceTimeTag(this), + new IssueTemplateNoteMissingStartReferenceTimeTag(this), + new IssueTemplateNoteStartReferenceTimeTagMissingTime(this), + new IssueTemplateNoteMissingEndReferenceTimeTag(this), + new IssueTemplateNoteEndReferenceTimeTagMissingTime(this), + }; + + protected override IEnumerable CheckReferenceProperty(Note note, IEnumerable allAvailableReferencedHitObjects) + { + if (note.ReferenceLyric == null) { - if (note.ReferenceLyric == null) - { - yield return new IssueTemplateNoteNullReferenceLyric(this).Create(note); + yield return new IssueTemplateNoteNullReferenceLyric(this).Create(note); - yield break; - } + yield break; + } - if (note.ReferenceLyric != null && !allAvailableReferencedHitObjects.Contains(note.ReferenceLyric)) - yield return new IssueTemplateNoteInvalidReferenceLyric(this).Create(note); + if (note.ReferenceLyric != null && !allAvailableReferencedHitObjects.Contains(note.ReferenceLyric)) + yield return new IssueTemplateNoteInvalidReferenceLyric(this).Create(note); - var startTimeTag = note.StartReferenceTimeTag; - var endTimeTag = note.EndReferenceTimeTag; + var startTimeTag = note.StartReferenceTimeTag; + var endTimeTag = note.EndReferenceTimeTag; - if (startTimeTag == null && endTimeTag == null) - { - yield return new IssueTemplateNoteMissingReferenceTimeTag(this).Create(note); + if (startTimeTag == null && endTimeTag == null) + { + yield return new IssueTemplateNoteMissingReferenceTimeTag(this).Create(note); - yield break; - } + yield break; + } - if (startTimeTag == null) - yield return new IssueTemplateNoteMissingStartReferenceTimeTag(this).Create(note); + if (startTimeTag == null) + yield return new IssueTemplateNoteMissingStartReferenceTimeTag(this).Create(note); - if (startTimeTag != null && startTimeTag.Time == null) - yield return new IssueTemplateNoteStartReferenceTimeTagMissingTime(this).Create(note); + if (startTimeTag != null && startTimeTag.Time == null) + yield return new IssueTemplateNoteStartReferenceTimeTagMissingTime(this).Create(note); - if (endTimeTag == null) - yield return new IssueTemplateNoteMissingEndReferenceTimeTag(this).Create(note); + if (endTimeTag == null) + yield return new IssueTemplateNoteMissingEndReferenceTimeTag(this).Create(note); - if (endTimeTag != null && endTimeTag.Time == null) - yield return new IssueTemplateNoteEndReferenceTimeTagMissingTime(this).Create(note); - } + if (endTimeTag != null && endTimeTag.Time == null) + yield return new IssueTemplateNoteEndReferenceTimeTagMissingTime(this).Create(note); + } - public class IssueTemplateNoteNullReferenceLyric : IssueTemplate + public class IssueTemplateNoteNullReferenceLyric : IssueTemplate + { + public IssueTemplateNoteNullReferenceLyric(ICheck check) + : base(check, IssueType.Error, "Note must have its parent lyric.") { - public IssueTemplateNoteNullReferenceLyric(ICheck check) - : base(check, IssueType.Error, "Note must have its parent lyric.") - { - } - - public Issue Create(Note note) - => new NoteIssue(note, this); } - public class IssueTemplateNoteInvalidReferenceLyric : IssueTemplate - { - public IssueTemplateNoteInvalidReferenceLyric(ICheck check) - : base(check, IssueType.Error, "Note's reference lyric must in the beatmap.") - { - } + public Issue Create(Note note) + => new NoteIssue(note, this); + } - public Issue Create(Note note) - => new NoteIssue(note, this); + public class IssueTemplateNoteInvalidReferenceLyric : IssueTemplate + { + public IssueTemplateNoteInvalidReferenceLyric(ICheck check) + : base(check, IssueType.Error, "Note's reference lyric must in the beatmap.") + { } - public class IssueTemplateNoteMissingReferenceTimeTag : IssueTemplate - { - public IssueTemplateNoteMissingReferenceTimeTag(ICheck check) - : base(check, IssueType.Problem, "Note's reference time-tag is missing.") - { - } + public Issue Create(Note note) + => new NoteIssue(note, this); + } - public Issue Create(Note note) - => new NoteIssue(note, this); + public class IssueTemplateNoteMissingReferenceTimeTag : IssueTemplate + { + public IssueTemplateNoteMissingReferenceTimeTag(ICheck check) + : base(check, IssueType.Problem, "Note's reference time-tag is missing.") + { } - public class IssueTemplateNoteMissingStartReferenceTimeTag : IssueTemplate - { - public IssueTemplateNoteMissingStartReferenceTimeTag(ICheck check) - : base(check, IssueType.Problem, "Note's start reference time-tag is missing.") - { - } + public Issue Create(Note note) + => new NoteIssue(note, this); + } - public Issue Create(Note note) - => new NoteIssue(note, this); + public class IssueTemplateNoteMissingStartReferenceTimeTag : IssueTemplate + { + public IssueTemplateNoteMissingStartReferenceTimeTag(ICheck check) + : base(check, IssueType.Problem, "Note's start reference time-tag is missing.") + { } - public class IssueTemplateNoteStartReferenceTimeTagMissingTime : IssueTemplate - { - public IssueTemplateNoteStartReferenceTimeTagMissingTime(ICheck check) - : base(check, IssueType.Problem, "Note's start reference time-tag is found but missing time.") - { - } + public Issue Create(Note note) + => new NoteIssue(note, this); + } - public Issue Create(Note note) - => new NoteIssue(note, this); + public class IssueTemplateNoteStartReferenceTimeTagMissingTime : IssueTemplate + { + public IssueTemplateNoteStartReferenceTimeTagMissingTime(ICheck check) + : base(check, IssueType.Problem, "Note's start reference time-tag is found but missing time.") + { } - public class IssueTemplateNoteMissingEndReferenceTimeTag : IssueTemplate - { - public IssueTemplateNoteMissingEndReferenceTimeTag(ICheck check) - : base(check, IssueType.Problem, "Note's end reference time-tag is missing.") - { - } + public Issue Create(Note note) + => new NoteIssue(note, this); + } - public Issue Create(Note note) - => new NoteIssue(note, this); + public class IssueTemplateNoteMissingEndReferenceTimeTag : IssueTemplate + { + public IssueTemplateNoteMissingEndReferenceTimeTag(ICheck check) + : base(check, IssueType.Problem, "Note's end reference time-tag is missing.") + { } - public class IssueTemplateNoteEndReferenceTimeTagMissingTime : IssueTemplate - { - public IssueTemplateNoteEndReferenceTimeTagMissingTime(ICheck check) - : base(check, IssueType.Problem, "Note's end reference time-tag is found but missing time.") - { - } + public Issue Create(Note note) + => new NoteIssue(note, this); + } - public Issue Create(Note note) - => new NoteIssue(note, this); + public class IssueTemplateNoteEndReferenceTimeTagMissingTime : IssueTemplate + { + public IssueTemplateNoteEndReferenceTimeTagMissingTime(ICheck check) + : base(check, IssueType.Problem, "Note's end reference time-tag is found but missing time.") + { } + + public Issue Create(Note note) + => new NoteIssue(note, this); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteText.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteText.cs index f12c1e9ea..e565a2fa2 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteText.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/CheckNoteText.cs @@ -6,47 +6,46 @@ using osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks +namespace osu.Game.Rulesets.Karaoke.Edit.Checks; + +public class CheckNoteText : CheckHitObjectProperty { - public class CheckNoteText : CheckHitObjectProperty - { - protected override string Description => "Note with invalid text."; + protected override string Description => "Note with invalid text."; - public override IEnumerable PossibleTemplates => new IssueTemplate[] - { - new IssueTemplateNoteNoText(this), - new IssueTemplateNoteNoRubyText(this), - }; + public override IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateNoteNoText(this), + new IssueTemplateNoteNoRubyText(this), + }; - protected override IEnumerable Check(Note note) - { - if (string.IsNullOrWhiteSpace(note.Text)) - yield return new IssueTemplateNoteNoText(this).Create(note); + protected override IEnumerable Check(Note note) + { + if (string.IsNullOrWhiteSpace(note.Text)) + yield return new IssueTemplateNoteNoText(this).Create(note); - if (note.RubyText != null && string.IsNullOrWhiteSpace(note.RubyText)) - yield return new IssueTemplateNoteNoRubyText(this).Create(note); - } + if (note.RubyText != null && string.IsNullOrWhiteSpace(note.RubyText)) + yield return new IssueTemplateNoteNoRubyText(this).Create(note); + } - public class IssueTemplateNoteNoText : IssueTemplate + public class IssueTemplateNoteNoText : IssueTemplate + { + public IssueTemplateNoteNoText(ICheck check) + : base(check, IssueType.Problem, "Note must have text.") { - public IssueTemplateNoteNoText(ICheck check) - : base(check, IssueType.Problem, "Note must have text.") - { - } - - public Issue Create(Note note) - => new NoteIssue(note, this); } - public class IssueTemplateNoteNoRubyText : IssueTemplate - { - public IssueTemplateNoteNoRubyText(ICheck check) - : base(check, IssueType.Error, "Note's ruby text should be null or has the value.") - { - } + public Issue Create(Note note) + => new NoteIssue(note, this); + } - public Issue Create(Note note) - => new NoteIssue(note, this); + public class IssueTemplateNoteNoRubyText : IssueTemplate + { + public IssueTemplateNoteNoRubyText(ICheck check) + : base(check, IssueType.Error, "Note's ruby text should be null or has the value.") + { } + + public Issue Create(Note note) + => new NoteIssue(note, this); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricIssue.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricIssue.cs index aa975bad6..3804742b4 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricIssue.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricIssue.cs @@ -4,18 +4,17 @@ using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues +namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; + +public class LyricIssue : Issue { - public class LyricIssue : Issue - { - public Lyric Lyric; + public Lyric Lyric; - public LyricIssue(Lyric lyric, IssueTemplate template, params object[] args) - : base(lyric, template, args) - { - Lyric = lyric; + public LyricIssue(Lyric lyric, IssueTemplate template, params object[] args) + : base(lyric, template, args) + { + Lyric = lyric; - Time = Lyric.LyricStartTime; - } + Time = Lyric.LyricStartTime; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRomajiTagIssue.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRomajiTagIssue.cs index 2056b751c..6cb7d0f37 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRomajiTagIssue.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRomajiTagIssue.cs @@ -4,16 +4,15 @@ using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues +namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; + +public class LyricRomajiTagIssue : LyricIssue { - public class LyricRomajiTagIssue : LyricIssue - { - public readonly RomajiTag RomajiTag; + public readonly RomajiTag RomajiTag; - public LyricRomajiTagIssue(Lyric lyric, IssueTemplate template, RomajiTag romajiTag, params object[] args) - : base(lyric, template, args) - { - RomajiTag = romajiTag; - } + public LyricRomajiTagIssue(Lyric lyric, IssueTemplate template, RomajiTag romajiTag, params object[] args) + : base(lyric, template, args) + { + RomajiTag = romajiTag; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRubyTagIssue.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRubyTagIssue.cs index d57b192f5..44098e60c 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRubyTagIssue.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricRubyTagIssue.cs @@ -4,16 +4,15 @@ using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues +namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; + +public class LyricRubyTagIssue : LyricIssue { - public class LyricRubyTagIssue : LyricIssue - { - public readonly RubyTag RubyTag; + public readonly RubyTag RubyTag; - public LyricRubyTagIssue(Lyric lyric, IssueTemplate template, RubyTag rubyTag, params object[] args) - : base(lyric, template, args) - { - RubyTag = rubyTag; - } + public LyricRubyTagIssue(Lyric lyric, IssueTemplate template, RubyTag rubyTag, params object[] args) + : base(lyric, template, args) + { + RubyTag = rubyTag; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricTimeTagIssue.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricTimeTagIssue.cs index 4de9798b7..beff0668e 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricTimeTagIssue.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/LyricTimeTagIssue.cs @@ -4,18 +4,17 @@ using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues +namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; + +public class LyricTimeTagIssue : LyricIssue { - public class LyricTimeTagIssue : LyricIssue - { - public readonly TimeTag TimeTag; + public readonly TimeTag TimeTag; - public LyricTimeTagIssue(Lyric lyric, IssueTemplate template, TimeTag timeTag, params object[] args) - : base(lyric, template, args) - { - TimeTag = timeTag; + public LyricTimeTagIssue(Lyric lyric, IssueTemplate template, TimeTag timeTag, params object[] args) + : base(lyric, template, args) + { + TimeTag = timeTag; - Time = TimeTag.Time ?? Lyric.LyricStartTime; - } + Time = TimeTag.Time ?? Lyric.LyricStartTime; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/NoteIssue.cs b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/NoteIssue.cs index edb55b17a..fec79b1fe 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/NoteIssue.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Checks/Issues/NoteIssue.cs @@ -4,16 +4,15 @@ using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues +namespace osu.Game.Rulesets.Karaoke.Edit.Checks.Issues; + +public class NoteIssue : Issue { - public class NoteIssue : Issue - { - public Note Note; + public Note Note; - public NoteIssue(Note note, IssueTemplate template, params object[] args) - : base(note, template, args) - { - Note = note; - } + public NoteIssue(Note note, IssueTemplate template, params object[] args) + : base(note, template, args) + { + Note = note; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Containers/Section.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Containers/Section.cs index 80b938bff..babdea9a2 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Containers/Section.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Containers/Section.cs @@ -10,43 +10,42 @@ using osu.Game.Graphics.Sprites; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Containers +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Containers; + +public abstract partial class Section : Container { - public abstract partial class Section : Container - { - protected const float SECTION_PADDING = 10; + protected const float SECTION_PADDING = 10; - protected const float SECTION_SPACING = 10; + protected const float SECTION_SPACING = 10; - private readonly FillFlowContainer flow; + private readonly FillFlowContainer flow; - protected override Container Content => flow; + protected override Container Content => flow; - protected abstract LocalisableString Title { get; } + protected abstract LocalisableString Title { get; } - protected Section() - { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; + protected Section() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; - Padding = new MarginPadding(SECTION_PADDING); + Padding = new MarginPadding(SECTION_PADDING); - InternalChildren = new Drawable[] + InternalChildren = new Drawable[] + { + new OsuSpriteText + { + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), + Text = Title, + }, + flow = new FillFlowContainer { - new OsuSpriteText - { - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18), - Text = Title, - }, - flow = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(SECTION_SPACING), - Direction = FillDirection.Vertical, - Margin = new MarginPadding { Top = 30 } - } - }; - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(SECTION_SPACING), + Direction = FillDirection.Vertical, + Margin = new MarginPadding { Top = 30 } + } + }; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/LyricLockContextMenu.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/LyricLockContextMenu.cs index 000ad89db..19b0bc3c6 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/LyricLockContextMenu.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/LyricLockContextMenu.cs @@ -9,25 +9,24 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.ContextMenu +namespace osu.Game.Rulesets.Karaoke.Edit.Components.ContextMenu; + +public class LyricLockContextMenu : OsuMenuItem { - public class LyricLockContextMenu : OsuMenuItem + public LyricLockContextMenu(ILockChangeHandler lockChangeHandler, Lyric lyric, string name) + : this(lockChangeHandler, new List { lyric }, name) { - public LyricLockContextMenu(ILockChangeHandler lockChangeHandler, Lyric lyric, string name) - : this(lockChangeHandler, new List { lyric }, name) - { - } + } - public LyricLockContextMenu(ILockChangeHandler lockChangeHandler, List lyrics, string name) - : base(name) + public LyricLockContextMenu(ILockChangeHandler lockChangeHandler, List lyrics, string name) + : base(name) + { + Items = Enum.GetValues().Select(l => new OsuMenuItem(l.ToString(), anyLyricInLockState(l) ? MenuItemType.Highlighted : MenuItemType.Standard, () => { - Items = Enum.GetValues().Select(l => new OsuMenuItem(l.ToString(), anyLyricInLockState(l) ? MenuItemType.Highlighted : MenuItemType.Standard, () => - { - // todo: how to make lyric as selected? - lockChangeHandler.Lock(l); - })).ToList(); + // todo: how to make lyric as selected? + lockChangeHandler.Lock(l); + })).ToList(); - bool anyLyricInLockState(LockState lockState) => lyrics.Any(lyric => lyric.Lock == lockState); - } + bool anyLyricInLockState(LockState lockState) => lyrics.Any(lyric => lyric.Lock == lockState); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/SingerContextMenu.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/SingerContextMenu.cs index 225cb3e31..ee736d5ef 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/SingerContextMenu.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/ContextMenu/SingerContextMenu.cs @@ -13,37 +13,36 @@ using osu.Game.Rulesets.Karaoke.Utils; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.ContextMenu +namespace osu.Game.Rulesets.Karaoke.Edit.Components.ContextMenu; + +public class SingerContextMenu : OsuMenuItem { - public class SingerContextMenu : OsuMenuItem + public SingerContextMenu(EditorBeatmap beatmap, ILyricSingerChangeHandler lyricSingerChangeHandler, string name, Action postProcess = null) + : base(name) { - public SingerContextMenu(EditorBeatmap beatmap, ILyricSingerChangeHandler lyricSingerChangeHandler, string name, Action postProcess = null) - : base(name) - { - var lyrics = beatmap.SelectedHitObjects.OfType().ToArray(); + var lyrics = beatmap.SelectedHitObjects.OfType().ToArray(); - // todo: should be able to support the sub-singer. - var karaokeBeatmap = EditorBeatmapUtils.GetPlayableBeatmap(beatmap); - var singers = karaokeBeatmap.SingerInfo.GetAllSingers(); + // todo: should be able to support the sub-singer. + var karaokeBeatmap = EditorBeatmapUtils.GetPlayableBeatmap(beatmap); + var singers = karaokeBeatmap.SingerInfo.GetAllSingers(); - Items = singers.Select(singer => new OsuMenuItem(singer.Name, anySingerInLyric(singer) ? MenuItemType.Highlighted : MenuItemType.Standard, () => + Items = singers.Select(singer => new OsuMenuItem(singer.Name, anySingerInLyric(singer) ? MenuItemType.Highlighted : MenuItemType.Standard, () => + { + // if only one lyric + if (allSingerInLyric(singer)) + { + lyricSingerChangeHandler.Remove(singer); + } + else { - // if only one lyric - if (allSingerInLyric(singer)) - { - lyricSingerChangeHandler.Remove(singer); - } - else - { - lyricSingerChangeHandler.Add(singer); - } - - postProcess?.Invoke(); - })).ToList(); - - bool anySingerInLyric(Singer singer) => lyrics.Any(lyric => LyricUtils.ContainsSinger(lyric, singer)); - - bool allSingerInLyric(Singer singer) => lyrics.All(lyric => LyricUtils.ContainsSinger(lyric, singer)); - } + lyricSingerChangeHandler.Add(singer); + } + + postProcess?.Invoke(); + })).ToList(); + + bool anySingerInLyric(Singer singer) => lyrics.Any(lyric => LyricUtils.ContainsSinger(lyric, singer)); + + bool allSingerInLyric(Singer singer) => lyrics.All(lyric => LyricUtils.ContainsSinger(lyric, singer)); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/LayoutToolTip.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/LayoutToolTip.cs index d93c3c6ab..e872ae4b5 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/LayoutToolTip.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/LayoutToolTip.cs @@ -11,40 +11,39 @@ using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Cursor +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Cursor; + +public partial class LayoutToolTip : BackgroundToolTip { - public partial class LayoutToolTip : BackgroundToolTip - { - private const float scale = 0.4f; + private const float scale = 0.4f; - private readonly DrawableLayoutPreview preview; + private readonly DrawableLayoutPreview preview; - [Resolved(canBeNull: true)] - private ISkinSource skinSource { get; set; } + [Resolved(canBeNull: true)] + private ISkinSource skinSource { get; set; } - public LayoutToolTip() + public LayoutToolTip() + { + Child = preview = new DrawableLayoutPreview { - Child = preview = new DrawableLayoutPreview - { - Size = new Vector2(512 * scale, 384 * scale), - }; - } + Size = new Vector2(512 * scale, 384 * scale), + }; + } - private Lyric lastLyric; + private Lyric lastLyric; - public override void SetContent(Lyric lyric) - { - if (lyric == lastLyric) - return; + public override void SetContent(Lyric lyric) + { + if (lyric == lastLyric) + return; - lastLyric = lyric; + lastLyric = lyric; - // Get layout - var layout = skinSource?.GetConfig(lyric).Value; + // Get layout + var layout = skinSource?.GetConfig(lyric).Value; - // Display in content - preview.Layout = layout; - preview.Lyric = lyric; - } + // Display in content + preview.Layout = layout; + preview.Lyric = lyric; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/TimeTagTooltip.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/TimeTagTooltip.cs index 291818804..e14b065e3 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/TimeTagTooltip.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Cursor/TimeTagTooltip.cs @@ -14,95 +14,94 @@ using osu.Game.Rulesets.Karaoke.Utils; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Cursor +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Cursor; + +public partial class TimeTagTooltip : BackgroundToolTip { - public partial class TimeTagTooltip : BackgroundToolTip - { - private const int time_display_height = 25; + private const int time_display_height = 25; - private Box background; - private readonly OsuSpriteText trackTimer; - private readonly OsuSpriteText index; - private readonly OsuSpriteText indexState; + private Box background; + private readonly OsuSpriteText trackTimer; + private readonly OsuSpriteText index; + private readonly OsuSpriteText indexState; - protected override float ContentPadding => 5; + protected override float ContentPadding => 5; - public TimeTagTooltip() + public TimeTagTooltip() + { + Child = new GridContainer { - Child = new GridContainer + AutoSizeAxes = Axes.Both, + RowDimensions = new[] { - AutoSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.Absolute, time_display_height), - new Dimension(GridSizeMode.Absolute, BORDER), - new Dimension(GridSizeMode.AutoSize) - }, - ColumnDimensions = new[] + new Dimension(GridSizeMode.Absolute, time_display_height), + new Dimension(GridSizeMode.Absolute, BORDER), + new Dimension(GridSizeMode.AutoSize) + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { - new Dimension(GridSizeMode.AutoSize) + trackTimer = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 21, fixedWidth: true) + } }, - Content = new[] + null, + new Drawable[] { - new Drawable[] - { - trackTimer = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 21, fixedWidth: true) - } - }, - null, - new Drawable[] + new FillFlowContainer { - new FillFlowContainer + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(10), + Children = new[] { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(10), - Children = new[] + index = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12) + }, + indexState = new OsuSpriteText { - index = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 12) - }, - indexState = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 12) - } + Font = OsuFont.GetFont(size: 12) } } } } - }; - } + } + }; + } - protected override Drawable SetBackground() + protected override Drawable SetBackground() + { + return background = new Box { - return background = new Box - { - RelativeSizeAxes = Axes.X, - Height = time_display_height + BORDER - }; - } + RelativeSizeAxes = Axes.X, + Height = time_display_height + BORDER + }; + } - private TimeTag lastTimeTag; + private TimeTag lastTimeTag; - public override void SetContent(TimeTag timeTag) - { - if (timeTag == lastTimeTag) - return; + public override void SetContent(TimeTag timeTag) + { + if (timeTag == lastTimeTag) + return; - lastTimeTag = timeTag; + lastTimeTag = timeTag; - trackTimer.Text = TimeTagUtils.FormattedString(timeTag); - index.Text = $"Position: {timeTag.Index.Index}"; - indexState.Text = TextIndexUtils.GetValueByState(timeTag.Index, "start", "end"); - } + trackTimer.Text = TimeTagUtils.FormattedString(timeTag); + index.Text = $"Position: {timeTag.Index.Index}"; + indexState.Text = TextIndexUtils.GetValueByState(timeTag.Index, "start", "end"); + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Gray2; - indexState.Colour = colours.Red; - } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray2; + indexState.Colour = colours.Red; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/EnumMenu.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/EnumMenu.cs index 7b8114915..7b5080fa6 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/EnumMenu.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/EnumMenu.cs @@ -10,47 +10,46 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.UserInterface; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus; + +public abstract class EnumMenu : MenuItem where T : struct, Enum { - public abstract class EnumMenu : MenuItem where T : struct, Enum - { - private readonly Bindable bindableEnum; + private readonly Bindable bindableEnum; - protected EnumMenu(Bindable bindable, string text) - : base(text) - { - Items = createMenuItems(); + protected EnumMenu(Bindable bindable, string text) + : base(text) + { + Items = createMenuItems(); - bindableEnum = bindable; + bindableEnum = bindable; - bindable.BindValueChanged(e => - { - var newSelection = e.NewValue; - Items.OfType().ForEach(x => - { - bool match = x.Text.Value == GetName(newSelection); - x.State.Value = match; - }); - }, true); - } - - private ToggleMenuItem[] createMenuItems() + bindable.BindValueChanged(e => { - return ValidEnums.Select(e => + var newSelection = e.NewValue; + Items.OfType().ForEach(x => { - var item = new ToggleMenuItem(GetName(e), MenuItemType.Standard, _ => UpdateSelection(e)); - return item; - }).ToArray(); - } + bool match = x.Text.Value == GetName(newSelection); + x.State.Value = match; + }); + }, true); + } - protected virtual IEnumerable ValidEnums => Enum.GetValues(); + private ToggleMenuItem[] createMenuItems() + { + return ValidEnums.Select(e => + { + var item = new ToggleMenuItem(GetName(e), MenuItemType.Standard, _ => UpdateSelection(e)); + return item; + }).ToArray(); + } - protected string GetName(T selection) - => selection.GetDescription(); + protected virtual IEnumerable ValidEnums => Enum.GetValues(); - protected virtual void UpdateSelection(T selection) - { - bindableEnum.Value = selection; - } + protected string GetName(T selection) + => selection.GetDescription(); + + protected virtual void UpdateSelection(T selection) + { + bindableEnum.Value = selection; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeEditorMenu.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeEditorMenu.cs index 297178643..949f5c553 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeEditorMenu.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeEditorMenu.cs @@ -7,18 +7,17 @@ using osu.Framework.Screens; using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus; + +public class KaraokeEditorMenu : MenuItem { - public class KaraokeEditorMenu : MenuItem + public KaraokeEditorMenu(IScreen screen, string text) + : base(text, () => openKaraokeEditor(screen)) { - public KaraokeEditorMenu(IScreen screen, string text) - : base(text, () => openKaraokeEditor(screen)) - { - } + } - private static void openKaraokeEditor(IScreen screen) - { - screen?.Push(new KaraokeBeatmapEditor()); - } + private static void openKaraokeEditor(IScreen screen) + { + screen?.Push(new KaraokeBeatmapEditor()); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeSkinEditorMenu.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeSkinEditorMenu.cs index f00b2e23c..8ce023272 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeSkinEditorMenu.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/KaraokeSkinEditorMenu.cs @@ -8,18 +8,17 @@ using osu.Game.Rulesets.Karaoke.Screens.Skin; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus; + +public class KaraokeSkinEditorMenu : MenuItem { - public class KaraokeSkinEditorMenu : MenuItem + public KaraokeSkinEditorMenu(IScreen screen, ISkin skin, string text) + : base(text, () => openKaraokeSkin(screen, skin)) { - public KaraokeSkinEditorMenu(IScreen screen, ISkin skin, string text) - : base(text, () => openKaraokeSkin(screen, skin)) - { - } + } - private static void openKaraokeSkin(IScreen screen, ISkin skin) - { - screen?.Push(new KaraokeSkinEditor(skin)); - } + private static void openKaraokeSkin(IScreen screen, ISkin skin) + { + screen?.Push(new KaraokeSkinEditor(skin)); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/NoteEditorPreviewMenu.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/NoteEditorPreviewMenu.cs index 426a47ac8..adaeb87c4 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/NoteEditorPreviewMenu.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Menus/NoteEditorPreviewMenu.cs @@ -8,38 +8,37 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Karaoke.Configuration; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Menus; + +public class NoteEditorPreviewMenu : MenuItem { - public class NoteEditorPreviewMenu : MenuItem + private readonly KaraokeRulesetEditConfigManager config; + + public NoteEditorPreviewMenu(KaraokeRulesetEditConfigManager config, string text) + : base(text) { - private readonly KaraokeRulesetEditConfigManager config; + this.config = config; - public NoteEditorPreviewMenu(KaraokeRulesetEditConfigManager config, string text) - : base(text) + Items = new[] { - this.config = config; + createToggleMenu("Display ruby", KaraokeRulesetEditSetting.DisplayRuby), + createToggleMenu("Display romaji", KaraokeRulesetEditSetting.DisplayRomaji), + createToggleMenu("Display translate", KaraokeRulesetEditSetting.DisplayTranslate), + }; + } - Items = new[] - { - createToggleMenu("Display ruby", KaraokeRulesetEditSetting.DisplayRuby), - createToggleMenu("Display romaji", KaraokeRulesetEditSetting.DisplayRomaji), - createToggleMenu("Display translate", KaraokeRulesetEditSetting.DisplayTranslate), - }; - } + private ToggleMenuItem createToggleMenu(string menu, KaraokeRulesetEditSetting setting) + { + var bindable = new Bindable(); + var menuItem = new ToggleMenuItem(menu, MenuItemType.Standard, _ => bindable.Value = !bindable.Value); - private ToggleMenuItem createToggleMenu(string menu, KaraokeRulesetEditSetting setting) + // create bindable + bindable.BindValueChanged(e => { - var bindable = new Bindable(); - var menuItem = new ToggleMenuItem(menu, MenuItemType.Standard, _ => bindable.Value = !bindable.Value); - - // create bindable - bindable.BindValueChanged(e => - { - menuItem.State.Value = e.NewValue; - }, true); - config.BindWith(setting, bindable); - - return menuItem; - } + menuItem.State.Value = e.NewValue; + }, true); + config.BindWith(setting, bindable); + + return menuItem; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs index 654a4c4e6..8d397a9b6 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableLayoutPreview.cs @@ -14,118 +14,117 @@ using osu.Game.Rulesets.Karaoke.Skinning.Elements; using osu.Game.Skinning; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Sprites +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Sprites; + +public partial class DrawableLayoutPreview : CompositeDrawable { - public partial class DrawableLayoutPreview : CompositeDrawable - { - private const float scale = 0.4f; + private const float scale = 0.4f; - private readonly Box background; - private readonly Box previewLyric; - private readonly OsuSpriteText notSupportText; + private readonly Box background; + private readonly Box previewLyric; + private readonly OsuSpriteText notSupportText; - [Resolved(canBeNull: true)] - private ISkinSource skinSource { get; set; } + [Resolved(canBeNull: true)] + private ISkinSource skinSource { get; set; } - public DrawableLayoutPreview() + public DrawableLayoutPreview() + { + InternalChildren = new Drawable[] { - InternalChildren = new Drawable[] + background = new Box { - background = new Box - { - RelativeSizeAxes = Axes.Both - }, - previewLyric = new Box - { - Height = 15 - }, - notSupportText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - } - }; + RelativeSizeAxes = Axes.Both + }, + previewLyric = new Box + { + Height = 15 + }, + notSupportText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }; - previewLyric.Hide(); - notSupportText.Hide(); - } + previewLyric.Hide(); + notSupportText.Hide(); + } - private LyricLayout layout; + private LyricLayout layout; - public LyricLayout Layout + public LyricLayout Layout + { + get => layout; + set { - get => layout; - set - { - if (layout == value) - return; + if (layout == value) + return; - layout = value; - updateLayout(); - } + layout = value; + updateLayout(); } + } - private Lyric lyric; + private Lyric lyric; - public Lyric Lyric + public Lyric Lyric + { + get => lyric; + set { - get => lyric; - set - { - if (lyric == value) - return; + if (lyric == value) + return; - lyric = value; - updateLayout(); - } + lyric = value; + updateLayout(); } + } - private void updateLayout() + private void updateLayout() + { + // Display in content + if (Layout == null) { - // Display in content - if (Layout == null) - { - // mark layout as not supported, or skin is not loaded - notSupportText.Show(); + // mark layout as not supported, or skin is not loaded + notSupportText.Show(); - if (skinSource == null) - notSupportText.Text = "Sorry, skin is not exist."; - else - notSupportText.Text = "Sorry, layout is not exist."; - } + if (skinSource == null) + notSupportText.Text = "Sorry, skin is not exist."; else - { - // Display box preview position - previewLyric.Show(); - - // Set preview width - const float text_size = 20; - previewLyric.Width = (Lyric?.Text.Length ?? 10) * text_size * scale; - previewLyric.Height = text_size * 1.5f * scale; - - // Set relative position - previewLyric.Anchor = layout.Alignment; - previewLyric.Origin = layout.Alignment; - - // Set margin - const float padding = 30 * scale; - float horizontalMargin = layout.HorizontalMargin * scale + padding; - float verticalMargin = layout.VerticalMargin * scale + padding; - previewLyric.Margin = new MarginPadding - { - Left = layout.Alignment.HasFlagFast(Anchor.x0) ? horizontalMargin : 0, - Right = layout.Alignment.HasFlagFast(Anchor.x2) ? horizontalMargin : 0, - Top = layout.Alignment.HasFlagFast(Anchor.y0) ? verticalMargin : 0, - Bottom = layout.Alignment.HasFlagFast(Anchor.y2) ? verticalMargin : 0 - }; - } + notSupportText.Text = "Sorry, layout is not exist."; } - - [BackgroundDependencyLoader] - private void load(OsuColour colours) + else { - background.Colour = colours.Gray2; - previewLyric.Colour = colours.Yellow; + // Display box preview position + previewLyric.Show(); + + // Set preview width + const float text_size = 20; + previewLyric.Width = (Lyric?.Text.Length ?? 10) * text_size * scale; + previewLyric.Height = text_size * 1.5f * scale; + + // Set relative position + previewLyric.Anchor = layout.Alignment; + previewLyric.Origin = layout.Alignment; + + // Set margin + const float padding = 30 * scale; + float horizontalMargin = layout.HorizontalMargin * scale + padding; + float verticalMargin = layout.VerticalMargin * scale + padding; + previewLyric.Margin = new MarginPadding + { + Left = layout.Alignment.HasFlagFast(Anchor.x0) ? horizontalMargin : 0, + Right = layout.Alignment.HasFlagFast(Anchor.x2) ? horizontalMargin : 0, + Top = layout.Alignment.HasFlagFast(Anchor.y0) ? verticalMargin : 0, + Bottom = layout.Alignment.HasFlagFast(Anchor.y2) ? verticalMargin : 0 + }; } } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray2; + previewLyric.Colour = colours.Yellow; + } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableTextIndex.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableTextIndex.cs index 6dbd18164..88a3d03eb 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableTextIndex.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/Sprites/DrawableTextIndex.cs @@ -7,26 +7,25 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Graphics.Shapes; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.Sprites +namespace osu.Game.Rulesets.Karaoke.Edit.Components.Sprites; + +public partial class DrawableTextIndex : RightTriangle { - public partial class DrawableTextIndex : RightTriangle - { - private TextIndex.IndexState state; + private TextIndex.IndexState state; - public TextIndex.IndexState State + public TextIndex.IndexState State + { + get => state; + set { - get => state; - set - { - state = value; + state = value; - RightAngleDirection = state switch - { - TextIndex.IndexState.Start => TriangleRightAngleDirection.BottomLeft, - TextIndex.IndexState.End => TriangleRightAngleDirection.BottomRight, - _ => throw new ArgumentOutOfRangeException(nameof(value)) - }; - } + RightAngleDirection = state switch + { + TextIndex.IndexState.Start => TriangleRightAngleDirection.BottomLeft, + TextIndex.IndexState.End => TriangleRightAngleDirection.BottomRight, + _ => throw new ArgumentOutOfRangeException(nameof(value)) + }; } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Components/UserInterfaceV2/NoteEditPopover.cs b/osu.Game.Rulesets.Karaoke/Edit/Components/UserInterfaceV2/NoteEditPopover.cs index f5e59766d..505bed6a5 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Components/UserInterfaceV2/NoteEditPopover.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Components/UserInterfaceV2/NoteEditPopover.cs @@ -15,106 +15,105 @@ using osu.Game.Rulesets.Karaoke.Edit.Components.Containers; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Components.UserInterfaceV2 +namespace osu.Game.Rulesets.Karaoke.Edit.Components.UserInterfaceV2; + +public partial class NoteEditPopover : OsuPopover { - public partial class NoteEditPopover : OsuPopover + public NoteEditPopover(Note note) { - public NoteEditPopover(Note note) - { - ArgumentNullException.ThrowIfNull(note); + ArgumentNullException.ThrowIfNull(note); - Child = new OsuScrollContainer + Child = new OsuScrollContainer + { + Height = 320, + Width = 300, + Child = new FillFlowContainer
{ - Height = 320, - Width = 300, - Child = new FillFlowContainer
+ Direction = FillDirection.Vertical, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Section[] { - Direction = FillDirection.Vertical, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Section[] - { - new NoteSection(note), - } + new NoteSection(note), } - }; - } + } + }; + } - private partial class NoteSection : Section - { - private INotePropertyChangeHandler notePropertyChangeHandler { get; set; } + private partial class NoteSection : Section + { + private INotePropertyChangeHandler notePropertyChangeHandler { get; set; } - protected override LocalisableString Title => "Note property"; + protected override LocalisableString Title => "Note property"; - public NoteSection(Note note) - { - LabelledTextBox text; - LabelledTextBox rubyText; - LabelledSwitchButton display; + public NoteSection(Note note) + { + LabelledTextBox text; + LabelledTextBox rubyText; + LabelledSwitchButton display; - Children = new Drawable[] + Children = new Drawable[] + { + text = new LabelledTextBox { - text = new LabelledTextBox - { - Label = "Text", - Description = "The text display on the note.", - Current = note.TextBindable, - TabbableContentContainer = this - }, - rubyText = new LabelledTextBox - { - Label = "Ruby text", - Description = "Should place something like ruby, 拼音 or ふりがな.", - Current = note.RubyTextBindable, - TabbableContentContainer = this - }, - display = new LabelledSwitchButton - { - Label = "Display", - Description = "This note will be hidden and not scorable if not display.", - Current = note.DisplayBindable, - } - }; - - ScheduleAfterChildren(() => + Label = "Text", + Description = "The text display on the note.", + Current = note.TextBindable, + TabbableContentContainer = this + }, + rubyText = new LabelledTextBox { - GetContainingInputManager().ChangeFocus(text); - }); - - text.OnCommit += (sender, newText) => + Label = "Ruby text", + Description = "Should place something like ruby, 拼音 or ふりがな.", + Current = note.RubyTextBindable, + TabbableContentContainer = this + }, + display = new LabelledSwitchButton { - if (!newText) - return; - - string text = sender.Text.Trim(); - notePropertyChangeHandler?.ChangeText(text); - }; + Label = "Display", + Description = "This note will be hidden and not scorable if not display.", + Current = note.DisplayBindable, + } + }; - rubyText.OnCommit += (sender, newText) => - { - if (!newText) - return; + ScheduleAfterChildren(() => + { + GetContainingInputManager().ChangeFocus(text); + }); - string text = sender.Text.Trim(); - notePropertyChangeHandler?.ChangeRubyText(text); - }; + text.OnCommit += (sender, newText) => + { + if (!newText) + return; - display.Current.BindValueChanged(v => - { - notePropertyChangeHandler?.ChangeDisplayState(v.NewValue); - }); - } + string text = sender.Text.Trim(); + notePropertyChangeHandler?.ChangeText(text); + }; - [BackgroundDependencyLoader(true)] - private void load(HitObjectComposer composer) + rubyText.OnCommit += (sender, newText) => { - if (notePropertyChangeHandler != null || composer == null) + if (!newText) return; - // todo: not a good way to get change handler, might remove or found another way eventually. - // cannot get change handler directly in editor screen, so should trying to get from karaoke hit object composer. - notePropertyChangeHandler = composer.Dependencies.Get(); - } + string text = sender.Text.Trim(); + notePropertyChangeHandler?.ChangeRubyText(text); + }; + + display.Current.BindValueChanged(v => + { + notePropertyChangeHandler?.ChangeDisplayState(v.NewValue); + }); + } + + [BackgroundDependencyLoader(true)] + private void load(HitObjectComposer composer) + { + if (notePropertyChangeHandler != null || composer == null) + return; + + // todo: not a good way to get change handler, might remove or found another way eventually. + // cannot get change handler directly in editor screen, so should trying to get from karaoke hit object composer. + notePropertyChangeHandler = composer.Dependencies.Get(); } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/DrawableKaraokeEditorRuleset.cs b/osu.Game.Rulesets.Karaoke/Edit/DrawableKaraokeEditorRuleset.cs index f2c4176d8..a9dc42001 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/DrawableKaraokeEditorRuleset.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/DrawableKaraokeEditorRuleset.cs @@ -13,37 +13,36 @@ using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; -namespace osu.Game.Rulesets.Karaoke.Edit +namespace osu.Game.Rulesets.Karaoke.Edit; + +public partial class DrawableKaraokeEditorRuleset : DrawableKaraokeRuleset { - public partial class DrawableKaraokeEditorRuleset : DrawableKaraokeRuleset + private readonly Bindable bindableDisplayRubyToggle = new(); + private readonly Bindable bindableDisplayRomajiToggle = new(); + private readonly Bindable bindableDisplayTranslateToggle = new(); + + public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; + + protected override bool DisplayNotePlayfield => true; + + public DrawableKaraokeEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods) + : base(ruleset, beatmap, mods) { - private readonly Bindable bindableDisplayRubyToggle = new(); - private readonly Bindable bindableDisplayRomajiToggle = new(); - private readonly Bindable bindableDisplayTranslateToggle = new(); - - public new IScrollingInfo ScrollingInfo => base.ScrollingInfo; - - protected override bool DisplayNotePlayfield => true; - - public DrawableKaraokeEditorRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods) - : base(ruleset, beatmap, mods) - { - bindableDisplayRubyToggle.BindValueChanged(x => { Session.SetValue(KaraokeRulesetSession.DisplayRuby, x.NewValue); }); - bindableDisplayRomajiToggle.BindValueChanged(x => { Session.SetValue(KaraokeRulesetSession.DisplayRomaji, x.NewValue); }); - bindableDisplayTranslateToggle.BindValueChanged(x => { Session.SetValue(KaraokeRulesetSession.UseTranslate, x.NewValue); }); - } - - protected override Playfield CreatePlayfield() => new KaraokeEditorPlayfield(); - - [BackgroundDependencyLoader] - private void load(KaraokeRulesetEditConfigManager editConfigManager) - { - editConfigManager.BindWith(KaraokeRulesetEditSetting.DisplayRuby, bindableDisplayRubyToggle); - editConfigManager.BindWith(KaraokeRulesetEditSetting.DisplayRomaji, bindableDisplayRomajiToggle); - editConfigManager.BindWith(KaraokeRulesetEditSetting.DisplayTranslate, bindableDisplayTranslateToggle); - } - - // todo: use default adjustment container because DrawableEditorRulesetWrapper will create it but contains no KaraokeRulesetConfigManager - public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new(); + bindableDisplayRubyToggle.BindValueChanged(x => { Session.SetValue(KaraokeRulesetSession.DisplayRuby, x.NewValue); }); + bindableDisplayRomajiToggle.BindValueChanged(x => { Session.SetValue(KaraokeRulesetSession.DisplayRomaji, x.NewValue); }); + bindableDisplayTranslateToggle.BindValueChanged(x => { Session.SetValue(KaraokeRulesetSession.UseTranslate, x.NewValue); }); } + + protected override Playfield CreatePlayfield() => new KaraokeEditorPlayfield(); + + [BackgroundDependencyLoader] + private void load(KaraokeRulesetEditConfigManager editConfigManager) + { + editConfigManager.BindWith(KaraokeRulesetEditSetting.DisplayRuby, bindableDisplayRubyToggle); + editConfigManager.BindWith(KaraokeRulesetEditSetting.DisplayRomaji, bindableDisplayRomajiToggle); + editConfigManager.BindWith(KaraokeRulesetEditSetting.DisplayTranslate, bindableDisplayTranslateToggle); + } + + // todo: use default adjustment container because DrawableEditorRulesetWrapper will create it but contains no KaraokeRulesetConfigManager + public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/EditorNotePlayfield.cs b/osu.Game.Rulesets.Karaoke/Edit/EditorNotePlayfield.cs index 607ddfd40..a0fba10a0 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/EditorNotePlayfield.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/EditorNotePlayfield.cs @@ -13,84 +13,83 @@ using osu.Game.Rulesets.Karaoke.UI.Scrolling; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.Edit +namespace osu.Game.Rulesets.Karaoke.Edit; + +public partial class EditorNotePlayfield : ScrollingNotePlayfield { - public partial class EditorNotePlayfield : ScrollingNotePlayfield - { - private readonly SingerVoiceVisualization singerVoiceVisualization; + private readonly SingerVoiceVisualization singerVoiceVisualization; - public EditorNotePlayfield(int columns) - : base(columns) + public EditorNotePlayfield(int columns) + : base(columns) + { + BackgroundLayer.AddRange(new Drawable[] { - BackgroundLayer.AddRange(new Drawable[] + new Box { - new Box - { - Depth = 1, - Name = "Background", - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black, - Alpha = 0.5f - }, - }); - - HitObjectArea.Add(singerVoiceVisualization = new SingerVoiceVisualization - { - Name = "Scoring Visualization", + Depth = 1, + Name = "Background", RelativeSizeAxes = Axes.Both, - Alpha = 0.6f - }); - } + Colour = Color4.Black, + Alpha = 0.5f + }, + }); - [BackgroundDependencyLoader(true)] - private void load() + HitObjectArea.Add(singerVoiceVisualization = new SingerVoiceVisualization { - // todo : load data from scoring manager. - } + Name = "Scoring Visualization", + RelativeSizeAxes = Axes.Both, + Alpha = 0.6f + }); + } - public partial class SingerVoiceVisualization : VoiceVisualization> - { - protected override double GetTime(KeyValuePair frame) => frame.Key; + [BackgroundDependencyLoader(true)] + private void load() + { + // todo : load data from scoring manager. + } - protected override float GetPosition(KeyValuePair frame) => frame.Value ?? 0; + public partial class SingerVoiceVisualization : VoiceVisualization> + { + protected override double GetTime(KeyValuePair frame) => frame.Key; - private bool createNew = true; + protected override float GetPosition(KeyValuePair frame) => frame.Value ?? 0; - private double minAvailableTime; + private bool createNew = true; - public void Add(KeyValuePair point) + private double minAvailableTime; + + public void Add(KeyValuePair point) + { + // Start time should be largest and cannot be removed. + double startTime = point.Key; + if (startTime <= minAvailableTime) + throw new ArgumentOutOfRangeException($"{nameof(startTime)} out of range."); + + minAvailableTime = startTime; + + if (!point.Value.HasValue) { - // Start time should be largest and cannot be removed. - double startTime = point.Key; - if (startTime <= minAvailableTime) - throw new ArgumentOutOfRangeException($"{nameof(startTime)} out of range."); - - minAvailableTime = startTime; - - if (!point.Value.HasValue) - { - // Next replay frame will create new path - createNew = true; - return; - } - - if (createNew) - { - createNew = false; - - CreateNew(point); - } - else - { - Append(point); - } + // Next replay frame will create new path + createNew = true; + return; } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + if (createNew) + { + createNew = false; + + CreateNew(point); + } + else { - Colour = colours.GrayF; + Append(point); } } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + Colour = colours.GrayF; + } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Export/ExportLyricManager.cs b/osu.Game.Rulesets.Karaoke/Edit/Export/ExportLyricManager.cs index 2ca250fd6..9bf1b7afa 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Export/ExportLyricManager.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Export/ExportLyricManager.cs @@ -17,147 +17,146 @@ using osu.Game.Screens.Edit; using SharpCompress.Archives.Zip; -namespace osu.Game.Rulesets.Karaoke.Edit.Export +namespace osu.Game.Rulesets.Karaoke.Edit.Export; + +public partial class ExportLyricManager : Component { - public partial class ExportLyricManager : Component - { - [Resolved] - private Storage storage { get; set; } + [Resolved] + private Storage storage { get; set; } - [Resolved] - private EditorBeatmap beatmap { get; set; } + [Resolved] + private EditorBeatmap beatmap { get; set; } - public void ExportToLrc() - { - var exportStorage = storage.GetStorageForDirectory("lrc"); - string filename = $"{beatmap.Name}.lrc"; + public void ExportToLrc() + { + var exportStorage = storage.GetStorageForDirectory("lrc"); + string filename = $"{beatmap.Name}.lrc"; - using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(outputStream)) + using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(outputStream)) + { + var encoder = new LrcEncoder(); + sw.WriteLine(encoder.Encode(new Beatmap { - var encoder = new LrcEncoder(); - sw.WriteLine(encoder.Encode(new Beatmap - { - HitObjects = beatmap.HitObjects.ToList() - })); - } - - exportStorage.PresentFileExternally(filename); + HitObjects = beatmap.HitObjects.ToList() + })); } - public void ExportToText() - { - var exportStorage = storage.GetStorageForDirectory("text"); - string filename = $"{beatmap.Name}.txt"; - - using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(outputStream)) - { - var encoder = new LyricTextEncoder(); - sw.WriteLine(encoder.Encode(new Beatmap - { - HitObjects = beatmap.HitObjects.ToList() - })); - } + exportStorage.PresentFileExternally(filename); + } - exportStorage.PresentFileExternally(filename); - } + public void ExportToText() + { + var exportStorage = storage.GetStorageForDirectory("text"); + string filename = $"{beatmap.Name}.txt"; - public void ExportToJson() + using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(outputStream)) { - // note : this is for develop testing purpose. - // will be removed eventually - string beatmapName = string.IsNullOrEmpty(beatmap.Name) ? "[NoName]" : beatmap.Name; - var exportStorage = storage.GetStorageForDirectory("json"); - string filename = $"{beatmapName}.json"; - - using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) - using (var sw = new StreamWriter(outputStream)) + var encoder = new LyricTextEncoder(); + sw.WriteLine(encoder.Encode(new Beatmap { - sw.WriteLine(generateJsonBeatmap()); - } - - exportStorage.PresentFileExternally(filename); + HitObjects = beatmap.HitObjects.ToList() + })); } - public void ExportToJsonBeatmap() - { - // note : this is for develop testing purpose. - // will be removed eventually - string beatmapName = string.IsNullOrEmpty(beatmap.Name) ? "[NoName]" : beatmap.Name; - string filename = $"{beatmapName}.osu"; - string beatmapText = generateJsonBeatmap(); + exportStorage.PresentFileExternally(filename); + } - new KaraokeLegacyBeatmapExporter(storage, filename, beatmapText).Export(beatmap.BeatmapInfo.BeatmapSet); + public void ExportToJson() + { + // note : this is for develop testing purpose. + // will be removed eventually + string beatmapName = string.IsNullOrEmpty(beatmap.Name) ? "[NoName]" : beatmap.Name; + var exportStorage = storage.GetStorageForDirectory("json"); + string filename = $"{beatmapName}.json"; + + using (var outputStream = exportStorage.GetStream(filename, FileAccess.Write, FileMode.Create)) + using (var sw = new StreamWriter(outputStream)) + { + sw.WriteLine(generateJsonBeatmap()); } - private string generateJsonBeatmap() + exportStorage.PresentFileExternally(filename); + } + + public void ExportToJsonBeatmap() + { + // note : this is for develop testing purpose. + // will be removed eventually + string beatmapName = string.IsNullOrEmpty(beatmap.Name) ? "[NoName]" : beatmap.Name; + string filename = $"{beatmapName}.osu"; + string beatmapText = generateJsonBeatmap(); + + new KaraokeLegacyBeatmapExporter(storage, filename, beatmapText).Export(beatmap.BeatmapInfo.BeatmapSet); + } + + private string generateJsonBeatmap() + { + var encoder = new KaraokeJsonBeatmapEncoder(); + var karaokeBeatmap = EditorBeatmapUtils.GetPlayableBeatmap(beatmap); + + var encodeBeatmap = new Beatmap + { + Difficulty = karaokeBeatmap.Difficulty.Clone(), + BeatmapInfo = karaokeBeatmap.BeatmapInfo.Clone(), + ControlPointInfo = karaokeBeatmap.ControlPointInfo.DeepClone(), + Breaks = karaokeBeatmap.Breaks, + HitObjects = beatmap.HitObjects.ToList(), + }; + encodeBeatmap.BeatmapInfo.BeatmapSet = new BeatmapSetInfo(); + encodeBeatmap.BeatmapInfo.Metadata = new BeatmapMetadata { - var encoder = new KaraokeJsonBeatmapEncoder(); - var karaokeBeatmap = EditorBeatmapUtils.GetPlayableBeatmap(beatmap); + Title = "json beatmap", + AudioFile = karaokeBeatmap.Metadata.AudioFile, + BackgroundFile = karaokeBeatmap.Metadata.BackgroundFile, + }; - var encodeBeatmap = new Beatmap - { - Difficulty = karaokeBeatmap.Difficulty.Clone(), - BeatmapInfo = karaokeBeatmap.BeatmapInfo.Clone(), - ControlPointInfo = karaokeBeatmap.ControlPointInfo.DeepClone(), - Breaks = karaokeBeatmap.Breaks, - HitObjects = beatmap.HitObjects.ToList(), - }; - encodeBeatmap.BeatmapInfo.BeatmapSet = new BeatmapSetInfo(); - encodeBeatmap.BeatmapInfo.Metadata = new BeatmapMetadata - { - Title = "json beatmap", - AudioFile = karaokeBeatmap.Metadata.AudioFile, - BackgroundFile = karaokeBeatmap.Metadata.BackgroundFile, - }; + return encoder.Encode(encodeBeatmap); + } - return encoder.Encode(encodeBeatmap); + private class KaraokeLegacyBeatmapExporter : LegacyBeatmapExporter + { + private readonly string filename; + private readonly string content; + + public KaraokeLegacyBeatmapExporter(Storage storage, string filename, string content) + : base(storage) + { + this.filename = filename; + this.content = content; } - private class KaraokeLegacyBeatmapExporter : LegacyBeatmapExporter + public override void ExportModelTo(BeatmapSetInfo model, Stream outputStream) { - private readonly string filename; - private readonly string content; + // base.ExportModelTo(model, outputStream); + using var zipArchive = ZipArchive.Create(); - public KaraokeLegacyBeatmapExporter(Storage storage, string filename, string content) - : base(storage) + foreach (INamedFileUsage file in model.Files) { - this.filename = filename; - this.content = content; - } + // do not export other osu beatmap. + if (file.Filename.EndsWith(".osu", StringComparison.Ordinal)) + continue; - public override void ExportModelTo(BeatmapSetInfo model, Stream outputStream) - { - // base.ExportModelTo(model, outputStream); - using var zipArchive = ZipArchive.Create(); - - foreach (INamedFileUsage file in model.Files) - { - // do not export other osu beatmap. - if (file.Filename.EndsWith(".osu", StringComparison.Ordinal)) - continue; - - zipArchive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); - } - - // add the json file. - using var jsonBeatmapStream = getJsonBeatmapStream(); - zipArchive.AddEntry(filename, jsonBeatmapStream); - zipArchive.SaveTo(outputStream); + zipArchive.AddEntry(file.Filename, UserFileStorage.GetStream(file.File.GetStoragePath())); } - private Stream getJsonBeatmapStream() - { - var memoryStream = new MemoryStream(); - var sw = new StreamWriter(memoryStream); + // add the json file. + using var jsonBeatmapStream = getJsonBeatmapStream(); + zipArchive.AddEntry(filename, jsonBeatmapStream); + zipArchive.SaveTo(outputStream); + } - sw.WriteLine(content); - sw.Flush(); + private Stream getJsonBeatmapStream() + { + var memoryStream = new MemoryStream(); + var sw = new StreamWriter(memoryStream); - memoryStream.Position = 0; - return memoryStream; - } + sw.WriteLine(content); + sw.Flush(); + + memoryStream.Position = 0; + return memoryStream; } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyDetector.cs index 9643858ca..e0946eed7 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyDetector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyDetector.cs @@ -3,19 +3,18 @@ using osu.Game.Rulesets.Karaoke.Beatmaps; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps; + +/// +/// Base interface of the detector. +/// +/// +/// +public abstract class BeatmapPropertyDetector : PropertyDetector + where TConfig : GeneratorConfig, new() { - /// - /// Base interface of the detector. - /// - /// - /// - public abstract class BeatmapPropertyDetector : PropertyDetector - where TConfig : GeneratorConfig, new() + protected BeatmapPropertyDetector(TConfig config) + : base(config) { - protected BeatmapPropertyDetector(TConfig config) - : base(config) - { - } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyGenerator.cs index 32a004e4c..930360e81 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyGenerator.cs @@ -3,19 +3,18 @@ using osu.Game.Rulesets.Karaoke.Beatmaps; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps; + +/// +/// Base interface of the auto-generator. +/// +/// +/// +public abstract class BeatmapPropertyGenerator : PropertyGenerator + where TConfig : GeneratorConfig, new() { - /// - /// Base interface of the auto-generator. - /// - /// - /// - public abstract class BeatmapPropertyGenerator : PropertyGenerator - where TConfig : GeneratorConfig, new() + protected BeatmapPropertyGenerator(TConfig config) + : base(config) { - protected BeatmapPropertyGenerator(TConfig config) - : base(config) - { - } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/GeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/GeneratorConfig.cs index 174105999..55d891d65 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/GeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/GeneratorConfig.cs @@ -1,9 +1,8 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.Generator +namespace osu.Game.Rulesets.Karaoke.Edit.Generator; + +public abstract class GeneratorConfig { - public abstract class GeneratorConfig - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs index db3f81124..7dfa48d2f 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs @@ -7,41 +7,40 @@ using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language; + +public class LanguageDetector : LyricPropertyDetector { - public class LanguageDetector : LyricPropertyDetector + private readonly LanguageDetection.LanguageDetector detector = new(); + + public LanguageDetector(LanguageDetectorConfig config) + : base(config) { - private readonly LanguageDetection.LanguageDetector detector = new(); + var targetLanguages = config.AcceptLanguages.Value ?? Array.Empty(); - public LanguageDetector(LanguageDetectorConfig config) - : base(config) + if (targetLanguages.Any()) { - var targetLanguages = config.AcceptLanguages.Value ?? Array.Empty(); - - if (targetLanguages.Any()) - { - detector.AddLanguages(targetLanguages.Select(x => x.Name).ToArray()); - } - else - { - detector.AddAllLanguages(); - } + detector.AddLanguages(targetLanguages.Select(x => x.Name).ToArray()); } - - protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + else { - if (string.IsNullOrWhiteSpace(item.Text)) - return "Lyric should not be empty."; - - return null; + detector.AddAllLanguages(); } + } - protected override CultureInfo? DetectFromItem(Lyric item) - { - var result = detector.DetectAll(item.Text); - string? languageCode = result.FirstOrDefault()?.Language; + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + if (string.IsNullOrWhiteSpace(item.Text)) + return "Lyric should not be empty."; - return languageCode == null ? null : new CultureInfo(languageCode); - } + return null; + } + + protected override CultureInfo? DetectFromItem(Lyric item) + { + var result = detector.DetectAll(item.Text); + string? languageCode = result.FirstOrDefault()?.Language; + + return languageCode == null ? null : new CultureInfo(languageCode); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetectorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetectorConfig.cs index 89de6853e..fbdcfaf66 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetectorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetectorConfig.cs @@ -5,11 +5,10 @@ using System.Globalization; using osu.Framework.Bindables; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language; + +public class LanguageDetectorConfig : GeneratorConfig { - public class LanguageDetectorConfig : GeneratorConfig - { - [ConfigSource("Accept languages", "All accepted languages.")] - public Bindable AcceptLanguages { get; } = new(Array.Empty()); - } + [ConfigSource("Accept languages", "All accepted languages.")] + public Bindable AcceptLanguages { get; } = new(Array.Empty()); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs index dd7d25ad3..0f6e5d060 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs @@ -7,46 +7,45 @@ using osu.Game.Rulesets.Karaoke.Configuration; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; + +public abstract class LyricGeneratorSelector : GeneratorSelector + where TBaseConfig : GeneratorConfig { - public abstract class LyricGeneratorSelector : GeneratorSelector - where TBaseConfig : GeneratorConfig + protected LyricGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) + : base(generatorConfigManager) + { + } + + protected void RegisterGenerator(CultureInfo cultureInfo) + where TGenerator : PropertyGenerator + where TConfig : TBaseConfig, new() { - protected LyricGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) - : base(generatorConfigManager) - { - } - - protected void RegisterGenerator(CultureInfo cultureInfo) - where TGenerator : PropertyGenerator - where TConfig : TBaseConfig, new() - { - RegisterGenerator(x => EqualityComparer.Default.Equals(x.Language, cultureInfo)); - } - - protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) - { - if (item.Language == null) - return "Oops, language is missing."; - - if (string.IsNullOrWhiteSpace(item.Text)) - return "Should have the text in the lyric"; - - if (!TryGetGenerator(item, out var generator)) - return "Sorry, the language of lyric is not supported yet."; - - return generator.GetInvalidMessage(item); - } - - protected override TProperty GenerateFromItem(Lyric item) - { - if (item.Language == null) - throw new GeneratorNotSupportedException(); - - if (!TryGetGenerator(item, out var generator)) - throw new GeneratorNotSupportedException(); - - return generator.Generate(item); - } + RegisterGenerator(x => EqualityComparer.Default.Equals(x.Language, cultureInfo)); + } + + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + if (item.Language == null) + return "Oops, language is missing."; + + if (string.IsNullOrWhiteSpace(item.Text)) + return "Should have the text in the lyric"; + + if (!TryGetGenerator(item, out var generator)) + return "Sorry, the language of lyric is not supported yet."; + + return generator.GetInvalidMessage(item); + } + + protected override TProperty GenerateFromItem(Lyric item) + { + if (item.Language == null) + throw new GeneratorNotSupportedException(); + + if (!TryGetGenerator(item, out var generator)) + throw new GeneratorNotSupportedException(); + + return generator.Generate(item); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyDetector.cs index 9f34a13a6..44cb6f96b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyDetector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyDetector.cs @@ -3,19 +3,18 @@ using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; + +/// +/// Base interface of the detector. +/// +/// +/// +public abstract class LyricPropertyDetector : PropertyDetector + where TConfig : GeneratorConfig, new() { - /// - /// Base interface of the detector. - /// - /// - /// - public abstract class LyricPropertyDetector : PropertyDetector - where TConfig : GeneratorConfig, new() + protected LyricPropertyDetector(TConfig config) + : base(config) { - protected LyricPropertyDetector(TConfig config) - : base(config) - { - } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyGenerator.cs index cd0eef4b4..2e82d4b37 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyGenerator.cs @@ -3,19 +3,18 @@ using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; + +/// +/// Base interface of the auto-generator. +/// +/// +/// +public abstract class LyricPropertyGenerator : PropertyGenerator + where TConfig : GeneratorConfig, new() { - /// - /// Base interface of the auto-generator. - /// - /// - /// - public abstract class LyricPropertyGenerator : PropertyGenerator - where TConfig : GeneratorConfig, new() + protected LyricPropertyGenerator(TConfig config) + : base(config) { - protected LyricPropertyGenerator(TConfig config) - : base(config) - { - } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs index 4cd13ed9a..2dd87a52e 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs @@ -9,68 +9,67 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes; + +public class NoteGenerator : LyricPropertyGenerator { - public class NoteGenerator : LyricPropertyGenerator + public NoteGenerator(NoteGeneratorConfig config) + : base(config) { - public NoteGenerator(NoteGeneratorConfig config) - : base(config) - { - } + } - protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) - { - var timeTags = item.TimeTags; + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + var timeTags = item.TimeTags; - if (item.TimeTags.Count < 2) - return "Sorry, lyric must have at least two time-tags."; + if (item.TimeTags.Count < 2) + return "Sorry, lyric must have at least two time-tags."; - if (timeTags.Any(x => x.Time == null)) - return "All time-tag should have the time."; + if (timeTags.Any(x => x.Time == null)) + return "All time-tag should have the time."; - return null; - } + return null; + } - protected override Note[] GenerateFromItem(Lyric item) - { - var timeTags = TimeTagsUtils.ToTimeBasedDictionary(item.TimeTags); - var notes = new List(); + protected override Note[] GenerateFromItem(Lyric item) + { + var timeTags = TimeTagsUtils.ToTimeBasedDictionary(item.TimeTags); + var notes = new List(); - foreach (var timeTag in timeTags) - { - // should not continue if - if (timeTags.LastOrDefault().Key == timeTag.Key) - break; + foreach (var timeTag in timeTags) + { + // should not continue if + if (timeTags.LastOrDefault().Key == timeTag.Key) + break; - (double _, var textIndex) = timeTag; - (double _, var nextTextIndex) = timeTags.GetNext(timeTag); + (double _, var textIndex) = timeTag; + (double _, var nextTextIndex) = timeTags.GetNext(timeTag); - int startIndex = TextIndexUtils.ToStringIndex(textIndex); - int endIndex = TextIndexUtils.ToStringIndex(nextTextIndex); + int startIndex = TextIndexUtils.ToStringIndex(textIndex); + int endIndex = TextIndexUtils.ToStringIndex(nextTextIndex); - // prevent reverse time-tag to generate the note. - if (startIndex >= endIndex) - continue; + // prevent reverse time-tag to generate the note. + if (startIndex >= endIndex) + continue; - int timeTagIndex = timeTags.IndexOf(timeTag); - string text = item.Text[startIndex..endIndex]; - string? ruby = item.RubyTags?.Where(x => x.StartIndex == startIndex && x.EndIndex == endIndex).FirstOrDefault()?.Text; + int timeTagIndex = timeTags.IndexOf(timeTag); + string text = item.Text[startIndex..endIndex]; + string? ruby = item.RubyTags?.Where(x => x.StartIndex == startIndex && x.EndIndex == endIndex).FirstOrDefault()?.Text; - if (!string.IsNullOrEmpty(text)) + if (!string.IsNullOrEmpty(text)) + { + notes.Add(new Note { - notes.Add(new Note - { - Text = text, - RubyText = ruby, - ReferenceLyricId = item.ID, - // technically this property should be assigned by beatmap processor, but should be OK to assign here for testing purpose. - ReferenceLyric = item, - ReferenceTimeTagIndex = timeTagIndex - }); - } + Text = text, + RubyText = ruby, + ReferenceLyricId = item.ID, + // technically this property should be assigned by beatmap processor, but should be OK to assign here for testing purpose. + ReferenceLyric = item, + ReferenceTimeTagIndex = timeTagIndex + }); } - - return notes.ToArray(); } + + return notes.ToArray(); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGeneratorConfig.cs index d77f0d9ab..1faff43fe 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGeneratorConfig.cs @@ -1,9 +1,8 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes; + +public class NoteGeneratorConfig : GeneratorConfig { - public class NoteGeneratorConfig : GeneratorConfig - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs index 670240747..f7cded939 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs @@ -8,70 +8,69 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric; + +public class ReferenceLyricDetector : LyricPropertyDetector { - public class ReferenceLyricDetector : LyricPropertyDetector + private readonly Lyric[] lyrics; + + public ReferenceLyricDetector(IEnumerable lyrics, ReferenceLyricDetectorConfig config) + : base(config) { - private readonly Lyric[] lyrics; + this.lyrics = lyrics.ToArray(); + } - public ReferenceLyricDetector(IEnumerable lyrics, ReferenceLyricDetectorConfig config) - : base(config) - { - this.lyrics = lyrics.ToArray(); - } + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + var referencedLyric = getReferenceLyric(item); + if (referencedLyric == null) + return "There's no matched lyric."; - protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) - { - var referencedLyric = getReferenceLyric(item); - if (referencedLyric == null) - return "There's no matched lyric."; + return null; + } + protected override Lyric? DetectFromItem(Lyric item) + { + var referencedLyric = getReferenceLyric(item); + if (referencedLyric == null) return null; - } - protected override Lyric? DetectFromItem(Lyric item) - { - var referencedLyric = getReferenceLyric(item); - if (referencedLyric == null) - return null; - - // prevent first lyric(referenced lyric) reference by other lyric. - if (referencedLyric.Order > item.Order) - return null; + // prevent first lyric(referenced lyric) reference by other lyric. + if (referencedLyric.Order > item.Order) + return null; - return referencedLyric; - } + return referencedLyric; + } - private Lyric? getReferenceLyric(Lyric lyric) - { - if (!lyrics.Contains(lyric)) - throw new InvalidOperationException(); + private Lyric? getReferenceLyric(Lyric lyric) + { + if (!lyrics.Contains(lyric)) + throw new InvalidOperationException(); - return lyrics.Except(new[] { lyric }).OrderBy(x => x.Order).FirstOrDefault(x => canBeReferenced(lyric, x)); - } + return lyrics.Except(new[] { lyric }).OrderBy(x => x.Order).FirstOrDefault(x => canBeReferenced(lyric, x)); + } - private bool canBeReferenced(Lyric lyric, Lyric referencedLyric) - { - string lyricText = lyric.Text; - string referencedLyricText = referencedLyric.Text; + private bool canBeReferenced(Lyric lyric, Lyric referencedLyric) + { + string lyricText = lyric.Text; + string referencedLyricText = referencedLyric.Text; - if (lyricText == referencedLyricText) - return true; + if (lyricText == referencedLyricText) + return true; - if (!Config.IgnorePrefixAndPostfixSymbol.Value) - return false; + if (!Config.IgnorePrefixAndPostfixSymbol.Value) + return false; - // check if contains intersect part between two lyrics. - if (!lyricText.Contains(referencedLyricText) && !referencedLyricText.Contains(lyricText)) - return false; + // check if contains intersect part between two lyrics. + if (!lyricText.Contains(referencedLyricText) && !referencedLyricText.Contains(lyricText)) + return false; - // check if except part are all symbols. - var except1 = lyricText.Except(referencedLyricText); - var except2 = referencedLyricText.Except(lyricText); - return allCharsEmptyOrSymbol(except1) && allCharsEmptyOrSymbol(except2); + // check if except part are all symbols. + var except1 = lyricText.Except(referencedLyricText); + var except2 = referencedLyricText.Except(lyricText); + return allCharsEmptyOrSymbol(except1) && allCharsEmptyOrSymbol(except2); - static bool allCharsEmptyOrSymbol(IEnumerable chars) - => chars.All(x => CharUtils.IsSpacing(x) || CharUtils.IsAsciiSymbol(x)); - } + static bool allCharsEmptyOrSymbol(IEnumerable chars) + => chars.All(x => CharUtils.IsSpacing(x) || CharUtils.IsAsciiSymbol(x)); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetectorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetectorConfig.cs index 98a0941d2..8ba3750d4 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetectorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetectorConfig.cs @@ -3,11 +3,10 @@ using osu.Framework.Bindables; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric; + +public class ReferenceLyricDetectorConfig : GeneratorConfig { - public class ReferenceLyricDetectorConfig : GeneratorConfig - { - [ConfigSource("Ruby as Katakana", "Ruby as Katakana.")] - public Bindable IgnorePrefixAndPostfixSymbol { get; } = new BindableBool(true); - } + [ConfigSource("Ruby as Katakana", "Ruby as Katakana.")] + public Bindable IgnorePrefixAndPostfixSymbol { get; } = new BindableBool(true); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs index d115f0e36..b1524cd8b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs @@ -10,101 +10,100 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags.Ja +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags.Ja; + +public class JaRomajiTagGenerator : RomajiTagGenerator { - public class JaRomajiTagGenerator : RomajiTagGenerator - { - private readonly Analyzer analyzer; + private readonly Analyzer analyzer; - public JaRomajiTagGenerator(JaRomajiTagGeneratorConfig config) - : base(config) + public JaRomajiTagGenerator(JaRomajiTagGeneratorConfig config) + : base(config) + { + analyzer = Analyzer.NewAnonymous((fieldName, reader) => { - analyzer = Analyzer.NewAnonymous((fieldName, reader) => - { - Tokenizer tokenizer = new JapaneseTokenizer(reader, null, true, JapaneseTokenizerMode.SEARCH); - return new TokenStreamComponents(tokenizer, new JapaneseReadingFormFilter(tokenizer, false)); - }); - } + Tokenizer tokenizer = new JapaneseTokenizer(reader, null, true, JapaneseTokenizerMode.SEARCH); + return new TokenStreamComponents(tokenizer, new JapaneseReadingFormFilter(tokenizer, false)); + }); + } - protected override RomajiTag[] GenerateFromItem(Lyric item) - { - string text = item.Text; - var processingTags = new List(); + protected override RomajiTag[] GenerateFromItem(Lyric item) + { + string text = item.Text; + var processingTags = new List(); - // Tokenize the text - var tokenStream = analyzer.GetTokenStream("dummy", new StringReader(text)); + // Tokenize the text + var tokenStream = analyzer.GetTokenStream("dummy", new StringReader(text)); - // Get result and offset - var result = tokenStream.GetAttribute(); - var offsetAtt = tokenStream.GetAttribute(); + // Get result and offset + var result = tokenStream.GetAttribute(); + var offsetAtt = tokenStream.GetAttribute(); - // Reset the stream and convert all result - tokenStream.Reset(); + // Reset the stream and convert all result + tokenStream.Reset(); - while (true) - { - // Read next token - tokenStream.ClearAttributes(); - tokenStream.IncrementToken(); + while (true) + { + // Read next token + tokenStream.ClearAttributes(); + tokenStream.IncrementToken(); - // Get parsed result, result is Katakana. - string katakana = result.ToString(); - if (string.IsNullOrEmpty(katakana)) - break; + // Get parsed result, result is Katakana. + string katakana = result.ToString(); + if (string.IsNullOrEmpty(katakana)) + break; - string parentText = text[offsetAtt.StartOffset..offsetAtt.EndOffset]; - bool fromKanji = JpStringUtils.ToKatakana(katakana) != JpStringUtils.ToKatakana(parentText); + string parentText = text[offsetAtt.StartOffset..offsetAtt.EndOffset]; + bool fromKanji = JpStringUtils.ToKatakana(katakana) != JpStringUtils.ToKatakana(parentText); - // Convert to romaji. - string romaji = JpStringUtils.ToRomaji(katakana); - if (Config.Uppercase.Value) - romaji = romaji.ToUpper(); + // Convert to romaji. + string romaji = JpStringUtils.ToRomaji(katakana); + if (Config.Uppercase.Value) + romaji = romaji.ToUpper(); - // Make tag - processingTags.Add(new RomajiTagGeneratorParameter + // Make tag + processingTags.Add(new RomajiTagGeneratorParameter + { + FromKanji = fromKanji, + RomajiTag = new RomajiTag { - FromKanji = fromKanji, - RomajiTag = new RomajiTag - { - Text = romaji, - StartIndex = offsetAtt.StartOffset, - EndIndex = offsetAtt.EndOffset - } - }); - } + Text = romaji, + StartIndex = offsetAtt.StartOffset, + EndIndex = offsetAtt.EndOffset + } + }); + } - // Dispose - tokenStream.End(); - tokenStream.Dispose(); + // Dispose + tokenStream.End(); + tokenStream.Dispose(); - var romajiTags = new List(); + var romajiTags = new List(); - foreach (var processingTag in processingTags) - { - // combine romajies of they are not from kanji. - var previousProcessingTag = processingTags.GetPrevious(processingTag); - bool fromKanji = processingTag.FromKanji; + foreach (var processingTag in processingTags) + { + // combine romajies of they are not from kanji. + var previousProcessingTag = processingTags.GetPrevious(processingTag); + bool fromKanji = processingTag.FromKanji; - if (previousProcessingTag != null && !fromKanji) - { - var combinedRomajiTag = TextTagsUtils.Combine(previousProcessingTag.RomajiTag, processingTag.RomajiTag); - romajiTags.Remove(previousProcessingTag.RomajiTag); - romajiTags.Add(combinedRomajiTag); - } - else - { - romajiTags.Add(processingTag.RomajiTag); - } + if (previousProcessingTag != null && !fromKanji) + { + var combinedRomajiTag = TextTagsUtils.Combine(previousProcessingTag.RomajiTag, processingTag.RomajiTag); + romajiTags.Remove(previousProcessingTag.RomajiTag); + romajiTags.Add(combinedRomajiTag); + } + else + { + romajiTags.Add(processingTag.RomajiTag); } - - return romajiTags.ToArray(); } - internal class RomajiTagGeneratorParameter - { - public bool FromKanji { get; set; } + return romajiTags.ToArray(); + } - public RomajiTag RomajiTag { get; set; } = null!; - } + internal class RomajiTagGeneratorParameter + { + public bool FromKanji { get; set; } + + public RomajiTag RomajiTag { get; set; } = null!; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGeneratorConfig.cs index 4829b044a..4008079aa 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGeneratorConfig.cs @@ -3,11 +3,10 @@ using osu.Framework.Bindables; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags.Ja +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags.Ja; + +public class JaRomajiTagGeneratorConfig : RomajiTagGeneratorConfig { - public class JaRomajiTagGeneratorConfig : RomajiTagGeneratorConfig - { - [ConfigSource("Uppercase", "Export romaji with uppercase.")] - public Bindable Uppercase { get; } = new BindableBool(); - } + [ConfigSource("Uppercase", "Export romaji with uppercase.")] + public Bindable Uppercase { get; } = new BindableBool(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs index 2ba9db6de..8d91c1d6b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs @@ -4,22 +4,21 @@ using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags; + +public abstract class RomajiTagGenerator : LyricPropertyGenerator + where TConfig : RomajiTagGeneratorConfig, new() { - public abstract class RomajiTagGenerator : LyricPropertyGenerator - where TConfig : RomajiTagGeneratorConfig, new() + protected RomajiTagGenerator(TConfig config) + : base(config) { - protected RomajiTagGenerator(TConfig config) - : base(config) - { - } + } - protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) - { - if (string.IsNullOrWhiteSpace(item.Text)) - return "Lyric should not be empty."; + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + if (string.IsNullOrWhiteSpace(item.Text)) + return "Lyric should not be empty."; - return null; - } + return null; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorConfig.cs index 70d6518ca..b8cc6a9e5 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorConfig.cs @@ -1,9 +1,8 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags; + +public abstract class RomajiTagGeneratorConfig : GeneratorConfig { - public abstract class RomajiTagGeneratorConfig : GeneratorConfig - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs index 66c0aacde..bdc06a004 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs @@ -6,15 +6,14 @@ using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags.Ja; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags; + +public class RomajiTagGeneratorSelector : LyricGeneratorSelector { - public class RomajiTagGeneratorSelector : LyricGeneratorSelector + public RomajiTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) + : base(generatorConfigManager) { - public RomajiTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) - : base(generatorConfigManager) - { - RegisterGenerator(new CultureInfo(17)); - RegisterGenerator(new CultureInfo(1041)); - } + RegisterGenerator(new CultureInfo(17)); + RegisterGenerator(new CultureInfo(1041)); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs index 6cfc2a7a7..840117e7a 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs @@ -9,73 +9,72 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags.Ja -{ - public class JaRubyTagGenerator : RubyTagGenerator - { - private readonly Analyzer analyzer; +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags.Ja; - public JaRubyTagGenerator(JaRubyTagGeneratorConfig config) - : base(config) - { - analyzer = Analyzer.NewAnonymous((fieldName, reader) => - { - Tokenizer tokenizer = new JapaneseTokenizer(reader, null, true, JapaneseTokenizerMode.SEARCH); - return new TokenStreamComponents(tokenizer, new JapaneseReadingFormFilter(tokenizer, false)); - }); - } +public class JaRubyTagGenerator : RubyTagGenerator +{ + private readonly Analyzer analyzer; - protected override RubyTag[] GenerateFromItem(Lyric item) + public JaRubyTagGenerator(JaRubyTagGeneratorConfig config) + : base(config) + { + analyzer = Analyzer.NewAnonymous((fieldName, reader) => { - string text = item.Text; - var tags = new List(); + Tokenizer tokenizer = new JapaneseTokenizer(reader, null, true, JapaneseTokenizerMode.SEARCH); + return new TokenStreamComponents(tokenizer, new JapaneseReadingFormFilter(tokenizer, false)); + }); + } - // Tokenize the text - var tokenStream = analyzer.GetTokenStream("dummy", new StringReader(text)); + protected override RubyTag[] GenerateFromItem(Lyric item) + { + string text = item.Text; + var tags = new List(); - // Get result and offset - var result = tokenStream.GetAttribute(); - var offsetAtt = tokenStream.GetAttribute(); + // Tokenize the text + var tokenStream = analyzer.GetTokenStream("dummy", new StringReader(text)); - // Reset the stream and convert all result - tokenStream.Reset(); + // Get result and offset + var result = tokenStream.GetAttribute(); + var offsetAtt = tokenStream.GetAttribute(); - while (true) - { - // Read next token - tokenStream.ClearAttributes(); - tokenStream.IncrementToken(); + // Reset the stream and convert all result + tokenStream.Reset(); - // Get parsed result, result is Katakana. - string katakana = result.ToString(); - if (string.IsNullOrEmpty(katakana)) - break; + while (true) + { + // Read next token + tokenStream.ClearAttributes(); + tokenStream.IncrementToken(); - // Convert to Hiragana as default. - string hiragana = JpStringUtils.ToHiragana(katakana); + // Get parsed result, result is Katakana. + string katakana = result.ToString(); + if (string.IsNullOrEmpty(katakana)) + break; - if (!Config.EnableDuplicatedRuby.Value) - { - // Not add duplicated ruby if same as parent. - string parentText = text[offsetAtt.StartOffset..offsetAtt.EndOffset]; - if (parentText == katakana || parentText == hiragana) - continue; - } + // Convert to Hiragana as default. + string hiragana = JpStringUtils.ToHiragana(katakana); - // Make tag - tags.Add(new RubyTag - { - Text = Config.RubyAsKatakana.Value ? katakana : hiragana, - StartIndex = offsetAtt.StartOffset, - EndIndex = offsetAtt.EndOffset - }); + if (!Config.EnableDuplicatedRuby.Value) + { + // Not add duplicated ruby if same as parent. + string parentText = text[offsetAtt.StartOffset..offsetAtt.EndOffset]; + if (parentText == katakana || parentText == hiragana) + continue; } - // Dispose - tokenStream.End(); - tokenStream.Dispose(); - - return tags.ToArray(); + // Make tag + tags.Add(new RubyTag + { + Text = Config.RubyAsKatakana.Value ? katakana : hiragana, + StartIndex = offsetAtt.StartOffset, + EndIndex = offsetAtt.EndOffset + }); } + + // Dispose + tokenStream.End(); + tokenStream.Dispose(); + + return tags.ToArray(); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGeneratorConfig.cs index 953ec416a..a973be378 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGeneratorConfig.cs @@ -3,20 +3,19 @@ using osu.Framework.Bindables; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags.Ja +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags.Ja; + +public class JaRubyTagGeneratorConfig : RubyTagGeneratorConfig { - public class JaRubyTagGeneratorConfig : RubyTagGeneratorConfig - { - /// - /// Generate ruby as Katakana. - /// - [ConfigSource("Ruby as Katakana", "Ruby as Katakana.")] - public Bindable RubyAsKatakana { get; } = new BindableBool(); + /// + /// Generate ruby as Katakana. + /// + [ConfigSource("Ruby as Katakana", "Ruby as Katakana.")] + public Bindable RubyAsKatakana { get; } = new BindableBool(); - /// - /// Generate ruby even it's same as lyric. - /// - [ConfigSource("Enable duplicated ruby.", "Enable output duplicated ruby even it's match with lyric.")] - public Bindable EnableDuplicatedRuby { get; } = new BindableBool(); - } + /// + /// Generate ruby even it's same as lyric. + /// + [ConfigSource("Enable duplicated ruby.", "Enable output duplicated ruby even it's match with lyric.")] + public Bindable EnableDuplicatedRuby { get; } = new BindableBool(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs index 62f346bc9..50a234c60 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs @@ -4,22 +4,21 @@ using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags; + +public abstract class RubyTagGenerator : LyricPropertyGenerator + where TConfig : RubyTagGeneratorConfig, new() { - public abstract class RubyTagGenerator : LyricPropertyGenerator - where TConfig : RubyTagGeneratorConfig, new() + protected RubyTagGenerator(TConfig config) + : base(config) { - protected RubyTagGenerator(TConfig config) - : base(config) - { - } + } - protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) - { - if (string.IsNullOrWhiteSpace(item.Text)) - return "Lyric should not be empty."; + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + if (string.IsNullOrWhiteSpace(item.Text)) + return "Lyric should not be empty."; - return null; - } + return null; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorConfig.cs index 221e7e73c..910a432be 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorConfig.cs @@ -1,9 +1,8 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags; + +public abstract class RubyTagGeneratorConfig : GeneratorConfig { - public abstract class RubyTagGeneratorConfig : GeneratorConfig - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs index 564eceb49..43c1184fb 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs @@ -6,15 +6,14 @@ using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags.Ja; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags; + +public class RubyTagGeneratorSelector : LyricGeneratorSelector { - public class RubyTagGeneratorSelector : LyricGeneratorSelector + public RubyTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) + : base(generatorConfigManager) { - public RubyTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) - : base(generatorConfigManager) - { - RegisterGenerator(new CultureInfo(17)); - RegisterGenerator(new CultureInfo(1041)); - } + RegisterGenerator(new CultureInfo(17)); + RegisterGenerator(new CultureInfo(1041)); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGenerator.cs index cb1b381ba..551013f78 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGenerator.cs @@ -7,127 +7,126 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Ja +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Ja; + +public class JaTimeTagGenerator : TimeTagGenerator { - public class JaTimeTagGenerator : TimeTagGenerator + public JaTimeTagGenerator(JaTimeTagGeneratorConfig config) + : base(config) { - public JaTimeTagGenerator(JaTimeTagGeneratorConfig config) - : base(config) - { - } + } - /// - /// Thanks for RhythmKaTTE's author writing this logic into C# - /// http://juna-idler.blogspot.com/2016/05/rhythmkatte-version-01.html - /// - protected override void TimeTagLogic(Lyric lyric, List timeTags) - { - timeTags.AddRange(generateTimeTagByText(lyric.Text)); + /// + /// Thanks for RhythmKaTTE's author writing this logic into C# + /// http://juna-idler.blogspot.com/2016/05/rhythmkatte-version-01.html + /// + protected override void TimeTagLogic(Lyric lyric, List timeTags) + { + timeTags.AddRange(generateTimeTagByText(lyric.Text)); - foreach (var ruby in lyric.RubyTags) - { - // remove exist time tag - timeTags.RemoveAll(x => x.Index.Index > ruby.StartIndex && x.Index.Index < ruby.EndIndex); + foreach (var ruby in lyric.RubyTags) + { + // remove exist time tag + timeTags.RemoveAll(x => x.Index.Index > ruby.StartIndex && x.Index.Index < ruby.EndIndex); - // add new time tags created from ruby - var rubyTags = generateTimeTagByText(ruby.Text); - var shiftingTimeTags = rubyTags.Select((x, _) => new TimeTag(new TextIndex(ruby.StartIndex, x.Index.State), x.Time)); - timeTags.AddRange(shiftingTimeTags); - } + // add new time tags created from ruby + var rubyTags = generateTimeTagByText(ruby.Text); + var shiftingTimeTags = rubyTags.Select((x, _) => new TimeTag(new TextIndex(ruby.StartIndex, x.Index.State), x.Time)); + timeTags.AddRange(shiftingTimeTags); } + } + + private IEnumerable generateTimeTagByText(string text) + { + if (string.IsNullOrEmpty(text)) + yield break; - private IEnumerable generateTimeTagByText(string text) + for (int i = 1; i < text.Length; i++) { - if (string.IsNullOrEmpty(text)) - yield break; + char c = text[i]; + char pc = text[i - 1]; - for (int i = 1; i < text.Length; i++) + if (CharUtils.IsSpacing(c) && Config.CheckWhiteSpace.Value) { - char c = text[i]; - char pc = text[i - 1]; + // ignore continuous white space. + if (CharUtils.IsSpacing(pc)) + continue; + + var timeTag = Config.CheckWhiteSpaceKeyUp.Value + ? new TimeTag(new TextIndex(i - 1, TextIndex.IndexState.End)) + : new TimeTag(new TextIndex(i)); - if (CharUtils.IsSpacing(c) && Config.CheckWhiteSpace.Value) + if (CharUtils.IsLatin(pc)) { - // ignore continuous white space. - if (CharUtils.IsSpacing(pc)) - continue; - - var timeTag = Config.CheckWhiteSpaceKeyUp.Value - ? new TimeTag(new TextIndex(i - 1, TextIndex.IndexState.End)) - : new TimeTag(new TextIndex(i)); - - if (CharUtils.IsLatin(pc)) - { - if (Config.CheckWhiteSpaceAlphabet.Value) - yield return timeTag; - } - else if (char.IsDigit(pc)) - { - if (Config.CheckWhiteSpaceDigit.Value) - yield return timeTag; - } - else if (CharUtils.IsAsciiSymbol(pc)) - { - if (Config.CheckWhiteSpaceAsciiSymbol.Value) - yield return timeTag; - } - else - { + if (Config.CheckWhiteSpaceAlphabet.Value) yield return timeTag; - } } - else if (CharUtils.IsLatin(c) || char.IsNumber(c) || CharUtils.IsAsciiSymbol(c)) + else if (char.IsDigit(pc)) { - if (CharUtils.IsSpacing(pc) || (!CharUtils.IsLatin(pc) && !char.IsNumber(pc) && !CharUtils.IsAsciiSymbol(pc))) - { - yield return new TimeTag(new TextIndex(i)); - } + if (Config.CheckWhiteSpaceDigit.Value) + yield return timeTag; } - else if (CharUtils.IsSpacing(pc)) + else if (CharUtils.IsAsciiSymbol(pc)) { - yield return new TimeTag(new TextIndex(i)); + if (Config.CheckWhiteSpaceAsciiSymbol.Value) + yield return timeTag; } else { - switch (c) - { - case 'ゃ': - case 'ゅ': - case 'ょ': - case 'ャ': - case 'ュ': - case 'ョ': - case 'ぁ': - case 'ぃ': - case 'ぅ': - case 'ぇ': - case 'ぉ': - case 'ァ': - case 'ィ': - case 'ゥ': - case 'ェ': - case 'ォ': - case 'ー': - case '~': - break; - - case 'ん': - if (Config.Checkん.Value) - yield return new TimeTag(new TextIndex(i)); - - break; - - case 'っ': - if (Config.Checkっ.Value) - yield return new TimeTag(new TextIndex(i)); - - break; - - default: + yield return timeTag; + } + } + else if (CharUtils.IsLatin(c) || char.IsNumber(c) || CharUtils.IsAsciiSymbol(c)) + { + if (CharUtils.IsSpacing(pc) || (!CharUtils.IsLatin(pc) && !char.IsNumber(pc) && !CharUtils.IsAsciiSymbol(pc))) + { + yield return new TimeTag(new TextIndex(i)); + } + } + else if (CharUtils.IsSpacing(pc)) + { + yield return new TimeTag(new TextIndex(i)); + } + else + { + switch (c) + { + case 'ゃ': + case 'ゅ': + case 'ょ': + case 'ャ': + case 'ュ': + case 'ョ': + case 'ぁ': + case 'ぃ': + case 'ぅ': + case 'ぇ': + case 'ぉ': + case 'ァ': + case 'ィ': + case 'ゥ': + case 'ェ': + case 'ォ': + case 'ー': + case '~': + break; + + case 'ん': + if (Config.Checkん.Value) + yield return new TimeTag(new TextIndex(i)); + + break; + + case 'っ': + if (Config.Checkっ.Value) yield return new TimeTag(new TextIndex(i)); - break; - } + break; + + default: + yield return new TimeTag(new TextIndex(i)); + + break; } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorConfig.cs index 51488edca..c5b15f7e8 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Ja/JaTimeTagGeneratorConfig.cs @@ -4,58 +4,57 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Ja +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Ja; + +public class JaTimeTagGeneratorConfig : TimeTagGeneratorConfig { - public class JaTimeTagGeneratorConfig : TimeTagGeneratorConfig + /// + /// Add the if character is "ん" + /// + [ConfigCategory(CATEGORY_CHECK_CHARACTER)] + [ConfigSource("Check ん", "Check ん or not.")] + public Bindable Checkん { get; } = new BindableBool(true); + + /// + /// Add the if character is "っ" + /// + [ConfigCategory(CATEGORY_CHECK_CHARACTER)] + [ConfigSource("Check っ", "Check っ or not.")] + public Bindable Checkっ { get; } = new BindableBool(); + + /// + /// Add the if spacing is next of the alphabet. + /// This feature will work only if enable the + /// + [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] + [ConfigSource("Check white space alphabet", "Check white space alphabet.")] + public Bindable CheckWhiteSpaceAlphabet { get; } = new BindableBool(); + + /// + /// Add the if spacing is next of the digit. + /// This feature will work only if enable the + /// + [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] + [ConfigSource("Check white space digit", "Check white space digit.")] + public Bindable CheckWhiteSpaceDigit { get; } = new BindableBool(); + + /// + /// Add the if spacing is next of the symbol. + /// This feature will work only if enable the + /// + [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] + [ConfigSource("Check white space ascii symbol", "Check white space ascii symbol.")] + public Bindable CheckWhiteSpaceAsciiSymbol { get; } = new BindableBool(); + + public JaTimeTagGeneratorConfig() { - /// - /// Add the if character is "ん" - /// - [ConfigCategory(CATEGORY_CHECK_CHARACTER)] - [ConfigSource("Check ん", "Check ん or not.")] - public Bindable Checkん { get; } = new BindableBool(true); - - /// - /// Add the if character is "っ" - /// - [ConfigCategory(CATEGORY_CHECK_CHARACTER)] - [ConfigSource("Check っ", "Check っ or not.")] - public Bindable Checkっ { get; } = new BindableBool(); - - /// - /// Add the if spacing is next of the alphabet. - /// This feature will work only if enable the - /// - [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] - [ConfigSource("Check white space alphabet", "Check white space alphabet.")] - public Bindable CheckWhiteSpaceAlphabet { get; } = new BindableBool(); - - /// - /// Add the if spacing is next of the digit. - /// This feature will work only if enable the - /// - [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] - [ConfigSource("Check white space digit", "Check white space digit.")] - public Bindable CheckWhiteSpaceDigit { get; } = new BindableBool(); - - /// - /// Add the if spacing is next of the symbol. - /// This feature will work only if enable the - /// - [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] - [ConfigSource("Check white space ascii symbol", "Check white space ascii symbol.")] - public Bindable CheckWhiteSpaceAsciiSymbol { get; } = new BindableBool(); - - public JaTimeTagGeneratorConfig() - { - CheckLineEndKeyUp.Default = true; - CheckLineEndKeyUp.SetDefault(); - - CheckWhiteSpace.Default = true; - CheckWhiteSpace.SetDefault(); - - CheckWhiteSpaceKeyUp.Default = true; - CheckWhiteSpaceKeyUp.SetDefault(); - } + CheckLineEndKeyUp.Default = true; + CheckLineEndKeyUp.SetDefault(); + + CheckWhiteSpace.Default = true; + CheckWhiteSpace.SetDefault(); + + CheckWhiteSpaceKeyUp.Default = true; + CheckWhiteSpaceKeyUp.SetDefault(); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs index ff22e73d1..76524b76d 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs @@ -7,51 +7,50 @@ using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags; + +public abstract class TimeTagGenerator : LyricPropertyGenerator + where TConfig : TimeTagGeneratorConfig, new() { - public abstract class TimeTagGenerator : LyricPropertyGenerator - where TConfig : TimeTagGeneratorConfig, new() + protected TimeTagGenerator(TConfig config) + : base(config) { - protected TimeTagGenerator(TConfig config) - : base(config) - { - } - - protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) - { - if (string.IsNullOrEmpty(item.Text)) - return "Lyric should not be empty."; + } - return null; - } + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + if (string.IsNullOrEmpty(item.Text)) + return "Lyric should not be empty."; - protected sealed override TimeTag[] GenerateFromItem(Lyric item) - { - var timeTags = new List(); - string text = item.Text; + return null; + } - if (string.IsNullOrEmpty(text)) - return timeTags.ToArray(); + protected sealed override TimeTag[] GenerateFromItem(Lyric item) + { + var timeTags = new List(); + string text = item.Text; - if (string.IsNullOrWhiteSpace(text)) - { - if (Config.CheckBlankLine.Value) - timeTags.Add(new TimeTag(new TextIndex(0))); + if (string.IsNullOrEmpty(text)) + return timeTags.ToArray(); - return timeTags.ToArray(); - } + if (string.IsNullOrWhiteSpace(text)) + { + if (Config.CheckBlankLine.Value) + timeTags.Add(new TimeTag(new TextIndex(0))); - // create tag at start of lyric - timeTags.Add(new TimeTag(new TextIndex(0))); + return timeTags.ToArray(); + } - if (Config.CheckLineEndKeyUp.Value) - timeTags.Add(new TimeTag(new TextIndex(text.Length - 1, TextIndex.IndexState.End))); + // create tag at start of lyric + timeTags.Add(new TimeTag(new TextIndex(0))); - TimeTagLogic(item, timeTags); + if (Config.CheckLineEndKeyUp.Value) + timeTags.Add(new TimeTag(new TextIndex(text.Length - 1, TextIndex.IndexState.End))); - return timeTags.OrderBy(x => x.Index).ToArray(); - } + TimeTagLogic(item, timeTags); - protected abstract void TimeTagLogic(Lyric lyric, List timeTags); + return timeTags.OrderBy(x => x.Index).ToArray(); } + + protected abstract void TimeTagLogic(Lyric lyric, List timeTags); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorConfig.cs index 78ab8e8ff..eeeb8d537 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorConfig.cs @@ -4,41 +4,40 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags; + +public abstract class TimeTagGeneratorConfig : GeneratorConfig { - public abstract class TimeTagGeneratorConfig : GeneratorConfig - { - protected const string CATEGORY_CHECK_CHARACTER = "Character checking"; - protected const string CATEGORY_CHECK_LINE_END = "Line end checking"; - protected const string CATEGORY_CHECK_WHITE_SPACE = "White space checking"; + protected const string CATEGORY_CHECK_CHARACTER = "Character checking"; + protected const string CATEGORY_CHECK_LINE_END = "Line end checking"; + protected const string CATEGORY_CHECK_WHITE_SPACE = "White space checking"; - /// - /// Will create a at the first of the lyric if only contains spacing in the . - /// - [ConfigCategory(CATEGORY_CHECK_CHARACTER)] - [ConfigSource("Check blank line", "Check blank line or not.")] - public Bindable CheckBlankLine { get; } = new BindableBool(); + /// + /// Will create a at the first of the lyric if only contains spacing in the . + /// + [ConfigCategory(CATEGORY_CHECK_CHARACTER)] + [ConfigSource("Check blank line", "Check blank line or not.")] + public Bindable CheckBlankLine { get; } = new BindableBool(); - /// - /// Add end at the end of the . - /// - [ConfigCategory(CATEGORY_CHECK_LINE_END)] - [ConfigSource("Use key-up time tag in line end", "Use key-up time tag in line end")] - public Bindable CheckLineEndKeyUp { get; } = new BindableBool(); + /// + /// Add end at the end of the . + /// + [ConfigCategory(CATEGORY_CHECK_LINE_END)] + [ConfigSource("Use key-up time tag in line end", "Use key-up time tag in line end")] + public Bindable CheckLineEndKeyUp { get; } = new BindableBool(); - /// - /// Will add the if meet the spacing. - /// - [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] - [ConfigSource("Check white space", "Check white space")] - public Bindable CheckWhiteSpace { get; } = new BindableBool(); + /// + /// Will add the if meet the spacing. + /// + [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] + [ConfigSource("Check white space", "Check white space")] + public Bindable CheckWhiteSpace { get; } = new BindableBool(); - /// - /// Add the end instead. - /// This feature will work only if enable the . - /// - [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] - [ConfigSource("Use key-up", "Use key-up")] - public Bindable CheckWhiteSpaceKeyUp { get; } = new BindableBool(); - } + /// + /// Add the end instead. + /// This feature will work only if enable the . + /// + [ConfigCategory(CATEGORY_CHECK_WHITE_SPACE)] + [ConfigSource("Use key-up", "Use key-up")] + public Bindable CheckWhiteSpaceKeyUp { get; } = new BindableBool(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs index cd4671fd2..dd52c54ca 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs @@ -7,16 +7,15 @@ using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Zh; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags; + +public class TimeTagGeneratorSelector : LyricGeneratorSelector { - public class TimeTagGeneratorSelector : LyricGeneratorSelector + public TimeTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) + : base(generatorConfigManager) { - public TimeTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generatorConfigManager) - : base(generatorConfigManager) - { - RegisterGenerator(new CultureInfo(17)); - RegisterGenerator(new CultureInfo(1041)); - RegisterGenerator(new CultureInfo(1028)); - } + RegisterGenerator(new CultureInfo(17)); + RegisterGenerator(new CultureInfo(1041)); + RegisterGenerator(new CultureInfo(1028)); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGenerator.cs index fb795f98a..7e7e09c11 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGenerator.cs @@ -6,25 +6,24 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Zh +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Zh; + +public class ZhTimeTagGenerator : TimeTagGenerator { - public class ZhTimeTagGenerator : TimeTagGenerator + public ZhTimeTagGenerator(ZhTimeTagGeneratorConfig config) + : base(config) { - public ZhTimeTagGenerator(ZhTimeTagGeneratorConfig config) - : base(config) - { - } + } - protected override void TimeTagLogic(Lyric lyric, List timeTags) - { - string text = lyric.Text; + protected override void TimeTagLogic(Lyric lyric, List timeTags) + { + string text = lyric.Text; - for (int i = 1; i < text.Length; i++) + for (int i = 1; i < text.Length; i++) + { + if (CharUtils.IsChinese(text[i])) { - if (CharUtils.IsChinese(text[i])) - { - timeTags.Add(new TimeTag(new TextIndex(i))); - } + timeTags.Add(new TimeTag(new TextIndex(i))); } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGeneratorConfig.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGeneratorConfig.cs index bee5ed449..d53b0ee60 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGeneratorConfig.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/Zh/ZhTimeTagGeneratorConfig.cs @@ -1,9 +1,8 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Zh +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags.Zh; + +public class ZhTimeTagGeneratorConfig : TimeTagGeneratorConfig { - public class ZhTimeTagGeneratorConfig : TimeTagGeneratorConfig - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/KaraokeBeatmapVerifier.cs b/osu.Game.Rulesets.Karaoke/Edit/KaraokeBeatmapVerifier.cs index 956dfb3a7..8662a2e12 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/KaraokeBeatmapVerifier.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/KaraokeBeatmapVerifier.cs @@ -7,30 +7,29 @@ using osu.Game.Rulesets.Edit.Checks.Components; using osu.Game.Rulesets.Karaoke.Edit.Checks; -namespace osu.Game.Rulesets.Karaoke.Edit +namespace osu.Game.Rulesets.Karaoke.Edit; + +public class KaraokeBeatmapVerifier : IBeatmapVerifier { - public class KaraokeBeatmapVerifier : IBeatmapVerifier + private readonly List checks = new() { - private readonly List checks = new() - { - new CheckBeatmapAvailableTranslates(), - new CheckBeatmapClassicStageInfo(), - new CheckBeatmapNoteInfo(), - new CheckBeatmapPageInfo(), - new CheckLyricLanguage(), - new CheckLyricReferenceLyric(), - new CheckLyricRomajiTag(), - new CheckLyricRubyTag(), - new CheckLyricSinger(), - new CheckLyricText(), - new CheckLyricTime(), - new CheckLyricTimeTag(), - new CheckLyricTranslate(), - new CheckNoteReferenceLyric(), - new CheckNoteText(), - new CheckNoteTime(), - }; + new CheckBeatmapAvailableTranslates(), + new CheckBeatmapClassicStageInfo(), + new CheckBeatmapNoteInfo(), + new CheckBeatmapPageInfo(), + new CheckLyricLanguage(), + new CheckLyricReferenceLyric(), + new CheckLyricRomajiTag(), + new CheckLyricRubyTag(), + new CheckLyricSinger(), + new CheckLyricText(), + new CheckLyricTime(), + new CheckLyricTimeTag(), + new CheckLyricTranslate(), + new CheckNoteReferenceLyric(), + new CheckNoteText(), + new CheckNoteTime(), + }; - public IEnumerable Run(BeatmapVerifierContext context) => checks.SelectMany(check => check.Run(context)); - } + public IEnumerable Run(BeatmapVerifierContext context) => checks.SelectMany(check => check.Run(context)); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/KaraokeBlueprintContainer.cs b/osu.Game.Rulesets.Karaoke/Edit/KaraokeBlueprintContainer.cs index 208638d8a..708988f90 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/KaraokeBlueprintContainer.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/KaraokeBlueprintContainer.cs @@ -11,23 +11,22 @@ using osu.Game.Rulesets.Objects; using osu.Game.Screens.Edit.Compose.Components; -namespace osu.Game.Rulesets.Karaoke.Edit +namespace osu.Game.Rulesets.Karaoke.Edit; + +public partial class KaraokeBlueprintContainer : ComposeBlueprintContainer { - public partial class KaraokeBlueprintContainer : ComposeBlueprintContainer + public KaraokeBlueprintContainer(HitObjectComposer composer) + : base(composer) { - public KaraokeBlueprintContainer(HitObjectComposer composer) - : base(composer) - { - } + } - public override HitObjectSelectionBlueprint CreateHitObjectBlueprintFor(HitObject hitObject) => - hitObject switch - { - Note note => new NoteSelectionBlueprint(note), - Lyric lyric => new LyricSelectionBlueprint(lyric), - _ => throw new ArgumentOutOfRangeException(nameof(hitObject)) - }; + public override HitObjectSelectionBlueprint CreateHitObjectBlueprintFor(HitObject hitObject) => + hitObject switch + { + Note note => new NoteSelectionBlueprint(note), + Lyric lyric => new LyricSelectionBlueprint(lyric), + _ => throw new ArgumentOutOfRangeException(nameof(hitObject)) + }; - protected override SelectionHandler CreateSelectionHandler() => new KaraokeSelectionHandler(); - } + protected override SelectionHandler CreateSelectionHandler() => new KaraokeSelectionHandler(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/KaraokeEditorPlayfield.cs b/osu.Game.Rulesets.Karaoke/Edit/KaraokeEditorPlayfield.cs index 84e8479f6..e6198a84f 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/KaraokeEditorPlayfield.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/KaraokeEditorPlayfield.cs @@ -6,11 +6,10 @@ using osu.Game.Rulesets.Karaoke.UI; using osu.Game.Rulesets.Karaoke.UI.Scrolling; -namespace osu.Game.Rulesets.Karaoke.Edit +namespace osu.Game.Rulesets.Karaoke.Edit; + +public partial class KaraokeEditorPlayfield : KaraokePlayfield { - public partial class KaraokeEditorPlayfield : KaraokePlayfield - { - protected override ScrollingNotePlayfield CreateNotePlayfield(int columns) - => new EditorNotePlayfield(columns); - } + protected override ScrollingNotePlayfield CreateNotePlayfield(int columns) + => new EditorNotePlayfield(columns); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/KaraokeHitObjectComposer.cs b/osu.Game.Rulesets.Karaoke/Edit/KaraokeHitObjectComposer.cs index 8994aeeb2..de90ce209 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/KaraokeHitObjectComposer.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/KaraokeHitObjectComposer.cs @@ -32,157 +32,156 @@ using osu.Game.Screens.Edit.Compose.Components; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Edit +namespace osu.Game.Rulesets.Karaoke.Edit; + +public partial class KaraokeHitObjectComposer : HitObjectComposer { - public partial class KaraokeHitObjectComposer : HitObjectComposer - { - private DrawableKaraokeEditorRuleset drawableRuleset; + private DrawableKaraokeEditorRuleset drawableRuleset; - [Cached] - private readonly KaraokeRulesetEditConfigManager editConfigManager; + [Cached] + private readonly KaraokeRulesetEditConfigManager editConfigManager; - [Cached] - private readonly KaraokeRulesetEditGeneratorConfigManager generatorConfigManager; + [Cached] + private readonly KaraokeRulesetEditGeneratorConfigManager generatorConfigManager; - [Cached] - private readonly FontManager fontManager; + [Cached] + private readonly FontManager fontManager; - [Cached(typeof(IKaraokeBeatmapResourcesProvider))] - private KaraokeBeatmapResourcesProvider karaokeBeatmapResourcesProvider; + [Cached(typeof(IKaraokeBeatmapResourcesProvider))] + private KaraokeBeatmapResourcesProvider karaokeBeatmapResourcesProvider; - [Cached(typeof(ILyricRubyTagsChangeHandler))] - private readonly LyricRubyTagsChangeHandler lyricRubyTagsChangeHandler; + [Cached(typeof(ILyricRubyTagsChangeHandler))] + private readonly LyricRubyTagsChangeHandler lyricRubyTagsChangeHandler; - [Cached(typeof(ILyricRomajiTagsChangeHandler))] - private readonly LyricRomajiTagsChangeHandler lyricRomajiTagsChangeHandler; + [Cached(typeof(ILyricRomajiTagsChangeHandler))] + private readonly LyricRomajiTagsChangeHandler lyricRomajiTagsChangeHandler; - [Cached(typeof(INotePositionInfo))] - private readonly NotePositionInfo notePositionInfo; + [Cached(typeof(INotePositionInfo))] + private readonly NotePositionInfo notePositionInfo; - [Cached(typeof(INotesChangeHandler))] - private readonly NotesChangeHandler notesChangeHandler; + [Cached(typeof(INotesChangeHandler))] + private readonly NotesChangeHandler notesChangeHandler; - [Cached(typeof(INotePropertyChangeHandler))] - private readonly NotePropertyChangeHandler notePropertyChangeHandler; + [Cached(typeof(INotePropertyChangeHandler))] + private readonly NotePropertyChangeHandler notePropertyChangeHandler; - [Cached(typeof(ILyricSingerChangeHandler))] - private readonly LyricSingerChangeHandler lyricSingerChangeHandler; + [Cached(typeof(ILyricSingerChangeHandler))] + private readonly LyricSingerChangeHandler lyricSingerChangeHandler; - [Cached(typeof(IBeatmapSingersChangeHandler))] - private readonly BeatmapSingersChangeHandler beatmapSingersChangeHandler; + [Cached(typeof(IBeatmapSingersChangeHandler))] + private readonly BeatmapSingersChangeHandler beatmapSingersChangeHandler; - [Cached] - private readonly ExportLyricManager exportLyricManager; + [Cached] + private readonly ExportLyricManager exportLyricManager; - [Resolved] - private Editor editor { get; set; } + [Resolved] + private Editor editor { get; set; } - public KaraokeHitObjectComposer(Ruleset ruleset) - : base(ruleset) - { - editConfigManager = new KaraokeRulesetEditConfigManager(); - generatorConfigManager = new KaraokeRulesetEditGeneratorConfigManager(); - - // Duplicated registration because selection handler need to use it. - AddInternal(fontManager = new FontManager()); - AddInternal(karaokeBeatmapResourcesProvider = new KaraokeBeatmapResourcesProvider()); - - AddInternal(lyricRubyTagsChangeHandler = new LyricRubyTagsChangeHandler()); - AddInternal(lyricRomajiTagsChangeHandler = new LyricRomajiTagsChangeHandler()); - AddInternal(notePositionInfo = new NotePositionInfo()); - AddInternal(notesChangeHandler = new NotesChangeHandler()); - AddInternal(notePropertyChangeHandler = new NotePropertyChangeHandler()); - AddInternal(lyricSingerChangeHandler = new LyricSingerChangeHandler()); - AddInternal(beatmapSingersChangeHandler = new BeatmapSingersChangeHandler()); - - AddInternal(exportLyricManager = new ExportLyricManager()); - } - - [BackgroundDependencyLoader] - private void load() - { - CreateMenuBar(); - } + public KaraokeHitObjectComposer(Ruleset ruleset) + : base(ruleset) + { + editConfigManager = new KaraokeRulesetEditConfigManager(); + generatorConfigManager = new KaraokeRulesetEditGeneratorConfigManager(); + + // Duplicated registration because selection handler need to use it. + AddInternal(fontManager = new FontManager()); + AddInternal(karaokeBeatmapResourcesProvider = new KaraokeBeatmapResourcesProvider()); + + AddInternal(lyricRubyTagsChangeHandler = new LyricRubyTagsChangeHandler()); + AddInternal(lyricRomajiTagsChangeHandler = new LyricRomajiTagsChangeHandler()); + AddInternal(notePositionInfo = new NotePositionInfo()); + AddInternal(notesChangeHandler = new NotesChangeHandler()); + AddInternal(notePropertyChangeHandler = new NotePropertyChangeHandler()); + AddInternal(lyricSingerChangeHandler = new LyricSingerChangeHandler()); + AddInternal(beatmapSingersChangeHandler = new BeatmapSingersChangeHandler()); + + AddInternal(exportLyricManager = new ExportLyricManager()); + } - private DependencyContainer dependencies; + [BackgroundDependencyLoader] + private void load() + { + CreateMenuBar(); + } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + private DependencyContainer dependencies; - public new KaraokePlayfield Playfield => drawableRuleset.Playfield; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) + => dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - protected override Playfield PlayfieldAtScreenSpacePosition(Vector2 screenSpacePosition) - { - // Only note and lyric playfield can interact with mouse input. - if (Playfield.NotePlayfield.ReceivePositionalInputAt(screenSpacePosition)) - return Playfield.NotePlayfield; - if (Playfield.LyricPlayfield.ReceivePositionalInputAt(screenSpacePosition)) - return Playfield.LyricPlayfield; + public new KaraokePlayfield Playfield => drawableRuleset.Playfield; - return null; - } + protected override Playfield PlayfieldAtScreenSpacePosition(Vector2 screenSpacePosition) + { + // Only note and lyric playfield can interact with mouse input. + if (Playfield.NotePlayfield.ReceivePositionalInputAt(screenSpacePosition)) + return Playfield.NotePlayfield; + if (Playfield.LyricPlayfield.ReceivePositionalInputAt(screenSpacePosition)) + return Playfield.LyricPlayfield; - public override SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All) - { - var result = base.FindSnappedPositionAndTime(screenSpacePosition, snapType); + return null; + } - // should not affect x position and time if dragging object in note playfield. - return result.Playfield is EditorNotePlayfield - ? new SnapResult(screenSpacePosition, null, result.Playfield) - : result; - } + public override SnapResult FindSnappedPositionAndTime(Vector2 screenSpacePosition, SnapType snapType = SnapType.All) + { + var result = base.FindSnappedPositionAndTime(screenSpacePosition, snapType); - protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) - { - drawableRuleset = new DrawableKaraokeEditorRuleset(ruleset, beatmap, mods); + // should not affect x position and time if dragging object in note playfield. + return result.Playfield is EditorNotePlayfield + ? new SnapResult(screenSpacePosition, null, result.Playfield) + : result; + } - // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it - dependencies.CacheAs(drawableRuleset.ScrollingInfo); + protected override DrawableRuleset CreateDrawableRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) + { + drawableRuleset = new DrawableKaraokeEditorRuleset(ruleset, beatmap, mods); - return drawableRuleset; - } + // This is the earliest we can cache the scrolling info to ourselves, before masks are added to the hierarchy and inject it + dependencies.CacheAs(drawableRuleset.ScrollingInfo); - protected override ComposeBlueprintContainer CreateBlueprintContainer() - => new KaraokeBlueprintContainer(this); + return drawableRuleset; + } - protected void CreateMenuBar() - { - var editorMenuBar = editor.ChildrenOfType().FirstOrDefault(); - if (editorMenuBar == null) - return; + protected override ComposeBlueprintContainer CreateBlueprintContainer() + => new KaraokeBlueprintContainer(this); - Schedule(() => + protected void CreateMenuBar() + { + var editorMenuBar = editor.ChildrenOfType().FirstOrDefault(); + if (editorMenuBar == null) + return; + + Schedule(() => + { + editorMenuBar.Items = new List(editorMenuBar.Items) { - editorMenuBar.Items = new List(editorMenuBar.Items) + new("Config") { - new("Config") + Items = new MenuItem[] { - Items = new MenuItem[] - { - new NoteEditorPreviewMenu(editConfigManager, "Note editor"), - } - }, - new("Tools") + new NoteEditorPreviewMenu(editConfigManager, "Note editor"), + } + }, + new("Tools") + { + Items = new MenuItem[] { - Items = new MenuItem[] - { - new KaraokeSkinEditorMenu(editor, null, "Skin editor"), - new KaraokeEditorMenu(editor, "Karaoke editor") - } - }, - new("Debug") + new KaraokeSkinEditorMenu(editor, null, "Skin editor"), + new KaraokeEditorMenu(editor, "Karaoke editor") + } + }, + new("Debug") + { + Items = new MenuItem[] { - Items = new MenuItem[] - { - new EditorMenuItem("Export to json beatmap", MenuItemType.Destructive, () => exportLyricManager.ExportToJsonBeatmap()), - } + new EditorMenuItem("Export to json beatmap", MenuItemType.Destructive, () => exportLyricManager.ExportToJsonBeatmap()), } - }; - }); - } + } + }; + }); + } - protected override IReadOnlyList CompositionTools => Array.Empty(); + protected override IReadOnlyList CompositionTools => Array.Empty(); - protected override IEnumerable CreateTernaryButtons() => Array.Empty(); - } + protected override IEnumerable CreateTernaryButtons() => Array.Empty(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs index 78c76b7ff..6d4bd8c52 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/KaraokeSelectionHandler.cs @@ -24,128 +24,127 @@ using osu.Game.Skinning; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Edit +namespace osu.Game.Rulesets.Karaoke.Edit; + +public partial class KaraokeSelectionHandler : EditorSelectionHandler { - public partial class KaraokeSelectionHandler : EditorSelectionHandler - { - [Resolved] - private EditorBeatmap beatmap { get; set; } + [Resolved] + private EditorBeatmap beatmap { get; set; } - [Resolved] - private INotePositionInfo notePositionInfo { get; set; } + [Resolved] + private INotePositionInfo notePositionInfo { get; set; } - [Resolved] - private ISkinSource source { get; set; } + [Resolved] + private ISkinSource source { get; set; } - [Resolved] - private HitObjectComposer composer { get; set; } + [Resolved] + private HitObjectComposer composer { get; set; } - [Resolved] - private INotesChangeHandler notesChangeHandler { get; set; } + [Resolved] + private INotesChangeHandler notesChangeHandler { get; set; } - [Resolved] - private INotePropertyChangeHandler notePropertyChangeHandler { get; set; } + [Resolved] + private INotePropertyChangeHandler notePropertyChangeHandler { get; set; } - [Resolved] - private ILyricSingerChangeHandler lyricSingerChangeHandler { get; set; } + [Resolved] + private ILyricSingerChangeHandler lyricSingerChangeHandler { get; set; } - protected ScrollingNotePlayfield NotePlayfield => ((KaraokeHitObjectComposer)composer).Playfield.NotePlayfield; + protected ScrollingNotePlayfield NotePlayfield => ((KaraokeHitObjectComposer)composer).Playfield.NotePlayfield; - protected override IEnumerable GetContextMenuItemsForSelection(IEnumerable> selection) + protected override IEnumerable GetContextMenuItemsForSelection(IEnumerable> selection) + { + if (selection.All(x => x is LyricSelectionBlueprint)) { - if (selection.All(x => x is LyricSelectionBlueprint)) - { - return new[] - { - createSingerMenuItem() - }; - } - - if (EditorBeatmap.SelectedHitObjects.All(x => x is Note) - && EditorBeatmap.SelectedHitObjects.Count > 1) + return new[] { - var menu = new List(); - var selectedObject = EditorBeatmap.SelectedHitObjects.Cast().OrderBy(x => x.StartTime).ToArray(); + createSingerMenuItem() + }; + } - // Set multi note display property - menu.Add(createMultiNoteDisplayPropertyMenuItem(selectedObject)); + if (EditorBeatmap.SelectedHitObjects.All(x => x is Note) + && EditorBeatmap.SelectedHitObjects.Count > 1) + { + var menu = new List(); + var selectedObject = EditorBeatmap.SelectedHitObjects.Cast().OrderBy(x => x.StartTime).ToArray(); - // Combine multi note if they has same start and end index. - var firstObject = selectedObject.FirstOrDefault(); - if (firstObject != null && selectedObject.All(x => x.ReferenceTimeTagIndex == firstObject.ReferenceTimeTagIndex)) - menu.Add(createCombineNoteMenuItem()); + // Set multi note display property + menu.Add(createMultiNoteDisplayPropertyMenuItem(selectedObject)); - return menu; - } + // Combine multi note if they has same start and end index. + var firstObject = selectedObject.FirstOrDefault(); + if (firstObject != null && selectedObject.All(x => x.ReferenceTimeTagIndex == firstObject.ReferenceTimeTagIndex)) + menu.Add(createCombineNoteMenuItem()); - return new List(); + return menu; } - private MenuItem createMultiNoteDisplayPropertyMenuItem(IReadOnlyCollection selectedObject) - { - bool display = selectedObject.Count(x => x.Display) >= selectedObject.Count(x => !x.Display); - string displayText = display ? "Hide" : "Show"; - return new OsuMenuItem($"{displayText} {selectedObject.Count} notes.", display ? MenuItemType.Destructive : MenuItemType.Standard, - () => - { - notePropertyChangeHandler.ChangeDisplayState(!display); - }); - } + return new List(); + } - private MenuItem createCombineNoteMenuItem() - { - return new OsuMenuItem("Combine", MenuItemType.Standard, () => + private MenuItem createMultiNoteDisplayPropertyMenuItem(IReadOnlyCollection selectedObject) + { + bool display = selectedObject.Count(x => x.Display) >= selectedObject.Count(x => !x.Display); + string displayText = display ? "Hide" : "Show"; + return new OsuMenuItem($"{displayText} {selectedObject.Count} notes.", display ? MenuItemType.Destructive : MenuItemType.Standard, + () => { - notesChangeHandler.Combine(); + notePropertyChangeHandler.ChangeDisplayState(!display); }); - } + } - private MenuItem createSingerMenuItem() + private MenuItem createCombineNoteMenuItem() + { + return new OsuMenuItem("Combine", MenuItemType.Standard, () => { - return new SingerContextMenu(beatmap, lyricSingerChangeHandler, "Singer"); - } + notesChangeHandler.Combine(); + }); + } - public override bool HandleMovement(MoveSelectionEvent moveEvent) - { - // Only note can be moved. - if (moveEvent.Blueprint is not NoteSelectionBlueprint noteSelectionBlueprint) - return false; + private MenuItem createSingerMenuItem() + { + return new SingerContextMenu(beatmap, lyricSingerChangeHandler, "Singer"); + } - var lastTone = noteSelectionBlueprint.HitObject.Tone; - performColumnMovement(lastTone, moveEvent); + public override bool HandleMovement(MoveSelectionEvent moveEvent) + { + // Only note can be moved. + if (moveEvent.Blueprint is not NoteSelectionBlueprint noteSelectionBlueprint) + return false; - return true; - } + var lastTone = noteSelectionBlueprint.HitObject.Tone; + performColumnMovement(lastTone, moveEvent); - private void performColumnMovement(Tone lastTone, MoveSelectionEvent moveEvent) - { - if (moveEvent.Blueprint is not NoteSelectionBlueprint) - return; + return true; + } - var calculator = notePositionInfo.Calculator; + private void performColumnMovement(Tone lastTone, MoveSelectionEvent moveEvent) + { + if (moveEvent.Blueprint is not NoteSelectionBlueprint) + return; - // get center position - var screenSpacePosition = moveEvent.Blueprint.ScreenSpaceSelectionPoint + moveEvent.ScreenSpaceDelta; - var position = NotePlayfield.ToLocalSpace(screenSpacePosition); - var centerPosition = new Vector2(position.X, position.Y - NotePlayfield.Height / 2); + var calculator = notePositionInfo.Calculator; - // get delta position - float lastCenterPosition = calculator.YPositionAt(lastTone); - float delta = centerPosition.Y - lastCenterPosition; + // get center position + var screenSpacePosition = moveEvent.Blueprint.ScreenSpaceSelectionPoint + moveEvent.ScreenSpaceDelta; + var position = NotePlayfield.ToLocalSpace(screenSpacePosition); + var centerPosition = new Vector2(position.X, position.Y - NotePlayfield.Height / 2); - // get offset tone. - const float trigger_height = ScrollingNotePlayfield.COLUMN_SPACING + DefaultColumnBackground.COLUMN_HEIGHT; - var offset = delta switch - { - > trigger_height => -new Tone { Half = true }, - < 0 => new Tone { Half = true }, - _ => default - }; + // get delta position + float lastCenterPosition = calculator.YPositionAt(lastTone); + float delta = centerPosition.Y - lastCenterPosition; - if (offset == default(Tone)) - return; + // get offset tone. + const float trigger_height = ScrollingNotePlayfield.COLUMN_SPACING + DefaultColumnBackground.COLUMN_HEIGHT; + var offset = delta switch + { + > trigger_height => -new Tone { Half = true }, + < 0 => new Tone { Half = true }, + _ => default + }; - notePropertyChangeHandler.OffsetTone(offset); - } + if (offset == default(Tone)) + return; + + notePropertyChangeHandler.OffsetTone(offset); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledSingerList.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledSingerList.cs index b063e3a13..7de576c0e 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledSingerList.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/LabelledSingerList.cs @@ -7,23 +7,22 @@ using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; -namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components +namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components; + +public partial class LabelledSingerList : LabelledDrawable { - public partial class LabelledSingerList : LabelledDrawable + public LabelledSingerList() + : base(true) { - public LabelledSingerList() - : base(true) - { - } - - public BindableList Singers => Component.Singers; + } - public string SingerNamePrefix - { - get => Component.SingerNamePrefix; - set => Component.SingerNamePrefix = value; - } + public BindableList Singers => Component.Singers; - protected override SingerList CreateComponent() => new(); + public string SingerNamePrefix + { + get => Component.SingerNamePrefix; + set => Component.SingerNamePrefix = value; } + + protected override SingerList CreateComponent() => new(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerDisplay.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerDisplay.cs index 6077e0805..1d180b2ce 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerDisplay.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerDisplay.cs @@ -20,114 +20,113 @@ using osu.Game.Rulesets.Karaoke.Utils; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components +namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components; + +/// +/// A component which displays a singer along with related description text. +/// +public partial class SingerDisplay : CompositeDrawable, IHasCurrentValue { /// - /// A component which displays a singer along with related description text. + /// Invoked when the user has requested the singer corresponding to this + /// to be removed from its palette. /// - public partial class SingerDisplay : CompositeDrawable, IHasCurrentValue - { - /// - /// Invoked when the user has requested the singer corresponding to this - /// to be removed from its palette. - /// - public event Action DeleteRequested; + public event Action DeleteRequested; - private readonly BindableWithCurrent current = new(); + private readonly BindableWithCurrent current = new(); - private OsuSpriteText singerName; + private OsuSpriteText singerName; - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } - [BackgroundDependencyLoader] - private void load() - { - AutoSizeAxes = Axes.Y; - Width = 100; + [BackgroundDependencyLoader] + private void load() + { + AutoSizeAxes = Axes.Y; + Width = 100; - InternalChild = new FillFlowContainer + InternalChild = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 10), - Children = new Drawable[] + new SingerCircle { - new SingerCircle - { - Current = { BindTarget = Current }, - DeleteRequested = () => DeleteRequested?.Invoke(this) - }, - singerName = new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - } + Current = { BindTarget = Current }, + DeleteRequested = () => DeleteRequested?.Invoke(this) + }, + singerName = new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre } - }; + } + }; - Current.BindValueChanged(singer => singerName.Text = singer.NewValue?.Name, true); - } + Current.BindValueChanged(singer => singerName.Text = singer.NewValue?.Name, true); + } - private partial class SingerCircle : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip - { - public Bindable Current { get; } = new(); + private partial class SingerCircle : OsuClickableContainer, IHasContextMenu, IHasCustomTooltip + { + public Bindable Current { get; } = new(); - public Action DeleteRequested { get; set; } + public Action DeleteRequested { get; set; } - private readonly DrawableSingerAvatar singerAvatar; + private readonly DrawableSingerAvatar singerAvatar; - [Resolved] - private OsuColour colours { get; set; } + [Resolved] + private OsuColour colours { get; set; } - public SingerCircle() + public SingerCircle() + { + RelativeSizeAxes = Axes.X; + Height = 100; + CornerRadius = 50; + Masking = true; + BorderThickness = 5; + Action = () => { - RelativeSizeAxes = Axes.X; - Height = 100; - CornerRadius = 50; - Masking = true; - BorderThickness = 5; - Action = () => - { - // todo: show edit singer dialog. - }; + // todo: show edit singer dialog. + }; - Children = new Drawable[] + Children = new Drawable[] + { + singerAvatar = new DrawableSingerAvatar { - singerAvatar = new DrawableSingerAvatar - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - } - }; - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + } + }; + } - protected override void LoadComplete() - { - base.LoadComplete(); + protected override void LoadComplete() + { + base.LoadComplete(); - Current.BindValueChanged(_ => updateSinger(), true); - } + Current.BindValueChanged(_ => updateSinger(), true); + } - private void updateSinger() - { - BorderColour = SingerUtils.GetContentColour(Current.Value); - singerAvatar.Singer = Current.Value; - } + private void updateSinger() + { + BorderColour = SingerUtils.GetContentColour(Current.Value); + singerAvatar.Singer = Current.Value; + } - public MenuItem[] ContextMenuItems => new MenuItem[] - { - new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteRequested?.Invoke()) - }; + public MenuItem[] ContextMenuItems => new MenuItem[] + { + new OsuMenuItem("Delete", MenuItemType.Destructive, () => DeleteRequested?.Invoke()) + }; - public ITooltip GetCustomTooltip() => new SingerToolTip(); + public ITooltip GetCustomTooltip() => new SingerToolTip(); - public Singer TooltipContent => Current.Value; - } + public Singer TooltipContent => Current.Value; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerList.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerList.cs index 050a223cf..3970c26f7 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerList.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/Components/SingerList.cs @@ -19,174 +19,173 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components +namespace osu.Game.Rulesets.Karaoke.Edit.Setup.Components; + +/// +/// A component which displays a collection of singers in individual s. +/// +public partial class SingerList : CompositeDrawable { - /// - /// A component which displays a collection of singers in individual s. - /// - public partial class SingerList : CompositeDrawable - { - public BindableList Singers { get; } = new(); + public BindableList Singers { get; } = new(); - private string singerNamePrefix = "Singer"; + private string singerNamePrefix = "Singer"; - public string SingerNamePrefix + public string SingerNamePrefix + { + get => singerNamePrefix; + set { - get => singerNamePrefix; - set - { - if (singerNamePrefix == value) - return; + if (singerNamePrefix == value) + return; - singerNamePrefix = value; + singerNamePrefix = value; - if (IsLoaded) - reindexItems(); - } + if (IsLoaded) + reindexItems(); } + } - private FillFlowContainer singers; + private FillFlowContainer singers; - private IEnumerable singerDisplays => singers.OfType(); + private IEnumerable singerDisplays => singers.OfType(); - [BackgroundDependencyLoader] - private void load() + [BackgroundDependencyLoader] + private void load() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + AutoSizeDuration = fade_duration; + AutoSizeEasing = Easing.OutQuint; + + InternalChild = singers = new FillFlowContainer { - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - AutoSizeDuration = fade_duration; - AutoSizeEasing = Easing.OutQuint; + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10), + Direction = FillDirection.Full + }; + } - InternalChild = singers = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(10), - Direction = FillDirection.Full - }; - } + protected override void LoadComplete() + { + base.LoadComplete(); - protected override void LoadComplete() + Singers.BindCollectionChanged((_, args) => { - base.LoadComplete(); + if (args.Action != NotifyCollectionChangedAction.Replace) + updateSingers(); + }, true); + FinishTransforms(true); + } - Singers.BindCollectionChanged((_, args) => - { - if (args.Action != NotifyCollectionChangedAction.Replace) - updateSingers(); - }, true); - FinishTransforms(true); - } + private const int fade_duration = 200; - private const int fade_duration = 200; + private void updateSingers() + { + singers.Clear(); - private void updateSingers() + for (int i = 0; i < Singers.Count; ++i) { - singers.Clear(); + // copy to avoid accesses to modified closure. + int singerIndex = i; + SingerDisplay display; - for (int i = 0; i < Singers.Count; ++i) + singers.Add(display = new SingerDisplay { - // copy to avoid accesses to modified closure. - int singerIndex = i; - SingerDisplay display; - - singers.Add(display = new SingerDisplay - { - Current = { Value = Singers[singerIndex] } - }); + Current = { Value = Singers[singerIndex] } + }); - // todo : might check does this like works because singer is object. - display.Current.BindValueChanged(singer => Singers[singerIndex] = singer.NewValue); - display.DeleteRequested += singerDeletionRequested; - } + // todo : might check does this like works because singer is object. + display.Current.BindValueChanged(singer => Singers[singerIndex] = singer.NewValue); + display.DeleteRequested += singerDeletionRequested; + } - singers.Add(new AddSingerButton + singers.Add(new AddSingerButton + { + // todo : use better way to create singer with right id. + Action = () => Singers.Add(new Singer { - // todo : use better way to create singer with right id. - Action = () => Singers.Add(new Singer - { - Name = "New singer" - }) - }); + Name = "New singer" + }) + }); - reindexItems(); - } + reindexItems(); + } - // todo : might have dialog to ask should delete singer or not if contains lyric. - private void singerDeletionRequested(SingerDisplay display) => Singers.RemoveAt(singers.IndexOf(display)); + // todo : might have dialog to ask should delete singer or not if contains lyric. + private void singerDeletionRequested(SingerDisplay display) => Singers.RemoveAt(singers.IndexOf(display)); - private void reindexItems() - { - int index = 1; + private void reindexItems() + { + int index = 1; - foreach (var singerDisplay in singerDisplays) - { - // todo : might call singer manager to update singer id? - index += 1; - } + foreach (var singerDisplay in singerDisplays) + { + // todo : might call singer manager to update singer id? + index += 1; } + } - internal partial class AddSingerButton : CompositeDrawable + internal partial class AddSingerButton : CompositeDrawable + { + public Action Action { - public Action Action - { - set => circularButton.Action = value; - } + set => circularButton.Action = value; + } - private readonly OsuClickableContainer circularButton; + private readonly OsuClickableContainer circularButton; - public AddSingerButton() - { - AutoSizeAxes = Axes.Y; - Width = 100; + public AddSingerButton() + { + AutoSizeAxes = Axes.Y; + Width = 100; - InternalChild = new FillFlowContainer + InternalChild = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 10), - Children = new Drawable[] + circularButton = new OsuClickableContainer { - circularButton = new OsuClickableContainer + RelativeSizeAxes = Axes.X, + Height = 100, + CornerRadius = 50, + Masking = true, + BorderThickness = 5, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = 100, - CornerRadius = 50, - Masking = true, - BorderThickness = 5, - Children = new Drawable[] + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.Transparent, + AlwaysPresent = true + }, + new SpriteIcon { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Colour4.Transparent, - AlwaysPresent = true - }, - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(20), - Icon = FontAwesome.Solid.Plus - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(20), + Icon = FontAwesome.Solid.Plus } - }, - new OsuSpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "New" } + }, + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "New" } - }; - } + } + }; + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - circularButton.BorderColour = colours.BlueDarker; - } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + circularButton.BorderColour = colours.BlueDarker; } } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSetupSection.cs b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSetupSection.cs index fd88f7f3e..8a9b41a5c 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSetupSection.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Setup/KaraokeSetupSection.cs @@ -11,52 +11,51 @@ using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Screens.Edit.Setup; -namespace osu.Game.Rulesets.Karaoke.Edit.Setup +namespace osu.Game.Rulesets.Karaoke.Edit.Setup; + +public partial class KaraokeSetupSection : RulesetSetupSection { - public partial class KaraokeSetupSection : RulesetSetupSection - { - private KaraokeBeatmap karaokeBeatmap => EditorBeatmapUtils.GetPlayableBeatmap(Beatmap); + private KaraokeBeatmap karaokeBeatmap => EditorBeatmapUtils.GetPlayableBeatmap(Beatmap); - private LabelledSwitchButton scorable; - private LabelledSingerList singerList; + private LabelledSwitchButton scorable; + private LabelledSingerList singerList; - public KaraokeSetupSection() - : base(new KaraokeRuleset().RulesetInfo) - { - } + public KaraokeSetupSection() + : base(new KaraokeRuleset().RulesetInfo) + { + } - [BackgroundDependencyLoader] - private void load() + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] { - Children = new Drawable[] + scorable = new LabelledSwitchButton { - scorable = new LabelledSwitchButton - { - Label = "Scorable", - Description = "Will not show score playfield if the option is unchecked.", - Current = { Value = true } - }, - singerList = new LabelledSingerList - { - Label = "Singer list", - Description = "All the singers in beatmap.", - FixedLabelWidth = LABEL_WIDTH, - SingerNamePrefix = "#" - } - }; - } - - protected override void LoadComplete() - { - base.LoadComplete(); + Label = "Scorable", + Description = "Will not show score playfield if the option is unchecked.", + Current = { Value = true } + }, + singerList = new LabelledSingerList + { + Label = "Singer list", + Description = "All the singers in beatmap.", + FixedLabelWidth = LABEL_WIDTH, + SingerNamePrefix = "#" + } + }; + } - scorable.Current.BindValueChanged(_ => updateBeatmap()); - } + protected override void LoadComplete() + { + base.LoadComplete(); - private void updateBeatmap() - { - // todo: update the value. - // karaokeBeatmap.Scorable = scorable.Current.Value; - } + scorable.Current.BindValueChanged(_ => updateBeatmap()); + } + + private void updateBeatmap() + { + // todo: update the value. + // karaokeBeatmap.Scorable = scorable.Current.Value; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Utils/EditorBeatmapUtils.cs b/osu.Game.Rulesets.Karaoke/Edit/Utils/EditorBeatmapUtils.cs index 438820ec9..f84ca7f0b 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Utils/EditorBeatmapUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Utils/EditorBeatmapUtils.cs @@ -8,22 +8,21 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.Utils +namespace osu.Game.Rulesets.Karaoke.Edit.Utils; + +public static class EditorBeatmapUtils { - public static class EditorBeatmapUtils - { - public static IEnumerable GetAllReferenceLyrics(EditorBeatmap editorBeatmap, Lyric referencedLyric) - => editorBeatmap.HitObjects.OfType().Where(x => x.ReferenceLyric == referencedLyric); + public static IEnumerable GetAllReferenceLyrics(EditorBeatmap editorBeatmap, Lyric referencedLyric) + => editorBeatmap.HitObjects.OfType().Where(x => x.ReferenceLyric == referencedLyric); - public static IEnumerable GetNotesByLyric(EditorBeatmap editorBeatmap, Lyric lyric) - => editorBeatmap.HitObjects.OfType().Where(x => x.ReferenceLyric == lyric); + public static IEnumerable GetNotesByLyric(EditorBeatmap editorBeatmap, Lyric lyric) + => editorBeatmap.HitObjects.OfType().Where(x => x.ReferenceLyric == lyric); - public static KaraokeBeatmap GetPlayableBeatmap(EditorBeatmap editorBeatmap) - { - if (editorBeatmap.PlayableBeatmap is not KaraokeBeatmap karaokeBeatmap) - throw new InvalidCastException(); + public static KaraokeBeatmap GetPlayableBeatmap(EditorBeatmap editorBeatmap) + { + if (editorBeatmap.PlayableBeatmap is not KaraokeBeatmap karaokeBeatmap) + throw new InvalidCastException(); - return karaokeBeatmap; - } + return karaokeBeatmap; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Utils/HitObjectWritableUtils.cs b/osu.Game.Rulesets.Karaoke/Edit/Utils/HitObjectWritableUtils.cs index f0965e12c..66e8002fc 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Utils/HitObjectWritableUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Utils/HitObjectWritableUtils.cs @@ -7,202 +7,201 @@ using osu.Game.Rulesets.Karaoke.Objects.Properties; using osu.Game.Rulesets.Karaoke.Objects.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.Utils +namespace osu.Game.Rulesets.Karaoke.Edit.Utils; + +public static class HitObjectWritableUtils { - public static class HitObjectWritableUtils - { - #region Remove lyrics. + #region Remove lyrics. - public static bool IsRemoveLyricLocked(Lyric lyric) - => GetRemoveLyricLockedBy(lyric) != null; + public static bool IsRemoveLyricLocked(Lyric lyric) + => GetRemoveLyricLockedBy(lyric) != null; - public static LockLyricPropertyBy? GetRemoveLyricLockedBy(Lyric lyric) - { - bool lockedByState = isRemoveLyricLockedByState(lyric.Lock); - if (lockedByState) - return LockLyricPropertyBy.LockState; + public static LockLyricPropertyBy? GetRemoveLyricLockedBy(Lyric lyric) + { + bool lockedByState = isRemoveLyricLockedByState(lyric.Lock); + if (lockedByState) + return LockLyricPropertyBy.LockState; - return null; - } + return null; + } - private static bool isRemoveLyricLockedByState(LockState lockState) - => lockState != LockState.None; + private static bool isRemoveLyricLockedByState(LockState lockState) + => lockState != LockState.None; - #endregion + #endregion - #region Lyric property + #region Lyric property - public static bool IsWriteLyricPropertyLocked(Lyric lyric, params string[] propertyNames) - => GetLyricPropertyLockedBy(lyric, propertyNames) != null; + public static bool IsWriteLyricPropertyLocked(Lyric lyric, params string[] propertyNames) + => GetLyricPropertyLockedBy(lyric, propertyNames) != null; - public static bool IsWriteLyricPropertyLocked(Lyric lyric, string propertyName) - => GetLyricPropertyLockedBy(lyric, propertyName) != null; + public static bool IsWriteLyricPropertyLocked(Lyric lyric, string propertyName) + => GetLyricPropertyLockedBy(lyric, propertyName) != null; - public static LockLyricPropertyBy? GetLyricPropertyLockedBy(Lyric lyric, params string[] propertyNames) - { - var reasons = propertyNames.Select(x => GetLyricPropertyLockedBy(lyric, x)) - .Where(x => x != null) - .OfType() - .ToArray(); + public static LockLyricPropertyBy? GetLyricPropertyLockedBy(Lyric lyric, params string[] propertyNames) + { + var reasons = propertyNames.Select(x => GetLyricPropertyLockedBy(lyric, x)) + .Where(x => x != null) + .OfType() + .ToArray(); - if (reasons.Contains(LockLyricPropertyBy.ReferenceLyricConfig)) - return LockLyricPropertyBy.ReferenceLyricConfig; + if (reasons.Contains(LockLyricPropertyBy.ReferenceLyricConfig)) + return LockLyricPropertyBy.ReferenceLyricConfig; - if (reasons.Contains(LockLyricPropertyBy.LockState)) - return LockLyricPropertyBy.LockState; + if (reasons.Contains(LockLyricPropertyBy.LockState)) + return LockLyricPropertyBy.LockState; - return null; - } + return null; + } - public static LockLyricPropertyBy? GetLyricPropertyLockedBy(Lyric lyric, string propertyName) - { - bool lockedByConfig = isWriteLyricPropertyLockedByConfig(lyric.ReferenceLyricConfig, propertyName); - if (lockedByConfig) - return LockLyricPropertyBy.ReferenceLyricConfig; + public static LockLyricPropertyBy? GetLyricPropertyLockedBy(Lyric lyric, string propertyName) + { + bool lockedByConfig = isWriteLyricPropertyLockedByConfig(lyric.ReferenceLyricConfig, propertyName); + if (lockedByConfig) + return LockLyricPropertyBy.ReferenceLyricConfig; - bool lockedByState = isWriteLyricPropertyLockedByState(lyric.Lock, propertyName); - if (lockedByState) - return LockLyricPropertyBy.LockState; + bool lockedByState = isWriteLyricPropertyLockedByState(lyric.Lock, propertyName); + if (lockedByState) + return LockLyricPropertyBy.LockState; - return null; - } + return null; + } - private static bool isWriteLyricPropertyLockedByState(LockState lockState, string propertyName) + private static bool isWriteLyricPropertyLockedByState(LockState lockState, string propertyName) + { + // partial lock will only lock some property change like texting because they are easy to be modified. + // fully lock will basically lock all lyric properties. + return propertyName switch { - // partial lock will only lock some property change like texting because they are easy to be modified. - // fully lock will basically lock all lyric properties. - return propertyName switch + nameof(Lyric.ID) => false, // although the id is not changeable, but it's not locked by config. + nameof(Lyric.Text) => lockState > LockState.None, + nameof(Lyric.TimeTags) => lockState > LockState.None, + nameof(Lyric.RubyTags) => lockState > LockState.None, + nameof(Lyric.RomajiTags) => lockState > LockState.None, + nameof(Lyric.StartTime) => lockState > LockState.Partial, + nameof(Lyric.Duration) => lockState > LockState.Partial, + nameof(Lyric.SingerIds) => lockState > LockState.Partial, + nameof(Lyric.Translates) => lockState > LockState.Partial, + nameof(Lyric.Language) => lockState > LockState.Partial, + nameof(Lyric.Order) => false, // order can always be changed. + nameof(Lyric.Lock) => false, // order can always be changed. + nameof(Lyric.ReferenceLyric) or nameof(Lyric.ReferenceLyricId) => lockState > LockState.Partial, + nameof(Lyric.ReferenceLyricConfig) => lockState > LockState.Partial, + // base class + nameof(Lyric.Samples) => false, + _ => throw new NotSupportedException() + }; + } + + private static bool isWriteLyricPropertyLockedByConfig(IReferenceLyricPropertyConfig? config, string propertyName) + { + return config switch + { + ReferenceLyricConfig => false, + SyncLyricConfig syncLyricConfig => propertyName switch { nameof(Lyric.ID) => false, // although the id is not changeable, but it's not locked by config. - nameof(Lyric.Text) => lockState > LockState.None, - nameof(Lyric.TimeTags) => lockState > LockState.None, - nameof(Lyric.RubyTags) => lockState > LockState.None, - nameof(Lyric.RomajiTags) => lockState > LockState.None, - nameof(Lyric.StartTime) => lockState > LockState.Partial, - nameof(Lyric.Duration) => lockState > LockState.Partial, - nameof(Lyric.SingerIds) => lockState > LockState.Partial, - nameof(Lyric.Translates) => lockState > LockState.Partial, - nameof(Lyric.Language) => lockState > LockState.Partial, - nameof(Lyric.Order) => false, // order can always be changed. - nameof(Lyric.Lock) => false, // order can always be changed. - nameof(Lyric.ReferenceLyric) or nameof(Lyric.ReferenceLyricId) => lockState > LockState.Partial, - nameof(Lyric.ReferenceLyricConfig) => lockState > LockState.Partial, + nameof(Lyric.Text) => true, + nameof(Lyric.TimeTags) => syncLyricConfig.SyncTimeTagProperty, + nameof(Lyric.RubyTags) => true, + nameof(Lyric.RomajiTags) => true, + nameof(Lyric.StartTime) => false, + nameof(Lyric.Duration) => false, + nameof(Lyric.SingerIds) => syncLyricConfig.SyncSingerProperty, + nameof(Lyric.Translates) => true, + nameof(Lyric.Language) => true, + nameof(Lyric.Order) => true, + nameof(Lyric.Lock) => true, + nameof(Lyric.ReferenceLyric) or nameof(Lyric.ReferenceLyricId) => false, + nameof(Lyric.ReferenceLyricConfig) => false, // base class nameof(Lyric.Samples) => false, _ => throw new NotSupportedException() - }; - } - - private static bool isWriteLyricPropertyLockedByConfig(IReferenceLyricPropertyConfig? config, string propertyName) - { - return config switch - { - ReferenceLyricConfig => false, - SyncLyricConfig syncLyricConfig => propertyName switch - { - nameof(Lyric.ID) => false, // although the id is not changeable, but it's not locked by config. - nameof(Lyric.Text) => true, - nameof(Lyric.TimeTags) => syncLyricConfig.SyncTimeTagProperty, - nameof(Lyric.RubyTags) => true, - nameof(Lyric.RomajiTags) => true, - nameof(Lyric.StartTime) => false, - nameof(Lyric.Duration) => false, - nameof(Lyric.SingerIds) => syncLyricConfig.SyncSingerProperty, - nameof(Lyric.Translates) => true, - nameof(Lyric.Language) => true, - nameof(Lyric.Order) => true, - nameof(Lyric.Lock) => true, - nameof(Lyric.ReferenceLyric) or nameof(Lyric.ReferenceLyricId) => false, - nameof(Lyric.ReferenceLyricConfig) => false, - // base class - nameof(Lyric.Samples) => false, - _ => throw new NotSupportedException() - }, - null => false, - _ => throw new NotSupportedException() - }; - } - - #endregion - - #region Create or remove notes. - - public static bool IsCreateOrRemoveNoteLocked(Lyric lyric) - => GetCreateOrRemoveNoteLockedBy(lyric) != null; - - public static LockLyricPropertyBy? GetCreateOrRemoveNoteLockedBy(Lyric lyric) - { - bool lockedByConfig = isCreateOrRemoveNoteLocked(lyric.ReferenceLyricConfig); - if (lockedByConfig) - return LockLyricPropertyBy.ReferenceLyricConfig; - - return null; - } + }, + null => false, + _ => throw new NotSupportedException() + }; + } - private static bool isCreateOrRemoveNoteLocked(IReferenceLyricPropertyConfig? config) - { - // todo: implementation. - return config switch - { - ReferenceLyricConfig => false, - SyncLyricConfig => true, - null => false, - _ => throw new NotSupportedException() - }; - } + #endregion - #endregion + #region Create or remove notes. - #region Note property + public static bool IsCreateOrRemoveNoteLocked(Lyric lyric) + => GetCreateOrRemoveNoteLockedBy(lyric) != null; - public static bool IsWriteNotePropertyLocked(Note note, params string[] propertyNames) - => GetNotePropertyLockedBy(note, propertyNames) != null; + public static LockLyricPropertyBy? GetCreateOrRemoveNoteLockedBy(Lyric lyric) + { + bool lockedByConfig = isCreateOrRemoveNoteLocked(lyric.ReferenceLyricConfig); + if (lockedByConfig) + return LockLyricPropertyBy.ReferenceLyricConfig; - public static bool IsWriteNotePropertyLocked(Note note, string propertyName) - => GetNotePropertyLockedBy(note, propertyName) != null; + return null; + } - public static LockNotePropertyBy? GetNotePropertyLockedBy(Note note, params string[] propertyNames) + private static bool isCreateOrRemoveNoteLocked(IReferenceLyricPropertyConfig? config) + { + // todo: implementation. + return config switch { - var reasons = propertyNames.Select(x => GetNotePropertyLockedBy(note, x)) - .Where(x => x != null) - .OfType() - .ToArray(); + ReferenceLyricConfig => false, + SyncLyricConfig => true, + null => false, + _ => throw new NotSupportedException() + }; + } - if (reasons.Contains(LockNotePropertyBy.ReferenceLyricConfig)) - return LockNotePropertyBy.ReferenceLyricConfig; + #endregion - return null; - } + #region Note property - public static LockNotePropertyBy? GetNotePropertyLockedBy(Note note, string propertyName) - { - var lyric = note.ReferenceLyric; + public static bool IsWriteNotePropertyLocked(Note note, params string[] propertyNames) + => GetNotePropertyLockedBy(note, propertyNames) != null; - bool lockByReferenceLyricConfig = lyric != null && isWriteNotePropertyLockedByReferenceLyric(lyric, propertyName); - if (lockByReferenceLyricConfig) - return LockNotePropertyBy.ReferenceLyricConfig; + public static bool IsWriteNotePropertyLocked(Note note, string propertyName) + => GetNotePropertyLockedBy(note, propertyName) != null; - return null; - } + public static LockNotePropertyBy? GetNotePropertyLockedBy(Note note, params string[] propertyNames) + { + var reasons = propertyNames.Select(x => GetNotePropertyLockedBy(note, x)) + .Where(x => x != null) + .OfType() + .ToArray(); - private static bool isWriteNotePropertyLockedByReferenceLyric(Lyric lyric, string propertyName) - { - // todo: implement. - return false; - } + if (reasons.Contains(LockNotePropertyBy.ReferenceLyricConfig)) + return LockNotePropertyBy.ReferenceLyricConfig; - #endregion + return null; } - public enum LockLyricPropertyBy + public static LockNotePropertyBy? GetNotePropertyLockedBy(Note note, string propertyName) { - ReferenceLyricConfig, + var lyric = note.ReferenceLyric; + + bool lockByReferenceLyricConfig = lyric != null && isWriteNotePropertyLockedByReferenceLyric(lyric, propertyName); + if (lockByReferenceLyricConfig) + return LockNotePropertyBy.ReferenceLyricConfig; - LockState, + return null; } - public enum LockNotePropertyBy + private static bool isWriteNotePropertyLockedByReferenceLyric(Lyric lyric, string propertyName) { - ReferenceLyricConfig, + // todo: implement. + return false; } + + #endregion +} + +public enum LockLyricPropertyBy +{ + ReferenceLyricConfig, + + LockState, +} + +public enum LockNotePropertyBy +{ + ReferenceLyricConfig, } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Utils/LockStateUtils.cs b/osu.Game.Rulesets.Karaoke/Edit/Utils/LockStateUtils.cs index d9ad24e14..394a632d4 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Utils/LockStateUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Utils/LockStateUtils.cs @@ -5,11 +5,10 @@ using System.Linq; using osu.Game.Rulesets.Karaoke.Objects.Types; -namespace osu.Game.Rulesets.Karaoke.Edit.Utils +namespace osu.Game.Rulesets.Karaoke.Edit.Utils; + +public static class LockStateUtils { - public static class LockStateUtils - { - public static TLock[] FindUnlockObjects(IEnumerable objects) where TLock : IHasLock - => objects.Where(x => x.Lock == LockState.None).ToArray(); - } + public static TLock[] FindUnlockObjects(IEnumerable objects) where TLock : IHasLock + => objects.Where(x => x.Lock == LockState.None).ToArray(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Utils/ValueChangedEventUtils.cs b/osu.Game.Rulesets.Karaoke/Edit/Utils/ValueChangedEventUtils.cs index 1978aaf08..2bf9f0880 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Utils/ValueChangedEventUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Utils/ValueChangedEventUtils.cs @@ -5,24 +5,23 @@ using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics; using osu.Game.Rulesets.Karaoke.Screens.Edit.Beatmaps.Lyrics.CaretPosition; -namespace osu.Game.Rulesets.Karaoke.Edit.Utils +namespace osu.Game.Rulesets.Karaoke.Edit.Utils; + +public static class ValueChangedEventUtils { - public static class ValueChangedEventUtils + public static bool LyricChanged(ValueChangedEvent e) { - public static bool LyricChanged(ValueChangedEvent e) - { - var oldLyric = e.OldValue?.Lyric; - var newLyric = e.NewValue?.Lyric; + var oldLyric = e.OldValue?.Lyric; + var newLyric = e.NewValue?.Lyric; - return oldLyric != newLyric; - } + return oldLyric != newLyric; + } - public static bool EditModeChanged(ValueChangedEvent e) - { - if (e.OldValue.Default ^ e.NewValue.Default) - return true; + public static bool EditModeChanged(ValueChangedEvent e) + { + if (e.OldValue.Default ^ e.NewValue.Default) + return true; - return e.OldValue.Mode != e.NewValue.Mode; - } + return e.OldValue.Mode != e.NewValue.Mode; } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Utils/ZoomableScrollContainerUtils.cs b/osu.Game.Rulesets.Karaoke/Edit/Utils/ZoomableScrollContainerUtils.cs index 8bd46bbda..000ed5c85 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Utils/ZoomableScrollContainerUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Utils/ZoomableScrollContainerUtils.cs @@ -6,11 +6,10 @@ using System; using osu.Game.Screens.Edit; -namespace osu.Game.Rulesets.Karaoke.Edit.Utils +namespace osu.Game.Rulesets.Karaoke.Edit.Utils; + +public static class ZoomableScrollContainerUtils { - public static class ZoomableScrollContainerUtils - { - public static float GetZoomLevelForVisibleMilliseconds(EditorClock editorClock, double milliseconds) - => Math.Max(1, (float)(editorClock.TrackLength / milliseconds)); - } + public static float GetZoomLevelForVisibleMilliseconds(EditorClock editorClock, double milliseconds) + => Math.Max(1, (float)(editorClock.TrackLength / milliseconds)); } diff --git a/osu.Game.Rulesets.Karaoke/Extensions/EnumerableExtensions.cs b/osu.Game.Rulesets.Karaoke/Extensions/EnumerableExtensions.cs index dc086055a..fd8ba693f 100644 --- a/osu.Game.Rulesets.Karaoke/Extensions/EnumerableExtensions.cs +++ b/osu.Game.Rulesets.Karaoke/Extensions/EnumerableExtensions.cs @@ -5,64 +5,63 @@ using System.Collections.Generic; using System.Linq; -namespace osu.Game.Rulesets.Karaoke.Extensions +namespace osu.Game.Rulesets.Karaoke.Extensions; + +public static class EnumerableExtensions { - public static class EnumerableExtensions + /// + /// Retrieves the item after a pivot from an . + /// + /// The type of the items stored in the collection. + /// The collection to iterate on. + /// The pivot value. + /// Match action + /// The item in appearing after , or null if no such item exists. + public static T? GetNextMatch(this IEnumerable collection, T pivot, Func action) where T : notnull { - /// - /// Retrieves the item after a pivot from an . - /// - /// The type of the items stored in the collection. - /// The collection to iterate on. - /// The pivot value. - /// Match action - /// The item in appearing after , or null if no such item exists. - public static T? GetNextMatch(this IEnumerable collection, T pivot, Func action) where T : notnull - { - return collection.SkipWhile(i => !EqualityComparer.Default.Equals(i, pivot)).Skip(1).SkipWhile(x => !action(x)).FirstOrDefault(); - } + return collection.SkipWhile(i => !EqualityComparer.Default.Equals(i, pivot)).Skip(1).SkipWhile(x => !action(x)).FirstOrDefault(); + } - /// - /// Retrieves the item before a pivot from an . - /// - /// The type of the items stored in the collection. - /// The collection to iterate on. - /// The pivot value. - /// Match action - /// The item in appearing before , or null if no such item exists. - public static T? GetPreviousMatch(this IEnumerable collection, T pivot, Func action) where T : notnull - { - return collection.Reverse().SkipWhile(i => !EqualityComparer.Default.Equals(i, pivot)).Skip(1).SkipWhile(x => !action(x)).FirstOrDefault(); - } + /// + /// Retrieves the item before a pivot from an . + /// + /// The type of the items stored in the collection. + /// The collection to iterate on. + /// The pivot value. + /// Match action + /// The item in appearing before , or null if no such item exists. + public static T? GetPreviousMatch(this IEnumerable collection, T pivot, Func action) where T : notnull + { + return collection.Reverse().SkipWhile(i => !EqualityComparer.Default.Equals(i, pivot)).Skip(1).SkipWhile(x => !action(x)).FirstOrDefault(); + } - /// - /// Convert [][] to [,] - /// - /// - /// - /// - public static T[,] To2DArray(this IEnumerable> source) - { - var data = source - .Select(x => x.ToArray()) - .ToArray(); + /// + /// Convert [][] to [,] + /// + /// + /// + /// + public static T[,] To2DArray(this IEnumerable> source) + { + var data = source + .Select(x => x.ToArray()) + .ToArray(); - var res = new T[data.Length, data.Max(x => x.Length)]; + var res = new T[data.Length, data.Max(x => x.Length)]; - for (int i = 0; i < data.Length; ++i) + for (int i = 0; i < data.Length; ++i) + { + for (int j = 0; j < data[i].Length; ++j) { - for (int j = 0; j < data[i].Length; ++j) - { - res[i, j] = data[i][j]; - } + res[i, j] = data[i][j]; } - - return res; } - public static int IndexOf(this IEnumerable array, T value) - { - return array.ToList().IndexOf(value); - } + return res; + } + + public static int IndexOf(this IEnumerable array, T value) + { + return array.ToList().IndexOf(value); } } diff --git a/osu.Game.Rulesets.Karaoke/Extensions/ListExtensions.cs b/osu.Game.Rulesets.Karaoke/Extensions/ListExtensions.cs index 62b1458ac..220ae0924 100644 --- a/osu.Game.Rulesets.Karaoke/Extensions/ListExtensions.cs +++ b/osu.Game.Rulesets.Karaoke/Extensions/ListExtensions.cs @@ -3,16 +3,15 @@ using System.Collections.Generic; -namespace osu.Game.Rulesets.Karaoke.Extensions +namespace osu.Game.Rulesets.Karaoke.Extensions; + +public static class ListExtensions { - public static class ListExtensions + public static void AddRangeWithNullCheck(this List collection, IEnumerable? newValue) { - public static void AddRangeWithNullCheck(this List collection, IEnumerable? newValue) - { - if (newValue == null) - return; + if (newValue == null) + return; - collection.AddRange(newValue); - } + collection.AddRange(newValue); } } diff --git a/osu.Game.Rulesets.Karaoke/Extensions/OsuGameExtensions.cs b/osu.Game.Rulesets.Karaoke/Extensions/OsuGameExtensions.cs index 89ffe2c2a..8d2924168 100644 --- a/osu.Game.Rulesets.Karaoke/Extensions/OsuGameExtensions.cs +++ b/osu.Game.Rulesets.Karaoke/Extensions/OsuGameExtensions.cs @@ -8,32 +8,31 @@ using osu.Game.Overlays; using osu.Game.Screens; -namespace osu.Game.Rulesets.Karaoke.Extensions +namespace osu.Game.Rulesets.Karaoke.Extensions; + +/// +/// Collect dirty logic to get target drawable from +/// +public static class OsuGameExtensions { - /// - /// Collect dirty logic to get target drawable from - /// - public static class OsuGameExtensions + public static KaraokeRuleset? GetRuleset(this DependencyContainer dependencies) { - public static KaraokeRuleset? GetRuleset(this DependencyContainer dependencies) - { - var rulesets = dependencies.Get().AvailableRulesets.Select(info => info.CreateInstance()); - return rulesets.FirstOrDefault(r => r is KaraokeRuleset) as KaraokeRuleset; - } + var rulesets = dependencies.Get().AvailableRulesets.Select(info => info.CreateInstance()); + return rulesets.FirstOrDefault(r => r is KaraokeRuleset) as KaraokeRuleset; + } - private static Container? getBasePlacementContainer(this OsuGame game) - => game.Children[3] as Container; + private static Container? getBasePlacementContainer(this OsuGame game) + => game.Children[3] as Container; - public static Container? GetChangelogPlacementContainer(this OsuGame game) - { - // will place the container with same location like WikiOverlay. - return game.getBasePlacementContainer()?.Children[0] as Container; - } + public static Container? GetChangelogPlacementContainer(this OsuGame game) + { + // will place the container with same location like WikiOverlay. + return game.getBasePlacementContainer()?.Children[0] as Container; + } - public static SettingsOverlay? GetSettingsOverlay(this OsuGame game) - => game.getBasePlacementContainer()?.ChildrenOfType().FirstOrDefault(); + public static SettingsOverlay? GetSettingsOverlay(this OsuGame game) + => game.getBasePlacementContainer()?.ChildrenOfType().FirstOrDefault(); - public static OsuScreenStack? GetScreenStack(this OsuGame game) - => ((game.Children[3] as Container)?.Child as Container)?.Children.OfType().FirstOrDefault(); - } + public static OsuScreenStack? GetScreenStack(this OsuGame game) + => ((game.Children[3] as Container)?.Child as Container)?.Children.OfType().FirstOrDefault(); } diff --git a/osu.Game.Rulesets.Karaoke/Extensions/RegexExtensions.cs b/osu.Game.Rulesets.Karaoke/Extensions/RegexExtensions.cs index cbbcd1efb..dd8a21e33 100644 --- a/osu.Game.Rulesets.Karaoke/Extensions/RegexExtensions.cs +++ b/osu.Game.Rulesets.Karaoke/Extensions/RegexExtensions.cs @@ -4,16 +4,15 @@ using System.Text.RegularExpressions; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Extensions +namespace osu.Game.Rulesets.Karaoke.Extensions; + +public static class RegexExtensions { - public static class RegexExtensions + public static TType GetGroupValue(this Match match, string key, bool useDefaultValueIfEmpty = true) { - public static TType GetGroupValue(this Match match, string key, bool useDefaultValueIfEmpty = true) - { - string value = match.Groups[key].Value; + string value = match.Groups[key].Value; - // if got empty value, should change to null. - return TypeUtils.ChangeType(string.IsNullOrEmpty(value) ? null : value)!; - } + // if got empty value, should change to null. + return TypeUtils.ChangeType(string.IsNullOrEmpty(value) ? null : value)!; } } diff --git a/osu.Game.Rulesets.Karaoke/Extensions/TrickyCompositeDrawableExtension.cs b/osu.Game.Rulesets.Karaoke/Extensions/TrickyCompositeDrawableExtension.cs index c00e9b52f..543ca20cf 100644 --- a/osu.Game.Rulesets.Karaoke/Extensions/TrickyCompositeDrawableExtension.cs +++ b/osu.Game.Rulesets.Karaoke/Extensions/TrickyCompositeDrawableExtension.cs @@ -6,25 +6,24 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -namespace osu.Game.Rulesets.Karaoke.Extensions +namespace osu.Game.Rulesets.Karaoke.Extensions; + +/// +/// It's a tricky extension to get all non-public methods. +/// Should be removed eventually. +/// +public static class TrickyCompositeDrawableExtension { - /// - /// It's a tricky extension to get all non-public methods. - /// Should be removed eventually. - /// - public static class TrickyCompositeDrawableExtension + public static IReadOnlyList? GetInternalChildren(this CompositeDrawable compositeDrawable) { - public static IReadOnlyList? GetInternalChildren(this CompositeDrawable compositeDrawable) - { - // see this shit to access internal property. - // https://stackoverflow.com/a/7575615/4105113 - var prop = compositeDrawable.GetType().GetProperty("InternalChildren", BindingFlags.Instance | - BindingFlags.NonPublic | - BindingFlags.Public); - if (prop == null) - return null; + // see this shit to access internal property. + // https://stackoverflow.com/a/7575615/4105113 + var prop = compositeDrawable.GetType().GetProperty("InternalChildren", BindingFlags.Instance | + BindingFlags.NonPublic | + BindingFlags.Public); + if (prop == null) + return null; - return (IReadOnlyList)prop.GetValue(compositeDrawable)!; - } + return (IReadOnlyList)prop.GetValue(compositeDrawable)!; } } diff --git a/osu.Game.Rulesets.Karaoke/Extensions/TypeExtensions.cs b/osu.Game.Rulesets.Karaoke/Extensions/TypeExtensions.cs index d59dae18f..1f9f0fdf6 100644 --- a/osu.Game.Rulesets.Karaoke/Extensions/TypeExtensions.cs +++ b/osu.Game.Rulesets.Karaoke/Extensions/TypeExtensions.cs @@ -4,28 +4,27 @@ using System; using System.Linq; -namespace osu.Game.Rulesets.Karaoke.Extensions +namespace osu.Game.Rulesets.Karaoke.Extensions; + +public static class TypeExtensions { - public static class TypeExtensions + /// + /// Returns 's + /// with the assembly version, culture and public key token values removed. + /// + /// + /// This method is usually used in extensibility scenarios (i.e. for custom rulesets or skins) + /// when a version-agnostic identifier associated with a C# class - potentially originating from + /// an external assembly - is needed. + /// Leaving only the type and assembly names in such a scenario allows to preserve compatibility + /// across assembly versions. + /// + public static string GetInvariantInstantiationInfo(this Type type) { - /// - /// Returns 's - /// with the assembly version, culture and public key token values removed. - /// - /// - /// This method is usually used in extensibility scenarios (i.e. for custom rulesets or skins) - /// when a version-agnostic identifier associated with a C# class - potentially originating from - /// an external assembly - is needed. - /// Leaving only the type and assembly names in such a scenario allows to preserve compatibility - /// across assembly versions. - /// - public static string GetInvariantInstantiationInfo(this Type type) - { - string? assemblyQualifiedName = type.AssemblyQualifiedName; - if (assemblyQualifiedName == null) - throw new ArgumentException($"{type}'s assembly-qualified name is null. Ensure that it is a concrete type and not a generic type parameter.", nameof(type)); + string? assemblyQualifiedName = type.AssemblyQualifiedName; + if (assemblyQualifiedName == null) + throw new ArgumentException($"{type}'s assembly-qualified name is null. Ensure that it is a concrete type and not a generic type parameter.", nameof(type)); - return string.Join(',', assemblyQualifiedName.Split(',').Take(2)); - } + return string.Join(',', assemblyQualifiedName.Split(',').Take(2)); } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Containers/MessageContainer.cs b/osu.Game.Rulesets.Karaoke/Graphics/Containers/MessageContainer.cs index 687edbeb7..7a7830dc7 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Containers/MessageContainer.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Containers/MessageContainer.cs @@ -10,56 +10,55 @@ using osu.Game.Graphics.Containers; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Graphics.Containers +namespace osu.Game.Rulesets.Karaoke.Graphics.Containers; + +public partial class MessageContainer : OsuTextFlowContainer { - public partial class MessageContainer : OsuTextFlowContainer - { - [Resolved] - private OsuColour colours { get; set; } + [Resolved] + private OsuColour colours { get; set; } - public MessageContainer(Action defaultCreationParameters = null) - : base(defaultCreationParameters) - { - } + public MessageContainer(Action defaultCreationParameters = null) + : base(defaultCreationParameters) + { + } - public void AddSuccessParagraph(string text, Action creationParameters = null) + public void AddSuccessParagraph(string text, Action creationParameters = null) + { + NewParagraph(); + AddIcon(FontAwesome.Solid.Check, icon => { - NewParagraph(); - AddIcon(FontAwesome.Solid.Check, icon => - { - icon.Colour = colours.Green; - }); - AddText($" {text}", creationParameters); - } + icon.Colour = colours.Green; + }); + AddText($" {text}", creationParameters); + } - public void AddWarningParagraph(string text, Action creationParameters = null) + public void AddWarningParagraph(string text, Action creationParameters = null) + { + NewParagraph(); + AddIcon(FontAwesome.Solid.ExclamationTriangle, icon => { - NewParagraph(); - AddIcon(FontAwesome.Solid.ExclamationTriangle, icon => - { - icon.Colour = colours.Yellow; - icon.Scale = new Vector2(0.9f); - }); - AddText($" {text}", creationParameters); - } + icon.Colour = colours.Yellow; + icon.Scale = new Vector2(0.9f); + }); + AddText($" {text}", creationParameters); + } - public void AddAlertParagraph(string text, Action creationParameters = null) + public void AddAlertParagraph(string text, Action creationParameters = null) + { + NewParagraph(); + AddIcon(FontAwesome.Solid.TimesCircle, icon => { - NewParagraph(); - AddIcon(FontAwesome.Solid.TimesCircle, icon => - { - icon.Colour = colours.Red; - }); - AddText($" {text}", creationParameters); - } + icon.Colour = colours.Red; + }); + AddText($" {text}", creationParameters); + } - public void AddHighlightText(string text, Action creationParameters = null) + public void AddHighlightText(string text, Action creationParameters = null) + { + AddText($" {text}", c => { - AddText($" {text}", c => - { - c.Colour = colours.Yellow; - creationParameters?.Invoke(c); - }); - } + c.Colour = colours.Yellow; + creationParameters?.Invoke(c); + }); } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Containers/OrderRearrangeableListContainer.cs b/osu.Game.Rulesets.Karaoke/Graphics/Containers/OrderRearrangeableListContainer.cs index 156336b5a..576ab1cb0 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Containers/OrderRearrangeableListContainer.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Containers/OrderRearrangeableListContainer.cs @@ -10,74 +10,73 @@ using osu.Game.Graphics.Containers; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Graphics.Containers +namespace osu.Game.Rulesets.Karaoke.Graphics.Containers; + +public abstract partial class OrderRearrangeableListContainer : OsuRearrangeableListContainer { - public abstract partial class OrderRearrangeableListContainer : OsuRearrangeableListContainer - { - public event Action OnOrderChanged; + public event Action OnOrderChanged; - protected abstract Vector2 Spacing { get; } + protected abstract Vector2 Spacing { get; } - protected OrderRearrangeableListContainer() - { - // this collection change event cannot directly register in parent bindable. - // So register in here. - Items.CollectionChanged += collectionChanged; - } + protected OrderRearrangeableListContainer() + { + // this collection change event cannot directly register in parent bindable. + // So register in here. + Items.CollectionChanged += collectionChanged; + } - private void collectionChanged(object sender, NotifyCollectionChangedEventArgs e) + private void collectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) { - switch (e.Action) - { - // should get the event if user change the position. - case NotifyCollectionChangedAction.Move: - var item = (TModel)e.NewItems[0]; - int newIndex = e.NewStartingIndex; - OnOrderChanged?.Invoke(item, newIndex); - break; - } + // should get the event if user change the position. + case NotifyCollectionChangedAction.Move: + var item = (TModel)e.NewItems[0]; + int newIndex = e.NewStartingIndex; + OnOrderChanged?.Invoke(item, newIndex); + break; } + } - protected override FillFlowContainer> CreateListFillFlowContainer() - => base.CreateListFillFlowContainer().With(x => x.Spacing = Spacing); + protected override FillFlowContainer> CreateListFillFlowContainer() + => base.CreateListFillFlowContainer().With(x => x.Spacing = Spacing); - private bool displayBottomDrawable; - private Drawable bottomDrawable; + private bool displayBottomDrawable; + private Drawable bottomDrawable; - public bool DisplayBottomDrawable + public bool DisplayBottomDrawable + { + get => displayBottomDrawable; + set { - get => displayBottomDrawable; - set + if (displayBottomDrawable == value) + return; + + displayBottomDrawable = value; + + if (displayBottomDrawable) { - if (displayBottomDrawable == value) + bottomDrawable = CreateBottomDrawable(); + if (bottomDrawable == null) return; - displayBottomDrawable = value; - - if (displayBottomDrawable) - { - bottomDrawable = CreateBottomDrawable(); - if (bottomDrawable == null) - return; - - bottomDrawable.Anchor |= Anchor.y2; - bottomDrawable.Origin |= Anchor.y2; - - // because scroll container only follow list container size, so change the margin to let content bigger. - ListContainer.Margin = new MarginPadding { Bottom = bottomDrawable.Height + Spacing.Y }; - ScrollContainer.Add(bottomDrawable); - } - else - { - if (bottomDrawable == null) - return; - - ListContainer.Margin = new MarginPadding(); - ScrollContainer.Remove(bottomDrawable, true); - } + bottomDrawable.Anchor |= Anchor.y2; + bottomDrawable.Origin |= Anchor.y2; + + // because scroll container only follow list container size, so change the margin to let content bigger. + ListContainer.Margin = new MarginPadding { Bottom = bottomDrawable.Height + Spacing.Y }; + ScrollContainer.Add(bottomDrawable); } - } + else + { + if (bottomDrawable == null) + return; - protected virtual Drawable CreateBottomDrawable() => null; + ListContainer.Margin = new MarginPadding(); + ScrollContainer.Remove(bottomDrawable, true); + } + } } + + protected virtual Drawable CreateBottomDrawable() => null; } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Cursor/BackgroundToolTip.cs b/osu.Game.Rulesets.Karaoke/Graphics/Cursor/BackgroundToolTip.cs index baf3c0eeb..442de9a12 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Cursor/BackgroundToolTip.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Cursor/BackgroundToolTip.cs @@ -11,56 +11,55 @@ using osu.Game.Graphics; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Graphics.Cursor +namespace osu.Game.Rulesets.Karaoke.Graphics.Cursor; + +public abstract partial class BackgroundToolTip : VisibilityContainer, ITooltip { - public abstract partial class BackgroundToolTip : VisibilityContainer, ITooltip - { - protected const int BORDER = 5; + protected const int BORDER = 5; - private readonly Box background; - private readonly Container content; + private readonly Box background; + private readonly Container content; - protected override Container Content => content; + protected override Container Content => content; - protected virtual float ContentPadding => 10; + protected virtual float ContentPadding => 10; - protected BackgroundToolTip() - { - AutoSizeAxes = Axes.Both; - Masking = true; - CornerRadius = BORDER; + protected BackgroundToolTip() + { + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = BORDER; - InternalChildren = new[] + InternalChildren = new[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + SetBackground(), + content = new Container { - background = new Box - { - RelativeSizeAxes = Axes.Both - }, - SetBackground(), - content = new Container - { - AutoSizeAxes = Axes.Both, - AutoSizeDuration = 200, - AutoSizeEasing = Easing.OutQuint, - Padding = new MarginPadding(ContentPadding) - } - }; - } + AutoSizeAxes = Axes.Both, + AutoSizeDuration = 200, + AutoSizeEasing = Easing.OutQuint, + Padding = new MarginPadding(ContentPadding) + } + }; + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Gray3; - } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray3; + } - public abstract void SetContent(T content); + public abstract void SetContent(T content); - protected virtual Drawable SetBackground() => Empty(); + protected virtual Drawable SetBackground() => Empty(); - public void Move(Vector2 pos) => Position = pos; + public void Move(Vector2 pos) => Position = pos; - protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); + protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); - protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); - } + protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Cursor/LyricToolTip.cs b/osu.Game.Rulesets.Karaoke/Graphics/Cursor/LyricToolTip.cs index 7645b1084..1eebc0bd2 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Cursor/LyricToolTip.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Cursor/LyricToolTip.cs @@ -8,26 +8,25 @@ using osu.Game.Rulesets.Karaoke.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.Graphics.Cursor +namespace osu.Game.Rulesets.Karaoke.Graphics.Cursor; + +public partial class LyricTooltip : BackgroundToolTip { - public partial class LyricTooltip : BackgroundToolTip - { - private Lyric lastLyric; + private Lyric lastLyric; - public override void SetContent(Lyric lyric) - { - if (lyric == lastLyric) - return; + public override void SetContent(Lyric lyric) + { + if (lyric == lastLyric) + return; - lastLyric = lyric; + lastLyric = lyric; - Child = new DrawableLyricSpriteText(lyric) - { - Margin = new MarginPadding(10), - Font = new FontUsage(size: 32), - RubyFont = new FontUsage(size: 12), - RomajiFont = new FontUsage(size: 12) - }; - } + Child = new DrawableLyricSpriteText(lyric) + { + Margin = new MarginPadding(10), + Font = new FontUsage(size: 32), + RubyFont = new FontUsage(size: 12), + RomajiFont = new FontUsage(size: 12) + }; } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Cursor/SingerToolTip.cs b/osu.Game.Rulesets.Karaoke/Graphics/Cursor/SingerToolTip.cs index 75d01d48f..79333e302 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Cursor/SingerToolTip.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Cursor/SingerToolTip.cs @@ -17,147 +17,146 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.Graphics.Cursor +namespace osu.Game.Rulesets.Karaoke.Graphics.Cursor; + +public partial class SingerToolTip : BackgroundToolTip { - public partial class SingerToolTip : BackgroundToolTip - { - private const int avatar_size = 60; - private const int main_text_size = 24; - private const int sub_text_size = 12; + private const int avatar_size = 60; + private const int main_text_size = 24; + private const int sub_text_size = 12; - private readonly IBindable bindableName = new Bindable(); - private readonly IBindable bindableRomajiName = new Bindable(); - private readonly IBindable bindableEnglishName = new Bindable(); - private readonly IBindable bindableDescription = new Bindable(); + private readonly IBindable bindableName = new Bindable(); + private readonly IBindable bindableRomajiName = new Bindable(); + private readonly IBindable bindableEnglishName = new Bindable(); + private readonly IBindable bindableDescription = new Bindable(); - [Cached(typeof(IKaraokeBeatmapResourcesProvider))] - private KaraokeBeatmapResourcesProvider karaokeBeatmapResourcesProvider; + [Cached(typeof(IKaraokeBeatmapResourcesProvider))] + private KaraokeBeatmapResourcesProvider karaokeBeatmapResourcesProvider; - private readonly DrawableSingerAvatar avatar; - private readonly OsuSpriteText singerName; - private readonly OsuSpriteText singerEnglishName; - private readonly OsuSpriteText singerRomajiName; - private readonly OsuSpriteText singerDescription; + private readonly DrawableSingerAvatar avatar; + private readonly OsuSpriteText singerName; + private readonly OsuSpriteText singerEnglishName; + private readonly OsuSpriteText singerRomajiName; + private readonly OsuSpriteText singerDescription; - public SingerToolTip() - { - // we need to inject this provide in the tooltip because in will need in the drawable singer avatar. - // and it's not able to get in the BDL due to tooltip container is in the osu.game level. - AddInternal(karaokeBeatmapResourcesProvider = new KaraokeBeatmapResourcesProvider()); + public SingerToolTip() + { + // we need to inject this provide in the tooltip because in will need in the drawable singer avatar. + // and it's not able to get in the BDL due to tooltip container is in the osu.game level. + AddInternal(karaokeBeatmapResourcesProvider = new KaraokeBeatmapResourcesProvider()); - Child = new FillFlowContainer + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + Width = 300, + Direction = FillDirection.Vertical, + Spacing = new Vector2(15), + Children = new Drawable[] { - AutoSizeAxes = Axes.Y, - Width = 300, - Direction = FillDirection.Vertical, - Spacing = new Vector2(15), - Children = new Drawable[] + new GridContainer { - new GridContainer + Name = "Basic info", + RelativeSizeAxes = Axes.X, + Height = avatar_size, + ColumnDimensions = new[] { - Name = "Basic info", - RelativeSizeAxes = Axes.X, - Height = avatar_size, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Absolute, avatar_size), - new Dimension(), - }, - Content = new[] + new Dimension(GridSizeMode.Absolute, avatar_size), + new Dimension(), + }, + Content = new[] + { + new Drawable[] { - new Drawable[] + avatar = new DrawableSingerAvatar { - avatar = new DrawableSingerAvatar - { - Name = "Avatar", - Size = new Vector2(avatar_size), - }, - new Container + Name = "Avatar", + Size = new Vector2(avatar_size), + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = 5 }, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Left = 5 }, - Children = new Drawable[] + new FillFlowContainer { - new FillFlowContainer + Name = "Singer name", + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(1), + Children = new[] { - Name = "Singer name", - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(1), - Children = new[] + singerName = new OsuSpriteText { - singerName = new OsuSpriteText - { - Name = "Singer name", - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: main_text_size), - RelativeSizeAxes = Axes.X, - Truncate = true, - }, - singerRomajiName = new OsuSpriteText - { - Name = "Romaji name", - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: sub_text_size), - RelativeSizeAxes = Axes.X, - Truncate = true, - }, - } - }, - singerEnglishName = new OsuSpriteText - { - Name = "English name", - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: sub_text_size), - RelativeSizeAxes = Axes.X, - Truncate = true, + Name = "Singer name", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: main_text_size), + RelativeSizeAxes = Axes.X, + Truncate = true, + }, + singerRomajiName = new OsuSpriteText + { + Name = "Romaji name", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: sub_text_size), + RelativeSizeAxes = Axes.X, + Truncate = true, + }, } + }, + singerEnglishName = new OsuSpriteText + { + Name = "English name", + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: sub_text_size), + RelativeSizeAxes = Axes.X, + Truncate = true, } } } } - }, - singerDescription = new OsuSpriteText - { - RelativeSizeAxes = Axes.X, - AllowMultiline = true, - Colour = Color4.White.Opacity(0.75f), - Font = OsuFont.Default.With(size: 14), - Name = "Description", } + }, + singerDescription = new OsuSpriteText + { + RelativeSizeAxes = Axes.X, + AllowMultiline = true, + Colour = Color4.White.Opacity(0.75f), + Font = OsuFont.Default.With(size: 14), + Name = "Description", } - }; + } + }; - bindableName.BindValueChanged(e => singerName.Text = e.NewValue, true); - bindableRomajiName.BindValueChanged(e => singerRomajiName.Text = string.IsNullOrEmpty(e.NewValue) ? string.Empty : $"({e.NewValue})", true); - bindableEnglishName.BindValueChanged(e => singerEnglishName.Text = e.NewValue, true); - bindableDescription.BindValueChanged(e => singerDescription.Text = string.IsNullOrEmpty(e.NewValue) ? "" : e.NewValue, true); - } + bindableName.BindValueChanged(e => singerName.Text = e.NewValue, true); + bindableRomajiName.BindValueChanged(e => singerRomajiName.Text = string.IsNullOrEmpty(e.NewValue) ? string.Empty : $"({e.NewValue})", true); + bindableEnglishName.BindValueChanged(e => singerEnglishName.Text = e.NewValue, true); + bindableDescription.BindValueChanged(e => singerDescription.Text = string.IsNullOrEmpty(e.NewValue) ? "" : e.NewValue, true); + } - private ISinger lastSinger; + private ISinger lastSinger; - public override void SetContent(ISinger singer) - { - if (singer == lastSinger) - return; + public override void SetContent(ISinger singer) + { + if (singer == lastSinger) + return; - avatar.Singer = singer; + avatar.Singer = singer; - lastSinger = singer; + lastSinger = singer; - // todo: other type of singer(e.g: sub-singer) might display different info. - if (singer is not Singer s) - return; + // todo: other type of singer(e.g: sub-singer) might display different info. + if (singer is not Singer s) + return; - bindableName.UnbindBindings(); - bindableRomajiName.UnbindBindings(); - bindableEnglishName.UnbindBindings(); - bindableDescription.UnbindBindings(); + bindableName.UnbindBindings(); + bindableRomajiName.UnbindBindings(); + bindableEnglishName.UnbindBindings(); + bindableDescription.UnbindBindings(); - bindableName.BindTo(s.NameBindable); - bindableRomajiName.BindTo(s.RomajiNameBindable); - bindableEnglishName.BindTo(s.EnglishNameBindable); - bindableDescription.BindTo(s.DescriptionBindable); - } + bindableName.BindTo(s.NameBindable); + bindableRomajiName.BindTo(s.RomajiNameBindable); + bindableEnglishName.BindTo(s.EnglishNameBindable); + bindableDescription.BindTo(s.DescriptionBindable); } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Overlays/Dialog/OkPopupDialog.cs b/osu.Game.Rulesets.Karaoke/Graphics/Overlays/Dialog/OkPopupDialog.cs index 9246a3e8a..649d50dfc 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Overlays/Dialog/OkPopupDialog.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Overlays/Dialog/OkPopupDialog.cs @@ -6,20 +6,19 @@ using System; using osu.Game.Overlays.Dialog; -namespace osu.Game.Rulesets.Karaoke.Graphics.Overlays.Dialog +namespace osu.Game.Rulesets.Karaoke.Graphics.Overlays.Dialog; + +public partial class OkPopupDialog : PopupDialog { - public partial class OkPopupDialog : PopupDialog + public OkPopupDialog(Action okAction = null) { - public OkPopupDialog(Action okAction = null) + Buttons = new PopupDialogButton[] { - Buttons = new PopupDialogButton[] + new PopupDialogOkButton { - new PopupDialogOkButton - { - Text = @"OK", - Action = () => okAction?.Invoke(true), - }, - }; - } + Text = @"OK", + Action = () => okAction?.Invoke(true), + }, + }; } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Shapes/CornerBackground.cs b/osu.Game.Rulesets.Karaoke/Graphics/Shapes/CornerBackground.cs index 37885877c..ead951bfa 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Shapes/CornerBackground.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Shapes/CornerBackground.cs @@ -7,15 +7,14 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -namespace osu.Game.Rulesets.Karaoke.Graphics.Shapes +namespace osu.Game.Rulesets.Karaoke.Graphics.Shapes; + +public partial class CornerBackground : CompositeDrawable { - public partial class CornerBackground : CompositeDrawable + public CornerBackground() { - public CornerBackground() - { - Masking = true; - CornerRadius = 5; - AddInternal(new Box { RelativeSizeAxes = Axes.Both }); - } + Masking = true; + CornerRadius = 5; + AddInternal(new Box { RelativeSizeAxes = Axes.Both }); } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Shapes/RightTriangle.cs b/osu.Game.Rulesets.Karaoke/Graphics/Shapes/RightTriangle.cs index 12a52e79a..cc0a434ee 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Shapes/RightTriangle.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Shapes/RightTriangle.cs @@ -9,104 +9,103 @@ using osu.Framework.Graphics.Sprites; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Graphics.Shapes +namespace osu.Game.Rulesets.Karaoke.Graphics.Shapes; + +public partial class RightTriangle : Sprite { - public partial class RightTriangle : Sprite + /// + /// Creates a new right triangle with a white pixel as texture. + /// + public RightTriangle() { - /// - /// Creates a new right triangle with a white pixel as texture. - /// - public RightTriangle() - { - // Setting the texture would normally set a size of (1, 1), but since the texture is set from BDL it needs to be set here instead. - // RelativeSizeAxes may not behave as expected if this is not done. - Size = Vector2.One; - } + // Setting the texture would normally set a size of (1, 1), but since the texture is set from BDL it needs to be set here instead. + // RelativeSizeAxes may not behave as expected if this is not done. + Size = Vector2.One; + } - [BackgroundDependencyLoader] - private void load(IRenderer renderer) - { - Texture ??= renderer.WhitePixel; - } + [BackgroundDependencyLoader] + private void load(IRenderer renderer) + { + Texture ??= renderer.WhitePixel; + } - public override RectangleF BoundingBox => toTriangle(ToParentSpace(LayoutRectangle), RightAngleDirection).AABBFloat; + public override RectangleF BoundingBox => toTriangle(ToParentSpace(LayoutRectangle), RightAngleDirection).AABBFloat; - private TriangleRightAngleDirection rightAngleDirection = TriangleRightAngleDirection.BottomLeft; + private TriangleRightAngleDirection rightAngleDirection = TriangleRightAngleDirection.BottomLeft; - public TriangleRightAngleDirection RightAngleDirection + public TriangleRightAngleDirection RightAngleDirection + { + get => rightAngleDirection; + set { - get => rightAngleDirection; - set - { - rightAngleDirection = value; - Invalidate(); - } + rightAngleDirection = value; + Invalidate(); } + } - private static Triangle toTriangle(Quad q, TriangleRightAngleDirection rightAngleDirection) => - rightAngleDirection switch - { - TriangleRightAngleDirection.TopLeft => new Triangle(q.TopLeft, q.TopRight, q.BottomLeft), - TriangleRightAngleDirection.TopRight => new Triangle(q.TopLeft, q.TopRight, q.BottomRight), - TriangleRightAngleDirection.BottomLeft => new Triangle(q.TopLeft, q.BottomLeft, q.BottomRight), - TriangleRightAngleDirection.BottomRight => new Triangle(q.TopRight, q.BottomLeft, q.BottomRight), - _ => throw new ArgumentOutOfRangeException(nameof(rightAngleDirection), rightAngleDirection, null) - }; + private static Triangle toTriangle(Quad q, TriangleRightAngleDirection rightAngleDirection) => + rightAngleDirection switch + { + TriangleRightAngleDirection.TopLeft => new Triangle(q.TopLeft, q.TopRight, q.BottomLeft), + TriangleRightAngleDirection.TopRight => new Triangle(q.TopLeft, q.TopRight, q.BottomRight), + TriangleRightAngleDirection.BottomLeft => new Triangle(q.TopLeft, q.BottomLeft, q.BottomRight), + TriangleRightAngleDirection.BottomRight => new Triangle(q.TopRight, q.BottomLeft, q.BottomRight), + _ => throw new ArgumentOutOfRangeException(nameof(rightAngleDirection), rightAngleDirection, null) + }; - public override bool Contains(Vector2 screenSpacePos) => toTriangle(ScreenSpaceDrawQuad, RightAngleDirection).Contains(screenSpacePos); + public override bool Contains(Vector2 screenSpacePos) => toTriangle(ScreenSpaceDrawQuad, RightAngleDirection).Contains(screenSpacePos); - protected override DrawNode CreateDrawNode() => new TriangleDrawNode(this); + protected override DrawNode CreateDrawNode() => new TriangleDrawNode(this); - private class TriangleDrawNode : SpriteDrawNode - { - protected new RightTriangle Source => (RightTriangle)base.Source; + private class TriangleDrawNode : SpriteDrawNode + { + protected new RightTriangle Source => (RightTriangle)base.Source; - private TriangleRightAngleDirection rightAngleDirection; + private TriangleRightAngleDirection rightAngleDirection; - public TriangleDrawNode(RightTriangle source) - : base(source) - { - } + public TriangleDrawNode(RightTriangle source) + : base(source) + { + } - public override void ApplyState() - { - base.ApplyState(); + public override void ApplyState() + { + base.ApplyState(); - rightAngleDirection = Source.RightAngleDirection; - } + rightAngleDirection = Source.RightAngleDirection; + } - protected override void Blit(IRenderer renderer) - { - if (DrawRectangle.Width == 0 || DrawRectangle.Height == 0) - return; + protected override void Blit(IRenderer renderer) + { + if (DrawRectangle.Width == 0 || DrawRectangle.Height == 0) + return; - renderer.DrawTriangle(Texture, toTriangle(ScreenSpaceDrawQuad, rightAngleDirection), DrawColourInfo.Colour, null, null, - new Vector2(InflationAmount.X / DrawRectangle.Width, InflationAmount.Y / DrawRectangle.Height), TextureCoords); - } + renderer.DrawTriangle(Texture, toTriangle(ScreenSpaceDrawQuad, rightAngleDirection), DrawColourInfo.Colour, null, null, + new Vector2(InflationAmount.X / DrawRectangle.Width, InflationAmount.Y / DrawRectangle.Height), TextureCoords); + } - protected override void BlitOpaqueInterior(IRenderer renderer) - { - if (DrawRectangle.Width == 0 || DrawRectangle.Height == 0) - return; + protected override void BlitOpaqueInterior(IRenderer renderer) + { + if (DrawRectangle.Width == 0 || DrawRectangle.Height == 0) + return; - var triangle = toTriangle(ConservativeScreenSpaceDrawQuad, rightAngleDirection); + var triangle = toTriangle(ConservativeScreenSpaceDrawQuad, rightAngleDirection); - if (renderer.IsMaskingActive) - renderer.DrawClipped(ref triangle, Texture, DrawColourInfo.Colour); - else - renderer.DrawTriangle(Texture, triangle, DrawColourInfo.Colour); - } + if (renderer.IsMaskingActive) + renderer.DrawClipped(ref triangle, Texture, DrawColourInfo.Colour); + else + renderer.DrawTriangle(Texture, triangle, DrawColourInfo.Colour); } } +} - public enum TriangleRightAngleDirection - { - TopLeft, +public enum TriangleRightAngleDirection +{ + TopLeft, - TopRight, + TopRight, - BottomLeft, + BottomLeft, - BottomRight, - } + BottomRight, } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableCircleSingerAvatar.cs b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableCircleSingerAvatar.cs index 3e1acf991..3909112b8 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableCircleSingerAvatar.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableCircleSingerAvatar.cs @@ -11,37 +11,36 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites +namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites; + +public partial class DrawableCircleSingerAvatar : DrawableSingerAvatar { - public partial class DrawableCircleSingerAvatar : DrawableSingerAvatar + private readonly IBindable bindableHue = new Bindable(); + + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures) { - private readonly IBindable bindableHue = new Bindable(); + Masking = true; + CornerRadius = Math.Min(DrawSize.X, DrawSize.Y) / 2f; + BorderThickness = 5; - [BackgroundDependencyLoader] - private void load(LargeTextureStore textures) + bindableHue.BindValueChanged(_ => { - Masking = true; - CornerRadius = Math.Min(DrawSize.X, DrawSize.Y) / 2f; - BorderThickness = 5; - - bindableHue.BindValueChanged(_ => - { - BorderColour = SingerUtils.GetContentColour(Singer); - }, true); - } + BorderColour = SingerUtils.GetContentColour(Singer); + }, true); + } - public override ISinger Singer + public override ISinger Singer + { + get => base.Singer; + set { - get => base.Singer; - set - { - base.Singer = value; + base.Singer = value; - bindableHue.UnbindBindings(); + bindableHue.UnbindBindings(); - if (value is Singer singer) - bindableHue.BindTo(singer.HueBindable); - } + if (value is Singer singer) + bindableHue.BindTo(singer.HueBindable); } } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableKaraokeSpriteText.cs b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableKaraokeSpriteText.cs index 24a8701b6..3d4198b5b 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableKaraokeSpriteText.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableKaraokeSpriteText.cs @@ -8,119 +8,118 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites +namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites; + +public partial class DrawableKaraokeSpriteText : KaraokeSpriteText where TSpriteText : LyricSpriteText, new() { - public partial class DrawableKaraokeSpriteText : KaraokeSpriteText where TSpriteText : LyricSpriteText, new() - { - private const int whole_chunk_index = -1; + private const int whole_chunk_index = -1; - private readonly IBindable textBindable = new Bindable(); - private readonly IBindable timeTagsVersion = new Bindable(); - private readonly IBindableList timeTagsBindable = new BindableList(); - private readonly IBindable rubyTagsVersion = new Bindable(); - private readonly IBindableList rubyTagsBindable = new BindableList(); - private readonly IBindable romajiTagsVersion = new Bindable(); - private readonly IBindableList romajiTagsBindable = new BindableList(); + private readonly IBindable textBindable = new Bindable(); + private readonly IBindable timeTagsVersion = new Bindable(); + private readonly IBindableList timeTagsBindable = new BindableList(); + private readonly IBindable rubyTagsVersion = new Bindable(); + private readonly IBindableList rubyTagsBindable = new BindableList(); + private readonly IBindable romajiTagsVersion = new Bindable(); + private readonly IBindableList romajiTagsBindable = new BindableList(); - private readonly int chunkIndex; + private readonly int chunkIndex; - protected DrawableKaraokeSpriteText(Lyric lyric, int chunkIndex = whole_chunk_index) + protected DrawableKaraokeSpriteText(Lyric lyric, int chunkIndex = whole_chunk_index) + { + this.chunkIndex = chunkIndex; + + textBindable.BindValueChanged(_ => UpdateText(), true); + timeTagsVersion.BindValueChanged(_ => UpdateTimeTags()); + timeTagsBindable.BindCollectionChanged((_, _) => UpdateTimeTags()); + rubyTagsVersion.BindValueChanged(_ => UpdateRubies()); + rubyTagsBindable.BindCollectionChanged((_, _) => UpdateRubies()); + romajiTagsVersion.BindValueChanged(_ => UpdateRomajies()); + romajiTagsBindable.BindCollectionChanged((_, _) => UpdateRomajies()); + + textBindable.BindTo(lyric.TextBindable); + timeTagsVersion.BindTo(lyric.TimeTagsVersion); + timeTagsBindable.BindTo(lyric.TimeTagsBindable); + rubyTagsVersion.BindTo(lyric.RubyTagsVersion); + rubyTagsBindable.BindTo(lyric.RubyTagsBindable); + romajiTagsVersion.BindTo(lyric.RomajiTagsVersion); + romajiTagsBindable.BindTo(lyric.RomajiTagsBindable); + } + + protected virtual void UpdateText() + { + if (chunkIndex == whole_chunk_index) { - this.chunkIndex = chunkIndex; - - textBindable.BindValueChanged(_ => UpdateText(), true); - timeTagsVersion.BindValueChanged(_ => UpdateTimeTags()); - timeTagsBindable.BindCollectionChanged((_, _) => UpdateTimeTags()); - rubyTagsVersion.BindValueChanged(_ => UpdateRubies()); - rubyTagsBindable.BindCollectionChanged((_, _) => UpdateRubies()); - romajiTagsVersion.BindValueChanged(_ => UpdateRomajies()); - romajiTagsBindable.BindCollectionChanged((_, _) => UpdateRomajies()); - - textBindable.BindTo(lyric.TextBindable); - timeTagsVersion.BindTo(lyric.TimeTagsVersion); - timeTagsBindable.BindTo(lyric.TimeTagsBindable); - rubyTagsVersion.BindTo(lyric.RubyTagsVersion); - rubyTagsBindable.BindTo(lyric.RubyTagsBindable); - romajiTagsVersion.BindTo(lyric.RomajiTagsVersion); - romajiTagsBindable.BindTo(lyric.RomajiTagsBindable); + Text = textBindable.Value; } - - protected virtual void UpdateText() + else { - if (chunkIndex == whole_chunk_index) - { - Text = textBindable.Value; - } - else - { - throw new NotImplementedException("Chunk lyric will be available until V2"); - } + throw new NotImplementedException("Chunk lyric will be available until V2"); } + } - protected virtual void UpdateTimeTags() + protected virtual void UpdateTimeTags() + { + if (chunkIndex == whole_chunk_index) + { + TimeTags = TimeTagsUtils.ToTimeBasedDictionary(timeTagsBindable.ToList()); + } + else { - if (chunkIndex == whole_chunk_index) - { - TimeTags = TimeTagsUtils.ToTimeBasedDictionary(timeTagsBindable.ToList()); - } - else - { - throw new NotImplementedException("Chunk lyric will be available until V2"); - } + throw new NotImplementedException("Chunk lyric will be available until V2"); } + } - protected virtual void UpdateRubies() + protected virtual void UpdateRubies() + { + if (chunkIndex == whole_chunk_index) { - if (chunkIndex == whole_chunk_index) - { - Rubies = DisplayRuby ? rubyTagsBindable.Select(TextTagUtils.ToPositionText).ToArray() : Array.Empty(); - } - else - { - throw new NotImplementedException("Chunk lyric will be available until V2"); - } + Rubies = DisplayRuby ? rubyTagsBindable.Select(TextTagUtils.ToPositionText).ToArray() : Array.Empty(); } + else + { + throw new NotImplementedException("Chunk lyric will be available until V2"); + } + } - protected virtual void UpdateRomajies() + protected virtual void UpdateRomajies() + { + if (chunkIndex == whole_chunk_index) + { + Romajies = DisplayRomaji ? romajiTagsBindable.Select(TextTagUtils.ToPositionText).ToArray() : Array.Empty(); + } + else { - if (chunkIndex == whole_chunk_index) - { - Romajies = DisplayRomaji ? romajiTagsBindable.Select(TextTagUtils.ToPositionText).ToArray() : Array.Empty(); - } - else - { - throw new NotImplementedException("Chunk lyric will be available until V2"); - } + throw new NotImplementedException("Chunk lyric will be available until V2"); } + } - private bool displayRuby = true; + private bool displayRuby = true; - public bool DisplayRuby + public bool DisplayRuby + { + get => displayRuby; + set { - get => displayRuby; - set - { - if (displayRuby == value) - return; - - displayRuby = value; - Schedule(UpdateRubies); - } + if (displayRuby == value) + return; + + displayRuby = value; + Schedule(UpdateRubies); } + } - private bool displayRomaji = true; + private bool displayRomaji = true; - public bool DisplayRomaji + public bool DisplayRomaji + { + get => displayRomaji; + set { - get => displayRomaji; - set - { - if (displayRomaji == value) - return; - - displayRomaji = value; - Schedule(UpdateRomajies); - } + if (displayRomaji == value) + return; + + displayRomaji = value; + Schedule(UpdateRomajies); } } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableLyricSpriteText.cs b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableLyricSpriteText.cs index f69721bcf..39ced4816 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableLyricSpriteText.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableLyricSpriteText.cs @@ -7,39 +7,38 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites +namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites; + +public partial class DrawableLyricSpriteText : LyricSpriteText { - public partial class DrawableLyricSpriteText : LyricSpriteText - { - private readonly IBindable textBindable = new Bindable(); - private readonly IBindable rubyTagsVersion = new Bindable(); - private readonly IBindableList rubyTagsBindable = new BindableList(); - private readonly IBindable romajiTagsVersion = new Bindable(); - private readonly IBindableList romajiTagsBindable = new BindableList(); + private readonly IBindable textBindable = new Bindable(); + private readonly IBindable rubyTagsVersion = new Bindable(); + private readonly IBindableList rubyTagsBindable = new BindableList(); + private readonly IBindable romajiTagsVersion = new Bindable(); + private readonly IBindableList romajiTagsBindable = new BindableList(); - public DrawableLyricSpriteText(Lyric lyric) - { - textBindable.BindValueChanged(text => { Text = text.NewValue; }, true); - rubyTagsVersion.BindValueChanged(_ => updateRubies()); - rubyTagsBindable.BindCollectionChanged((_, _) => updateRubies()); - romajiTagsVersion.BindValueChanged(_ => updateRubies()); - romajiTagsBindable.BindCollectionChanged((_, _) => updateRomajies()); + public DrawableLyricSpriteText(Lyric lyric) + { + textBindable.BindValueChanged(text => { Text = text.NewValue; }, true); + rubyTagsVersion.BindValueChanged(_ => updateRubies()); + rubyTagsBindable.BindCollectionChanged((_, _) => updateRubies()); + romajiTagsVersion.BindValueChanged(_ => updateRubies()); + romajiTagsBindable.BindCollectionChanged((_, _) => updateRomajies()); - textBindable.BindTo(lyric.TextBindable); - rubyTagsVersion.BindTo(lyric.RubyTagsVersion); - rubyTagsBindable.BindTo(lyric.RubyTagsBindable); - romajiTagsVersion.BindTo(lyric.RomajiTagsVersion); - romajiTagsBindable.BindTo(lyric.RomajiTagsBindable); - } + textBindable.BindTo(lyric.TextBindable); + rubyTagsVersion.BindTo(lyric.RubyTagsVersion); + rubyTagsBindable.BindTo(lyric.RubyTagsBindable); + romajiTagsVersion.BindTo(lyric.RomajiTagsVersion); + romajiTagsBindable.BindTo(lyric.RomajiTagsBindable); + } - private void updateRubies() - { - Rubies = rubyTagsBindable.Select(TextTagUtils.ToPositionText).ToArray(); - } + private void updateRubies() + { + Rubies = rubyTagsBindable.Select(TextTagUtils.ToPositionText).ToArray(); + } - private void updateRomajies() - { - Romajies = romajiTagsBindable.Select(TextTagUtils.ToPositionText).ToArray(); - } + private void updateRomajies() + { + Romajies = romajiTagsBindable.Select(TextTagUtils.ToPositionText).ToArray(); } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableSingerAvatar.cs b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableSingerAvatar.cs index bfb6484f9..fb50240ad 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableSingerAvatar.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/DrawableSingerAvatar.cs @@ -13,57 +13,56 @@ using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas; using osu.Game.Rulesets.Karaoke.Beatmaps.Metadatas.Types; -namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites +namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites; + +public partial class DrawableSingerAvatar : CompositeDrawable { - public partial class DrawableSingerAvatar : CompositeDrawable - { - private readonly IBindable bindableAvatarFile = new Bindable(); + private readonly IBindable bindableAvatarFile = new Bindable(); - private readonly Sprite avatar; + private readonly Sprite avatar; - public DrawableSingerAvatar() + public DrawableSingerAvatar() + { + InternalChild = avatar = new Sprite { - InternalChild = avatar = new Sprite - { - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fit, - Anchor = Anchor.Centre, - Origin = Anchor.Centre - }; - } + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + } - [BackgroundDependencyLoader] - private void load(LargeTextureStore textures, IKaraokeBeatmapResourcesProvider karaokeBeatmapResourcesProvider) + [BackgroundDependencyLoader] + private void load(LargeTextureStore textures, IKaraokeBeatmapResourcesProvider karaokeBeatmapResourcesProvider) + { + bindableAvatarFile.BindValueChanged(_ => { - bindableAvatarFile.BindValueChanged(_ => - { - if (singer == null) - avatar.Texture = getDefaultAvatar(); - else - avatar.Texture = karaokeBeatmapResourcesProvider.GetSingerAvatar(singer) ?? getDefaultAvatar(); + if (singer == null) + avatar.Texture = getDefaultAvatar(); + else + avatar.Texture = karaokeBeatmapResourcesProvider.GetSingerAvatar(singer) ?? getDefaultAvatar(); - avatar.FadeInFromZero(500); - }, true); + avatar.FadeInFromZero(500); + }, true); - Texture getDefaultAvatar() - => textures.Get(@"Online/avatar-guest"); - } + Texture getDefaultAvatar() + => textures.Get(@"Online/avatar-guest"); + } - private ISinger singer; + private ISinger singer; - public virtual ISinger Singer + public virtual ISinger Singer + { + get => singer; + set { - get => singer; - set - { - singer = value; + singer = value; - if (singer is not Singer s) - return; + if (singer is not Singer s) + return; - bindableAvatarFile.UnbindBindings(); - bindableAvatarFile.BindTo(s.AvatarFileBindable); - } + bindableAvatarFile.UnbindBindings(); + bindableAvatarFile.BindTo(s.AvatarFileBindable); } } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/KaraokeIcon.cs b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/KaraokeIcon.cs index 9d61fcc65..9022c75d7 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/Sprites/KaraokeIcon.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/Sprites/KaraokeIcon.cs @@ -6,20 +6,19 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; -namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites +namespace osu.Game.Rulesets.Karaoke.Graphics.Sprites; + +public static class KaraokeIcon { - public static class KaraokeIcon - { - public static IconUsage Get(int icon) => new((char)icon, "osuFont"); + public static IconUsage Get(int icon) => new((char)icon, "osuFont"); - // ruleset icons in circles - public static IconUsage RulesetKaraoke => FontAwesome.Solid.PlayCircle; + // ruleset icons in circles + public static IconUsage RulesetKaraoke => FontAwesome.Solid.PlayCircle; - // mod icons - public static IconUsage ModDisableNote => FontAwesome.Solid.Eraser; - public static IconUsage ModHiddenNote => OsuIcon.ModHidden; - public static IconUsage ModHiddenRuby => FontAwesome.Solid.Gem; - public static IconUsage ModPractice => FontAwesome.Solid.Music; - public static IconUsage ModAutoPlayBySinger => FontAwesome.Solid.Music; - } + // mod icons + public static IconUsage ModDisableNote => FontAwesome.Solid.Eraser; + public static IconUsage ModHiddenNote => OsuIcon.ModHidden; + public static IconUsage ModHiddenRuby => FontAwesome.Solid.Gem; + public static IconUsage ModPractice => FontAwesome.Solid.Music; + public static IconUsage ModAutoPlayBySinger => FontAwesome.Solid.Music; } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/CircleCheckbox.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/CircleCheckbox.cs index 33fa59a5e..d5b529dac 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/CircleCheckbox.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/CircleCheckbox.cs @@ -18,98 +18,97 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface; + +public partial class CircleCheckbox : Checkbox, IHasAccentColour, IHasTooltip { - public partial class CircleCheckbox : Checkbox, IHasAccentColour, IHasTooltip - { - private const float expanded_size = 24; + private const float expanded_size = 24; - private readonly Circle background; - private readonly SpriteIcon border; - private readonly SpriteIcon selectedIcon; + private readonly Circle background; + private readonly SpriteIcon border; + private readonly SpriteIcon selectedIcon; - private Sample sampleChecked; - private Sample sampleUnchecked; + private Sample sampleChecked; + private Sample sampleUnchecked; - /// - /// Whether to play sounds when the state changes as a result of user interaction. - /// - protected virtual bool PlaySoundsOnUserChange => true; + /// + /// Whether to play sounds when the state changes as a result of user interaction. + /// + protected virtual bool PlaySoundsOnUserChange => true; - public CircleCheckbox() - { - Size = new Vector2(expanded_size); + public CircleCheckbox() + { + Size = new Vector2(expanded_size); - Children = new Drawable[] + Children = new Drawable[] + { + background = new Circle { - background = new Circle - { - RelativeSizeAxes = Axes.Both, - Alpha = 0.5f, - }, - border = new SpriteIcon - { - RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Regular.Circle, - }, - selectedIcon = new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Icon = FontAwesome.Solid.Check, - Scale = new Vector2(0), - }, - new HoverSounds() - }; - - Current.DisabledChanged += disabled => + RelativeSizeAxes = Axes.Both, + Alpha = 0.5f, + }, + border = new SpriteIcon { - background.Alpha = disabled ? 0.2f : 0.5f; - border.Alpha = selectedIcon.Alpha = disabled ? 0.2f : 1; - }; - - Current.ValueChanged += e => + RelativeSizeAxes = Axes.Both, + Icon = FontAwesome.Regular.Circle, + }, + selectedIcon = new SpriteIcon { - selectedIcon.ScaleTo(e.NewValue ? 0.6f : 0, 200, Easing.OutElastic); - }; - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Icon = FontAwesome.Solid.Check, + Scale = new Vector2(0), + }, + new HoverSounds() + }; + + Current.DisabledChanged += disabled => + { + background.Alpha = disabled ? 0.2f : 0.5f; + border.Alpha = selectedIcon.Alpha = disabled ? 0.2f : 1; + }; - [BackgroundDependencyLoader] - private void load(AudioManager audio) + Current.ValueChanged += e => { - sampleChecked = audio.Samples.Get(@"UI/check-on"); - sampleUnchecked = audio.Samples.Get(@"UI/check-off"); - } + selectedIcon.ScaleTo(e.NewValue ? 0.6f : 0, 200, Easing.OutElastic); + }; + } - private Color4 accentColour; + [BackgroundDependencyLoader] + private void load(AudioManager audio) + { + sampleChecked = audio.Samples.Get(@"UI/check-on"); + sampleUnchecked = audio.Samples.Get(@"UI/check-off"); + } + + private Color4 accentColour; - public Color4 AccentColour + public Color4 AccentColour + { + get => accentColour; + set { - get => accentColour; - set - { - accentColour = value; + accentColour = value; - background.Colour = AccentColour.Darken(1.5f); - border.Colour = AccentColour; - selectedIcon.Colour = AccentColour; - } + background.Colour = AccentColour.Darken(1.5f); + border.Colour = AccentColour; + selectedIcon.Colour = AccentColour; } + } - protected override void OnUserChange(bool value) - { - base.OnUserChange(value); - - if (!PlaySoundsOnUserChange) - return; + protected override void OnUserChange(bool value) + { + base.OnUserChange(value); - if (value) - sampleChecked?.Play(); - else - sampleUnchecked?.Play(); - } + if (!PlaySoundsOnUserChange) + return; - public LocalisableString TooltipText { get; set; } + if (value) + sampleChecked?.Play(); + else + sampleUnchecked?.Play(); } + + public LocalisableString TooltipText { get; set; } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/MicrophoneSoundVisualizer.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/MicrophoneSoundVisualizer.cs index 4c23aead7..f81f0cf63 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/MicrophoneSoundVisualizer.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/MicrophoneSoundVisualizer.cs @@ -17,422 +17,421 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface; + +public partial class MicrophoneSoundVisualizer : CompositeDrawable { - public partial class MicrophoneSoundVisualizer : CompositeDrawable - { - private const float max_decibel = 100; - private const float max_pitch = 60; + private const float max_decibel = 100; + private const float max_pitch = 60; - private readonly Box background; - private readonly MicrophoneInfo microphoneInfo; - private readonly DecibelVisualizer decibelVisualizer; - private readonly PitchVisualizer pitchVisualizer; + private readonly Box background; + private readonly MicrophoneInfo microphoneInfo; + private readonly DecibelVisualizer decibelVisualizer; + private readonly PitchVisualizer pitchVisualizer; - public MicrophoneSoundVisualizer() + public MicrophoneSoundVisualizer() + { + Width = 310; + Height = 100; + Masking = true; + CornerRadius = 5f; + InternalChildren = new Drawable[] { - Width = 310; - Height = 100; - Masking = true; - CornerRadius = 5f; - InternalChildren = new Drawable[] + background = new Box { - background = new Box + RelativeSizeAxes = Axes.Both, + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - RelativeSizeAxes = Axes.Both, + new Dimension(GridSizeMode.Relative, 0.6f), + new Dimension(GridSizeMode.Relative, 0.2f), + new Dimension(GridSizeMode.Relative, 0.2f), }, - new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + new Drawable[] { - new Dimension(GridSizeMode.Relative, 0.6f), - new Dimension(GridSizeMode.Relative, 0.2f), - new Dimension(GridSizeMode.Relative, 0.2f), + microphoneInfo = new MicrophoneInfo + { + RelativeSizeAxes = Axes.Both, + }, }, - Content = new[] + new Drawable[] { - new Drawable[] + decibelVisualizer = new DecibelVisualizer { - microphoneInfo = new MicrophoneInfo - { - RelativeSizeAxes = Axes.Both, - }, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Y = 2, }, - new Drawable[] + }, + new Drawable[] + { + pitchVisualizer = new PitchVisualizer { - decibelVisualizer = new DecibelVisualizer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = 2, - }, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, }, - new Drawable[] - { - pitchVisualizer = new PitchVisualizer - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, - } } } - }; + } + }; - updateDeviceInfo(); - } + updateDeviceInfo(); + } - private string deviceName; + private string deviceName; - public string DeviceName + public string DeviceName + { + get => deviceName; + set { - get => deviceName; - set - { - if (deviceName == value) - return; + if (deviceName == value) + return; - deviceName = value; - updateDeviceInfo(); - } + deviceName = value; + updateDeviceInfo(); } + } - private bool hasDevice; + private bool hasDevice; - public bool HasDevice + public bool HasDevice + { + get => hasDevice; + set { - get => hasDevice; - set - { - if (hasDevice == value) - return; + if (hasDevice == value) + return; - hasDevice = value; - updateDeviceInfo(); - } + hasDevice = value; + updateDeviceInfo(); } + } - private void updateDeviceInfo() - { - microphoneInfo.DeviceName = HasDevice ? DeviceName : "Seems no microphone device."; - microphoneInfo.HasDevice = HasDevice; - } + private void updateDeviceInfo() + { + microphoneInfo.DeviceName = HasDevice ? DeviceName : "Seems no microphone device."; + microphoneInfo.HasDevice = HasDevice; + } - protected override bool Handle(UIEvent e) + protected override bool Handle(UIEvent e) + { + return e switch { - return e switch - { - MicrophoneStartPitchingEvent microphoneStartPitching => OnMicrophoneStartSinging(microphoneStartPitching), - MicrophoneEndPitchingEvent microphoneEndPitching => OnMicrophoneEndSinging(microphoneEndPitching), - MicrophonePitchingEvent microphonePitching => OnMicrophoneSinging(microphonePitching), - _ => base.Handle(e) - }; - } + MicrophoneStartPitchingEvent microphoneStartPitching => OnMicrophoneStartSinging(microphoneStartPitching), + MicrophoneEndPitchingEvent microphoneEndPitching => OnMicrophoneEndSinging(microphoneEndPitching), + MicrophonePitchingEvent microphonePitching => OnMicrophoneSinging(microphonePitching), + _ => base.Handle(e) + }; + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Gray2; - } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Gray2; + } - protected virtual bool OnMicrophoneStartSinging(MicrophoneStartPitchingEvent e) - { - return false; - } + protected virtual bool OnMicrophoneStartSinging(MicrophoneStartPitchingEvent e) + { + return false; + } - protected virtual bool OnMicrophoneEndSinging(MicrophoneEndPitchingEvent e) - { - decibelVisualizer.Decibel = 0; - pitchVisualizer.Pitch = 0; + protected virtual bool OnMicrophoneEndSinging(MicrophoneEndPitchingEvent e) + { + decibelVisualizer.Decibel = 0; + pitchVisualizer.Pitch = 0; - return false; - } + return false; + } - protected virtual bool OnMicrophoneSinging(MicrophonePitchingEvent e) - { - var voice = e.CurrentState.Microphone.Voice; - float decibel = voice.Decibel; - float pitch = voice.Pitch; + protected virtual bool OnMicrophoneSinging(MicrophonePitchingEvent e) + { + var voice = e.CurrentState.Microphone.Voice; + float decibel = voice.Decibel; + float pitch = voice.Pitch; - // todo : should convert to better value. - decibelVisualizer.Decibel = decibel; - pitchVisualizer.Pitch = pitch / 8; + // todo : should convert to better value. + decibelVisualizer.Decibel = decibel; + pitchVisualizer.Pitch = pitch / 8; - return false; - } + return false; + } - internal partial class MicrophoneInfo : CompositeDrawable - { - private readonly Box background; - private readonly SpriteIcon microphoneIcon; - private readonly OsuSpriteText deviceName; + internal partial class MicrophoneInfo : CompositeDrawable + { + private readonly Box background; + private readonly SpriteIcon microphoneIcon; + private readonly OsuSpriteText deviceName; - [Resolved] - private OsuColour colours { get; set; } + [Resolved] + private OsuColour colours { get; set; } - public MicrophoneInfo() + public MicrophoneInfo() + { + InternalChildren = new Drawable[] { - InternalChildren = new Drawable[] + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new FillFlowContainer { - background = new Box + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { - RelativeSizeAxes = Axes.Both, + Top = 20, + Left = 15 }, - new FillFlowContainer + Spacing = new Vector2(15), + Direction = FillDirection.Horizontal, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding + microphoneIcon = new SpriteIcon { - Top = 20, - Left = 15 + Size = new Vector2(24), + Icon = FontAwesome.Solid.Microphone }, - Spacing = new Vector2(15), - Direction = FillDirection.Horizontal, - Children = new Drawable[] + deviceName = new OsuSpriteText { - microphoneIcon = new SpriteIcon - { - Size = new Vector2(24), - Icon = FontAwesome.Solid.Microphone - }, - deviceName = new OsuSpriteText - { - Width = 250, - Font = OsuFont.Default.With(size: 20), - Text = "Microphone name", - Truncate = true, - } + Width = 250, + Font = OsuFont.Default.With(size: 20), + Text = "Microphone name", + Truncate = true, } } - }; - } - - public string DeviceName - { - set => deviceName.Text = value; - } + } + }; + } - public bool HasDevice - { - set => - Schedule(() => - { - microphoneIcon.Colour = value ? colours.GrayF : colours.RedLight; - }); - } + public string DeviceName + { + set => deviceName.Text = value; + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Gray3; - } + public bool HasDevice + { + set => + Schedule(() => + { + microphoneIcon.Colour = value ? colours.GrayF : colours.RedLight; + }); } - internal partial class DecibelVisualizer : CompositeDrawable + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - private const float var_width = 294; + background.Colour = colours.Gray3; + } + } + + internal partial class DecibelVisualizer : CompositeDrawable + { + private const float var_width = 294; - private readonly Box background; - private readonly Box decibelMarker; - private readonly Box decibelRippleMarker; - private readonly Box maxDecibelMarker; + private readonly Box background; + private readonly Box decibelMarker; + private readonly Box decibelRippleMarker; + private readonly Box maxDecibelMarker; - public DecibelVisualizer() + public DecibelVisualizer() + { + Width = var_width; + Height = 8; + InternalChildren = new Drawable[] { - Width = var_width; - Height = 8; - InternalChildren = new Drawable[] + background = new Box { - background = new Box - { - RelativeSizeAxes = Axes.Both, - }, - decibelMarker = new Box - { - RelativeSizeAxes = Axes.Y, - }, - decibelRippleMarker = new Box - { - RelativeSizeAxes = Axes.Y, - }, - maxDecibelMarker = new Box - { - RelativeSizeAxes = Axes.Y, - Width = 5, - }, - }; - } + RelativeSizeAxes = Axes.Both, + }, + decibelMarker = new Box + { + RelativeSizeAxes = Axes.Y, + }, + decibelRippleMarker = new Box + { + RelativeSizeAxes = Axes.Y, + }, + maxDecibelMarker = new Box + { + RelativeSizeAxes = Axes.Y, + Width = 5, + }, + }; + } - private float decibel; + private float decibel; - private float maxDecibel; + private float maxDecibel; - public float Decibel + public float Decibel + { + get => decibel; + set { - get => decibel; - set - { - if (decibel == value) - return; + if (decibel == value) + return; - decibel = value; - if (decibel > maxDecibel) - maxDecibel = decibel; + decibel = value; + if (decibel > maxDecibel) + maxDecibel = decibel; - if (decibel > rippleDecibel) - rippleDecibel = value; + if (decibel > rippleDecibel) + rippleDecibel = value; - decibelMarker.Width = calculatePosition(Decibel); - maxDecibelMarker.X = calculatePosition(maxDecibel); - } + decibelMarker.Width = calculatePosition(Decibel); + maxDecibelMarker.X = calculatePosition(maxDecibel); } + } - private float rippleDecibel; - - protected override void Update() - { - base.Update(); - - if (rippleDecibel <= 0) - return; + private float rippleDecibel; - //1% of extra bar length to make it a little faster when bar is almost at it's minimum - rippleDecibel *= 0.99f; + protected override void Update() + { + base.Update(); - // just make value to 0 if too small; - if (rippleDecibel < 0.5) - rippleDecibel = 0; + if (rippleDecibel <= 0) + return; - decibelRippleMarker.Width = rippleDecibel; - } + //1% of extra bar length to make it a little faster when bar is almost at it's minimum + rippleDecibel *= 0.99f; - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.Gray5; - decibelMarker.Colour = colours.GrayD; - decibelRippleMarker.Colour = colours.GrayA; - maxDecibelMarker.Colour = colours.Red; - } + // just make value to 0 if too small; + if (rippleDecibel < 0.5) + rippleDecibel = 0; - private static float calculatePosition(float decibel) - => decibel / max_decibel * var_width; + decibelRippleMarker.Width = rippleDecibel; } - internal partial class PitchVisualizer : CompositeDrawable + [BackgroundDependencyLoader] + private void load(OsuColour colours) { - private const int dot_width = 5; - private const int dot_height = 10; - private const int dot_amount = 30; - private const float spacing = 5; + background.Colour = colours.Gray5; + decibelMarker.Colour = colours.GrayD; + decibelRippleMarker.Colour = colours.GrayA; + maxDecibelMarker.Colour = colours.Red; + } + + private static float calculatePosition(float decibel) + => decibel / max_decibel * var_width; + } - private readonly PitchDot currentDot; + internal partial class PitchVisualizer : CompositeDrawable + { + private const int dot_width = 5; + private const int dot_height = 10; + private const int dot_amount = 30; + private const float spacing = 5; - public PitchVisualizer() - { - AutoSizeAxes = Axes.Both; + private readonly PitchDot currentDot; - // todo : draw that stupid shapes with progressive background color. - InternalChildren = new Drawable[] + public PitchVisualizer() + { + AutoSizeAxes = Axes.Both; + + // todo : draw that stupid shapes with progressive background color. + InternalChildren = new Drawable[] + { + new FillFlowContainer { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Spacing = new Vector2(spacing), - Children = Enumerable.Range(0, dot_amount).Select(i => new PitchDot - { - Colour = calculateDotColour(i, 0.8f) - }).ToArray() - }, - currentDot = new PitchDot + AutoSizeAxes = Axes.Both, + Spacing = new Vector2(spacing), + Children = Enumerable.Range(0, dot_amount).Select(i => new PitchDot { - Alpha = 0, - }, - }; - } + Colour = calculateDotColour(i, 0.8f) + }).ToArray() + }, + currentDot = new PitchDot + { + Alpha = 0, + }, + }; + } - private float pitch; + private float pitch; - private bool showPitch; + private bool showPitch; - public float Pitch + public float Pitch + { + get => pitch; + set { - get => pitch; - set - { - if (EqualityComparer.Default.Equals(pitch, value)) - return; + if (EqualityComparer.Default.Equals(pitch, value)) + return; - pitch = value; + pitch = value; - // adjust dot position - currentDot.X = calculateDotPosition((int)pitch); + // adjust dot position + currentDot.X = calculateDotPosition((int)pitch); - // adjust show / hide. - bool show = pitch != 0; - if (showPitch == show) - return; + // adjust show / hide. + bool show = pitch != 0; + if (showPitch == show) + return; - showPitch = show; + showPitch = show; - if (show) - { - currentDot.FadeIn(200); - } - else - { - currentDot.FadeOut(200); - } + if (show) + { + currentDot.FadeIn(200); + } + else + { + currentDot.FadeOut(200); } } + } - private Color4 calculateDotColour(int index, float s) - { - const float start_v = 0.4f; - const float end_v = 0.7f; - float v = (end_v - start_v) / dot_amount * index + start_v; - return Color4Extensions.FromHSV(0, s, v); - } + private Color4 calculateDotColour(int index, float s) + { + const float start_v = 0.4f; + const float end_v = 0.7f; + float v = (end_v - start_v) / dot_amount * index + start_v; + return Color4Extensions.FromHSV(0, s, v); + } - private float calculateDotPosition(int index) - => (dot_width + spacing) * index; + private float calculateDotPosition(int index) + => (dot_width + spacing) * index; - public partial class PitchDot : Container - { - private readonly CircularContainer circle; + public partial class PitchDot : Container + { + private readonly CircularContainer circle; - public PitchDot() + public PitchDot() + { + Size = new Vector2(dot_width, dot_height); + Children = new[] { - Size = new Vector2(dot_width, dot_height); - Children = new[] + circle = new CircularContainer { - circle = new CircularContainer + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Masking = true, + Alpha = 0, + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.8f, 0), + Children = new[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Masking = true, - Alpha = 0, - RelativeSizeAxes = Axes.Both, - Size = new Vector2(0.8f, 0), - Children = new[] + new Box { - new Box - { - Colour = Color4.White, - RelativeSizeAxes = Axes.Both, - } - }, - } - }; - } + Colour = Color4.White, + RelativeSizeAxes = Axes.Both, + } + }, + } + }; + } - protected override void LoadComplete() - { - base.LoadComplete(); - circle.FadeIn(500, Easing.OutQuint); - circle.ResizeTo(new Vector2(0.8f), 500, Easing.OutQuint); - } + protected override void LoadComplete() + { + base.LoadComplete(); + circle.FadeIn(500, Easing.OutQuint); + circle.ResizeTo(new Vector2(0.8f), 500, Easing.OutQuint); } } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/RearrangeableTextFlowListContainer.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/RearrangeableTextFlowListContainer.cs index 2ae479754..47904d15f 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/RearrangeableTextFlowListContainer.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/RearrangeableTextFlowListContainer.cs @@ -16,126 +16,125 @@ using osuTK; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface; + +/// +/// Implement most feature for searchable text container. +/// +/// +public partial class RearrangeableTextFlowListContainer : OsuRearrangeableListContainer { - /// - /// Implement most feature for searchable text container. - /// - /// - public partial class RearrangeableTextFlowListContainer : OsuRearrangeableListContainer - { - public readonly Bindable SelectedSet = new(); + public readonly Bindable SelectedSet = new(); - public Action RequestSelection; + public Action RequestSelection; - private SearchContainer> searchContainer; + private SearchContainer> searchContainer; - protected sealed override FillFlowContainer> CreateListFillFlowContainer() => searchContainer = new SearchContainer> - { - Spacing = new Vector2(0, 3), - LayoutDuration = 200, - LayoutEasing = Easing.OutQuint, - }; + protected sealed override FillFlowContainer> CreateListFillFlowContainer() => searchContainer = new SearchContainer> + { + Spacing = new Vector2(0, 3), + LayoutDuration = 200, + LayoutEasing = Easing.OutQuint, + }; - public void Filter(string text) + public void Filter(string text) + { + searchContainer.SearchTerm = text; + } + + protected sealed override OsuRearrangeableListItem CreateOsuDrawable(TModel item) + => CreateDrawable(item).With(d => { - searchContainer.SearchTerm = text; - } + d.SelectedSet.BindTarget = SelectedSet; + d.RequestSelection = set => RequestSelection?.Invoke(set); + }); - protected sealed override OsuRearrangeableListItem CreateOsuDrawable(TModel item) - => CreateDrawable(item).With(d => - { - d.SelectedSet.BindTarget = SelectedSet; - d.RequestSelection = set => RequestSelection?.Invoke(set); - }); + protected new virtual DrawableTextListItem CreateDrawable(TModel item) + => new(item); - protected new virtual DrawableTextListItem CreateDrawable(TModel item) - => new(item); + public partial class DrawableTextListItem : OsuRearrangeableListItem, IFilterable + { + public readonly Bindable SelectedSet = new(); - public partial class DrawableTextListItem : OsuRearrangeableListItem, IFilterable - { - public readonly Bindable SelectedSet = new(); + public Action RequestSelection; - public Action RequestSelection; + private TextFlowContainer text; - private TextFlowContainer text; + private Color4 selectedColour; - private Color4 selectedColour; + public DrawableTextListItem(TModel item) + : base(item) + { + Padding = new MarginPadding { Left = 5 }; + ShowDragHandle.Value = false; + } - public DrawableTextListItem(TModel item) - : base(item) - { - Padding = new MarginPadding { Left = 5 }; - ShowDragHandle.Value = false; - } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + selectedColour = colours.Yellow; + HandleColour = colours.Gray5; + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - selectedColour = colours.Yellow; - HandleColour = colours.Gray5; - } + protected override void LoadComplete() + { + base.LoadComplete(); - protected override void LoadComplete() + SelectedSet.BindValueChanged(set => { - base.LoadComplete(); - - SelectedSet.BindValueChanged(set => - { - bool oldValueMatched = EqualityComparer.Default.Equals(set.OldValue, Model); - bool newValueMatched = EqualityComparer.Default.Equals(set.NewValue, Model); - if (!oldValueMatched && !newValueMatched) - return; + bool oldValueMatched = EqualityComparer.Default.Equals(set.OldValue, Model); + bool newValueMatched = EqualityComparer.Default.Equals(set.NewValue, Model); + if (!oldValueMatched && !newValueMatched) + return; - text.FadeColour(newValueMatched ? selectedColour : Color4.White, FADE_DURATION); - }, true); - } + text.FadeColour(newValueMatched ? selectedColour : Color4.White, FADE_DURATION); + }, true); + } - protected sealed override Drawable CreateContent() => text = new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }.With(x => + protected sealed override Drawable CreateContent() => text = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }.With(x => + { + Schedule(() => { - Schedule(() => - { - // should create the text after BDL loaded. - CreateDisplayContent(x, Model); - }); + // should create the text after BDL loaded. + CreateDisplayContent(x, Model); }); + }); - protected override bool OnClick(ClickEvent e) - { - RequestSelection?.Invoke(Model); - return true; - } + protected override bool OnClick(ClickEvent e) + { + RequestSelection?.Invoke(Model); + return true; + } - public virtual IEnumerable FilterTerms => new[] - { - new LocalisableString(Model.ToString()) - }; + public virtual IEnumerable FilterTerms => new[] + { + new LocalisableString(Model.ToString()) + }; - protected virtual void CreateDisplayContent(OsuTextFlowContainer textFlowContainer, TModel model) - => textFlowContainer.AddText(model.ToString()); + protected virtual void CreateDisplayContent(OsuTextFlowContainer textFlowContainer, TModel model) + => textFlowContainer.AddText(model.ToString()); - private bool matchingFilter = true; + private bool matchingFilter = true; - public bool MatchingFilter + public bool MatchingFilter + { + get => matchingFilter; + set { - get => matchingFilter; - set - { - if (matchingFilter == value) - return; - - matchingFilter = value; - updateFilter(); - } + if (matchingFilter == value) + return; + + matchingFilter = value; + updateFilter(); } + } - private void updateFilter() => this.FadeTo(MatchingFilter ? 1 : 0, 200); + private void updateFilter() => this.FadeTo(MatchingFilter ? 1 : 0, 200); - public bool FilteringActive { get; set; } - } + public bool FilteringActive { get; set; } } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/SingerDisplay.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/SingerDisplay.cs index 00018d9fe..8dc0567c9 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/SingerDisplay.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterface/SingerDisplay.cs @@ -18,142 +18,141 @@ using osu.Game.Rulesets.Karaoke.Graphics.Sprites; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterface; + +public partial class SingerDisplay : Container, IHasCurrentValue> { - public partial class SingerDisplay : Container, IHasCurrentValue> - { - private const int fade_duration = 1000; + private const int fade_duration = 1000; - public bool DisplayUnrankedText = true; + public bool DisplayUnrankedText = true; - public ExpansionMode ExpansionMode = ExpansionMode.ExpandOnHover; + public ExpansionMode ExpansionMode = ExpansionMode.ExpandOnHover; - private readonly Bindable> current = new(); + private readonly Bindable> current = new(); - public Bindable> Current + public Bindable> Current + { + get => current; + set { - get => current; - set - { - ArgumentNullException.ThrowIfNull(value); + ArgumentNullException.ThrowIfNull(value); - current.UnbindBindings(); - current.BindTo(value); - } + current.UnbindBindings(); + current.BindTo(value); } + } - private readonly FillFlowContainer iconsContainer; + private readonly FillFlowContainer iconsContainer; - public SingerDisplay() - { - AutoSizeAxes = Axes.Both; + public SingerDisplay() + { + AutoSizeAxes = Axes.Both; - Child = new FillFlowContainer + Child = new FillFlowContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Vertical, - Children = new Drawable[] + iconsContainer = new ReverseChildIDFillFlowContainer { - iconsContainer = new ReverseChildIDFillFlowContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - }, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, }, - }; + }, + }; - Current.ValueChanged += singers => - { - iconsContainer.Clear(); + Current.ValueChanged += singers => + { + iconsContainer.Clear(); - foreach (var singer in singers.NewValue) + foreach (var singer in singers.NewValue) + { + iconsContainer.Add(new DrawableSinger { - iconsContainer.Add(new DrawableSinger - { - Singer = singer, - Name = "Avatar", - Size = new Vector2(32) - }); - } - - if (IsLoaded) - appearTransform(); - }; - } - - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); - Current.UnbindAll(); - } + Singer = singer, + Name = "Avatar", + Size = new Vector2(32) + }); + } - protected override void LoadComplete() - { - base.LoadComplete(); + if (IsLoaded) + appearTransform(); + }; + } - appearTransform(); - iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint); - } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + Current.UnbindAll(); + } - private void appearTransform() - { - expand(); + protected override void LoadComplete() + { + base.LoadComplete(); - using (iconsContainer.BeginDelayedSequence(1200)) - contract(); - } + appearTransform(); + iconsContainer.FadeInFromZero(fade_duration, Easing.OutQuint); + } - private void expand() - { - if (ExpansionMode != ExpansionMode.AlwaysContracted) - iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint); - } + private void appearTransform() + { + expand(); - private void contract() - { - if (ExpansionMode != ExpansionMode.AlwaysExpanded) - iconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint); - } + using (iconsContainer.BeginDelayedSequence(1200)) + contract(); + } - protected override bool OnHover(HoverEvent e) - { - expand(); - return base.OnHover(e); - } + private void expand() + { + if (ExpansionMode != ExpansionMode.AlwaysContracted) + iconsContainer.TransformSpacingTo(new Vector2(5, 0), 500, Easing.OutQuint); + } - protected override void OnHoverLost(HoverLostEvent e) - { - contract(); - base.OnHoverLost(e); - } + private void contract() + { + if (ExpansionMode != ExpansionMode.AlwaysExpanded) + iconsContainer.TransformSpacingTo(new Vector2(-25, 0), 500, Easing.OutQuint); + } - private partial class DrawableSinger : DrawableCircleSingerAvatar, IHasCustomTooltip - { - public ITooltip GetCustomTooltip() => new SingerToolTip(); + protected override bool OnHover(HoverEvent e) + { + expand(); + return base.OnHover(e); + } - public ISinger TooltipContent => Singer; - } + protected override void OnHoverLost(HoverLostEvent e) + { + contract(); + base.OnHoverLost(e); } - public enum ExpansionMode + private partial class DrawableSinger : DrawableCircleSingerAvatar, IHasCustomTooltip { - /// - /// The will expand only when hovered. - /// - ExpandOnHover, - - /// - /// The will always be expanded. - /// - AlwaysExpanded, - - /// - /// The will always be contracted. - /// - AlwaysContracted + public ITooltip GetCustomTooltip() => new SingerToolTip(); + + public ISinger TooltipContent => Singer; } } + +public enum ExpansionMode +{ + /// + /// The will expand only when hovered. + /// + ExpandOnHover, + + /// + /// The will always be expanded. + /// + AlwaysExpanded, + + /// + /// The will always be contracted. + /// + AlwaysContracted +} diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/FontSelector.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/FontSelector.cs index aa5fc46fe..c147fa8ef 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/FontSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/FontSelector.cs @@ -26,397 +26,396 @@ using osu.Game.Rulesets.Karaoke.Utils; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2 +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; + +public partial class FontSelector : CompositeDrawable, IHasCurrentValue { - public partial class FontSelector : CompositeDrawable, IHasCurrentValue - { - private readonly SpriteText previewText; - private readonly FontFamilyPropertyList familyProperty; - private readonly FontPropertyList weightProperty; - private readonly FontPropertyList fontSizeProperty; - private readonly OsuCheckbox fixedWidthCheckbox; + private readonly SpriteText previewText; + private readonly FontFamilyPropertyList familyProperty; + private readonly FontPropertyList weightProperty; + private readonly FontPropertyList fontSizeProperty; + private readonly OsuCheckbox fixedWidthCheckbox; - private readonly BindableWithCurrent current = new(); - private readonly BindableList fonts = new(); + private readonly BindableWithCurrent current = new(); + private readonly BindableList fonts = new(); - [Resolved] - private FontStore fontStore { get; set; } + [Resolved] + private FontStore fontStore { get; set; } - private KaraokeLocalFontStore localFontStore; + private KaraokeLocalFontStore localFontStore; - public Bindable Current + public Bindable Current + { + get => current.Current; + set { - get => current.Current; - set - { - current.Current = value; + current.Current = value; - // should calculate available size until has bindable text. - fontSizeProperty.Items.Clear(); + // should calculate available size until has bindable text. + fontSizeProperty.Items.Clear(); - if (value is BindableFontUsage bindableFontUsage) - { - fontSizeProperty.Items.AddRange(FontUtils.DefaultFontSize(bindableFontUsage.MinFontSize, bindableFontUsage.MaxFontSize)); - } - else - { - fontSizeProperty.Items.AddRange(FontUtils.DefaultFontSize()); - } + if (value is BindableFontUsage bindableFontUsage) + { + fontSizeProperty.Items.AddRange(FontUtils.DefaultFontSize(bindableFontUsage.MinFontSize, bindableFontUsage.MaxFontSize)); + } + else + { + fontSizeProperty.Items.AddRange(FontUtils.DefaultFontSize()); } } + } - public FontSelector() + public FontSelector() + { + InternalChild = new GridContainer { - InternalChild = new GridContainer + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + new Dimension(GridSizeMode.Relative, 0.4f), + new Dimension() + }, + Content = new[] + { + new Drawable[] { - new Dimension(GridSizeMode.Relative, 0.4f), - new Dimension() + previewText = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = "カラオケ, karaoke" + } }, - Content = new[] + new Drawable[] { - new Drawable[] - { - previewText = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = "カラオケ, karaoke" - } - }, - new Drawable[] + new Container { - new Container + Padding = new MarginPadding(10), + RelativeSizeAxes = Axes.Both, + Child = new GridContainer { - Padding = new MarginPadding(10), RelativeSizeAxes = Axes.Both, - Child = new GridContainer + ColumnDimensions = new[] { - RelativeSizeAxes = Axes.Both, - ColumnDimensions = new[] - { - new Dimension(GridSizeMode.Relative, 0.5f), - new Dimension(GridSizeMode.Relative, 0.3f), - new Dimension(GridSizeMode.Relative, 0.2f), - }, - Content = new[] + new Dimension(GridSizeMode.Relative, 0.5f), + new Dimension(GridSizeMode.Relative, 0.3f), + new Dimension(GridSizeMode.Relative, 0.2f), + }, + Content = new[] + { + new Drawable[] { - new Drawable[] + familyProperty = new FontFamilyPropertyList { - familyProperty = new FontFamilyPropertyList - { - Name = "Font family selection area", - RelativeSizeAxes = Axes.Both - }, - weightProperty = new FontPropertyList + Name = "Font family selection area", + RelativeSizeAxes = Axes.Both + }, + weightProperty = new FontPropertyList + { + Name = "Font widget selection area", + RelativeSizeAxes = Axes.Both + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - Name = "Font widget selection area", - RelativeSizeAxes = Axes.Both + new Dimension(), + new Dimension(GridSizeMode.Absolute, 48), }, - new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + new Drawable[] { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 48), + fontSizeProperty = new FontPropertyList + { + Name = "Font size selection area", + RelativeSizeAxes = Axes.Both, + }, }, - Content = new[] + new Drawable[] { - new Drawable[] + fixedWidthCheckbox = new OsuCheckbox { - fontSizeProperty = new FontPropertyList - { - Name = "Font size selection area", - RelativeSizeAxes = Axes.Both, - }, + Name = "Font fixed width selection area", + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding(10), + LabelText = "FixedWidth", }, - new Drawable[] - { - fixedWidthCheckbox = new OsuCheckbox - { - Name = "Font fixed width selection area", - RelativeSizeAxes = Axes.X, - Padding = new MarginPadding(10), - LabelText = "FixedWidth", - }, - } } } - }, - } + } + }, } } } } - }; + } + }; - fonts.BindCollectionChanged((_, b) => + fonts.BindCollectionChanged((_, b) => + { + // re-calculate if source changed. + Schedule(() => { - // re-calculate if source changed. - Schedule(() => - { - string[] oldFamilies = b.OldItems?.OfType().Select(x => x.Family).Distinct().ToArray(); - string[] newFamilies = b.NewItems?.OfType().Select(x => x.Family).Distinct().ToArray(); + string[] oldFamilies = b.OldItems?.OfType().Select(x => x.Family).Distinct().ToArray(); + string[] newFamilies = b.NewItems?.OfType().Select(x => x.Family).Distinct().ToArray(); - if (oldFamilies != null) - { - familyProperty.Items.RemoveAll(x => oldFamilies.Contains(x)); - } + if (oldFamilies != null) + { + familyProperty.Items.RemoveAll(x => oldFamilies.Contains(x)); + } - if (newFamilies != null) - { - familyProperty.Items.AddRange(newFamilies); - } + if (newFamilies != null) + { + familyProperty.Items.AddRange(newFamilies); + } - // should reset family selection if user select the font that will be removed or added. - string currentFamily = familyProperty.Current.Value; - bool resetFamily = oldFamilies?.Contains(currentFamily) ?? false; + // should reset family selection if user select the font that will be removed or added. + string currentFamily = familyProperty.Current.Value; + bool resetFamily = oldFamilies?.Contains(currentFamily) ?? false; - if (resetFamily) - { - familyProperty.Current.Value = familyProperty.Items.FirstOrDefault(); - } - }); + if (resetFamily) + { + familyProperty.Current.Value = familyProperty.Items.FirstOrDefault(); + } }); + }); - familyProperty.Current.BindValueChanged(x => - { - performChange(); + familyProperty.Current.BindValueChanged(x => + { + performChange(); + + // re-calculate if family changed. + string[] weight = fonts.Where(f => f.Family == x.NewValue).Select(f => f.Weight).Where(s => !string.IsNullOrEmpty(s)).Distinct().ToArray(); + weightProperty.Items.Clear(); + weightProperty.Items.AddRange(weight); + + // set to first or empty if change new family. + weightProperty.Current.Value = weight.FirstOrDefault(); + }); + weightProperty.Current.BindValueChanged(_ => performChange()); + fontSizeProperty.Current.BindValueChanged(_ => performChange()); + fixedWidthCheckbox.Current.BindValueChanged(_ => performChange()); + } - // re-calculate if family changed. - string[] weight = fonts.Where(f => f.Family == x.NewValue).Select(f => f.Weight).Where(s => !string.IsNullOrEmpty(s)).Distinct().ToArray(); - weightProperty.Items.Clear(); - weightProperty.Items.AddRange(weight); + [BackgroundDependencyLoader] + private void load(FontManager fontManager, IRenderer renderer) + { + fonts.BindTo(fontManager.Fonts); - // set to first or empty if change new family. - weightProperty.Current.Value = weight.FirstOrDefault(); - }); - weightProperty.Current.BindValueChanged(_ => performChange()); - fontSizeProperty.Current.BindValueChanged(_ => performChange()); - fixedWidthCheckbox.Current.BindValueChanged(_ => performChange()); - } + // create local font store and import those files + localFontStore = new KaraokeLocalFontStore(fontManager, renderer); + fontStore.AddStore(localFontStore); - [BackgroundDependencyLoader] - private void load(FontManager fontManager, IRenderer renderer) + Current.BindValueChanged(e => { - fonts.BindTo(fontManager.Fonts); - - // create local font store and import those files - localFontStore = new KaraokeLocalFontStore(fontManager, renderer); - fontStore.AddStore(localFontStore); + var newFont = e.NewValue; + familyProperty.Current.Value = newFont.Family; + weightProperty.Current.Value = newFont.Weight; + fontSizeProperty.Current.Value = newFont.Size; + fixedWidthCheckbox.Current.Value = newFont.FixedWidth; + }, true); + } - Current.BindValueChanged(e => - { - var newFont = e.NewValue; - familyProperty.Current.Value = newFont.Family; - weightProperty.Current.Value = newFont.Weight; - fontSizeProperty.Current.Value = newFont.Size; - fixedWidthCheckbox.Current.Value = newFont.FixedWidth; - }, true); - } + private void performChange() + { + var fontUsage = generateFontUsage(); - private void performChange() - { - var fontUsage = generateFontUsage(); + // add font to local font store for preview purpose. + localFontStore.ClearFont(); + localFontStore.AddFont(fontUsage); - // add font to local font store for preview purpose. - localFontStore.ClearFont(); - localFontStore.AddFont(fontUsage); + previewText.Font = fontUsage; - previewText.Font = fontUsage; + // write-back the value. + Current.Value = fontUsage; + } - // write-back the value. - Current.Value = fontUsage; - } + private FontUsage generateFontUsage() + { + string family = familyProperty.Current.Value; + string weight = weightProperty.Current.Value; + float size = fontSizeProperty.Current.Value; + bool fixedWidth = fixedWidthCheckbox.Current.Value; + return new FontUsage(family, size, weight, false, fixedWidth); + } - private FontUsage generateFontUsage() - { - string family = familyProperty.Current.Value; - string weight = weightProperty.Current.Value; - float size = fontSizeProperty.Current.Value; - bool fixedWidth = fixedWidthCheckbox.Current.Value; - return new FontUsage(family, size, weight, false, fixedWidth); - } + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); - protected override void Dispose(bool isDisposing) - { - base.Dispose(isDisposing); + fontStore?.RemoveStore(localFontStore); + } - fontStore?.RemoveStore(localFontStore); - } + internal partial class FontFamilyPropertyList : FontPropertyList + { + protected override RearrangeableTextFlowListContainer CreateRearrangeableListContainer() + => new RearrangeableFontFamilyListContainer(); - internal partial class FontFamilyPropertyList : FontPropertyList + private partial class RearrangeableFontFamilyListContainer : RearrangeableTextFlowListContainer { - protected override RearrangeableTextFlowListContainer CreateRearrangeableListContainer() - => new RearrangeableFontFamilyListContainer(); + protected override DrawableTextListItem CreateDrawable(string item) + => new DrawableFontFamilyListItem(item); - private partial class RearrangeableFontFamilyListContainer : RearrangeableTextFlowListContainer + private partial class DrawableFontFamilyListItem : DrawableTextListItem { - protected override DrawableTextListItem CreateDrawable(string item) - => new DrawableFontFamilyListItem(item); + [Resolved] + private FontManager fontManager { get; set; } - private partial class DrawableFontFamilyListItem : DrawableTextListItem + public DrawableFontFamilyListItem(string item) + : base(item) { - [Resolved] - private FontManager fontManager { get; set; } - - public DrawableFontFamilyListItem(string item) - : base(item) - { - } + } - protected override void CreateDisplayContent(OsuTextFlowContainer textFlowContainer, string model) - { - textFlowContainer.TextAnchor = Anchor.BottomLeft; - textFlowContainer.AddText(model); + protected override void CreateDisplayContent(OsuTextFlowContainer textFlowContainer, string model) + { + textFlowContainer.TextAnchor = Anchor.BottomLeft; + textFlowContainer.AddText(model); - var matchedFormat = fontManager.Fonts - .Where(x => x.Family == Model).Select(x => x.FontFormat) - .Distinct() - .ToArray(); + var matchedFormat = fontManager.Fonts + .Where(x => x.Family == Model).Select(x => x.FontFormat) + .Distinct() + .ToArray(); - foreach (var format in matchedFormat) - { - textFlowContainer.AddText(" "); - textFlowContainer.AddArbitraryDrawable(new FontFormatBadge(format)); - } + foreach (var format in matchedFormat) + { + textFlowContainer.AddText(" "); + textFlowContainer.AddArbitraryDrawable(new FontFormatBadge(format)); } } } + } - private partial class FontFormatBadge : Container + private partial class FontFormatBadge : Container + { + private readonly FontFormat fontFormat; + private readonly Box box; + private readonly OsuSpriteText badgeText; + + public FontFormatBadge(FontFormat fontFormat) { - private readonly FontFormat fontFormat; - private readonly Box box; - private readonly OsuSpriteText badgeText; + this.fontFormat = fontFormat; - public FontFormatBadge(FontFormat fontFormat) + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 3; + Children = new Drawable[] { - this.fontFormat = fontFormat; - - AutoSizeAxes = Axes.Both; - Masking = true; - CornerRadius = 3; - Children = new Drawable[] + box = new Box + { + RelativeSizeAxes = Axes.Both + }, + badgeText = new OsuSpriteText { - box = new Box + Font = OsuFont.Default.With(size: 10), + Margin = new MarginPadding { - RelativeSizeAxes = Axes.Both + Vertical = 1, + Horizontal = 3 }, - badgeText = new OsuSpriteText - { - Font = OsuFont.Default.With(size: 10), - Margin = new MarginPadding - { - Vertical = 1, - Horizontal = 3 - }, - } - }; - } + } + }; + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + box.Colour = fontFormat switch { - box.Colour = fontFormat switch - { - FontFormat.Internal => colours.Gray7, - FontFormat.Fnt => colours.Pink, - FontFormat.Ttf => colours.Blue, - _ => throw new ArgumentOutOfRangeException(nameof(fontFormat)) - }; - - // todo : might apply translate. - badgeText.Text = fontFormat.ToString(); - } + FontFormat.Internal => colours.Gray7, + FontFormat.Fnt => colours.Pink, + FontFormat.Ttf => colours.Blue, + _ => throw new ArgumentOutOfRangeException(nameof(fontFormat)) + }; + + // todo : might apply translate. + badgeText.Text = fontFormat.ToString(); } } + } - internal partial class FontPropertyList : CompositeDrawable - { - private readonly CornerBackground background; - private readonly TextPropertySearchTextBox filter; - private readonly RearrangeableTextFlowListContainer propertyFlowList; + internal partial class FontPropertyList : CompositeDrawable + { + private readonly CornerBackground background; + private readonly TextPropertySearchTextBox filter; + private readonly RearrangeableTextFlowListContainer propertyFlowList; - private readonly BindableWithCurrent current = new(); + private readonly BindableWithCurrent current = new(); - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } - public BindableList Items => propertyFlowList.Items; + public BindableList Items => propertyFlowList.Items; - public FontPropertyList() + public FontPropertyList() + { + InternalChild = new Container { - InternalChild = new Container + Padding = new MarginPadding(10), + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - Padding = new MarginPadding(10), - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + background = new CornerBackground { - background = new CornerBackground + RelativeSizeAxes = Axes.Both + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - RelativeSizeAxes = Axes.Both + new Dimension(GridSizeMode.Absolute, 40), + new Dimension() }, - new GridContainer + Content = new[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + new Drawable[] { - new Dimension(GridSizeMode.Absolute, 40), - new Dimension() + filter = new TextPropertySearchTextBox + { + RelativeSizeAxes = Axes.X, + } }, - Content = new[] + new Drawable[] { - new Drawable[] - { - filter = new TextPropertySearchTextBox - { - RelativeSizeAxes = Axes.X, - } - }, - new Drawable[] + propertyFlowList = CreateRearrangeableListContainer().With(x => { - propertyFlowList = CreateRearrangeableListContainer().With(x => + x.RelativeSizeAxes = Axes.Both; + x.RequestSelection = item => { - x.RelativeSizeAxes = Axes.Both; - x.RequestSelection = item => - { - Current.Value = item; - }; - }) - } + Current.Value = item; + }; + }) } } } - }; + } + }; - filter.Current.BindValueChanged(e => propertyFlowList.Filter(e.NewValue)); - Current.BindValueChanged(e => propertyFlowList.SelectedSet.Value = e.NewValue); - } + filter.Current.BindValueChanged(e => propertyFlowList.Filter(e.NewValue)); + Current.BindValueChanged(e => propertyFlowList.SelectedSet.Value = e.NewValue); + } - protected virtual RearrangeableTextFlowListContainer CreateRearrangeableListContainer() - => new(); + protected virtual RearrangeableTextFlowListContainer CreateRearrangeableListContainer() + => new(); - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - background.Colour = colours.ContextMenuGray; - } + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.ContextMenuGray; + } - private partial class TextPropertySearchTextBox : SearchTextBox - { - protected override Color4 SelectionColour => Color4.Gray; + private partial class TextPropertySearchTextBox : SearchTextBox + { + protected override Color4 SelectionColour => Color4.Gray; - public TextPropertySearchTextBox() - { - PlaceholderText = @"Search..."; - } + public TextPropertySearchTextBox() + { + PlaceholderText = @"Search..."; } } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledColourSelector.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledColourSelector.cs index 5ddab3716..cca79fee9 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledColourSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledColourSelector.cs @@ -17,94 +17,93 @@ using osu.Game.Graphics.UserInterfaceV2; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2 +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; + +// refactor this shit +public partial class LabelledColourSelector : LabelledComponent { - // refactor this shit - public partial class LabelledColourSelector : LabelledComponent + public LabelledColourSelector() + : base(true) { - public LabelledColourSelector() - : base(true) - { - } + } - protected override ColourSelectorDisplay CreateComponent() - => new(); + protected override ColourSelectorDisplay CreateComponent() + => new(); - public partial class ColourSelectorDisplay : CompositeDrawable, IHasCurrentValue, IHasPopover - { - private readonly BindableWithCurrent current = new(); + public partial class ColourSelectorDisplay : CompositeDrawable, IHasCurrentValue, IHasPopover + { + private readonly BindableWithCurrent current = new(); - private Box fill; - private OsuSpriteText colourHexCode; + private Box fill; + private OsuSpriteText colourHexCode; - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } - [BackgroundDependencyLoader] - private void load(OsuColour colours) - { - AutoSizeAxes = Axes.Y; - RelativeSizeAxes = Axes.X; + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + AutoSizeAxes = Axes.Y; + RelativeSizeAxes = Axes.X; - InternalChild = new FillFlowContainer + InternalChild = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 10), - Children = new Drawable[] + new OsuClickableContainer { - new OsuClickableContainer + RelativeSizeAxes = Axes.X, + Height = 60, + CornerRadius = 10, + Masking = true, + BorderThickness = 2f, + BorderColour = colours.Gray5, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = 60, - CornerRadius = 10, - Masking = true, - BorderThickness = 2f, - BorderColour = colours.Gray5, - Children = new Drawable[] + fill = new Box { - fill = new Box - { - RelativeSizeAxes = Axes.Both - }, - colourHexCode = new OsuSpriteText - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Font = OsuFont.Default.With(size: 12) - } + RelativeSizeAxes = Axes.Both }, - Action = this.ShowPopover + colourHexCode = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.Default.With(size: 12) + } }, - } - }; - } + Action = this.ShowPopover + }, + } + }; + } - protected override void LoadComplete() - { - base.LoadComplete(); + protected override void LoadComplete() + { + base.LoadComplete(); - current.BindValueChanged(_ => updateColour(), true); - } + current.BindValueChanged(_ => updateColour(), true); + } - private void updateColour() - { - fill.Colour = current.Value; - colourHexCode.Text = current.Value.ToHex(); - colourHexCode.Colour = OsuColour.ForegroundTextColourFor(current.Value); - } + private void updateColour() + { + fill.Colour = current.Value; + colourHexCode.Text = current.Value.ToHex(); + colourHexCode.Colour = OsuColour.ForegroundTextColourFor(current.Value); + } - public Popover GetPopover() => new OsuPopover(false) + public Popover GetPopover() => new OsuPopover(false) + { + Child = new OsuColourPicker { - Child = new OsuColourPicker - { - Current = { BindTarget = Current } - } - }; - } + Current = { BindTarget = Current } + } + }; } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledHueSelector.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledHueSelector.cs index fbe92b95c..0a8fb6441 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledHueSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledHueSelector.cs @@ -13,84 +13,83 @@ using osu.Game.Graphics.UserInterfaceV2; using osuTK; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2 +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; + +public partial class LabelledHueSelector : LabelledComponent { - public partial class LabelledHueSelector : LabelledComponent + public LabelledHueSelector() + : base(true) { - public LabelledHueSelector() - : base(true) - { - } + } - protected override OsuHueSelector CreateComponent() - => new(); + protected override OsuHueSelector CreateComponent() + => new(); - private static EdgeEffectParameters createShadowParameters() => new() - { - Type = EdgeEffectType.Shadow, - Offset = new Vector2(0, 1), - Radius = 3, - Colour = Colour4.Black.Opacity(0.3f) - }; + private static EdgeEffectParameters createShadowParameters() => new() + { + Type = EdgeEffectType.Shadow, + Offset = new Vector2(0, 1), + Radius = 3, + Colour = Colour4.Black.Opacity(0.3f) + }; - /// - /// Copied from - /// - public partial class OsuHueSelector : HSVColourPicker.HueSelector, IHasCurrentValue - { - private const float corner_radius = 10; - private const float control_border_thickness = 3; + /// + /// Copied from + /// + public partial class OsuHueSelector : HSVColourPicker.HueSelector, IHasCurrentValue + { + private const float corner_radius = 10; + private const float control_border_thickness = 3; - public Bindable Current + public Bindable Current + { + get => Hue; + set { - get => Hue; - set - { - ArgumentNullException.ThrowIfNull(value); + ArgumentNullException.ThrowIfNull(value); - Hue.UnbindBindings(); - Hue.BindTo(value); - } + Hue.UnbindBindings(); + Hue.BindTo(value); } + } - public OsuHueSelector() - { - SliderBar.CornerRadius = corner_radius; - SliderBar.Masking = true; - } + public OsuHueSelector() + { + SliderBar.CornerRadius = corner_radius; + SliderBar.Masking = true; + } + + protected override Drawable CreateSliderNub() => new SliderNub(this); - protected override Drawable CreateSliderNub() => new SliderNub(this); + private partial class SliderNub : CompositeDrawable + { + private readonly Bindable hue; + private readonly Box fill; - private partial class SliderNub : CompositeDrawable + public SliderNub(OsuHueSelector osuHueSelector) { - private readonly Bindable hue; - private readonly Box fill; + hue = osuHueSelector.Hue.GetBoundCopy(); - public SliderNub(OsuHueSelector osuHueSelector) + InternalChild = new CircularContainer { - hue = osuHueSelector.Hue.GetBoundCopy(); - - InternalChild = new CircularContainer + Height = 35, + Width = 10, + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Masking = true, + BorderColour = Colour4.White, + BorderThickness = control_border_thickness, + EdgeEffect = createShadowParameters(), + Child = fill = new Box { - Height = 35, - Width = 10, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - Masking = true, - BorderColour = Colour4.White, - BorderThickness = control_border_thickness, - EdgeEffect = createShadowParameters(), - Child = fill = new Box - { - RelativeSizeAxes = Axes.Both - } - }; - } + RelativeSizeAxes = Axes.Both + } + }; + } - protected override void LoadComplete() - { - hue.BindValueChanged(h => fill.Colour = Colour4.FromHSV(h.NewValue, 1, 1), true); - } + protected override void LoadComplete() + { + hue.BindValueChanged(h => fill.Colour = Colour4.FromHSV(h.NewValue, 1, 1), true); } } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledImageSelector.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledImageSelector.cs index a490869ac..2ed14c7a9 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledImageSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledImageSelector.cs @@ -5,13 +5,12 @@ using osu.Game.Graphics.UserInterfaceV2; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2 +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; + +/// +/// A labelled text box which reveals an inline file chooser when clicked. +/// Will be replaced after has official one. +/// +public partial class LabelledImageSelector : LabelledTextBox { - /// - /// A labelled text box which reveals an inline file chooser when clicked. - /// Will be replaced after has official one. - /// - public partial class LabelledImageSelector : LabelledTextBox - { - } } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledRealTimeSliderBar.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledRealTimeSliderBar.cs index ef2a5c46d..094700bad 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledRealTimeSliderBar.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LabelledRealTimeSliderBar.cs @@ -8,12 +8,11 @@ using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays.Settings; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2 +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; + +public partial class LabelledRealTimeSliderBar : LabelledSliderBar + where TNumber : struct, IEquatable, IComparable, IConvertible { - public partial class LabelledRealTimeSliderBar : LabelledSliderBar - where TNumber : struct, IEquatable, IComparable, IConvertible - { - protected override SettingsSlider CreateComponent() - => base.CreateComponent().With(x => x.TransferValueOnCommit = false); - } + protected override SettingsSlider CreateComponent() + => base.CreateComponent().With(x => x.TransferValueOnCommit = false); } diff --git a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LanguageSelector.cs b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LanguageSelector.cs index 1fc3d2ecb..2344759c8 100644 --- a/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LanguageSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Graphics/UserInterfaceV2/LanguageSelector.cs @@ -15,105 +15,104 @@ using osu.Game.Rulesets.Karaoke.Utils; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2 +namespace osu.Game.Rulesets.Karaoke.Graphics.UserInterfaceV2; + +public partial class LanguageSelector : CompositeDrawable, IHasCurrentValue { - public partial class LanguageSelector : CompositeDrawable, IHasCurrentValue - { - private readonly LanguageSelectionSearchTextBox filter; + private readonly LanguageSelectionSearchTextBox filter; - private readonly BindableWithCurrent current = new(); + private readonly BindableWithCurrent current = new(); - public Bindable Current - { - get => current.Current; - set => current.Current = value; - } + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } - public override bool AcceptsFocus => true; + public override bool AcceptsFocus => true; - public override bool RequestsFocus => true; + public override bool RequestsFocus => true; - public LanguageSelector() - { - var languages = new BindableList(CultureInfoUtils.GetAvailableLanguages()); + public LanguageSelector() + { + var languages = new BindableList(CultureInfoUtils.GetAvailableLanguages()); - RearrangeableLanguageListContainer languageList; - InternalChild = new GridContainer + RearrangeableLanguageListContainer languageList; + InternalChild = new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, 40), + new Dimension() + }, + Content = new[] { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + new Drawable[] { - new Dimension(GridSizeMode.Absolute, 40), - new Dimension() + filter = new LanguageSelectionSearchTextBox + { + RelativeSizeAxes = Axes.X, + } }, - Content = new[] + new Drawable[] { - new Drawable[] + languageList = new RearrangeableLanguageListContainer { - filter = new LanguageSelectionSearchTextBox + RelativeSizeAxes = Axes.Both, + RequestSelection = item => { - RelativeSizeAxes = Axes.X, - } - }, - new Drawable[] - { - languageList = new RearrangeableLanguageListContainer - { - RelativeSizeAxes = Axes.Both, - RequestSelection = item => - { - Current.Value = item; - }, - Items = { BindTarget = languages } - } + Current.Value = item; + }, + Items = { BindTarget = languages } } } - }; + } + }; - filter.Current.BindValueChanged(e => languageList.Filter(e.NewValue)); - Current.BindValueChanged(e => languageList.SelectedSet.Value = e.NewValue); - } + filter.Current.BindValueChanged(e => languageList.Filter(e.NewValue)); + Current.BindValueChanged(e => languageList.SelectedSet.Value = e.NewValue); + } - protected override void OnFocus(FocusEvent e) - { - base.OnFocus(e); + protected override void OnFocus(FocusEvent e) + { + base.OnFocus(e); - GetContainingInputManager().ChangeFocus(filter); - } + GetContainingInputManager().ChangeFocus(filter); + } - private partial class LanguageSelectionSearchTextBox : SearchTextBox - { - protected override Color4 SelectionColour => Color4.Gray; + private partial class LanguageSelectionSearchTextBox : SearchTextBox + { + protected override Color4 SelectionColour => Color4.Gray; - public LanguageSelectionSearchTextBox() - { - PlaceholderText = @"type in keywords..."; - } + public LanguageSelectionSearchTextBox() + { + PlaceholderText = @"type in keywords..."; } + } - private partial class RearrangeableLanguageListContainer : RearrangeableTextFlowListContainer + private partial class RearrangeableLanguageListContainer : RearrangeableTextFlowListContainer + { + protected override DrawableTextListItem CreateDrawable(CultureInfo item) + => new DrawableLanguageListItem(item); + + private partial class DrawableLanguageListItem : DrawableTextListItem { - protected override DrawableTextListItem CreateDrawable(CultureInfo item) - => new DrawableLanguageListItem(item); + public DrawableLanguageListItem(CultureInfo item) + : base(item) + { + } - private partial class DrawableLanguageListItem : DrawableTextListItem + public override IEnumerable FilterTerms => new[] { - public DrawableLanguageListItem(CultureInfo item) - : base(item) - { - } + new LocalisableString(Model.Name), + new LocalisableString(Model.DisplayName), + new LocalisableString(Model.EnglishName), + new LocalisableString(Model.NativeName) + }; - public override IEnumerable FilterTerms => new[] - { - new LocalisableString(Model.Name), - new LocalisableString(Model.DisplayName), - new LocalisableString(Model.EnglishName), - new LocalisableString(Model.NativeName) - }; - - protected override void CreateDisplayContent(OsuTextFlowContainer textFlowContainer, CultureInfo model) - => textFlowContainer.AddText(CultureInfoUtils.GetLanguageDisplayText(model)); - } + protected override void CreateDisplayContent(OsuTextFlowContainer textFlowContainer, CultureInfo model) + => textFlowContainer.AddText(CultureInfoUtils.GetLanguageDisplayText(model)); } } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Archives/CachedFontArchiveReader.cs b/osu.Game.Rulesets.Karaoke/IO/Archives/CachedFontArchiveReader.cs index 53eafa357..9b157aff4 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Archives/CachedFontArchiveReader.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Archives/CachedFontArchiveReader.cs @@ -10,50 +10,49 @@ using osu.Game.IO.Archives; using SharpCompress.Archives.Zip; -namespace osu.Game.Rulesets.Karaoke.IO.Archives +namespace osu.Game.Rulesets.Karaoke.IO.Archives; + +/// +/// For reading cached font reader. +/// Cached font will be saved as xxx.cached fnt into cached folder. +/// And notice that this class is just copied from +/// +public class CachedFontArchiveReader : ArchiveReader { - /// - /// For reading cached font reader. - /// Cached font will be saved as xxx.cached fnt into cached folder. - /// And notice that this class is just copied from - /// - public class CachedFontArchiveReader : ArchiveReader + private readonly Stream archiveStream; + private readonly ZipArchive archive; + + public CachedFontArchiveReader(Stream archiveStream, string name = null) + : base(name) + { + this.archiveStream = archiveStream; + archive = ZipArchive.Open(archiveStream); + } + + public override Stream GetStream(string name) + { + // will search .fnt file or image in here. + string file = Path.HasExtension(name) ? name : $"{name}.bin"; + var entry = archive.Entries.SingleOrDefault(e => e.Key == file); + if (entry == null) + throw new FileNotFoundException(); + + // allow seeking + var copy = new MemoryStream(); + + using (var s = entry.OpenEntryStream()) + s.CopyTo(copy); + + copy.Position = 0; + + return copy; + } + + public override void Dispose() { - private readonly Stream archiveStream; - private readonly ZipArchive archive; - - public CachedFontArchiveReader(Stream archiveStream, string name = null) - : base(name) - { - this.archiveStream = archiveStream; - archive = ZipArchive.Open(archiveStream); - } - - public override Stream GetStream(string name) - { - // will search .fnt file or image in here. - string file = Path.HasExtension(name) ? name : $"{name}.bin"; - var entry = archive.Entries.SingleOrDefault(e => e.Key == file); - if (entry == null) - throw new FileNotFoundException(); - - // allow seeking - var copy = new MemoryStream(); - - using (var s = entry.OpenEntryStream()) - s.CopyTo(copy); - - copy.Position = 0; - - return copy; - } - - public override void Dispose() - { - archive.Dispose(); - archiveStream.Dispose(); - } - - public override IEnumerable Filenames => archive.Entries.Select(e => e.Key).ExcludeSystemFileNames(); + archive.Dispose(); + archiveStream.Dispose(); } + + public override IEnumerable Filenames => archive.Entries.Select(e => e.Key).ExcludeSystemFileNames(); } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ColourConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ColourConverter.cs index eafe9089f..144749d7a 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ColourConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ColourConverter.cs @@ -7,24 +7,23 @@ using osu.Framework.Extensions.Color4Extensions; using osuTK.Graphics; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class ColourConverter : JsonConverter { - public class ColourConverter : JsonConverter + public override Color4 ReadJson(JsonReader reader, Type objectType, Color4 existingValue, bool hasExistingValue, JsonSerializer serializer) { - public override Color4 ReadJson(JsonReader reader, Type objectType, Color4 existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JToken.Load(reader); - string? value = obj.Value(); + var obj = JToken.Load(reader); + string? value = obj.Value(); - if (value == null) - return new Color4(); + if (value == null) + return new Color4(); - return Color4Extensions.FromHex(value); - } + return Color4Extensions.FromHex(value); + } - public override void WriteJson(JsonWriter writer, Color4 value, JsonSerializer serializer) - { - writer.WriteValue(value.ToHex()); - } + public override void WriteJson(JsonWriter writer, Color4 value, JsonSerializer serializer) + { + writer.WriteValue(value.ToHex()); } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/CultureInfoConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/CultureInfoConverter.cs index 28ba518f4..9ca3058ec 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/CultureInfoConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/CultureInfoConverter.cs @@ -7,26 +7,25 @@ using Newtonsoft.Json.Linq; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class CultureInfoConverter : JsonConverter { - public class CultureInfoConverter : JsonConverter + public override CultureInfo? ReadJson(JsonReader reader, Type objectType, CultureInfo? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public override CultureInfo? ReadJson(JsonReader reader, Type objectType, CultureInfo? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JToken.Load(reader); - int? value = obj.Value(); + var obj = JToken.Load(reader); + int? value = obj.Value(); - if (value == null) - return null; + if (value == null) + return null; - return CultureInfoUtils.CreateLoadCultureInfoById(value.Value); - } + return CultureInfoUtils.CreateLoadCultureInfoById(value.Value); + } - public override void WriteJson(JsonWriter writer, CultureInfo? value, JsonSerializer serializer) - { - int? id = value != null ? CultureInfoUtils.GetSaveCultureInfoId(value) : null; + public override void WriteJson(JsonWriter writer, CultureInfo? value, JsonSerializer serializer) + { + int? id = value != null ? CultureInfoUtils.GetSaveCultureInfoId(value) : null; - writer.WriteValue(id); - } + writer.WriteValue(id); } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/DictionaryConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/DictionaryConverter.cs index 9be01e082..aac8950c4 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/DictionaryConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/DictionaryConverter.cs @@ -7,38 +7,37 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public abstract class DictionaryConverter : JsonConverter> where TKey : notnull { - public abstract class DictionaryConverter : JsonConverter> where TKey : notnull + public sealed override IDictionary ReadJson(JsonReader reader, Type objectType, IDictionary? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public sealed override IDictionary ReadJson(JsonReader reader, Type objectType, IDictionary? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JArray.Load(reader); - return obj.OfType().ToDictionary( - x => deserializeKey((JProperty)x.First!), - x => deserializeValue((JProperty)x.Last!) - ); + var obj = JArray.Load(reader); + return obj.OfType().ToDictionary( + x => deserializeKey((JProperty)x.First!), + x => deserializeValue((JProperty)x.Last!) + ); - TKey deserializeKey(JProperty token) - => serializer.Deserialize(token.Value.CreateReader())!; + TKey deserializeKey(JProperty token) + => serializer.Deserialize(token.Value.CreateReader())!; - TValue deserializeValue(JProperty token) - => serializer.Deserialize(token.Value.CreateReader())!; - } - - public override void WriteJson(JsonWriter writer, IDictionary? value, JsonSerializer serializer) - { - ArgumentNullException.ThrowIfNull(value); + TValue deserializeValue(JProperty token) + => serializer.Deserialize(token.Value.CreateReader())!; + } - writer.WriteStartArray(); + public override void WriteJson(JsonWriter writer, IDictionary? value, JsonSerializer serializer) + { + ArgumentNullException.ThrowIfNull(value); - foreach (var keyValuePair in value) - { - var jObject = JObject.FromObject(keyValuePair, serializer); - jObject.WriteTo(writer); - } + writer.WriteStartArray(); - writer.WriteEndArray(); + foreach (var keyValuePair in value) + { + var jObject = JObject.FromObject(keyValuePair, serializer); + jObject.WriteTo(writer); } + + writer.WriteEndArray(); } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/FontUsageConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/FontUsageConverter.cs index ad056a160..44c432dbe 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/FontUsageConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/FontUsageConverter.cs @@ -7,68 +7,67 @@ using Newtonsoft.Json.Linq; using osu.Framework.Graphics.Sprites; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class FontUsageConverter : JsonConverter { - public class FontUsageConverter : JsonConverter - { - private const float default_text_size = 20; + private const float default_text_size = 20; - public override FontUsage ReadJson(JsonReader reader, Type objectType, FontUsage existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JToken.Load(reader); - var properties = obj.Children().OfType().ToArray(); + public override FontUsage ReadJson(JsonReader reader, Type objectType, FontUsage existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var obj = JToken.Load(reader); + var properties = obj.Children().OfType().ToArray(); - if (!properties.Any()) - return new FontUsage(size: default_text_size); + if (!properties.Any()) + return new FontUsage(size: default_text_size); - var font = new FontUsage(size: default_text_size); + var font = new FontUsage(size: default_text_size); - return properties.Aggregate(font, (current, property) => property.Name switch - { - "family" => current.With(property.Value.ToObject()), - "weight" => current.With(weight: property.Value.ToObject()), - "size" => current.With(size: property.Value.ToObject()), - "italics" => current.With(italics: property.Value.ToObject()), - "fixedWidth" => current.With(fixedWidth: property.Value.ToObject()), - _ => current - }); - } - - public override void WriteJson(JsonWriter writer, FontUsage value, JsonSerializer serializer) + return properties.Aggregate(font, (current, property) => property.Name switch { - writer.WriteStartObject(); + "family" => current.With(property.Value.ToObject()), + "weight" => current.With(weight: property.Value.ToObject()), + "size" => current.With(size: property.Value.ToObject()), + "italics" => current.With(italics: property.Value.ToObject()), + "fixedWidth" => current.With(fixedWidth: property.Value.ToObject()), + _ => current + }); + } - if (!string.IsNullOrEmpty(value.Family)) - { - writer.WritePropertyName("family"); - writer.WriteValue(value.Family); - } + public override void WriteJson(JsonWriter writer, FontUsage value, JsonSerializer serializer) + { + writer.WriteStartObject(); - if (!string.IsNullOrEmpty(value.Weight)) - { - writer.WritePropertyName("weight"); - writer.WriteValue(value.Weight); - } + if (!string.IsNullOrEmpty(value.Family)) + { + writer.WritePropertyName("family"); + writer.WriteValue(value.Family); + } - if (value.Size != default_text_size) - { - writer.WritePropertyName("size"); - writer.WriteValue(value.Size); - } + if (!string.IsNullOrEmpty(value.Weight)) + { + writer.WritePropertyName("weight"); + writer.WriteValue(value.Weight); + } - if (value.Italics) - { - writer.WritePropertyName("italics"); - writer.WriteValue(true); - } + if (value.Size != default_text_size) + { + writer.WritePropertyName("size"); + writer.WriteValue(value.Size); + } - if (value.FixedWidth) - { - writer.WritePropertyName("fixedWidth"); - writer.WriteValue(true); - } + if (value.Italics) + { + writer.WritePropertyName("italics"); + writer.WriteValue(true); + } - writer.WriteEndObject(); + if (value.FixedWidth) + { + writer.WritePropertyName("fixedWidth"); + writer.WriteValue(true); } + + writer.WriteEndObject(); } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/GenericTypeConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/GenericTypeConverter.cs index c662d7ce3..c3520df7e 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/GenericTypeConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/GenericTypeConverter.cs @@ -7,76 +7,75 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public abstract class GenericTypeConverter : GenericTypeConverter { - public abstract class GenericTypeConverter : GenericTypeConverter - { - protected override string GetNameByType(MemberInfo type) - => type.Name; - } + protected override string GetNameByType(MemberInfo type) + => type.Name; +} - public abstract class GenericTypeConverter : JsonConverter where TTypeName : notnull +public abstract class GenericTypeConverter : JsonConverter where TTypeName : notnull +{ + public sealed override TType ReadJson(JsonReader reader, Type objectType, TType? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public sealed override TType ReadJson(JsonReader reader, Type objectType, TType? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var jObject = JObject.Load(reader); - var type = objectType != typeof(TType) ? objectType : getTypeByProperties(jObject); + var jObject = JObject.Load(reader); + var type = objectType != typeof(TType) ? objectType : getTypeByProperties(jObject); - var newReader = jObject.CreateReader(); + var newReader = jObject.CreateReader(); - var instance = (TType)Activator.CreateInstance(type)!; - serializer.Populate(newReader, instance); - PostProcessValue(instance, jObject, serializer); - return instance; + var instance = (TType)Activator.CreateInstance(type)!; + serializer.Populate(newReader, instance); + PostProcessValue(instance, jObject, serializer); + return instance; - Type getTypeByProperties(JObject jObj) - { - var elementType = GetValueFromProperty(jObj, "$type"); - return GetTypeByName(elementType); - } + Type getTypeByProperties(JObject jObj) + { + var elementType = GetValueFromProperty(jObj, "$type"); + return GetTypeByName(elementType); } + } - protected static TPropertyType GetValueFromProperty(JObject jObject, string propertyName) - { - var jProperties = jObject.Children().OfType().ToArray(); - var value = jProperties.FirstOrDefault(x => x.Name == propertyName)?.Value; - if (value == null) - throw new ArgumentNullException(nameof(value)); + protected static TPropertyType GetValueFromProperty(JObject jObject, string propertyName) + { + var jProperties = jObject.Children().OfType().ToArray(); + var value = jProperties.FirstOrDefault(x => x.Name == propertyName)?.Value; + if (value == null) + throw new ArgumentNullException(nameof(value)); - var elementType = value.ToObject(); - if (elementType == null) - throw new InvalidCastException(nameof(elementType)); + var elementType = value.ToObject(); + if (elementType == null) + throw new InvalidCastException(nameof(elementType)); - return elementType; - } + return elementType; + } - protected virtual void PostProcessValue(TType existingValue, JObject jObject, JsonSerializer serializer) { } + protected virtual void PostProcessValue(TType existingValue, JObject jObject, JsonSerializer serializer) { } - public sealed override void WriteJson(JsonWriter writer, TType? value, JsonSerializer serializer) - { - ArgumentNullException.ThrowIfNull(value); + public sealed override void WriteJson(JsonWriter writer, TType? value, JsonSerializer serializer) + { + ArgumentNullException.ThrowIfNull(value); - var resolver = serializer.ContractResolver; + var resolver = serializer.ContractResolver; - // follow: https://stackoverflow.com/a/59329703 - // not a good way but seems there's no better choice. - serializer.Converters.Remove(this); - serializer.ContractResolver = new WritablePropertiesOnlyResolver(); + // follow: https://stackoverflow.com/a/59329703 + // not a good way but seems there's no better choice. + serializer.Converters.Remove(this); + serializer.ContractResolver = new WritablePropertiesOnlyResolver(); - var jObject = JObject.FromObject(value, serializer); + var jObject = JObject.FromObject(value, serializer); - serializer.Converters.Add(this); - serializer.ContractResolver = resolver; + serializer.Converters.Add(this); + serializer.ContractResolver = resolver; - jObject.AddFirst(new JProperty("$type", GetNameByType(value.GetType()))); - PostProcessJObject(jObject, value, serializer); - jObject.WriteTo(writer); - } + jObject.AddFirst(new JProperty("$type", GetNameByType(value.GetType()))); + PostProcessJObject(jObject, value, serializer); + jObject.WriteTo(writer); + } - protected virtual void PostProcessJObject(JObject jObject, TType value, JsonSerializer serializer) { } + protected virtual void PostProcessJObject(JObject jObject, TType value, JsonSerializer serializer) { } - protected abstract Type GetTypeByName(TTypeName name); + protected abstract Type GetTypeByName(TTypeName name); - protected abstract TTypeName GetNameByType(MemberInfo type); - } + protected abstract TTypeName GetNameByType(MemberInfo type); } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/KaraokeSkinElementConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/KaraokeSkinElementConverter.cs index 233beadd6..70192847e 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/KaraokeSkinElementConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/KaraokeSkinElementConverter.cs @@ -5,34 +5,33 @@ using System.Reflection; using osu.Game.Rulesets.Karaoke.Skinning.Elements; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class KaraokeSkinElementConverter : GenericTypeConverter { - public class KaraokeSkinElementConverter : GenericTypeConverter - { - protected override Type GetTypeByName(ElementType name) - => GetObjectType(name); + protected override Type GetTypeByName(ElementType name) + => GetObjectType(name); - protected override ElementType GetNameByType(MemberInfo type) - => GetElementType(type); + protected override ElementType GetNameByType(MemberInfo type) + => GetElementType(type); - public static ElementType GetElementType(MemberInfo elementType) => - elementType switch - { - _ when elementType == typeof(LyricFontInfo) => ElementType.LyricFontInfo, - _ when elementType == typeof(LyricLayout) => ElementType.LyricLayout, - _ when elementType == typeof(LyricStyle) => ElementType.LyricStyle, - _ when elementType == typeof(NoteStyle) => ElementType.NoteStyle, - _ => throw new NotSupportedException() - }; + public static ElementType GetElementType(MemberInfo elementType) => + elementType switch + { + _ when elementType == typeof(LyricFontInfo) => ElementType.LyricFontInfo, + _ when elementType == typeof(LyricLayout) => ElementType.LyricLayout, + _ when elementType == typeof(LyricStyle) => ElementType.LyricStyle, + _ when elementType == typeof(NoteStyle) => ElementType.NoteStyle, + _ => throw new NotSupportedException() + }; - public static Type GetObjectType(ElementType elementType) => - elementType switch - { - ElementType.LyricFontInfo => typeof(LyricFontInfo), - ElementType.LyricLayout => typeof(LyricLayout), - ElementType.LyricStyle => typeof(LyricStyle), - ElementType.NoteStyle => typeof(NoteStyle), - _ => throw new NotSupportedException() - }; - } + public static Type GetObjectType(ElementType elementType) => + elementType switch + { + ElementType.LyricFontInfo => typeof(LyricFontInfo), + ElementType.LyricLayout => typeof(LyricLayout), + ElementType.LyricStyle => typeof(LyricStyle), + ElementType.NoteStyle => typeof(NoteStyle), + _ => throw new NotSupportedException() + }; } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/LyricConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/LyricConverter.cs index 2a11d9f79..14ac7e528 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/LyricConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/LyricConverter.cs @@ -11,83 +11,82 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Properties; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class LyricConverter : JsonConverter { - public class LyricConverter : JsonConverter + public override Lyric ReadJson(JsonReader reader, Type objectType, Lyric? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public override Lyric ReadJson(JsonReader reader, Type objectType, Lyric? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var jObject = JObject.Load(reader); + var jObject = JObject.Load(reader); - var newReader = jObject.CreateReader(); + var newReader = jObject.CreateReader(); - var instance = (Lyric)Activator.CreateInstance(objectType)!; - serializer.Populate(newReader, instance); - return instance; - } + var instance = (Lyric)Activator.CreateInstance(objectType)!; + serializer.Populate(newReader, instance); + return instance; + } - public override void WriteJson(JsonWriter writer, Lyric? value, JsonSerializer serializer) - { - ArgumentNullException.ThrowIfNull(value); + public override void WriteJson(JsonWriter writer, Lyric? value, JsonSerializer serializer) + { + ArgumentNullException.ThrowIfNull(value); - // follow: https://stackoverflow.com/a/59329703 - // not a good way but seems there's no better choice. - serializer.Converters.Remove(this); + // follow: https://stackoverflow.com/a/59329703 + // not a good way but seems there's no better choice. + serializer.Converters.Remove(this); - var jObject = JObject.FromObject(value, serializer); + var jObject = JObject.FromObject(value, serializer); - serializer.Converters.Add(this); + serializer.Converters.Add(this); - // should remove some properties from jObject if has the config. - if (value.ReferenceLyricConfig != null) - { - Debug.Assert(value.ReferenceLyricConfig != null); + // should remove some properties from jObject if has the config. + if (value.ReferenceLyricConfig != null) + { + Debug.Assert(value.ReferenceLyricConfig != null); - // note: should convert into snake case. - string[] removedProperties = removePropertyNamesByConfig(value.ReferenceLyricConfig) - .Select(x => x.ToSnakeCase()) - .ToArray(); + // note: should convert into snake case. + string[] removedProperties = removePropertyNamesByConfig(value.ReferenceLyricConfig) + .Select(x => x.ToSnakeCase()) + .ToArray(); - foreach (string removedProperty in removedProperties) - { - jObject.Remove(removedProperty); - } + foreach (string removedProperty in removedProperties) + { + jObject.Remove(removedProperty); } - - jObject.WriteTo(writer); } - private IEnumerable removePropertyNamesByConfig(IReferenceLyricPropertyConfig config) + jObject.WriteTo(writer); + } + + private IEnumerable removePropertyNamesByConfig(IReferenceLyricPropertyConfig config) + { + switch (config) { - switch (config) - { - case ReferenceLyricConfig: - yield break; + case ReferenceLyricConfig: + yield break; - case SyncLyricConfig syncLyricConfig: - yield return nameof(Lyric.Text); + case SyncLyricConfig syncLyricConfig: + yield return nameof(Lyric.Text); - if (syncLyricConfig.SyncTimeTagProperty) - yield return nameof(Lyric.TimeTags); + if (syncLyricConfig.SyncTimeTagProperty) + yield return nameof(Lyric.TimeTags); - yield return nameof(Lyric.RubyTags); - yield return nameof(Lyric.RomajiTags); - yield return nameof(Lyric.StartTime); - yield return nameof(Lyric.Duration); - yield return nameof(Lyric.EndTime); + yield return nameof(Lyric.RubyTags); + yield return nameof(Lyric.RomajiTags); + yield return nameof(Lyric.StartTime); + yield return nameof(Lyric.Duration); + yield return nameof(Lyric.EndTime); - if (syncLyricConfig.SyncSingerProperty) - yield return nameof(Lyric.SingerIds); + if (syncLyricConfig.SyncSingerProperty) + yield return nameof(Lyric.SingerIds); - yield return nameof(Lyric.Translates); - yield return nameof(Lyric.Language); - yield return nameof(Lyric.Order); + yield return nameof(Lyric.Translates); + yield return nameof(Lyric.Language); + yield return nameof(Lyric.Order); - yield break; + yield break; - default: - throw new ArgumentOutOfRangeException(nameof(config), config, "unknown config."); - } + default: + throw new ArgumentOutOfRangeException(nameof(config), config, "unknown config."); } } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ReferenceLyricPropertyConfigConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ReferenceLyricPropertyConfigConverter.cs index f7eaecf6d..6d2b76072 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ReferenceLyricPropertyConfigConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ReferenceLyricPropertyConfigConverter.cs @@ -6,16 +6,15 @@ using System.Reflection; using osu.Game.Rulesets.Karaoke.Objects.Properties; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class ReferenceLyricPropertyConfigConverter : GenericTypeConverter { - public class ReferenceLyricPropertyConfigConverter : GenericTypeConverter + protected override Type GetTypeByName(string name) { - protected override Type GetTypeByName(string name) - { - var assembly = Assembly.GetExecutingAssembly(); - var type = assembly.GetType($"osu.Game.Rulesets.Karaoke.Objects.Properties.{name}"); - Debug.Assert(type != null); - return type; - } + var assembly = Assembly.GetExecutingAssembly(); + var type = assembly.GetType($"osu.Game.Rulesets.Karaoke.Objects.Properties.{name}"); + Debug.Assert(type != null); + return type; } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagConverter.cs index 3cce0046d..6ba198625 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagConverter.cs @@ -8,37 +8,36 @@ using osu.Game.Rulesets.Karaoke.Extensions; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class RomajiTagConverter : JsonConverter { - public class RomajiTagConverter : JsonConverter + public override RomajiTag ReadJson(JsonReader reader, Type objectType, RomajiTag? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public override RomajiTag ReadJson(JsonReader reader, Type objectType, RomajiTag? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JToken.Load(reader); - string? value = obj.Value(); - - if (string.IsNullOrEmpty(value)) - return new RomajiTag(); - - var regex = new Regex("(?[-0-9]+),(?[-0-9]+)]:(?.*$)"); - var result = regex.Match(value); - if (!result.Success) - return new RomajiTag(); - - return new RomajiTag - { - StartIndex = result.GetGroupValue("start"), - EndIndex = result.GetGroupValue("end"), - Text = result.GetGroupValue("romaji") - }; - } - - public override void WriteJson(JsonWriter writer, RomajiTag? value, JsonSerializer serializer) + var obj = JToken.Load(reader); + string? value = obj.Value(); + + if (string.IsNullOrEmpty(value)) + return new RomajiTag(); + + var regex = new Regex("(?[-0-9]+),(?[-0-9]+)]:(?.*$)"); + var result = regex.Match(value); + if (!result.Success) + return new RomajiTag(); + + return new RomajiTag { - ArgumentNullException.ThrowIfNull(value); + StartIndex = result.GetGroupValue("start"), + EndIndex = result.GetGroupValue("end"), + Text = result.GetGroupValue("romaji") + }; + } + + public override void WriteJson(JsonWriter writer, RomajiTag? value, JsonSerializer serializer) + { + ArgumentNullException.ThrowIfNull(value); - string str = $"[{value.StartIndex},{value.EndIndex}]:{value.Text}"; - writer.WriteValue(str); - } + string str = $"[{value.StartIndex},{value.EndIndex}]:{value.Text}"; + writer.WriteValue(str); } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagsConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagsConverter.cs index f9352677c..f63896e3e 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagsConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RomajiTagsConverter.cs @@ -5,11 +5,10 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class RomajiTagsConverter : SortableJsonConverter { - public class RomajiTagsConverter : SortableJsonConverter - { - protected override IEnumerable GetSortedValue(IEnumerable objects) - => TextTagsUtils.Sort(objects); - } + protected override IEnumerable GetSortedValue(IEnumerable objects) + => TextTagsUtils.Sort(objects); } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagConverter.cs index c78257c4a..2fba3da9a 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagConverter.cs @@ -8,38 +8,37 @@ using osu.Game.Rulesets.Karaoke.Extensions; using osu.Game.Rulesets.Karaoke.Objects; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class RubyTagConverter : JsonConverter { - public class RubyTagConverter : JsonConverter + public override RubyTag ReadJson(JsonReader reader, Type objectType, RubyTag? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public override RubyTag ReadJson(JsonReader reader, Type objectType, RubyTag? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JToken.Load(reader); - string? value = obj.Value(); - - if (string.IsNullOrEmpty(value)) - return new RubyTag(); - - var regex = new Regex("(?[-0-9]+),(?[-0-9]+)]:(?.*$)"); - var result = regex.Match(value); - if (!result.Success) - return new RubyTag(); - - return new RubyTag - { - StartIndex = result.GetGroupValue("start"), - EndIndex = result.GetGroupValue("end"), - Text = result.GetGroupValue("ruby") - }; - } - - public override void WriteJson(JsonWriter writer, RubyTag? value, JsonSerializer serializer) + var obj = JToken.Load(reader); + string? value = obj.Value(); + + if (string.IsNullOrEmpty(value)) + return new RubyTag(); + + var regex = new Regex("(?[-0-9]+),(?[-0-9]+)]:(?.*$)"); + var result = regex.Match(value); + if (!result.Success) + return new RubyTag(); + + return new RubyTag { - if (value == null) - throw new ArgumentNullException(nameof(value)); + StartIndex = result.GetGroupValue("start"), + EndIndex = result.GetGroupValue("end"), + Text = result.GetGroupValue("ruby") + }; + } + + public override void WriteJson(JsonWriter writer, RubyTag? value, JsonSerializer serializer) + { + if (value == null) + throw new ArgumentNullException(nameof(value)); - string str = $"[{value.StartIndex},{value.EndIndex}]:{value.Text}"; - writer.WriteValue(str); - } + string str = $"[{value.StartIndex},{value.EndIndex}]:{value.Text}"; + writer.WriteValue(str); } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagsConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagsConverter.cs index f16144a0e..fc9aca9f9 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagsConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/RubyTagsConverter.cs @@ -5,11 +5,10 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class RubyTagsConverter : SortableJsonConverter { - public class RubyTagsConverter : SortableJsonConverter - { - protected override IEnumerable GetSortedValue(IEnumerable objects) - => TextTagsUtils.Sort(objects); - } + protected override IEnumerable GetSortedValue(IEnumerable objects) + => TextTagsUtils.Sort(objects); } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ShaderConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ShaderConverter.cs index 83e97e03a..cea967e6f 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ShaderConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/ShaderConverter.cs @@ -8,38 +8,37 @@ using osu.Framework.Graphics.Shaders; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class ShaderConverter : GenericTypeConverter { - public class ShaderConverter : GenericTypeConverter + protected override void PostProcessJObject(JObject jObject, ICustomizedShader value, JsonSerializer serializer) { - protected override void PostProcessJObject(JObject jObject, ICustomizedShader value, JsonSerializer serializer) - { - var childShader = getShadersFromParent(value, serializer); - - if (childShader != null) - { - jObject.Remove("step_shaders"); - jObject.Add("step_shaders", childShader); - } + var childShader = getShadersFromParent(value, serializer); - static JArray? getShadersFromParent(ICustomizedShader shader, JsonSerializer serializer) - { - if (shader is not StepShader stepShader) - return null; - - return JArray.FromObject(stepShader.StepShaders, serializer); - } + if (childShader != null) + { + jObject.Remove("step_shaders"); + jObject.Add("step_shaders", childShader); } - protected override Type GetTypeByName(string name) + static JArray? getShadersFromParent(ICustomizedShader shader, JsonSerializer serializer) { - // only get name from font - var assembly = AssemblyUtils.GetAssemblyByName("osu.Framework.KaraokeFont"); - Debug.Assert(assembly != null); + if (shader is not StepShader stepShader) + return null; - var type = assembly.GetType($"osu.Framework.Graphics.Shaders.{name}"); - Debug.Assert(type != null); - return type; + return JArray.FromObject(stepShader.StepShaders, serializer); } } + + protected override Type GetTypeByName(string name) + { + // only get name from font + var assembly = AssemblyUtils.GetAssemblyByName("osu.Framework.KaraokeFont"); + Debug.Assert(assembly != null); + + var type = assembly.GetType($"osu.Framework.Graphics.Shaders.{name}"); + Debug.Assert(type != null); + return type; + } } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/SortableJsonConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/SortableJsonConverter.cs index d4e90677b..10cc3afe5 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/SortableJsonConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/SortableJsonConverter.cs @@ -7,34 +7,33 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public abstract class SortableJsonConverter : JsonConverter> { - public abstract class SortableJsonConverter : JsonConverter> + public sealed override IEnumerable ReadJson(JsonReader reader, Type objectType, IEnumerable? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public sealed override IEnumerable ReadJson(JsonReader reader, Type objectType, IEnumerable? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JArray.Load(reader); - var timeTags = obj.Select(x => serializer.Deserialize(x.CreateReader())!); - return GetSortedValue(timeTags); - } - - public override void WriteJson(JsonWriter writer, IEnumerable? value, JsonSerializer serializer) - { - ArgumentNullException.ThrowIfNull(value); + var obj = JArray.Load(reader); + var timeTags = obj.Select(x => serializer.Deserialize(x.CreateReader())!); + return GetSortedValue(timeTags); + } - // see: https://stackoverflow.com/questions/3330989/order-of-serialized-fields-using-json-net - var sortedTimeTags = GetSortedValue(value); + public override void WriteJson(JsonWriter writer, IEnumerable? value, JsonSerializer serializer) + { + ArgumentNullException.ThrowIfNull(value); - writer.WriteStartArray(); + // see: https://stackoverflow.com/questions/3330989/order-of-serialized-fields-using-json-net + var sortedTimeTags = GetSortedValue(value); - foreach (var timeTag in sortedTimeTags) - { - serializer.Serialize(writer, timeTag); - } + writer.WriteStartArray(); - writer.WriteEndArray(); + foreach (var timeTag in sortedTimeTags) + { + serializer.Serialize(writer, timeTag); } - protected abstract IEnumerable GetSortedValue(IEnumerable objects); + writer.WriteEndArray(); } + + protected abstract IEnumerable GetSortedValue(IEnumerable objects); } diff --git a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/TimeTagConverter.cs b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/TimeTagConverter.cs index ac2415267..bb5435221 100644 --- a/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/TimeTagConverter.cs +++ b/osu.Game.Rulesets.Karaoke/IO/Serialization/Converters/TimeTagConverter.cs @@ -10,40 +10,39 @@ using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; -namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters +namespace osu.Game.Rulesets.Karaoke.IO.Serialization.Converters; + +public class TimeTagConverter : JsonConverter { - public class TimeTagConverter : JsonConverter + public override TimeTag ReadJson(JsonReader reader, Type objectType, TimeTag? existingValue, bool hasExistingValue, JsonSerializer serializer) { - public override TimeTag ReadJson(JsonReader reader, Type objectType, TimeTag? existingValue, bool hasExistingValue, JsonSerializer serializer) - { - var obj = JToken.Load(reader); - string? value = obj.Value(); + var obj = JToken.Load(reader); + string? value = obj.Value(); - if (string.IsNullOrEmpty(value)) - return new TimeTag(new TextIndex()); + if (string.IsNullOrEmpty(value)) + return new TimeTag(new TextIndex()); - var regex = new Regex("(?[-0-9]+),(?start|end)]:(?