osu/osu.Game.Tournament/Screens/MapPool/MapPoolScreen.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

317 lines
11 KiB
C#
Raw Normal View History

2019-03-04 04:24:19 +00:00
// 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.
2018-11-06 07:15:03 +00:00
2018-11-07 21:29:04 +00:00
using System.Linq;
using osu.Framework.Allocation;
2019-03-02 04:40:43 +00:00
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2018-11-07 21:29:04 +00:00
using osu.Framework.Input.Events;
using osu.Framework.Threading;
2018-11-07 21:29:04 +00:00
using osu.Game.Graphics.UserInterface;
using osu.Game.Tournament.Components;
2018-11-07 21:36:36 +00:00
using osu.Game.Tournament.IPC;
2019-06-18 05:51:48 +00:00
using osu.Game.Tournament.Models;
using osu.Game.Tournament.Screens.Gameplay;
2018-11-15 12:28:42 +00:00
using osu.Game.Tournament.Screens.Gameplay.Components;
using osuTK;
using osuTK.Graphics;
using osuTK.Input;
namespace osu.Game.Tournament.Screens.MapPool
{
public partial class MapPoolScreen : TournamentMatchScreen
{
2023-07-25 11:50:55 +00:00
private FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>> mapFlows = null!;
2018-11-07 21:29:04 +00:00
2023-07-29 16:57:44 +00:00
[Resolved]
2023-07-25 11:50:55 +00:00
private TournamentSceneManager? sceneManager { get; set; }
2019-06-14 08:20:15 +00:00
2018-11-07 21:36:36 +00:00
private TeamColour pickColour;
private ChoiceType pickType;
2023-07-25 11:50:55 +00:00
private OsuButton buttonRedBan = null!;
private OsuButton buttonBlueBan = null!;
private OsuButton buttonRedPick = null!;
private OsuButton buttonBluePick = null!;
2018-11-07 21:36:36 +00:00
2023-07-25 11:50:55 +00:00
private ScheduledDelegate? scheduledScreenChange;
[BackgroundDependencyLoader]
private void load(MatchIPCInfo ipc)
2018-11-07 21:29:04 +00:00
{
InternalChildren = new Drawable[]
{
2020-05-14 19:51:39 +00:00
new TourneyVideo("mappool")
{
Loop = true,
RelativeSizeAxes = Axes.Both,
},
new MatchHeader
{
ShowScores = true,
},
2018-11-17 07:06:43 +00:00
mapFlows = new FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>>
{
2020-03-13 05:09:09 +00:00
Y = 160,
Spacing = new Vector2(10, 10),
2018-11-17 07:06:43 +00:00
Direction = FillDirection.Vertical,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
2018-11-07 21:29:04 +00:00
},
new ControlPanel
{
Children = new Drawable[]
{
new TournamentSpriteText
2018-11-07 21:29:04 +00:00
{
Text = "Current Mode"
},
buttonRedBan = new TourneyButton
2018-11-07 21:29:04 +00:00
{
RelativeSizeAxes = Axes.X,
Text = "Red Ban",
Action = () => setMode(TeamColour.Red, ChoiceType.Ban)
},
buttonBlueBan = new TourneyButton
2018-11-07 21:29:04 +00:00
{
RelativeSizeAxes = Axes.X,
Text = "Blue Ban",
Action = () => setMode(TeamColour.Blue, ChoiceType.Ban)
},
buttonRedPick = new TourneyButton
2018-11-07 21:29:04 +00:00
{
RelativeSizeAxes = Axes.X,
Text = "Red Pick",
Action = () => setMode(TeamColour.Red, ChoiceType.Pick)
},
buttonBluePick = new TourneyButton
2018-11-07 21:29:04 +00:00
{
RelativeSizeAxes = Axes.X,
Text = "Blue Pick",
Action = () => setMode(TeamColour.Blue, ChoiceType.Pick)
2018-11-07 21:47:42 +00:00
},
new ControlPanel.Spacer(),
new TourneyButton
2018-11-07 21:47:42 +00:00
{
RelativeSizeAxes = Axes.X,
Text = "Reset",
Action = reset
},
new ControlPanel.Spacer(),
new OsuCheckbox
{
LabelText = "Split display by mods",
Current = LadderInfo.SplitMapPoolByMods,
},
},
}
};
ipc.Beatmap.BindValueChanged(beatmapChanged);
2018-11-07 21:29:04 +00:00
}
2023-07-25 11:50:55 +00:00
private Bindable<bool>? splitMapPoolByMods;
protected override void LoadComplete()
2018-11-07 21:36:36 +00:00
{
base.LoadComplete();
splitMapPoolByMods = LadderInfo.SplitMapPoolByMods.GetBoundCopy();
splitMapPoolByMods.BindValueChanged(_ => updateDisplay());
2018-11-07 21:36:36 +00:00
}
2023-08-09 10:11:51 +00:00
private void beatmapChanged(ValueChangedEvent<TournamentBeatmap?> beatmap)
2018-11-07 21:36:36 +00:00
{
if (CurrentMatch.Value?.Round.Value == null)
return;
int totalBansRequired = CurrentMatch.Value.Round.Value.BanCount.Value * 2;
if (CurrentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) < totalBansRequired)
2018-11-10 15:48:22 +00:00
return;
2023-09-19 06:27:55 +00:00
// if bans have already been placed, beatmap changes result in a selection being made automatically
2023-08-09 10:11:51 +00:00
if (beatmap.NewValue?.OnlineID > 0)
addForBeatmap(beatmap.NewValue.OnlineID);
2018-11-07 21:36:36 +00:00
}
2018-11-07 21:29:04 +00:00
private void setMode(TeamColour colour, ChoiceType choiceType)
{
pickColour = colour;
pickType = choiceType;
2018-11-07 21:47:42 +00:00
buttonRedBan.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Ban);
buttonBlueBan.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Ban);
buttonRedPick.Colour = setColour(pickColour == TeamColour.Red && pickType == ChoiceType.Pick);
buttonBluePick.Colour = setColour(pickColour == TeamColour.Blue && pickType == ChoiceType.Pick);
static Color4 setColour(bool active) => active ? Color4.White : Color4.Gray;
2018-11-07 21:29:04 +00:00
}
private void setNextMode()
{
if (CurrentMatch.Value?.Round.Value == null)
2023-07-25 11:50:55 +00:00
return;
int totalBansRequired = CurrentMatch.Value.Round.Value.BanCount.Value * 2;
2023-12-06 02:50:43 +00:00
TeamColour lastPickColour = CurrentMatch.Value.PicksBans.LastOrDefault()?.Team ?? TeamColour.Red;
TeamColour nextColour;
2018-11-07 21:29:04 +00:00
bool hasAllBans = CurrentMatch.Value.PicksBans.Count(p => p.Type == ChoiceType.Ban) >= totalBansRequired;
if (!hasAllBans)
{
2023-12-06 02:50:43 +00:00
// Ban phase: switch teams every second ban.
nextColour = CurrentMatch.Value.PicksBans.Count % 2 == 1
2023-12-06 02:50:43 +00:00
? getOppositeTeamColour(lastPickColour)
: lastPickColour;
}
else
{
2023-12-06 02:50:43 +00:00
// Pick phase : switch teams every pick, except for the first pick which generally goes to the team that placed the last ban.
nextColour = pickType == ChoiceType.Pick
? getOppositeTeamColour(lastPickColour)
: lastPickColour;
}
setMode(nextColour, hasAllBans ? ChoiceType.Pick : ChoiceType.Ban);
TeamColour getOppositeTeamColour(TeamColour colour) => colour == TeamColour.Red ? TeamColour.Blue : TeamColour.Red;
2018-11-07 21:29:04 +00:00
}
protected override bool OnMouseDown(MouseDownEvent e)
{
2018-11-17 07:06:43 +00:00
var maps = mapFlows.Select(f => f.FirstOrDefault(m => m.ReceivePositionalInputAt(e.ScreenSpaceMousePosition)));
var map = maps.FirstOrDefault(m => m != null);
2018-11-07 21:29:04 +00:00
if (map != null)
{
2023-07-27 08:41:27 +00:00
if (e.Button == MouseButton.Left && map.Beatmap?.OnlineID > 0)
addForBeatmap(map.Beatmap.OnlineID);
2018-11-07 21:29:04 +00:00
else
{
2023-07-25 11:50:55 +00:00
var existing = CurrentMatch.Value?.PicksBans.FirstOrDefault(p => p.BeatmapID == map.Beatmap?.OnlineID);
2018-11-07 21:29:04 +00:00
if (existing != null)
{
2023-07-25 11:50:55 +00:00
CurrentMatch.Value?.PicksBans.Remove(existing);
2018-11-07 21:29:04 +00:00
setNextMode();
}
}
return true;
}
return base.OnMouseDown(e);
}
2018-11-07 21:47:42 +00:00
private void reset()
{
2023-07-25 11:50:55 +00:00
CurrentMatch.Value?.PicksBans.Clear();
2018-11-07 21:47:42 +00:00
setNextMode();
}
2018-11-07 21:36:36 +00:00
private void addForBeatmap(int beatmapId)
2018-11-07 21:29:04 +00:00
{
2023-07-25 11:50:55 +00:00
if (CurrentMatch.Value?.Round.Value == null)
2018-11-08 04:08:59 +00:00
return;
if (CurrentMatch.Value.Round.Value.Beatmaps.All(b => b.Beatmap?.OnlineID != beatmapId))
2018-11-07 21:36:36 +00:00
// don't attempt to add if the beatmap isn't in our pool
return;
if (CurrentMatch.Value.PicksBans.Any(p => p.BeatmapID == beatmapId))
2018-11-07 21:36:36 +00:00
// don't attempt to add if already exists.
return;
CurrentMatch.Value.PicksBans.Add(new BeatmapChoice
2018-11-07 21:36:36 +00:00
{
Team = pickColour,
Type = pickType,
BeatmapID = beatmapId
});
setNextMode();
if (LadderInfo.AutoProgressScreens.Value)
{
if (pickType == ChoiceType.Pick && CurrentMatch.Value.PicksBans.Any(i => i.Type == ChoiceType.Pick))
{
scheduledScreenChange?.Cancel();
scheduledScreenChange = Scheduler.AddDelayed(() => { sceneManager?.SetScreen(typeof(GameplayScreen)); }, 10000);
}
}
}
public override void Hide()
{
scheduledScreenChange?.Cancel();
base.Hide();
2018-11-07 21:29:04 +00:00
}
2023-07-25 11:50:55 +00:00
protected override void CurrentMatchChanged(ValueChangedEvent<TournamentMatch?> match)
2018-11-07 21:29:04 +00:00
{
base.CurrentMatchChanged(match);
updateDisplay();
}
private void updateDisplay()
{
2018-11-17 07:06:43 +00:00
mapFlows.Clear();
if (CurrentMatch.Value == null)
return;
int totalRows = 0;
if (CurrentMatch.Value.Round.Value != null)
{
2023-07-25 11:50:55 +00:00
FillFlowContainer<TournamentBeatmapPanel>? currentFlow = null;
string? currentMods = null;
int flowCount = 0;
foreach (var b in CurrentMatch.Value.Round.Value.Beatmaps)
2018-11-17 07:06:43 +00:00
{
if (currentFlow == null || (LadderInfo.SplitMapPoolByMods.Value && currentMods != b.Mods))
2018-11-17 07:06:43 +00:00
{
mapFlows.Add(currentFlow = new FillFlowContainer<TournamentBeatmapPanel>
2018-11-17 07:06:43 +00:00
{
Spacing = new Vector2(10, 5),
Direction = FillDirection.Full,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y
});
currentMods = b.Mods;
totalRows++;
flowCount = 0;
}
if (++flowCount > 2)
{
totalRows++;
2020-03-11 06:34:52 +00:00
flowCount = 1;
2018-11-17 07:06:43 +00:00
}
currentFlow.Add(new TournamentBeatmapPanel(b.Beatmap, b.Mods)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Height = 42,
});
2018-11-17 07:06:43 +00:00
}
}
2020-03-13 05:25:25 +00:00
mapFlows.Padding = new MarginPadding(5)
{
// remove horizontal padding to increase flow width to 3 panels
2020-03-13 05:25:25 +00:00
Horizontal = totalRows > 9 ? 0 : 100
};
}
}
}