1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 19:22:54 +08:00

Merge branch 'master' into scrolling-hitobjects-rewrite

This commit is contained in:
Dean Herbert 2018-01-12 17:35:24 +09:00 committed by GitHub
commit 29c8400ec7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 407 additions and 183 deletions

View File

@ -1,13 +1,26 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using osu.Game.Overlays;
using osu.Game.Overlays.Social;
using osu.Game.Users;
namespace osu.Game.Tests.Visual
{
public class TestCaseSocial : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(UserPanel),
typeof(SocialPanel),
typeof(FilterControl),
typeof(SocialOverlay),
typeof(SocialGridPanel),
typeof(SocialListPanel)
};
public TestCaseSocial()
{
SocialOverlay s = new SocialOverlay

View File

@ -0,0 +1,13 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Users;
namespace osu.Game.Online.API.Requests
{
public class GetFriendsRequest : APIRequest<List<User>>
{
protected override string Target => @"friends";
}
}

View File

@ -22,7 +22,8 @@ namespace osu.Game.Overlays.Social
public enum SocialSortCriteria
{
Rank,
//Location,
Name,
Location,
//[Description("Time Zone")]
//TimeZone,
//[Description("World Map")]

View File

@ -18,7 +18,8 @@ namespace osu.Game.Overlays.Social
protected override Color4 BackgroundColour => OsuColour.FromHex(@"38202e");
protected override float TabStripWidth => 438;
protected override SocialTab DefaultTab => SocialTab.OnlinePlayers;
protected override SocialTab DefaultTab => SocialTab.AllPlayers;
protected override FontAwesome Icon => FontAwesome.fa_users;
protected override Drawable CreateHeaderText()
@ -53,12 +54,12 @@ namespace osu.Game.Overlays.Social
public enum SocialTab
{
[Description("Online Players")]
OnlinePlayers,
//[Description("Online Friends")]
//OnlineFriends,
//[Description("Online Team Members")]
//OnlineTeamMembers,
[Description("All Players")]
AllPlayers,
[Description("Friends")]
Friends,
//[Description("Team Members")]
//TeamMembers,
//[Description("Chat Channels")]
//ChatChannels,
}

View File

@ -0,0 +1,15 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Users;
namespace osu.Game.Overlays.Social
{
public class SocialGridPanel : SocialPanel
{
public SocialGridPanel(User user) : base(user)
{
Width = 300;
}
}
}

View File

@ -0,0 +1,16 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using osu.Game.Users;
namespace osu.Game.Overlays.Social
{
public class SocialListPanel : SocialPanel
{
public SocialListPanel(User user) : base(user)
{
RelativeSizeAxes = Axes.X;
}
}
}

View File

@ -0,0 +1,60 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Game.Users;
namespace osu.Game.Overlays.Social
{
public class SocialPanel : UserPanel
{
private const double hover_transition_time = 400;
public SocialPanel(User user) : base(user)
{
}
private readonly EdgeEffectParameters edgeEffectNormal = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Offset = new Vector2(0f, 1f),
Radius = 2f,
Colour = Color4.Black.Opacity(0.25f),
};
private readonly EdgeEffectParameters edgeEffectHovered = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Offset = new Vector2(0f, 5f),
Radius = 10f,
Colour = Color4.Black.Opacity(0.3f),
};
protected override bool OnHover(InputState state)
{
Content.TweenEdgeEffectTo(edgeEffectHovered, hover_transition_time, Easing.OutQuint);
Content.MoveToY(-4, hover_transition_time, Easing.OutQuint);
return base.OnHover(state);
}
protected override void OnHoverLost(InputState state)
{
Content.TweenEdgeEffectTo(edgeEffectNormal, hover_transition_time, Easing.OutQuint);
Content.MoveToY(0, hover_transition_time, Easing.OutQuint);
base.OnHoverLost(state);
}
protected override void LoadComplete()
{
base.LoadComplete();
this.FadeInFromZero(200, Easing.Out);
}
}
}

View File

