1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 18:47:27 +08:00

Add user interaction and stricter change validation rules

This commit is contained in:
Dean Herbert 2018-08-26 19:11:46 +09:00
parent 041d826396
commit e4ea802c7b
5 changed files with 129 additions and 45 deletions

View File

@ -3,6 +3,8 @@
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Tests.Visual;
@ -21,6 +23,9 @@ namespace osu.Game.Tournament.Tests
typeof(DrawableTournamentTeam),
};
[Cached]
private Bindable<TournamentConditions> conditions = new Bindable<TournamentConditions>(new TournamentConditions { BestOf = 9 });
public TestCaseMatchPairings()
{
FillFlowContainer<DrawableMatchPairing> level1;
@ -30,8 +35,8 @@ namespace osu.Game.Tournament.Tests
new TournamentTeam { FlagName = "AU", FullName = "Australia", },
new TournamentTeam { FlagName = "JP", FullName = "Japan", Acronym = "JPN" })
{
Team1Score = { Value = 8 },
Team2Score = { Value = 6 },
Team1Score = { Value = 4 },
Team2Score = { Value = 1 },
};
var pairing2 = new MatchPairing(
@ -76,21 +81,19 @@ namespace osu.Game.Tournament.Tests
level1.Children[0].Progression = level2.Children[0];
level1.Children[1].Progression = level2.Children[0];
AddStep("mark complete", () => pairing1.Completed.Value = true);
AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 5);
AddStep("mark complete", () => pairing1.Completed.Value = true);
AddRepeatStep("change scores", () => pairing1.Team2Score.Value++, 4);
AddStep("add new team", () => pairing2.Team2.Value = new TournamentTeam { FlagName = "PT", FullName = "Portugal" });
AddStep("Add progression", () => level1.Children[2].Progression = level2.Children[1]);
AddStep("start match", () => pairing2.ResetScores());
AddStep("start match", () => pairing2.StartMatch());
AddRepeatStep("change scores", () => pairing2.Team1Score.Value++, 5);
AddStep("mark complete", () => pairing2.Completed.Value = true);
AddRepeatStep("change scores", () => pairing2.Team1Score.Value++, 10);
AddStep("start submatch", () => level2.Children[0].Pairing.ResetScores());
AddStep("start submatch", () => level2.Children[0].Pairing.StartMatch());
AddRepeatStep("change scores", () => level2.Children[0].Pairing.Team1Score.Value++, 5);
AddStep("mark complete", () => level2.Children[0].Pairing.Completed.Value = true);
AddRepeatStep("change scores", () => level2.Children[0].Pairing.Team2Score.Value++, 4);
}
}
}

View File

