mirror of
https://github.com/osukey/osukey.git
synced 2025-08-05 07:33:55 +09:00
Merge branch 'master' into remove-duplicated-load
This commit is contained in:
@ -0,0 +1,12 @@
|
||||
// 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.Game.Screens.Select;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class BeatmapDetailAreaPlaylistTabItem : BeatmapDetailAreaTabItem
|
||||
{
|
||||
public override string Name => "Playlist";
|
||||
}
|
||||
}
|
98
osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs
Normal file
98
osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs
Normal file
@ -0,0 +1,98 @@
|
||||
// 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;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Screens.Select;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
public class MatchBeatmapDetailArea : BeatmapDetailArea
|
||||
{
|
||||
public Action CreateNewItem;
|
||||
|
||||
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
|
||||
|
||||
[Resolved(typeof(Room))]
|
||||
protected BindableList<PlaylistItem> Playlist { get; private set; }
|
||||
|
||||
private readonly Drawable playlistArea;
|
||||
private readonly DrawableRoomPlaylist playlist;
|
||||
|
||||
public MatchBeatmapDetailArea()
|
||||
{
|
||||
Add(playlistArea = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Vertical = 10 },
|
||||
Child = new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Content = new[]
|
||||
{
|
||||
new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Bottom = 10 },
|
||||
Child = playlist = new DrawableRoomPlaylist(true, false)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
}
|
||||
},
|
||||
new Drawable[]
|
||||
{
|
||||
new TriangleButton
|
||||
{
|
||||
Text = "create new item",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = Vector2.One,
|
||||
Action = () => CreateNewItem?.Invoke()
|
||||
}
|
||||
},
|
||||
},
|
||||
RowDimensions = new[]
|
||||
{
|
||||
new Dimension(),
|
||||
new Dimension(GridSizeMode.Absolute, 50),
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
playlist.Items.BindTo(Playlist);
|
||||
playlist.SelectedItem.BindTo(SelectedItem);
|
||||
}
|
||||
|
||||
protected override void OnTabChanged(BeatmapDetailAreaTabItem tab, bool selectedMods)
|
||||
{
|
||||
base.OnTabChanged(tab, selectedMods);
|
||||
|
||||
switch (tab)
|
||||
{
|
||||
case BeatmapDetailAreaPlaylistTabItem _:
|
||||
playlistArea.Show();
|
||||
break;
|
||||
|
||||
default:
|
||||
playlistArea.Hide();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override BeatmapDetailAreaTabItem[] CreateTabItems() => base.CreateTabItems().Prepend(new BeatmapDetailAreaPlaylistTabItem()).ToArray();
|
||||
}
|
||||
}
|
72
osu.Game/Screens/Multi/DrawableRoomPlaylist.cs
Normal file
72
osu.Game/Screens/Multi/DrawableRoomPlaylist.cs
Normal file
@ -0,0 +1,72 @@
|
||||
// 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.Bindables;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public class DrawableRoomPlaylist : OsuRearrangeableListContainer<PlaylistItem>
|
||||
{
|
||||
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
|
||||
|
||||
private readonly bool allowEdit;
|
||||
private readonly bool allowSelection;
|
||||
|
||||
public DrawableRoomPlaylist(bool allowEdit, bool allowSelection)
|
||||
{
|
||||
this.allowEdit = allowEdit;
|
||||
this.allowSelection = allowSelection;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
// Scheduled since items are removed and re-added upon rearrangement
|
||||
Items.ItemsRemoved += items => Schedule(() =>
|
||||
{
|
||||
if (!Items.Contains(SelectedItem.Value))
|
||||
SelectedItem.Value = null;
|
||||
});
|
||||
}
|
||||
|
||||
protected override ScrollContainer<Drawable> CreateScrollContainer() => base.CreateScrollContainer().With(d =>
|
||||
{
|
||||
d.ScrollbarVisible = false;
|
||||
});
|
||||
|
||||
protected override FillFlowContainer<RearrangeableListItem<PlaylistItem>> CreateListFillFlowContainer() => new FillFlowContainer<RearrangeableListItem<PlaylistItem>>
|
||||
{
|
||||
LayoutDuration = 200,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
Spacing = new Vector2(0, 2)
|
||||
};
|
||||
|
||||
protected override OsuRearrangeableListItem<PlaylistItem> CreateOsuDrawable(PlaylistItem item) => new DrawableRoomPlaylistItem(item, allowEdit, allowSelection)
|
||||
{
|
||||
SelectedItem = { BindTarget = SelectedItem },
|
||||
RequestDeletion = requestDeletion
|
||||
};
|
||||
|
||||
private void requestSelection(PlaylistItem item) => SelectedItem.Value = item;
|
||||
|
||||
private void requestDeletion(PlaylistItem item)
|
||||
{
|
||||
if (SelectedItem.Value == item)
|
||||
{
|
||||
if (Items.Count == 1)
|
||||
SelectedItem.Value = null;
|
||||
else
|
||||
SelectedItem.Value = Items.GetNext(item) ?? Items[^2];
|
||||
}
|
||||
|
||||
Items.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
275
osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs
Normal file
275
osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs
Normal file
@ -0,0 +1,275 @@
|
||||
// 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;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Multi
|
||||
{
|
||||
public class DrawableRoomPlaylistItem : OsuRearrangeableListItem<PlaylistItem>
|
||||
{
|
||||
public Action<PlaylistItem> RequestDeletion;
|
||||
|
||||
public readonly Bindable<PlaylistItem> SelectedItem = new Bindable<PlaylistItem>();
|
||||
|
||||
protected override bool ShowDragHandle => allowEdit;
|
||||
|
||||
private Container maskingContainer;
|
||||
private Container difficultyIconContainer;
|
||||
private LinkFlowContainer beatmapText;
|
||||
private LinkFlowContainer authorText;
|
||||
private ModDisplay modDisplay;
|
||||
|
||||
private readonly Bindable<BeatmapInfo> beatmap = new Bindable<BeatmapInfo>();
|
||||
private readonly Bindable<RulesetInfo> ruleset = new Bindable<RulesetInfo>();
|
||||
private readonly BindableList<Mod> requiredMods = new BindableList<Mod>();
|
||||
|
||||
private readonly PlaylistItem item;
|
||||
private readonly bool allowEdit;
|
||||
private readonly bool allowSelection;
|
||||
|
||||
public DrawableRoomPlaylistItem(PlaylistItem item, bool allowEdit, bool allowSelection)
|
||||
: base(item)
|
||||
{
|
||||
this.item = item;
|
||||
this.allowEdit = allowEdit;
|
||||
this.allowSelection = allowSelection;
|
||||
|
||||
beatmap.BindTo(item.Beatmap);
|
||||
ruleset.BindTo(item.Ruleset);
|
||||
requiredMods.BindTo(item.RequiredMods);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
if (!allowEdit)
|
||||
HandleColour = HandleColour.Opacity(0);
|
||||
|
||||
maskingContainer.BorderColour = colours.Yellow;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
SelectedItem.BindValueChanged(selected => maskingContainer.BorderThickness = selected.NewValue == Model ? 5 : 0, true);
|
||||
|
||||
beatmap.BindValueChanged(_ => scheduleRefresh());
|
||||
ruleset.BindValueChanged(_ => scheduleRefresh());
|
||||
|
||||
requiredMods.ItemsAdded += _ => scheduleRefresh();
|
||||
requiredMods.ItemsRemoved += _ => scheduleRefresh();
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
private ScheduledDelegate scheduledRefresh;
|
||||
|
||||
private void scheduleRefresh()
|
||||
{
|
||||
scheduledRefresh?.Cancel();
|
||||
scheduledRefresh = Schedule(refresh);
|
||||
}
|
||||
|
||||
private void refresh()
|
||||
{
|
||||
difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value) { Size = new Vector2(32) };
|
||||
|
||||
beatmapText.Clear();
|
||||
beatmapText.AddLink(item.Beatmap.ToString(), LinkAction.OpenBeatmap, item.Beatmap.Value.OnlineBeatmapID.ToString());
|
||||
|
||||
authorText.Clear();
|
||||
|
||||
if (item.Beatmap?.Value?.Metadata?.Author != null)
|
||||
{
|
||||
authorText.AddText("mapped by ");
|
||||
authorText.AddUserLink(item.Beatmap.Value?.Metadata.Author);
|
||||
}
|
||||
|
||||
modDisplay.Current.Value = requiredMods.ToArray();
|
||||
}
|
||||
|
||||
protected override Drawable CreateContent() => maskingContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 50,
|
||||
Masking = true,
|
||||
CornerRadius = 10,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box // A transparent box that forces the border to be drawn if the panel background is opaque
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
},
|
||||
new PanelBackground
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Beatmap = { BindTarget = beatmap }
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = 8 },
|
||||
Spacing = new Vector2(8, 0),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
difficultyIconContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
beatmapText = new LinkFlowContainer { AutoSizeAxes = Axes.Both },
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
authorText = new LinkFlowContainer { AutoSizeAxes = Axes.Both },
|
||||
modDisplay = new ModDisplay
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.4f),
|
||||
DisplayUnrankedText = false,
|
||||
ExpansionMode = ExpansionMode.AlwaysExpanded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
X = -18,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new IconButton
|
||||
{
|
||||
Icon = FontAwesome.Solid.MinusSquare,
|
||||
Alpha = allowEdit ? 1 : 0,
|
||||
Action = () => RequestDeletion?.Invoke(Model),
|
||||
},
|
||||
new PanelDownloadButton(item.Beatmap.Value.BeatmapSet)
|
||||
{
|
||||
Size = new Vector2(50, 30),
|
||||
Alpha = allowEdit ? 0 : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (allowSelection)
|
||||
SelectedItem.Value = Model;
|
||||
return true;
|
||||
}
|
||||
|
||||
// For now, this is the same implementation as in PanelBackground, but supports a beatmap info rather than a working beatmap
|
||||
private class PanelBackground : Container // todo: should be a buffered container (https://github.com/ppy/osu-framework/issues/3222)
|
||||
{
|
||||
public readonly Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
|
||||
|
||||
public PanelBackground()
|
||||
{
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new UpdateableBeatmapBackgroundSprite
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fill,
|
||||
Beatmap = { BindTarget = Beatmap }
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Depth = -1,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// This makes the gradient not be perfectly horizontal, but diagonal at a ~40° angle
|
||||
Shear = new Vector2(0.8f, 0),
|
||||
Alpha = 0.5f,
|
||||
Children = new[]
|
||||
{
|
||||
// The left half with no gradient applied
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
Width = 0.4f,
|
||||
},
|
||||
// Piecewise-linear gradient with 3 segments to make it appear smoother
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(Color4.Black, new Color4(0f, 0f, 0f, 0.9f)),
|
||||
Width = 0.05f,
|
||||
X = 0.4f,
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.9f), new Color4(0f, 0f, 0f, 0.1f)),
|
||||
Width = 0.2f,
|
||||
X = 0.45f,
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(new Color4(0f, 0f, 0f, 0.1f), new Color4(0, 0, 0, 0)),
|
||||
Width = 0.05f,
|
||||
X = 0.65f,
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -67,7 +67,14 @@ namespace osu.Game.Screens.Play
|
||||
}
|
||||
|
||||
private bool readyForPush =>
|
||||
player.LoadState == LoadState.Ready && (IsHovered || idleTracker.IsIdle.Value) && inputManager?.DraggedDrawable == null;
|
||||
// don't push unless the player is completely loaded
|
||||
player.LoadState == LoadState.Ready
|
||||
// don't push if the user is hovering one of the panes, unless they are idle.
|
||||
&& (IsHovered || idleTracker.IsIdle.Value)
|
||||
// don't push if the user is dragging a slider or otherwise.
|
||||
&& inputManager?.DraggedDrawable == null
|
||||
// don't push if a focused overlay is visible, like settings.
|
||||
&& inputManager?.FocusedDrawable == null;
|
||||
|
||||
private readonly Func<Player> createPlayer;
|
||||
|
||||
|
@ -12,6 +12,7 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Multi;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
@ -35,7 +36,7 @@ namespace osu.Game.Screens.Select
|
||||
Padding = new MarginPadding { Horizontal = HORIZONTAL_OVERFLOW_PADDING };
|
||||
}
|
||||
|
||||
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea(); // Todo: Temporary
|
||||
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new MatchBeatmapDetailArea();
|
||||
|
||||
protected override bool OnStart()
|
||||
{
|
||||
|
Reference in New Issue
Block a user