diff --git a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs index 9540e35780..99a064d35f 100644 --- a/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs +++ b/osu.Game.Rulesets.Taiko/Mods/TaikoModDifficultyAdjust.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Mods { get { - string scrollSpeed = ScrollSpeed.IsDefault ? string.Empty : $"Scroll x{ScrollSpeed.Value:N1}"; + string scrollSpeed = ScrollSpeed.IsDefault ? string.Empty : $"Scroll x{ScrollSpeed.Value:N2}"; return string.Join(", ", new[] { diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs index 98d8a41674..2efd125f81 100644 --- a/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs +++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorScreenModes.cs @@ -4,11 +4,9 @@ using System; using System.Linq; using NUnit.Framework; -using osu.Framework.Testing; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Edit; -using osu.Game.Screens.Edit.Components.Menus; namespace osu.Game.Tests.Visual.Editing { @@ -22,7 +20,7 @@ namespace osu.Game.Tests.Visual.Editing AddStep("switch between all screens at once", () => { foreach (var screen in Enum.GetValues(typeof(EditorScreenMode)).Cast()) - Editor.ChildrenOfType().Single().Mode.Value = screen; + Editor.Mode.Value = screen; }); } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs index 9460ec680c..1326395695 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreEncoder.cs @@ -8,9 +8,14 @@ using System.Text; using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.IO.Legacy; +using osu.Game.Replays.Legacy; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays.Types; using SharpCompress.Compressors.LZMA; +#nullable enable + namespace osu.Game.Scoring.Legacy { public class LegacyScoreEncoder @@ -27,15 +32,24 @@ namespace osu.Game.Scoring.Legacy public const int FIRST_LAZER_VERSION = 30000000; private readonly Score score; - private readonly IBeatmap beatmap; + private readonly IBeatmap? beatmap; - public LegacyScoreEncoder(Score score, IBeatmap beatmap) + /// + /// Create a new score encoder for a specific score. + /// + /// The score to be encoded. + /// The beatmap used to convert frames for the score. May be null if the frames are already s. + /// + public LegacyScoreEncoder(Score score, IBeatmap? beatmap) { this.score = score; this.beatmap = beatmap; - if (score.ScoreInfo.BeatmapInfo.Ruleset.OnlineID < 0 || score.ScoreInfo.BeatmapInfo.Ruleset.OnlineID > 3) - throw new ArgumentException("Only scores in the osu, taiko, catch, or mania rulesets can be encoded to the legacy score format.", nameof(score)); + if (beatmap == null && !score.Replay.Frames.All(f => f is LegacyReplayFrame)) + throw new ArgumentException(@"Beatmap must be provided if frames are not already legacy frames.", nameof(beatmap)); + + if (score.ScoreInfo.Ruleset.OnlineID < 0 || score.ScoreInfo.Ruleset.OnlineID > ILegacyRuleset.MAX_LEGACY_RULESET_ID) + throw new ArgumentException(@"Only scores in the osu, taiko, catch, or mania rulesets can be encoded to the legacy score format.", nameof(score)); } public void Encode(Stream stream) @@ -101,11 +115,13 @@ namespace osu.Game.Scoring.Legacy { int lastTime = 0; - foreach (var f in score.Replay.Frames.OfType().Select(f => f.ToLegacy(beatmap))) + foreach (var f in score.Replay.Frames) { + var legacyFrame = getLegacyFrame(f); + // Rounding because stable could only parse integral values - int time = (int)Math.Round(f.Time); - replayData.Append(FormattableString.Invariant($"{time - lastTime}|{f.MouseX ?? 0}|{f.MouseY ?? 0}|{(int)f.ButtonState},")); + int time = (int)Math.Round(legacyFrame.Time); + replayData.Append(FormattableString.Invariant($"{time - lastTime}|{legacyFrame.MouseX ?? 0}|{legacyFrame.MouseY ?? 0}|{(int)legacyFrame.ButtonState},")); lastTime = time; } } @@ -117,6 +133,21 @@ namespace osu.Game.Scoring.Legacy } } + private LegacyReplayFrame getLegacyFrame(ReplayFrame replayFrame) + { + switch (replayFrame) + { + case LegacyReplayFrame legacyFrame: + return legacyFrame; + + case IConvertibleReplayFrame convertibleFrame: + return convertibleFrame.ToLegacy(beatmap); + + default: + throw new ArgumentException(@"Frame could not be converted to legacy frames", nameof(replayFrame)); + } + } + private string getHpGraphFormatted() { // todo: implement, maybe? diff --git a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs index c6787a1fb1..2a8435ff47 100644 --- a/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs +++ b/osu.Game/Screens/Edit/Components/Menus/EditorMenuBar.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -18,8 +17,6 @@ namespace osu.Game.Screens.Edit.Components.Menus { public class EditorMenuBar : OsuMenu { - public readonly Bindable Mode = new Bindable(); - public EditorMenuBar() : base(Direction.Horizontal, true) { @@ -28,25 +25,6 @@ namespace osu.Game.Screens.Edit.Components.Menus MaskingContainer.CornerRadius = 0; ItemsContainer.Padding = new MarginPadding { Left = 100 }; BackgroundColour = Color4Extensions.FromHex("111"); - - ScreenSelectionTabControl tabControl; - AddRangeInternal(new Drawable[] - { - tabControl = new ScreenSelectionTabControl - { - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - X = -15 - } - }); - - Mode.BindTo(tabControl.Current); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Mode.TriggerChange(); } protected override Framework.Graphics.UserInterface.Menu CreateSubMenu() => new SubMenu(); diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index c2775ae101..dcb7e3a282 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -89,6 +89,8 @@ namespace osu.Game.Screens.Edit [Resolved(canBeNull: true)] private NotificationOverlay notifications { get; set; } + public readonly Bindable Mode = new Bindable(); + public IBindable SamplePlaybackDisabled => samplePlaybackDisabled; private readonly Bindable samplePlaybackDisabled = new Bindable(); @@ -115,8 +117,6 @@ namespace osu.Game.Screens.Edit [CanBeNull] // Should be non-null once it can support custom rulesets. private EditorChangeHandler changeHandler; - private EditorMenuBar menuBar; - private DependencyContainer dependencies; private TestGameplayButton testGameplayButton; @@ -239,40 +239,49 @@ namespace osu.Game.Screens.Edit Name = "Top bar", RelativeSizeAxes = Axes.X, Height = 40, - Child = menuBar = new EditorMenuBar + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - RelativeSizeAxes = Axes.Both, - Mode = { Value = isNewBeatmap ? EditorScreenMode.SongSetup : EditorScreenMode.Compose }, - Items = new[] + new EditorMenuBar { - new MenuItem("File") + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + Items = new[] { - Items = createFileMenuItems() - }, - new MenuItem("Edit") - { - Items = new[] + new MenuItem("File") { - undoMenuItem = new EditorMenuItem("Undo", MenuItemType.Standard, Undo), - redoMenuItem = new EditorMenuItem("Redo", MenuItemType.Standard, Redo), - new EditorMenuItemSpacer(), - cutMenuItem = new EditorMenuItem("Cut", MenuItemType.Standard, Cut), - copyMenuItem = new EditorMenuItem("Copy", MenuItemType.Standard, Copy), - pasteMenuItem = new EditorMenuItem("Paste", MenuItemType.Standard, Paste), - } - }, - new MenuItem("View") - { - Items = new MenuItem[] + Items = createFileMenuItems() + }, + new MenuItem("Edit") { - new WaveformOpacityMenuItem(config.GetBindable(OsuSetting.EditorWaveformOpacity)), - new HitAnimationsMenuItem(config.GetBindable(OsuSetting.EditorHitAnimations)) + Items = new[] + { + undoMenuItem = new EditorMenuItem("Undo", MenuItemType.Standard, Undo), + redoMenuItem = new EditorMenuItem("Redo", MenuItemType.Standard, Redo), + new EditorMenuItemSpacer(), + cutMenuItem = new EditorMenuItem("Cut", MenuItemType.Standard, Cut), + copyMenuItem = new EditorMenuItem("Copy", MenuItemType.Standard, Copy), + pasteMenuItem = new EditorMenuItem("Paste", MenuItemType.Standard, Paste), + } + }, + new MenuItem("View") + { + Items = new MenuItem[] + { + new WaveformOpacityMenuItem(config.GetBindable(OsuSetting.EditorWaveformOpacity)), + new HitAnimationsMenuItem(config.GetBindable(OsuSetting.EditorHitAnimations)) + } } } - } - } + }, + new ScreenSelectionTabControl + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + X = -15, + Current = Mode, + }, + }, }, new Container { @@ -340,14 +349,15 @@ namespace osu.Game.Screens.Edit changeHandler?.CanUndo.BindValueChanged(v => undoMenuItem.Action.Disabled = !v.NewValue, true); changeHandler?.CanRedo.BindValueChanged(v => redoMenuItem.Action.Disabled = !v.NewValue, true); - - menuBar.Mode.ValueChanged += onModeChanged; } protected override void LoadComplete() { base.LoadComplete(); setUpClipboardActionAvailability(); + + Mode.Value = isNewBeatmap ? EditorScreenMode.SongSetup : EditorScreenMode.Compose; + Mode.BindValueChanged(onModeChanged, true); } /// @@ -517,23 +527,23 @@ namespace osu.Game.Screens.Edit return true; case GlobalAction.EditorComposeMode: - menuBar.Mode.Value = EditorScreenMode.Compose; + Mode.Value = EditorScreenMode.Compose; return true; case GlobalAction.EditorDesignMode: - menuBar.Mode.Value = EditorScreenMode.Design; + Mode.Value = EditorScreenMode.Design; return true; case GlobalAction.EditorTimingMode: - menuBar.Mode.Value = EditorScreenMode.Timing; + Mode.Value = EditorScreenMode.Timing; return true; case GlobalAction.EditorSetupMode: - menuBar.Mode.Value = EditorScreenMode.SongSetup; + Mode.Value = EditorScreenMode.SongSetup; return true; case GlobalAction.EditorVerifyMode: - menuBar.Mode.Value = EditorScreenMode.Verify; + Mode.Value = EditorScreenMode.Verify; return true; case GlobalAction.EditorTestGameplay: diff --git a/osu.Game/Skinning/Editor/SkinEditor.cs b/osu.Game/Skinning/Editor/SkinEditor.cs index 8052f82c93..ae5cbc95f0 100644 --- a/osu.Game/Skinning/Editor/SkinEditor.cs +++ b/osu.Game/Skinning/Editor/SkinEditor.cs @@ -8,14 +8,14 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Framework.Testing; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.UserInterface; -using osu.Game.Resources.Localisation.Web; -using osuTK; +using osu.Game.Screens.Edit.Components.Menus; namespace osu.Game.Skinning.Editor { @@ -57,13 +57,43 @@ namespace osu.Game.Skinning.Editor RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - headerText = new OsuTextFlowContainer + new Container { - TextAnchor = Anchor.TopCentre, - Padding = new MarginPadding(20), - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - RelativeSizeAxes = Axes.X + Name = "Top bar", + RelativeSizeAxes = Axes.X, + Depth = float.MinValue, + Height = 40, + Children = new Drawable[] + { + new EditorMenuBar + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + RelativeSizeAxes = Axes.Both, + Items = new[] + { + new MenuItem("File") + { + Items = new[] + { + new EditorMenuItem("Save", MenuItemType.Standard, Save), + new EditorMenuItem("Revert to default", MenuItemType.Destructive, revert), + new EditorMenuItemSpacer(), + new EditorMenuItem("Exit", MenuItemType.Standard, Hide), + }, + }, + } + }, + headerText = new OsuTextFlowContainer + { + TextAnchor = Anchor.TopRight, + Padding = new MarginPadding(5), + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + }, + }, }, new GridContainer { @@ -89,46 +119,6 @@ namespace osu.Game.Skinning.Editor Children = new Drawable[] { new SkinBlueprintContainer(targetScreen), - new TriangleButton - { - Margin = new MarginPadding(10), - Text = CommonStrings.ButtonsClose, - Width = 100, - Action = Hide, - }, - new FillFlowContainer - { - Direction = FillDirection.Horizontal, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Spacing = new Vector2(5), - Padding = new MarginPadding - { - Top = 10, - Left = 10, - }, - Margin = new MarginPadding - { - Right = 10, - Bottom = 10, - }, - Children = new Drawable[] - { - new TriangleButton - { - Text = "Save Changes", - Width = 140, - Action = Save, - }, - new DangerousTriangleButton - { - Text = "Revert to default", - Width = 140, - Action = revert, - }, - } - }, } }, } @@ -161,7 +151,7 @@ namespace osu.Game.Skinning.Editor { headerText.Clear(); - headerText.AddParagraph("Skin editor", cp => cp.Font = OsuFont.Default.With(size: 24)); + headerText.AddParagraph("Skin editor", cp => cp.Font = OsuFont.Default.With(size: 16)); headerText.NewParagraph(); headerText.AddText("Currently editing ", cp => {