@ -2,6 +2,8 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Lines;
@ -14,9 +16,10 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{
public readonly MatchPairing Pairing;
private readonly FillFlowContainer<DrawableMatchTeam> flow;
private DrawableMatchPairing progression;
private readonly Bindable<TournamentConditions> conditions = new Bindable<TournamentConditions>();
private readonly Path path;
public DrawableMatchPairing Progression
@ -39,6 +42,51 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
private const float line_width = 2;
public DrawableMatchPairing(MatchPairing pairing)
{
Pairing = pairing;
AutoSizeAxes = Axes.Both;
Margin = new MarginPadding(5);
InternalChildren = new Drawable[]
{
flow = new FillFlowContainer<DrawableMatchTeam>
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(2)
},
path = new Path
{
Alpha = 0,
BypassAutoSizeAxes = Axes.Both,
Anchor = Anchor.CentreRight,
PathWidth = line_width,
},
};
pairing.Team1.BindValueChanged(_ => updateTeams());
pairing.Team2.BindValueChanged(_ => updateTeams());
pairing.Team1Score.BindValueChanged(_ => updateWinConditions());
pairing.Team2Score.BindValueChanged(_ => updateWinConditions());
pairing.Completed.BindValueChanged(_ => updateProgression());
updateTeams();
}
[BackgroundDependencyLoader(true)]
private void load(Bindable<TournamentConditions> conditions)
{
this.conditions.BindValueChanged(_ => updateWinConditions());
if (conditions != null)
this.conditions.BindTo(conditions);
}
private void updateProgression()
{
if (progression == null)
@ -83,37 +131,11 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
destinationForWinner.Value = Pairing.Winner;
}
public DrawableMatchPairing(MatchPairing pairing)
private void updateWinConditions()
{
Pairing = pairing;
if (conditions.Value == null) return;
AutoSizeAxes = Axes.Both;
Margin = new MarginPadding(5);
InternalChildren = new Drawable[]
{
flow = new FillFlowContainer<DrawableMatchTeam>
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Vertical,
Spacing = new Vector2(2)
},
path = new Path
{
Alpha = 0,
BypassAutoSizeAxes = Axes.Both,
Anchor = Anchor.CentreRight,
PathWidth = line_width,
},
};
pairing.Team1.BindValueChanged(_ => updateTeams());
pairing.Team2.BindValueChanged(_ => updateTeams());
pairing.Completed.BindValueChanged(_ => updateProgression());
updateTeams();
Pairing.Completed.Value = Pairing.Team1Score.Value + Pairing.Team2Score.Value >= conditions.Value.BestOf;
}
protected override void LoadComplete()
@ -136,6 +158,9 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
// todo: teams may need to be bindable for transitions at a later point.
if (Pairing.Team1.Value == null || Pairing.Team2.Value == null)
Pairing.CancelMatchStart();
flow.Children = new[]
{
new DrawableMatchTeam(Pairing.Team1, Pairing),
@ -143,6 +168,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
};
updateProgression();
updateWinConditions();
}
}
}

View File

@ -7,16 +7,20 @@ using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.EventArgs;
using osu.Framework.Input.States;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Tournament.Components;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Input;
namespace osu.Game.Tournament.Screens.Ladder.Components
{
public class DrawableMatchTeam : DrawableTournamentTeam
{
private readonly MatchPairing pairing;
private OsuSpriteText scoreText;
private Box background;
@ -31,6 +35,7 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
public DrawableMatchTeam(TournamentTeam team, MatchPairing pairing)
: base(team)
{
this.pairing = pairing;
Size = new Vector2(150, 40);
Masking = true;
@ -48,7 +53,8 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
isWinner = () => pairing.Winner == Team;
completed.BindTo(pairing.Completed);
score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score);
if (team != null)
score.BindTo(team == pairing.Team1.Value ? pairing.Team1Score : pairing.Team2Score);
}
}
@ -109,6 +115,30 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
}, true);
}
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
{
if (Team == null) return true;
if (args.Button == MouseButton.Left)
{
if (score.Value == null)
{
pairing.StartMatch();
}
else if (!pairing.Completed)
score.Value++;
}
else
{
if (score.Value > 0)
score.Value--;
else
pairing.CancelMatchStart();
}
return true;
}
private void updateWinStyle()
{
bool winner = completed && isWinner?.Invoke() == true;

View File

@ -23,15 +23,27 @@ namespace osu.Game.Tournament.Screens.Ladder.Components
{
Team1.Value = team1;
Team2.Value = team2;
Team1Score.ValueChanged += _ => Completed.Value = false;
Team2Score.ValueChanged += _ => Completed.Value = false;
}
public TournamentTeam Winner => !Completed.Value ? null : (Team1Score.Value > Team2Score.Value ? Team1.Value : Team2.Value);
public void ResetScores()
/// <summary>
/// Remove scores from the match, in case of a false click or false start.
/// </summary>
public void CancelMatchStart()
{
Team1Score.Value = null;
Team2Score.Value = null;
}
/// <summary>
/// Initialise this match with zeroed scores. Will be a noop if either team is not present.
/// </summary>
public void StartMatch()
{
if (Team1.Value == null || Team2.Value == null)
return;
Team1Score.Value = 0;
Team2Score.Value = 0;
}

View File

@ -0,0 +1,13 @@
namespace osu.Game.Tournament.Screens.Ladder.Components
{
/// <summary>
/// Conditions governing a tournament.
/// </summary>
public class TournamentConditions
{
/// <summary>
/// How many matches before a winner is decided.
/// </summary>
public int BestOf;
}
}