@ -9,19 +9,22 @@ using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Overlays.SearchableList;
using osu.Game.Overlays.Social;
using osu.Game.Users;
using osu.Framework.Configuration;
using osu.Framework.Threading;
namespace osu.Game.Overlays
{
public class SocialOverlay : SearchableListOverlay<SocialTab, SocialSortCriteria, SortDirection>, IOnlineComponent
{
private readonly FillFlowContainer<UserPanel> panelFlow;
private APIAccess api;
private readonly LoadingAnimation loading;
private FillFlowContainer<SocialPanel> panels;
protected override Color4 BackgroundColour => OsuColour.FromHex(@"60284b");
protected override Color4 TrianglesColourLight => OsuColour.FromHex(@"672b51");
@ -31,27 +34,15 @@ namespace osu.Game.Overlays
protected override SearchableListFilterControl<SocialSortCriteria, SortDirection> CreateFilterControl() => new FilterControl();
private IEnumerable<User> users;
private readonly LoadingAnimation loading;
public IEnumerable<User> Users
{
get { return users; }
set
{
if (users?.Equals(value) ?? false) return;
users = value;
if (users?.Equals(value) ?? false)
return;
if (users == null)
panelFlow.Clear();
else
{
panelFlow.ChildrenEnumerable = users.Select(u =>
{
var p = new UserPanel(u) { Width = 300 };
p.Status.BindTo(u.Status);
return p;
});
}
users = value?.ToList();
}
}
@ -62,57 +53,153 @@ namespace osu.Game.Overlays
ThirdWaveColour = OsuColour.FromHex(@"9b2b6e");
FourthWaveColour = OsuColour.FromHex(@"6d214d");
ScrollFlow.Children = new[]
Add(loading = new LoadingAnimation());
Filter.Search.Current.ValueChanged += text =>
{
new OsuContextMenuContainer
if (!string.IsNullOrEmpty(text))
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Child = panelFlow = new FillFlowContainer<UserPanel>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Margin = new MarginPadding { Top = 20 },
Spacing = new Vector2(10f),
}
},
// force searching in players until searching for friends is supported
Header.Tabs.Current.Value = SocialTab.AllPlayers;
if (Filter.Tabs.Current.Value != SocialSortCriteria.Rank)
Filter.Tabs.Current.Value = SocialSortCriteria.Rank;
}
};
Add(loading = new LoadingAnimation());
Header.Tabs.Current.ValueChanged += tab => Scheduler.AddOnce(updateSearch);
Filter.Tabs.Current.ValueChanged += sortCriteria => Scheduler.AddOnce(updateSearch);
Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels;
Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += sortOrder => Scheduler.AddOnce(updateSearch);
currentQuery.ValueChanged += query =>
{
queryChangedDebounce?.Cancel();
if (string.IsNullOrEmpty(query))
Scheduler.AddOnce(updateSearch);
else
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500);
};
currentQuery.BindTo(Filter.Search.Current);
}
[BackgroundDependencyLoader]
private void load(APIAccess api)
{
if (Users == null)
reloadUsers(api);
this.api = api;
api.Register(this);
}
private void reloadUsers(APIAccess api)
private void recreatePanels(PanelDisplayStyle displayStyle)
{
Users = null;
clearPanels();
// no this is not the correct data source, but it's something.
var request = new GetUsersRequest();
request.Success += res =>
if (Users == null)
return;
var newPanels = new FillFlowContainer<SocialPanel>
{
Users = res.Select(e => e.User);
loading.Hide();
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Spacing = new Vector2(10f),
Margin = new MarginPadding { Top = 10 },
ChildrenEnumerable = Users.Select(u =>
{
SocialPanel panel;
switch (displayStyle)
{
case PanelDisplayStyle.Grid:
panel = new SocialGridPanel(u)
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre
};
break;
default:
panel = new SocialListPanel(u);
break;
}
panel.Status.BindTo(u.Status);
return panel;
})
};
api.Queue(request);
LoadComponentAsync(newPanels, f =>
{
if(panels != null)
ScrollFlow.Remove(panels);
ScrollFlow.Add(panels = newPanels);
});
}
private APIRequest getUsersRequest;
private readonly Bindable<string> currentQuery = new Bindable<string>();
private ScheduledDelegate queryChangedDebounce;
private void updateSearch()
{
queryChangedDebounce?.Cancel();
if (!IsLoaded)
return;
Users = null;
clearPanels();
loading.Hide();
getUsersRequest?.Cancel();
if (api?.IsLoggedIn == false)
return;
switch (Header.Tabs.Current.Value)
{
case SocialTab.Friends:
var friendRequest = new GetFriendsRequest(); // TODO filter arguments?
friendRequest.Success += updateUsers;
api.Queue(getUsersRequest = friendRequest);
break;
default:
var userRequest = new GetUsersRequest(); // TODO filter arguments!
userRequest.Success += response => updateUsers(response.Select(r => r.User));
api.Queue(getUsersRequest = userRequest);
break;
}
loading.Show();
}
private void updateUsers(IEnumerable<User> newUsers)
{
Users = newUsers;
loading.Hide();
recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value);
}
private void clearPanels()
{
if (panels != null)
{
panels.Expire();
panels = null;
}
}
public void APIStateChanged(APIAccess api, APIState state)
{
switch (state)
{
case APIState.Online:
reloadUsers(api);
Scheduler.AddOnce(updateSearch);
break;
default:
Users = null;
clearPanels();
break;
}
}
@ -120,7 +207,7 @@ namespace osu.Game.Overlays
public enum SortDirection
{
Descending,
Ascending,
Descending
}
}

