1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 22:27:25 +08:00

Merge branch 'master' into musiccontroller-init-fix

This commit is contained in:
Dean Herbert 2017-05-26 10:48:32 +09:00 committed by GitHub
commit 8ae7e84563
14 changed files with 779 additions and 66 deletions

View File

@ -0,0 +1,74 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Screens.Multiplayer;
using osu.Game.Online.Multiplayer;
using osu.Game.Users;
using osu.Game.Database;
namespace osu.Desktop.VisualTests.Tests
{
internal class TestCaseDrawableRoom : TestCase
{
public override string Description => @"Select your favourite room";
public override void Reset()
{
base.Reset();
DrawableRoom first;
DrawableRoom second;
Add(new FillFlowContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
AutoSizeAxes = Axes.Y,
Width = 500f,
Direction = FillDirection.Vertical,
Children = new Drawable[]
{
first = new DrawableRoom(new Room()),
second = new DrawableRoom(new Room()),
}
});
first.Room.Name.Value = @"Great Room Right Here";
first.Room.Host.Value = new User { Username = @"Naeferith", Id = 9492835, Country = new Country { FlagName = @"FR" }};
first.Room.Status.Value = new RoomStatusOpen();
first.Room.Beatmap.Value = new BeatmapMetadata { Title = @"Seiryu", Artist = @"Critical Crystal" };
second.Room.Name.Value = @"Relax It's The Weekend";
second.Room.Host.Value = new User { Username = @"peppy", Id = 2, Country = new Country { FlagName = @"AU" }};
second.Room.Status.Value = new RoomStatusPlaying();
second.Room.Beatmap.Value = new BeatmapMetadata { Title = @"ZAQ", Artist = @"Serendipity" };
AddStep(@"change state", () =>
{
first.Room.Status.Value = new RoomStatusPlaying();
});
AddStep(@"change name", () =>
{
first.Room.Name.Value = @"I Changed Name";
});
AddStep(@"change host", () =>
{
first.Room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } };
});
AddStep(@"change beatmap", () =>
{
first.Room.Beatmap.Value = null;
});
AddStep(@"change state", () =>
{
first.Room.Status.Value = new RoomStatusOpen();
});
}
}
}

View File

@ -220,6 +220,7 @@
<Compile Include="Tests\TestCaseLeaderboard.cs" />
<Compile Include="Beatmaps\TestWorkingBeatmap.cs" />
<Compile Include="Tests\TestCaseBeatmapDetailArea.cs" />
<Compile Include="Tests\TestCaseDrawableRoom.cs" />
<Compile Include="Tests\TestCaseUserPanel.cs" />
<Compile Include="Tests\TestCaseDirect.cs" />
</ItemGroup>

View File

@ -24,6 +24,9 @@ namespace osu.Game.Rulesets.Osu.Objects
base.ApplyDefaults(controlPointInfo, difficulty);
SpinsRequired = (int)(Duration / 1000 * BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5));
// spinning doesn't match 1:1 with stable, so let's fudge them easier for the time being.
SpinsRequired = (int)(SpinsRequired * 0.6);
}
}
}

View File

