1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 20:07:25 +08:00

Add more functionality and share more logic between editor screens

This commit is contained in:
Dean Herbert 2019-06-18 17:59:33 +09:00
parent 711214ed09
commit ba589b2139
6 changed files with 108 additions and 99 deletions

View File

@ -22,7 +22,7 @@ namespace osu.Game.Tournament.Models
[JsonProperty]
public readonly BindableList<RoundBeatmap> Beatmaps = new BindableList<RoundBeatmap>();
public readonly Bindable<DateTimeOffset> StartDate = new Bindable<DateTimeOffset>();
public readonly Bindable<DateTimeOffset> StartDate = new Bindable<DateTimeOffset> { Value = DateTimeOffset.UtcNow };
// only used for serialisation
public List<int> Matches = new List<int>();

View File

@ -0,0 +1,16 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Tournament.Screens.Editors
{
/// <summary>
/// Provides a mechanism to access a related model from a representing class.
/// </summary>
/// <typeparam name="TModel">The type of model.</typeparam>
public interface IModelBacked<out TModel>
{
/// <summary>
/// The model.
/// </summary>
TModel Model { get; }
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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<RoundEditorScreen.RoundRow>
public class RoundEditorScreen : TournamentEditorScreen<RoundEditorScreen.RoundRow, TournamentRound>
{
[BackgroundDependencyLoader]
private void load()
{
foreach (var r in LadderInfo.Rounds)
Flow.Add(new RoundRow(r));
}
protected override BindableList<TournamentRound> Storage => LadderInfo.Rounds;
protected override void AddNew()
public class RoundRow : CompositeDrawable, IModelBacked<TournamentRound>
{
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<int>
{
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);
}
}

View File

@ -1,13 +1,17 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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<TeamEditorScreen.TeamRow>
public class TeamEditorScreen : TournamentEditorScreen<TeamEditorScreen.TeamRow, TournamentTeam>
{
[Resolved]
private Framework.Game game { get; set; }
protected override BindableList<TournamentTeam> 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<TournamentTeam> countries;
using (Stream stream = game.Resources.GetStream("Resources/countries.json"))
using (var sr = new StreamReader(stream))
countries = JsonConvert.DeserializeObject<List<TournamentTeam>>(sr.ReadToEnd());
foreach (var c in countries)
Storage.Add(c);
}
public class TeamRow : CompositeDrawable
public class TeamRow : CompositeDrawable, IModelBacked<TournamentTeam>
{
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<string> flag)
{
drawableContainer.Child = new DrawableTeamFlag(Team);
drawableContainer.Child = new DrawableTeamFlag(Model);
}
private class DrawableTeamFlag : DrawableTournamentTeam

View File

@ -1,23 +1,33 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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<T> : TournamentScreen, IProvideVideo
where T : Drawable
public abstract class TournamentEditorScreen<TDrawable, TModel> : TournamentScreen, IProvideVideo
where TDrawable : Drawable, IModelBacked<TModel>
where TModel : class, new()
{
protected readonly FillFlowContainer<T> Flow;
protected abstract BindableList<TModel> Storage { get; }
protected TournamentEditorScreen()
private FillFlowContainer<TDrawable> 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<T>
Child = flow = new FillFlowContainer<TDrawable>
{
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);
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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;
}
/// <summary>
/// Add missing country info based on acronyms.
/// </summary>
private bool addCountries()
{
bool addedInfo = false;
List<TournamentTeam> countries;
using (Stream stream = Resources.GetStream("Resources/countries.json"))
using (var sr = new StreamReader(stream))
countries = JsonConvert.DeserializeObject<List<TournamentTeam>>(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