View File

@ -44,7 +44,7 @@ namespace osu.Game.Users
new Avatar(user)
{
RelativeSizeAxes = Axes.Both,
OnLoadComplete = d => d.FadeInFromZero(200),
OnLoadComplete = d => d.FadeInFromZero(300, Easing.OutQuint),
})
);
}

View File

@ -39,10 +39,14 @@ namespace osu.Game.Users
public string AvatarUrl;
[JsonProperty(@"cover_url")]
public string CoverUrl;
public string CoverUrl
{
get { return Cover?.Url; }
set { Cover = new UserCover { Url = value }; }
}
//[JsonProperty(@"cover")]
//public UserCover Cover;
[JsonProperty(@"cover")]
public UserCover Cover;
public class UserCover
{

View File

@ -28,9 +28,12 @@ namespace osu.Game.Users
private const float content_padding = 10;
private const float status_height = 30;
private readonly Container statusBar;
private readonly Box statusBg;
private readonly OsuSpriteText statusMessage;
private Container statusBar;
private Box statusBg;
private OsuSpriteText statusMessage;
private Container content;
protected override Container<Drawable> Content => content;
public readonly Bindable<UserStatus> Status = new Bindable<UserStatus>();
@ -45,133 +48,7 @@ namespace osu.Game.Users
this.user = user;
FillFlowContainer infoContainer;
Height = height - status_height;
Masking = true;
CornerRadius = 5;
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(0.25f),
Radius = 4,
};
Children = new Drawable[]
{
new DelayedLoadWrapper(new UserCoverBackground(user)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fill,
OnLoadComplete = d => d.FadeInFromZero(200),
}, 0) { RelativeSizeAxes = Axes.Both },
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.7f),
},
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Top = content_padding, Left = content_padding, Right = content_padding },
Children = new Drawable[]
{
new UpdateableAvatar
{
Size = new Vector2(height - status_height - content_padding * 2),
User = user,
Masking = true,
CornerRadius = 5,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(0.25f),
Radius = 4,
},
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = height - status_height - content_padding },
Children = new Drawable[]
{
new OsuSpriteText
{
Text = user.Username,
TextSize = 18,
Font = @"Exo2.0-SemiBoldItalic",
},
infoContainer = new FillFlowContainer
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
AutoSizeAxes = Axes.X,
Height = 20f,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(5f, 0f),
Children = new Drawable[]
{
new DrawableFlag(user.Country)
{
Width = 30f,
RelativeSizeAxes = Axes.Y,
},
},
},
},
},
},
},
statusBar = new Container
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
Alpha = 0f,
Children = new Drawable[]
{
statusBg = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.5f,
},
new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(5f, 0f),
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Icon = FontAwesome.fa_circle_o,
Shadow = true,
Size = new Vector2(14),
},
statusMessage = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = @"Exo2.0-Semibold",
},
},
},
},
},
};
if (user.IsSupporter)
infoContainer.Add(new SupporterIcon
{
RelativeSizeAxes = Axes.Y,
Width = 20f,
});
}
[BackgroundDependencyLoader(permitNulls: true)]
@ -180,6 +57,139 @@ namespace osu.Game.Users
if (colours == null)
throw new ArgumentNullException(nameof(colours));
FillFlowContainer infoContainer;
AddInternal(content = new Container
{
RelativeSizeAxes = Axes.Both,
Masking = true,
CornerRadius = 5,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(0.25f),
Radius = 4,
},
Children = new Drawable[]
{
new DelayedLoadWrapper(new UserCoverBackground(user)
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
FillMode = FillMode.Fill,
OnLoadComplete = d => d.FadeInFromZero(400, Easing.Out)
}, 300) { RelativeSizeAxes = Axes.Both },
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black.Opacity(0.7f),
},
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Top = content_padding, Horizontal = content_padding },
Children = new Drawable[]
{
new UpdateableAvatar
{
Size = new Vector2(height - status_height - content_padding * 2),
User = user,
Masking = true,
CornerRadius = 5,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(0.25f),
Radius = 4,
},
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = height - status_height - content_padding },
Children = new Drawable[]
{
new OsuSpriteText
{
Text = user.Username,
TextSize = 18,
Font = @"Exo2.0-SemiBoldItalic",
},
infoContainer = new FillFlowContainer
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
AutoSizeAxes = Axes.X,
Height = 20f,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(5f, 0f),
Children = new Drawable[]
{
new DrawableFlag(user.Country)
{
Width = 30f,
RelativeSizeAxes = Axes.Y,
},
},
},
},
},
},
},
statusBar = new Container
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
Alpha = 0f,
Children = new Drawable[]
{
statusBg = new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0.5f,
},
new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Both,
Spacing = new Vector2(5f, 0f),
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Icon = FontAwesome.fa_circle_o,
Shadow = true,
Size = new Vector2(14),
},
statusMessage = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = @"Exo2.0-Semibold",
},
},
},
},
},
}
});
if (user.IsSupporter)
{
infoContainer.Add(new SupporterIcon
{
RelativeSizeAxes = Axes.Y,
Width = 20f,
});
}
Status.ValueChanged += displayStatus;
Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint);