@ -1,20 +1,29 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils;
using OpenTK;
using OpenTK.Graphics;
using System;
using osu.Framework.Graphics.OpenGL;
using osu.Framework.Graphics.Shaders;
using osu.Framework.Graphics.Textures;
using OpenTK.Graphics.ES30;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Allocation;
using System.Collections.Generic;
using osu.Framework.Graphics.Batches;
using osu.Framework.Lists;
namespace osu.Game.Graphics.Backgrounds
{
public class Triangles : Container<Triangle>
public class Triangles : Drawable
{
private const float triangle_size = 100;
public override bool HandleInput => false;
public Color4 ColourLight = Color4.White;
@ -49,6 +58,28 @@ namespace osu.Game.Graphics.Backgrounds
/// </summary>
public float Velocity = 1;
private readonly SortedList<TriangleParticle> parts = new SortedList<TriangleParticle>(Comparer<TriangleParticle>.Default);
private Shader shader;
private readonly Texture texture;
public Triangles()
{
texture = Texture.WhitePixel;
}
[BackgroundDependencyLoader]
private void load(ShaderManager shaders)
{
shader = shaders?.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
}
protected override void LoadComplete()
{
base.LoadComplete();
addTriangles(true);
}
public float TriangleScale
{
get { return triangleScale; }
@ -57,42 +88,71 @@ namespace osu.Game.Graphics.Backgrounds
float change = value / triangleScale;
triangleScale = value;
if (change != 1)
Children.ForEach(t => t.Scale *= change);
for (int i = 0; i < parts.Count; i++)
{
TriangleParticle newParticle = parts[i];
newParticle.Scale *= change;
parts[i] = newParticle;
}
}
}
protected override void LoadComplete()
{
base.LoadComplete();
addTriangles(true);
}
private int aimTriangleCount => (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio);
protected override void Update()
{
base.Update();
float adjustedAlpha = HideAlphaDiscrepancies ?
// Cubically scale alpha to make it drop off more sharply.
(float)Math.Pow(DrawInfo.Colour.AverageColour.Linear.A, 3) :
1;
Invalidate(Invalidation.DrawNode, shallPropagate: false);
foreach (var t in Children)
for (int i = 0; i < parts.Count; i++)
{
t.Alpha = adjustedAlpha;
t.Position -= new Vector2(0, (float)(t.Scale.X * (50 / DrawHeight) * (Time.Elapsed / 950)) / triangleScale * Velocity);
if (ExpireOffScreenTriangles && t.DrawPosition.Y + t.DrawSize.Y * t.Scale.Y < 0)
t.Expire();
TriangleParticle newParticle = parts[i];
float adjustedAlpha = HideAlphaDiscrepancies ?
// Cubically scale alpha to make it drop off more sharply.
(float)Math.Pow(DrawInfo.Colour.AverageColour.Linear.A, 3) :
1;
newParticle.Position += new Vector2(0, -(parts[i].Scale * (50 / DrawHeight)) / triangleScale * Velocity) * ((float)Time.Elapsed / 950);
newParticle.Colour.A = adjustedAlpha;
parts[i] = newParticle;
if (!CreateNewTriangles)
continue;
float bottomPos = parts[i].Position.Y + triangle_size * parts[i].Scale * 0.866f / DrawHeight;
if (bottomPos < 0)
parts.RemoveAt(i);
}
if (CreateNewTriangles)
addTriangles(false);
addTriangles(false);
}
protected virtual Triangle CreateTriangle()
private void addTriangles(bool randomY)
{
int aimTriangleCount = (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio);
for (int i = 0; i < aimTriangleCount - parts.Count; i++)
parts.Add(createTriangle(randomY));
}
private TriangleParticle createTriangle(bool randomY)
{
TriangleParticle particle = CreateTriangle();
particle.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() : 1);
particle.Colour = CreateTriangleShade();
return particle;
}
/// <summary>
/// Creates a triangle particle with a random scale.
/// </summary>
/// <returns>The triangle particle.</returns>
protected virtual TriangleParticle CreateTriangle()
{
const float std_dev = 0.16f;
const float mean = 0.5f;
@ -102,32 +162,100 @@ namespace osu.Game.Graphics.Backgrounds
float randStdNormal = (float)(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2)); //random normal(0,1)
var scale = Math.Max(triangleScale * (mean + std_dev * randStdNormal), 0.1f); //random normal(mean,stdDev^2)
const float size = 100;
return new EquilateralTriangle
{
Origin = Anchor.TopCentre,
RelativePositionAxes = Axes.Both,
Size = new Vector2(size),
Scale = new Vector2(scale),
EdgeSmoothness = new Vector2(1),
Colour = GetTriangleShade(),
Depth = scale,
};
return new TriangleParticle { Scale = scale };
}
protected virtual Color4 GetTriangleShade() => Interpolation.ValueAt(RNG.NextSingle(), ColourDark, ColourLight, 0, 1);
/// <summary>
/// Creates a shade of colour for the triangles.
/// </summary>
/// <returns>The colour.</returns>
protected virtual Color4 CreateTriangleShade() => Interpolation.ValueAt(RNG.NextSingle(), ColourDark, ColourLight, 0, 1);
private void addTriangles(bool randomY)
protected override DrawNode CreateDrawNode() => new TrianglesDrawNode();
private readonly TrianglesDrawNodeSharedData sharedData = new TrianglesDrawNodeSharedData();
protected override void ApplyDrawNode(DrawNode node)
{
int addCount = aimTriangleCount - Children.Count();
for (int i = 0; i < addCount; i++)
base.ApplyDrawNode(node);
var trianglesNode = (TrianglesDrawNode)node;
trianglesNode.Shader = shader;
trianglesNode.Texture = texture;
trianglesNode.Size = DrawSize;
trianglesNode.Shared = sharedData;
trianglesNode.Parts.Clear();
trianglesNode.Parts.AddRange(parts);
}
private class TrianglesDrawNodeSharedData
{
public readonly LinearBatch<TexturedVertex2D> VertexBatch = new LinearBatch<TexturedVertex2D>(100 * 3, 10, PrimitiveType.Triangles);
}
private class TrianglesDrawNode : DrawNode
{
public Shader Shader;
public Texture Texture;
public TrianglesDrawNodeSharedData Shared;
public readonly List<TriangleParticle> Parts = new List<TriangleParticle>();
public Vector2 Size;
public override void Draw(Action<TexturedVertex2D> vertexAction)
{
var sprite = CreateTriangle();
float triangleHeight = sprite.DrawHeight / DrawHeight;
sprite.Position = new Vector2(RNG.NextSingle(), randomY ? RNG.NextSingle() * (1 + triangleHeight) - triangleHeight : 1);
Add(sprite);
base.Draw(vertexAction);
Shader.Bind();
Texture.TextureGL.Bind();
foreach (TriangleParticle particle in Parts)
{
var offset = new Vector2(particle.Scale * 0.5f, particle.Scale * 0.866f);
var triangle = new Triangle(
particle.Position * Size * DrawInfo.Matrix,
(particle.Position * Size + offset * triangle_size) * DrawInfo.Matrix,
(particle.Position * Size + new Vector2(-offset.X, offset.Y) * triangle_size) * DrawInfo.Matrix
);
ColourInfo colourInfo = DrawInfo.Colour;
colourInfo.ApplyChild(particle.Colour);
Texture.DrawTriangle(triangle, colourInfo, null, Shared.VertexBatch.Add);
}
Shader.Unbind();
}
}
protected struct TriangleParticle : IComparable<TriangleParticle>
{
/// <summary>
/// The position of the top vertex of the triangle.
/// </summary>
public Vector2 Position;
/// <summary>
/// The colour of the triangle.
/// </summary>
public Color4 Colour;
/// <summary>
/// The scale of the triangle.
/// </summary>
public float Scale;
/// <summary>
/// Compares two <see cref="TriangleParticle"/>s. This is a reverse comparer because when the
/// triangles are added to the particles list, they should be drawn from largest to smallest
/// such that the smaller triangles appear on top.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public int CompareTo(TriangleParticle other) => other.Scale.CompareTo(Scale);
}
}
}

