From ba589b2139c28bf88c4db2bd4b3d5f292ed2cbc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 17:59:33 +0900 Subject: [PATCH] Add more functionality and share more logic between editor screens --- osu.Game.Tournament/Models/TournamentRound.cs | 2 +- .../Screens/Editors/IModelBacked.cs | 16 +++++ .../Screens/Editors/RoundEditorScreen.cs | 65 +++++++------------ .../Screens/Editors/TeamEditorScreen.cs | 54 ++++++++++----- .../Screens/Editors/TournamentEditorScreen.cs | 38 ++++++++--- osu.Game.Tournament/TournamentGameBase.cs | 32 --------- 6 files changed, 108 insertions(+), 99 deletions(-) create mode 100644 osu.Game.Tournament/Screens/Editors/IModelBacked.cs diff --git a/osu.Game.Tournament/Models/TournamentRound.cs b/osu.Game.Tournament/Models/TournamentRound.cs index 1b900d5a22..08b3143be1 100644 --- a/osu.Game.Tournament/Models/TournamentRound.cs +++ b/osu.Game.Tournament/Models/TournamentRound.cs @@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Models [JsonProperty] public readonly BindableList Beatmaps = new BindableList(); - public readonly Bindable StartDate = new Bindable(); + public readonly Bindable StartDate = new Bindable { Value = DateTimeOffset.UtcNow }; // only used for serialisation public List Matches = new List(); diff --git a/osu.Game.Tournament/Screens/Editors/IModelBacked.cs b/osu.Game.Tournament/Screens/Editors/IModelBacked.cs new file mode 100644 index 0000000000..2f2d972b2c --- /dev/null +++ b/osu.Game.Tournament/Screens/Editors/IModelBacked.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. +namespace osu.Game.Tournament.Screens.Editors +{ + /// + /// Provides a mechanism to access a related model from a representing class. + /// + /// The type of model. + public interface IModelBacked + { + /// + /// The model. + /// + TModel Model { get; } + } +} diff --git a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs index b2c3a97cbc..1dc91abe6d 100644 --- a/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/RoundEditorScreen.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -20,36 +19,20 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public class RoundEditorScreen : TournamentEditorScreen + public class RoundEditorScreen : TournamentEditorScreen { - [BackgroundDependencyLoader] - private void load() - { - foreach (var r in LadderInfo.Rounds) - Flow.Add(new RoundRow(r)); - } + protected override BindableList Storage => LadderInfo.Rounds; - protected override void AddNew() + public class RoundRow : CompositeDrawable, IModelBacked { - var round = new TournamentRound - { - StartDate = { Value = DateTimeOffset.UtcNow } - }; - - Flow.Add(new RoundRow(round)); - LadderInfo.Rounds.Add(round); - } - - public class RoundRow : CompositeDrawable - { - public readonly TournamentRound Round; + public TournamentRound Model { get; } [Resolved] private LadderInfo ladderInfo { get; set; } public RoundRow(TournamentRound round) { - Round = round; + Model = round; Masking = true; CornerRadius = 10; @@ -80,25 +63,25 @@ namespace osu.Game.Tournament.Screens.Editors { LabelText = "Name", Width = 0.33f, - Bindable = Round.Name + Bindable = Model.Name }, new SettingsTextBox { LabelText = "Description", Width = 0.33f, - Bindable = Round.Description + Bindable = Model.Description }, new DateTextBox { LabelText = "Start Time", Width = 0.33f, - Bindable = Round.StartDate + Bindable = Model.StartDate }, new SettingsSlider { LabelText = "Best of", Width = 0.33f, - Bindable = Round.BestOf + Bindable = Model.BestOf }, new SettingsButton { @@ -120,7 +103,7 @@ namespace osu.Game.Tournament.Screens.Editors Action = () => { Expire(); - ladderInfo.Rounds.Remove(Round); + ladderInfo.Rounds.Remove(Model); }, } }; @@ -161,7 +144,7 @@ namespace osu.Game.Tournament.Screens.Editors public class RoundBeatmapRow : CompositeDrawable { - private readonly RoundBeatmap beatmap; + public RoundBeatmap Model { get; } [Resolved] protected IAPIProvider API { get; private set; } @@ -174,7 +157,7 @@ namespace osu.Game.Tournament.Screens.Editors public RoundBeatmapRow(TournamentRound team, RoundBeatmap beatmap) { - this.beatmap = beatmap; + Model = beatmap; Margin = new MarginPadding(10); @@ -239,51 +222,51 @@ namespace osu.Game.Tournament.Screens.Editors [BackgroundDependencyLoader] private void load(RulesetStore rulesets) { - beatmapId.Value = beatmap.ID.ToString(); + beatmapId.Value = Model.ID.ToString(); beatmapId.BindValueChanged(idString => { int parsed; int.TryParse(idString.NewValue, out parsed); - beatmap.ID = parsed; + Model.ID = parsed; if (idString.NewValue != idString.OldValue) - beatmap.BeatmapInfo = null; + Model.BeatmapInfo = null; - if (beatmap.BeatmapInfo != null) + if (Model.BeatmapInfo != null) { updatePanel(); return; } - var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmap.ID }); + var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = Model.ID }); req.Success += res => { - beatmap.BeatmapInfo = res.ToBeatmap(rulesets); + Model.BeatmapInfo = res.ToBeatmap(rulesets); updatePanel(); }; req.Failure += _ => { - beatmap.BeatmapInfo = null; + Model.BeatmapInfo = null; updatePanel(); }; API.Queue(req); }, true); - mods.Value = beatmap.Mods; - mods.BindValueChanged(modString => beatmap.Mods = modString.NewValue); + mods.Value = Model.Mods; + mods.BindValueChanged(modString => Model.Mods = modString.NewValue); } private void updatePanel() { drawableContainer.Clear(); - if (beatmap.BeatmapInfo != null) - drawableContainer.Child = new TournamentBeatmapPanel(beatmap.BeatmapInfo, beatmap.Mods) + if (Model.BeatmapInfo != null) + drawableContainer.Child = new TournamentBeatmapPanel(Model.BeatmapInfo, Model.Mods) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, @@ -293,5 +276,7 @@ namespace osu.Game.Tournament.Screens.Editors } } } + + protected override RoundRow CreateDrawable(TournamentRound model) => new RoundRow(model); } } diff --git a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs index c435cc669a..93745acabf 100644 --- a/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TeamEditorScreen.cs @@ -1,13 +1,17 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.IO; using System.Linq; +using Newtonsoft.Json; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Overlays.Settings; @@ -18,26 +22,40 @@ using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public class TeamEditorScreen : TournamentEditorScreen + public class TeamEditorScreen : TournamentEditorScreen { + [Resolved] + private Framework.Game game { get; set; } + + protected override BindableList Storage => LadderInfo.Teams; + [BackgroundDependencyLoader] private void load() { - foreach (var t in LadderInfo.Teams) - Flow.Add(new TeamRow(t)); + ControlPanel.Add(new OsuButton + { + RelativeSizeAxes = Axes.X, + Text = "Add all countries", + Action = addAllCountries + }); } - protected override void AddNew() - { - var team = new TournamentTeam(); + protected override TeamRow CreateDrawable(TournamentTeam model) => new TeamRow(model); - Flow.Add(new TeamRow(team)); - LadderInfo.Teams.Add(team); + private void addAllCountries() + { + List countries; + using (Stream stream = game.Resources.GetStream("Resources/countries.json")) + using (var sr = new StreamReader(stream)) + countries = JsonConvert.DeserializeObject>(sr.ReadToEnd()); + + foreach (var c in countries) + Storage.Add(c); } - public class TeamRow : CompositeDrawable + public class TeamRow : CompositeDrawable, IModelBacked { - public readonly TournamentTeam Team; + public TournamentTeam Model { get; } private readonly Container drawableContainer; @@ -46,12 +64,12 @@ namespace osu.Game.Tournament.Screens.Editors public TeamRow(TournamentTeam team) { - Team = team; + Model = team; Masking = true; CornerRadius = 10; - PlayerEditor playerEditor = new PlayerEditor(Team) + PlayerEditor playerEditor = new PlayerEditor(Model) { Width = 0.95f }; @@ -83,19 +101,19 @@ namespace osu.Game.Tournament.Screens.Editors { LabelText = "Name", Width = 0.2f, - Bindable = Team.FullName + Bindable = Model.FullName }, new SettingsTextBox { LabelText = "Acronym", Width = 0.2f, - Bindable = Team.Acronym + Bindable = Model.Acronym }, new SettingsTextBox { LabelText = "Flag", Width = 0.2f, - Bindable = Team.FlagName + Bindable = Model.FlagName }, new SettingsButton { @@ -112,7 +130,7 @@ namespace osu.Game.Tournament.Screens.Editors Action = () => { Expire(); - ladderInfo.Teams.Remove(Team); + ladderInfo.Teams.Remove(Model); }, }, playerEditor @@ -123,12 +141,12 @@ namespace osu.Game.Tournament.Screens.Editors RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Team.FlagName.BindValueChanged(updateDrawable, true); + Model.FlagName.BindValueChanged(updateDrawable, true); } private void updateDrawable(ValueChangedEvent flag) { - drawableContainer.Child = new DrawableTeamFlag(Team); + drawableContainer.Child = new DrawableTeamFlag(Model); } private class DrawableTeamFlag : DrawableTournamentTeam diff --git a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs index a454b682aa..50d3207345 100644 --- a/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs +++ b/osu.Game.Tournament/Screens/Editors/TournamentEditorScreen.cs @@ -1,23 +1,33 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; +using osu.Game.Overlays.Settings; using osu.Game.Tournament.Components; using osuTK; namespace osu.Game.Tournament.Screens.Editors { - public abstract class TournamentEditorScreen : TournamentScreen, IProvideVideo - where T : Drawable + public abstract class TournamentEditorScreen : TournamentScreen, IProvideVideo + where TDrawable : Drawable, IModelBacked + where TModel : class, new() { - protected readonly FillFlowContainer Flow; + protected abstract BindableList Storage { get; } - protected TournamentEditorScreen() + private FillFlowContainer flow; + + protected ControlPanel ControlPanel; + + [BackgroundDependencyLoader] + private void load() { AddRangeInternal(new Drawable[] { @@ -32,7 +42,7 @@ namespace osu.Game.Tournament.Screens.Editors Width = 0.9f, Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Child = Flow = new FillFlowContainer + Child = flow = new FillFlowContainer { Direction = FillDirection.Vertical, RelativeSizeAxes = Axes.X, @@ -42,7 +52,7 @@ namespace osu.Game.Tournament.Screens.Editors Spacing = new Vector2(20) }, }, - new ControlPanel + ControlPanel = new ControlPanel { Children = new Drawable[] { @@ -50,13 +60,25 @@ namespace osu.Game.Tournament.Screens.Editors { RelativeSizeAxes = Axes.X, Text = "Add new", - Action = AddNew + Action = () => Storage.Add(new TModel()) + }, + new DangerousSettingsButton + { + RelativeSizeAxes = Axes.X, + Text = "Clear all", + Action = Storage.Clear }, } } }); + + Storage.ItemsAdded += items => items.ForEach(i => flow.Add(CreateDrawable(i))); + Storage.ItemsRemoved += items => items.ForEach(i => flow.RemoveAll(d => d.Model == i)); + + foreach (var model in Storage) + flow.Add(CreateDrawable(model)); } - protected abstract void AddNew(); + protected abstract TDrawable CreateDrawable(TModel model); } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index 2f8d084848..628f64dc73 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; @@ -140,7 +139,6 @@ namespace osu.Game.Tournament addedInfo |= addPlayers(); addedInfo |= addBeatmaps(); - addedInfo |= addCountries(); if (addedInfo) SaveChanges(); @@ -189,36 +187,6 @@ namespace osu.Game.Tournament return addedInfo; } - /// - /// Add missing country info based on acronyms. - /// - private bool addCountries() - { - bool addedInfo = false; - - List countries; - using (Stream stream = Resources.GetStream("Resources/countries.json")) - using (var sr = new StreamReader(stream)) - countries = JsonConvert.DeserializeObject>(sr.ReadToEnd()); - - foreach (var t in ladder.Teams) - { - if (!string.IsNullOrEmpty(t.FullName.Value)) - continue; - - var result = countries.FirstOrDefault(c => c.Acronym == t.Acronym); - - if (result == null) continue; - - t.Acronym = result.Acronym; - t.FlagName = result.FlagName; - t.FullName = result.FullName; - addedInfo = true; - } - - return addedInfo; - } - protected override void LoadComplete() { MenuCursorContainer.Cursor.AlwaysPresent = true; // required for tooltip display