View File

@ -270,6 +270,7 @@
<Compile Include="Database\IHasPrimaryKey.cs" />
<Compile Include="Graphics\Textures\LargeTextureStore.cs" />
<Compile Include="Overlays\Profile\SupporterIcon.cs" />
<Compile Include="Online\API\Requests\GetFriendsRequest.cs" />
<Compile Include="Overlays\Settings\DangerousSettingsButton.cs" />
<Compile Include="Graphics\UserInterface\HoverClickSounds.cs" />
<Compile Include="Graphics\UserInterface\HoverSounds.cs" />
@ -316,6 +317,9 @@
<Compile Include="Rulesets\Mods\IApplicableFailOverride.cs" />
<Compile Include="Rulesets\Mods\IApplicableMod.cs" />
<Compile Include="Rulesets\Mods\IApplicableToBeatmapConverter.cs" />
<Compile Include="Overlays\Social\SocialGridPanel.cs" />
<Compile Include="Overlays\Social\SocialListPanel.cs" />
<Compile Include="Overlays\Social\SocialPanel.cs" />
<Compile Include="Rulesets\Mods\IApplicableToDrawableHitObject.cs" />
<Compile Include="Rulesets\UI\HitObjectContainer.cs" />
<Compile Include="Rulesets\UI\Scrolling\Visualisers\SequentialSpeedChangeVisualiser.cs" />