View File

@ -42,7 +42,7 @@ namespace osu.Game.Graphics.UserInterface
protected override DropdownMenuItem<T> CreateMenuItem(string text, T value) => new OsuDropdownMenuItem(text, value) { AccentColour = AccentColour };
private class OsuDropdownMenuItem : DropdownMenuItem<T>
public class OsuDropdownMenuItem : DropdownMenuItem<T>
{
public OsuDropdownMenuItem(string text, T current) : base(text, current)
{
@ -60,7 +60,7 @@ namespace osu.Game.Graphics.UserInterface
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
chevron = new TextAwesome
Chevron = new TextAwesome
{
AlwaysPresent = true,
Icon = FontAwesome.fa_chevron_right,
@ -84,12 +84,12 @@ namespace osu.Game.Graphics.UserInterface
private Color4? accentColour;
private readonly TextAwesome chevron;
protected readonly TextAwesome Chevron;
protected override void FormatForeground(bool hover = false)
{
base.FormatForeground(hover);
chevron.Alpha = hover ? 1 : 0;
Chevron.Alpha = hover ? 1 : 0;
}
public Color4 AccentColour
@ -115,11 +115,11 @@ namespace osu.Game.Graphics.UserInterface
public class OsuDropdownHeader : DropdownHeader
{
private readonly SpriteText label;
protected readonly SpriteText Text;
protected override string Label
{
get { return label.Text; }
set { label.Text = value; }
get { return Text.Text; }
set { Text.Text = value; }
}
protected readonly TextAwesome Icon;
@ -146,7 +146,7 @@ namespace osu.Game.Graphics.UserInterface
Foreground.Children = new Drawable[]
{
label = new OsuSpriteText
Text = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Configuration;
using osu.Game.Database;
using osu.Game.Users;
namespace osu.Game.Online.Multiplayer
{
public class Room
{
public Bindable<string> Name = new Bindable<string>();
public Bindable<User> Host = new Bindable<User>();
public Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
public Bindable<BeatmapMetadata> Beatmap = new Bindable<BeatmapMetadata>();
}
}

View File

@ -0,0 +1,26 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK.Graphics;
using osu.Game.Graphics;
namespace osu.Game.Online.Multiplayer
{
public abstract class RoomStatus
{
public abstract string Message { get; }
public abstract Color4 GetAppropriateColour(OsuColour colours);
}
public class RoomStatusOpen : RoomStatus
{
public override string Message => @"Welcoming Players";
public override Color4 GetAppropriateColour(OsuColour colours) => colours.GreenLight;
}
public class RoomStatusPlaying : RoomStatus
{
public override string Message => @"Now Playing";
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Purple;
}
}

View File

@ -13,15 +13,23 @@ using osu.Game.Online.API;
using OpenTK;
using osu.Framework.Input;
using osu.Game.Users;
using System.ComponentModel;
using osu.Game.Graphics;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using Container = osu.Framework.Graphics.Containers.Container;
namespace osu.Game.Overlays.Settings.Sections.General
{
public class LoginSettings : SettingsSubsection, IOnlineComponent
public class LoginSettings : FillFlowContainer, IOnlineComponent
{
private bool bounding = true;
private LoginForm form;
private OsuColour colours;
protected override string Header => "Account";
private UserPanel panel;
private UserDropdown dropdown;
public override RectangleF BoundingBox => bounding ? base.BoundingBox : RectangleF.Empty;
@ -35,9 +43,18 @@ namespace osu.Game.Overlays.Settings.Sections.General
}
}
[BackgroundDependencyLoader(permitNulls: true)]
private void load(APIAccess api)
public LoginSettings()
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
Direction = FillDirection.Vertical;
Spacing = new Vector2(0f, 5f);
}
[BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours, APIAccess api)
{
this.colours = colours;
api?.Register(this);
}
@ -50,6 +67,12 @@ namespace osu.Game.Overlays.Settings.Sections.General
case APIState.Offline:
Children = new Drawable[]
{
new OsuSpriteText
{
Text = "ACCOUNT",
Margin = new MarginPadding { Bottom = 5 },
Font = @"Exo2.0-Black",
},
form = new LoginForm()
};
break;
@ -67,24 +90,73 @@ namespace osu.Game.Overlays.Settings.Sections.General
{
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Connecting...",
Margin = new MarginPadding { Top = 10, Bottom = 10 },
},
};
break;
case APIState.Online:
Children = new Drawable[]
{
new UserPanel(api.LocalUser.Value)
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding { Left = 20, Right = 20 },
Direction = FillDirection.Vertical,
Spacing = new Vector2(0f, 10f),
Children = new Drawable[]
{
new Container
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Children = new[]
{
new OsuSpriteText
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "Signed in",
TextSize = 18,
Font = @"Exo2.0-Bold",
Margin = new MarginPadding { Top = 5, Bottom = 5 },
},
},
},
panel = new UserPanel(api.LocalUser.Value) { RelativeSizeAxes = Axes.X },
dropdown = new UserDropdown { RelativeSizeAxes = Axes.X },
},
},
new OsuButton
};
panel.Status.BindTo(api.LocalUser.Value.Status);
dropdown.Current.ValueChanged += newValue =>
{
switch (newValue)
{
RelativeSizeAxes = Axes.X,
Text = "Sign out",
Action = api.Logout
case UserAction.Online:
api.LocalUser.Value.Status.Value = new UserStatusOnline();
dropdown.StatusColour = colours.Green;
break;
case UserAction.DoNotDisturb:
api.LocalUser.Value.Status.Value = new UserStatusDoNotDisturb();
dropdown.StatusColour = colours.Red;
break;
case UserAction.AppearOffline:
api.LocalUser.Value.Status.Value = new UserStatusOffline();
dropdown.StatusColour = colours.Gray7;
break;
case UserAction.SignOut:
api.Logout();
break;
}
};
dropdown.Current.TriggerChange();
break;
}
@ -171,5 +243,119 @@ namespace osu.Game.Overlays.Settings.Sections.General
return base.OnFocus(state);
}
}
private class UserDropdown : OsuEnumDropdown<UserAction>
{
protected override DropdownHeader CreateHeader() => new UserDropdownHeader { AccentColour = AccentColour };
protected override Menu CreateMenu() => new UserDropdownMenu();
protected override DropdownMenuItem<UserAction> CreateMenuItem(string text, UserAction value) => new UserDropdownMenuItem(text, value) { AccentColour = AccentColour };
public Color4 StatusColour
{
set
{
var h = Header as UserDropdownHeader;
if (h == null) return;
h.StatusColour = value;
}
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
AccentColour = colours.Gray5;
}
private class UserDropdownHeader : OsuDropdownHeader
{
public const float LABEL_LEFT_MARGIN = 20;
private readonly TextAwesome statusIcon;
public Color4 StatusColour
{
set
{
statusIcon.FadeColour(value, 500, EasingTypes.OutQuint);
}
}
public UserDropdownHeader()
{
Foreground.Padding = new MarginPadding { Left = 10, Right = 10 };
Margin = new MarginPadding { Bottom = 5 };
Masking = true;
CornerRadius = 5;
EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(0.25f),
Radius = 4,
};
Icon.TextSize = 14;
Icon.Margin = new MarginPadding(0);
Foreground.Add(statusIcon = new TextAwesome
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Icon = FontAwesome.fa_circle_o,
TextSize = 14,
});
Text.Margin = new MarginPadding { Left = LABEL_LEFT_MARGIN };
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
BackgroundColour = colours.Gray3;
}
}
private class UserDropdownMenu : OsuMenu
{
public UserDropdownMenu()
{
Margin = new MarginPadding { Bottom = 5 };
CornerRadius = 5;
ItemsContainer.Padding = new MarginPadding(0);
Masking = true;
EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(0.25f),
Radius = 4,
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Background.Colour = colours.Gray3;
}
}
private class UserDropdownMenuItem : OsuDropdownMenuItem
{
public UserDropdownMenuItem(string text, UserAction current) : base(text, current)
{
Foreground.Padding = new MarginPadding { Top = 5, Bottom = 5, Left = UserDropdownHeader.LABEL_LEFT_MARGIN, Right = 5 };
Chevron.Margin = new MarginPadding { Left = 2, Right = 3 };
CornerRadius = 5;
}
}
}
private enum UserAction
{
Online,
[Description(@"Do not disturb")]
DoNotDisturb,
[Description(@"Appear offline")]
AppearOffline,
[Description(@"Sign out")]
SignOut,
}
}
}

View File

@ -36,6 +36,8 @@ namespace osu.Game.Screens.Menu
public MenuSideFlashes()
{
EarlyActivationMilliseconds = box_fade_in_time;
RelativeSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;

View File

@ -0,0 +1,259 @@
// Copyright (c) 2007-2017 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.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Game.Online.Multiplayer;
using osu.Game.Users;
namespace osu.Game.Screens.Multiplayer
{
public class DrawableRoom : ClickableContainer
{
private const float content_padding = 5;
private const float height = 90;
private readonly Box sideStrip;
private readonly UpdateableAvatar avatar;
private readonly OsuSpriteText name;
private readonly Container flagContainer;
private readonly OsuSpriteText host;
private readonly OsuSpriteText rankBounds;
private readonly OsuSpriteText status;
private readonly FillFlowContainer<OsuSpriteText> beatmapInfoFlow;
private readonly OsuSpriteText beatmapTitle;
private readonly OsuSpriteText beatmapDash;
private readonly OsuSpriteText beatmapArtist;
private OsuColour colours;
private LocalisationEngine localisation;
public readonly Room Room;
public DrawableRoom(Room room)
{
Room = room;
RelativeSizeAxes = Axes.X;
Height = height;
CornerRadius = 5;
Masking = true;
EdgeEffect = new EdgeEffect
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Black.Opacity(40),
Radius = 5,
};
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(34),
},
sideStrip = new Box
{
RelativeSizeAxes = Axes.Y,
Width = content_padding,
},
avatar = new UpdateableAvatar
{
Size = new Vector2(Height - content_padding* 2),
Masking = true,
CornerRadius = 5f,
Margin = new MarginPadding { Left = content_padding * 2, Top = content_padding },
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = content_padding, Bottom = content_padding, Left = Height + content_padding * 2, Right = content_padding },
Children = new Drawable[]
{
new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Spacing = new Vector2(5f),
Children = new Drawable[]
{
name = new OsuSpriteText
{
TextSize = 18,
},
new Container
{
RelativeSizeAxes = Axes.X,
Height = 20f,
Children = new Drawable[]
{
new FillFlowContainer
{
AutoSizeAxes = Axes.X,
RelativeSizeAxes = Axes.Y,
Direction = FillDirection.Horizontal,
Spacing = new Vector2(5f, 0f),
Children = new Drawable[]
{
flagContainer = new Container
{
Width = 30f,
RelativeSizeAxes = Axes.Y,
},
new Container
{
Width = 40f,
RelativeSizeAxes = Axes.Y,
},
new OsuSpriteText
{
Text = "hosted by",
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
TextSize = 14,
},
host = new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
TextSize = 14,
Font = @"Exo2.0-BoldItalic",
},
},
},
rankBounds = new OsuSpriteText
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Text = "#0 - #0",
TextSize = 14,
Margin = new MarginPadding { Right = 10 },
},
},
},
},
},
new FillFlowContainer
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
Margin = new MarginPadding { Bottom = content_padding },
Children = new Drawable[]
{
status = new OsuSpriteText
{
TextSize = 14,
Font = @"Exo2.0-Bold",
},
beatmapInfoFlow = new FillFlowContainer<OsuSpriteText>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Horizontal,
Children = new[]
{
beatmapTitle = new OsuSpriteText
{
TextSize = 14,
Font = @"Exo2.0-BoldItalic",
},
beatmapDash = new OsuSpriteText
{
TextSize = 14,
Font = @"Exo2.0-RegularItalic",
},
beatmapArtist = new OsuSpriteText
{
TextSize = 14,
Font = @"Exo2.0-RegularItalic",
},
},
},
},
},
},
},
};
Room.Name.ValueChanged += displayName;
Room.Host.ValueChanged += displayUser;
Room.Status.ValueChanged += displayStatus;
Room.Beatmap.ValueChanged += displayBeatmap;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours, LocalisationEngine localisation)
{
this.localisation = localisation;
this.colours = colours;
beatmapInfoFlow.Colour = rankBounds.Colour = colours.Gray9;
host.Colour = colours.Blue;
displayStatus(Room.Status.Value);
}
private void displayName(string value)
{
name.Text = value;
}
private void displayUser(User value)
{
avatar.User = value;
host.Text = value.Username;
flagContainer.Children = new[] { new DrawableFlag(value.Country?.FlagName ?? @"__") { RelativeSizeAxes = Axes.Both } };
}
private void displayStatus(RoomStatus value)
{
if (value == null) return;
status.Text = value.Message;
foreach (Drawable d in new Drawable[] { sideStrip, status })
d.FadeColour(value.GetAppropriateColour(colours), 100);
}
private void displayBeatmap(BeatmapMetadata value)
{
if (value != null)
{
beatmapTitle.Current = localisation.GetUnicodePreference(value.TitleUnicode, value.Title);
beatmapDash.Text = @" - ";
beatmapArtist.Current = localisation.GetUnicodePreference(value.ArtistUnicode, value.Artist);
}
else
{
beatmapTitle.Current = null;
beatmapArtist.Current = null;
beatmapTitle.Text = @"Changing map";
beatmapDash.Text = string.Empty;
beatmapArtist.Text = string.Empty;
}
}
protected override void Dispose(bool isDisposing)
{
Room.Name.ValueChanged -= displayName;
Room.Host.ValueChanged -= displayUser;
Room.Status.ValueChanged -= displayStatus;
Room.Beatmap.ValueChanged -= displayBeatmap;
base.Dispose(isDisposing);
}
}
}

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json;
using osu.Framework.Configuration;
namespace osu.Game.Users
{
@ -19,6 +20,8 @@ namespace osu.Game.Users
[JsonProperty(@"country")]
public Country Country;
public Bindable<UserStatus> Status = new Bindable<UserStatus>();
//public Team Team;
[JsonProperty(@"profile_colour")]

View File

@ -158,14 +158,19 @@ namespace osu.Game.Users
},
},
};
Status.ValueChanged += displayStatus;
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
this.colours = colours;
Status.ValueChanged += displayStatus;
}
protected override void LoadComplete()
{
base.LoadComplete();
Status.TriggerChange();
}
private void displayStatus(UserStatus status)

View File

@ -58,4 +58,10 @@ namespace osu.Game.Users
public override string Message => @"Modding a map";
public override Color4 GetAppropriateColour(OsuColour colours) => colours.PurpleDark;
}
public class UserStatusDoNotDisturb : UserStatus
{
public override string Message => @"Do not disturb";
public override Color4 GetAppropriateColour(OsuColour colours) => colours.RedDark;
}
}

View File

@ -432,6 +432,9 @@
<Compile Include="Overlays\Music\PlaylistOverlay.cs" />
<Compile Include="Rulesets\Replays\IAutoGenerator.cs" />
<Compile Include="Rulesets\Replays\AutoGenerator.cs" />
<Compile Include="Screens\Multiplayer\DrawableRoom.cs" />
<Compile Include="Online\Multiplayer\Room.cs" />
<Compile Include="Online\Multiplayer\RoomStatus.cs" />
<Compile Include="Users\UserPanel.cs" />
<Compile Include="Users\UserStatus.cs" />
<Compile Include="Overlays\DirectOverlay.cs" />