mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 23:47:24 +08:00
Merge branch 'master' into channel-selector-tab-item
This commit is contained in:
commit
f6f1ea42ee
@ -1 +1 @@
|
||||
Subproject commit c6f030d6f1ab65a48de9ff1d0c424acb686e0149
|
||||
Subproject commit 8baad1b9484b9f35724e2f965c18cfe710907d80
|
199
osu.Desktop.VisualTests/Tests/TestCaseDirect.cs
Normal file
199
osu.Desktop.VisualTests/Tests/TestCaseDirect.cs
Normal file
@ -0,0 +1,199 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
public class TestCaseDirect : TestCase
|
||||
{
|
||||
public override string Description => @"osu!direct overlay";
|
||||
|
||||
private DirectOverlay direct;
|
||||
private RulesetDatabase rulesets;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
Add(direct = new DirectOverlay());
|
||||
newBeatmaps();
|
||||
|
||||
AddStep(@"toggle", direct.ToggleVisibility);
|
||||
AddStep(@"result counts", () => direct.ResultAmounts = new DirectOverlay.ResultCounts(1, 4, 13));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetDatabase rulesets)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
}
|
||||
|
||||
private void newBeatmaps()
|
||||
{
|
||||
var ruleset = rulesets.GetRuleset(0);
|
||||
|
||||
direct.BeatmapSets = new[]
|
||||
{
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"OrVid",
|
||||
Artist = @"An",
|
||||
Author = @"RLC",
|
||||
Source = @"",
|
||||
},
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 5.35f,
|
||||
Metadata = new BeatmapMetadata(),
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Covers = new[] { @"https://assets.ppy.sh//beatmaps/578332/covers/cover.jpg?1494591390" },
|
||||
Preview = @"https://b.ppy.sh/preview/578332.mp3",
|
||||
PlayCount = 97,
|
||||
FavouriteCount = 72,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"tiny lamp",
|
||||
Artist = @"fhana",
|
||||
Author = @"Sotarks",
|
||||
Source = @"ぎんぎつね",
|
||||
},
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 5.81f,
|
||||
Metadata = new BeatmapMetadata(),
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Covers = new[] { @"https://assets.ppy.sh//beatmaps/599627/covers/cover.jpg?1494539318" },
|
||||
Preview = @"https//b.ppy.sh/preview/599627.mp3",
|
||||
PlayCount = 3082,
|
||||
FavouriteCount = 14,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"At Gwanghwamun",
|
||||
Artist = @"KYUHYUN",
|
||||
Author = @"Cerulean Veyron",
|
||||
Source = @"",
|
||||
},
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 0.9f,
|
||||
Metadata = new BeatmapMetadata(),
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Covers = new[] { @"https://assets.ppy.sh//beatmaps/513268/covers/cover.jpg?1494502863" },
|
||||
Preview = @"https//b.ppy.sh/preview/513268.mp3",
|
||||
PlayCount = 2762,
|
||||
FavouriteCount = 15,
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 1.1f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 2.02f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 3.49f,
|
||||
},
|
||||
},
|
||||
},
|
||||
new BeatmapSetInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
{
|
||||
Title = @"RHAPSODY OF BLUE SKY",
|
||||
Artist = @"fhana",
|
||||
Author = @"[Kamiya]",
|
||||
Source = @"小林さんちのメイドラゴン",
|
||||
},
|
||||
Beatmaps = new List<BeatmapInfo>
|
||||
{
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 1.26f,
|
||||
Metadata = new BeatmapMetadata(),
|
||||
OnlineInfo = new BeatmapOnlineInfo
|
||||
{
|
||||
Covers = new[] { @"https://assets.ppy.sh//beatmaps/586841/covers/cover.jpg?1494052741" },
|
||||
Preview = @"https//b.ppy.sh/preview/586841.mp3",
|
||||
PlayCount = 62317,
|
||||
FavouriteCount = 161,
|
||||
},
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 2.01f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 2.87f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 3.76f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 3.93f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 4.37f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 5.13f,
|
||||
},
|
||||
new BeatmapInfo
|
||||
{
|
||||
Ruleset = ruleset,
|
||||
StarDifficulty = 5.42f,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
74
osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
Normal file
74
osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
Normal 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
57
osu.Desktop.VisualTests/Tests/TestCaseUserPanel.cs
Normal file
57
osu.Desktop.VisualTests/Tests/TestCaseUserPanel.cs
Normal file
@ -0,0 +1,57 @@
|
||||
// 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.Testing;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Users;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Desktop.VisualTests.Tests
|
||||
{
|
||||
internal class TestCaseUserPanel : TestCase
|
||||
{
|
||||
public override string Description => @"Panels for displaying a user's status";
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
UserPanel flyte;
|
||||
UserPanel peppy;
|
||||
Add(new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(10f),
|
||||
Children = new[]
|
||||
{
|
||||
flyte = new UserPanel(new User
|
||||
{
|
||||
Username = @"flyte",
|
||||
Id = 3103765,
|
||||
Country = new Country { FlagName = @"JP" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/3103765/5b012e13611d5761caa7e24fecb3d3a16e1cf48fc2a3032cfd43dd444af83d82.jpeg"
|
||||
}) { Width = 300 },
|
||||
peppy = new UserPanel(new User
|
||||
{
|
||||
Username = @"peppy",
|
||||
Id = 2,
|
||||
Country = new Country { FlagName = @"AU" },
|
||||
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/2/08cad88747c235a64fca5f1b770e100f120827ded1ffe3b66bfcd19c940afa65.jpeg"
|
||||
}) { Width = 300 },
|
||||
},
|
||||
});
|
||||
|
||||
flyte.Status.Value = new UserStatusOnline();
|
||||
peppy.Status.Value = new UserStatusSoloGame();
|
||||
|
||||
AddStep(@"spectating", () => { flyte.Status.Value = new UserStatusSpectating(); });
|
||||
AddStep(@"multiplaying", () => { flyte.Status.Value = new UserStatusMultiplayerGame(); });
|
||||
AddStep(@"modding", () => { flyte.Status.Value = new UserStatusModding(); });
|
||||
AddStep(@"offline", () => { flyte.Status.Value = new UserStatusOffline(); });
|
||||
AddStep(@"null status", () => { flyte.Status.Value = null; });
|
||||
}
|
||||
}
|
||||
}
|
@ -220,6 +220,9 @@
|
||||
<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>
|
||||
<ItemGroup />
|
||||
<ItemGroup />
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Framework.Audio.Track;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||
{
|
||||
@ -22,6 +24,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||
public const float SYMBOL_SIZE = TaikoHitObject.DEFAULT_CIRCLE_DIAMETER * 0.45f;
|
||||
public const float SYMBOL_BORDER = 8;
|
||||
public const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER;
|
||||
private const double pre_beat_transition_time = 80;
|
||||
|
||||
/// <summary>
|
||||
/// The colour of the inner circle and outer glows.
|
||||
@ -63,6 +66,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||
|
||||
public CirclePiece(bool isStrong = false)
|
||||
{
|
||||
EarlyActivationMilliseconds = pre_beat_transition_time;
|
||||
|
||||
AddInternal(new Drawable[]
|
||||
{
|
||||
background = new CircularContainer
|
||||
@ -139,14 +144,31 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||
Content.Width = 1 / Content.Scale.X;
|
||||
}
|
||||
|
||||
private const float edge_alpha_kiai = 0.5f;
|
||||
|
||||
private void resetEdgeEffects()
|
||||
{
|
||||
background.EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = AccentColour,
|
||||
Radius = KiaiMode ? 50 : 8
|
||||
Colour = AccentColour.Opacity(KiaiMode ? edge_alpha_kiai : 1f),
|
||||
Radius = KiaiMode ? 32 : 8
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
if (!effectPoint.KiaiMode)
|
||||
return;
|
||||
|
||||
if (beatIndex % (int)timingPoint.TimeSignature != 0)
|
||||
return;
|
||||
|
||||
double duration = timingPoint.BeatLength * 2;
|
||||
|
||||
background.FadeEdgeEffectTo(1, pre_beat_transition_time, EasingTypes.OutQuint);
|
||||
using (background.BeginDelayedSequence(pre_beat_transition_time))
|
||||
background.FadeEdgeEffectTo(edge_alpha_kiai, duration, EasingTypes.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
// 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.Game.Graphics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||
{
|
||||
public class TaikoPiece : Container, IHasAccentColour
|
||||
public class TaikoPiece : BeatSyncedContainer, IHasAccentColour
|
||||
{
|
||||
private Color4 accentColour;
|
||||
/// <summary>
|
||||
@ -17,10 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||
public virtual Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
set
|
||||
{
|
||||
accentColour = value;
|
||||
}
|
||||
set { accentColour = value; }
|
||||
}
|
||||
|
||||
private bool kiaiMode;
|
||||
|
@ -13,12 +13,12 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
/// <summary>
|
||||
/// Diameter of a circle relative to the size of the <see cref="TaikoPlayfield"/>.
|
||||
/// </summary>
|
||||
public const float PLAYFIELD_RELATIVE_DIAMETER = 0.5f;
|
||||
public const float PLAYFIELD_RELATIVE_DIAMETER = 0.45f;
|
||||
|
||||
/// <summary>
|
||||
/// Scale multiplier for a strong circle.
|
||||
/// </summary>
|
||||
public const float STRONG_CIRCLE_DIAMETER_SCALE = 1.5f;
|
||||
public const float STRONG_CIRCLE_DIAMETER_SCALE = 1.4f;
|
||||
|
||||
/// <summary>
|
||||
/// Default circle diameter.
|
||||
|
@ -18,22 +18,23 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// </summary>
|
||||
internal class HitExplosion : CircularContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// The judgement this hit explosion visualises.
|
||||
/// </summary>
|
||||
public readonly TaikoJudgement Judgement;
|
||||
|
||||
private readonly Box innerFill;
|
||||
|
||||
public HitExplosion(TaikoJudgement judgement)
|
||||
{
|
||||
Judgement = judgement;
|
||||
private readonly bool isRim;
|
||||
|
||||
Size = new Vector2(TaikoHitObject.DEFAULT_CIRCLE_DIAMETER);
|
||||
public HitExplosion(TaikoJudgement judgement, bool isRim)
|
||||
{
|
||||
this.isRim = isRim;
|
||||
|
||||
Judgement = judgement;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Size = new Vector2(TaikoPlayfield.HIT_TARGET_OFFSET + TaikoHitObject.DEFAULT_CIRCLE_DIAMETER);
|
||||
|
||||
RelativePositionAxes = Axes.Both;
|
||||
|
||||
BorderColour = Color4.White;
|
||||
@ -54,22 +55,14 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
switch (Judgement.TaikoResult)
|
||||
{
|
||||
case TaikoHitResult.Good:
|
||||
innerFill.Colour = colours.Green;
|
||||
break;
|
||||
case TaikoHitResult.Great:
|
||||
innerFill.Colour = colours.Blue;
|
||||
break;
|
||||
}
|
||||
innerFill.Colour = isRim ? colours.BlueDarker : colours.PinkDarker;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
ScaleTo(5f, 1000, EasingTypes.OutQuint);
|
||||
ScaleTo(3f, 1000, EasingTypes.OutQuint);
|
||||
FadeOut(500);
|
||||
|
||||
Expire();
|
||||
@ -80,7 +73,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// </summary>
|
||||
public void VisualiseSecondHit()
|
||||
{
|
||||
ResizeTo(Size * TaikoHitObject.STRONG_CIRCLE_DIAMETER_SCALE, 50);
|
||||
ResizeTo(new Vector2(TaikoPlayfield.HIT_TARGET_OFFSET + TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER), 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
68
osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs
Normal file
68
osu.Game.Rulesets.Taiko/UI/KiaiHitExplosion.cs
Normal file
@ -0,0 +1,68 @@
|
||||
// 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 osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Taiko.Judgements;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
public class KiaiHitExplosion : CircularContainer
|
||||
{
|
||||
public readonly TaikoJudgement Judgement;
|
||||
|
||||
private readonly bool isRim;
|
||||
|
||||
public KiaiHitExplosion(TaikoJudgement judgement, bool isRim)
|
||||
{
|
||||
this.isRim = isRim;
|
||||
|
||||
Judgement = judgement;
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Size = new Vector2(TaikoHitObject.DEFAULT_CIRCLE_DIAMETER, 1);
|
||||
|
||||
Masking = true;
|
||||
Alpha = 0.25f;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = isRim ? colours.BlueDarker : colours.PinkDarker,
|
||||
Radius = 60,
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
ScaleTo(new Vector2(1, 3f), 500, EasingTypes.OutQuint);
|
||||
FadeOut(250);
|
||||
|
||||
Expire();
|
||||
}
|
||||
}
|
||||
}
|
@ -24,12 +24,12 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// <summary>
|
||||
/// The default play field height.
|
||||
/// </summary>
|
||||
public const float DEFAULT_PLAYFIELD_HEIGHT = 168f;
|
||||
public const float DEFAULT_PLAYFIELD_HEIGHT = 178f;
|
||||
|
||||
/// <summary>
|
||||
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
|
||||
/// </summary>
|
||||
private const float hit_target_offset = TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER / 2f + 40;
|
||||
public const float HIT_TARGET_OFFSET = TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER / 2f + 40;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the left area of the playfield. This area contains the input drum.
|
||||
@ -39,15 +39,18 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
protected override Container<Drawable> Content => hitObjectContainer;
|
||||
|
||||
private readonly Container<HitExplosion> hitExplosionContainer;
|
||||
private readonly Container<KiaiHitExplosion> kiaiExplosionContainer;
|
||||
private readonly Container<DrawableBarLine> barLineContainer;
|
||||
private readonly Container<DrawableTaikoJudgement> judgementContainer;
|
||||
|
||||
private readonly Container hitObjectContainer;
|
||||
private readonly Container topLevelHitContainer;
|
||||
private readonly Container leftBackgroundContainer;
|
||||
private readonly Container rightBackgroundContainer;
|
||||
private readonly Box leftBackground;
|
||||
private readonly Box rightBackground;
|
||||
|
||||
private readonly Container overlayBackgroundContainer;
|
||||
private readonly Container backgroundContainer;
|
||||
|
||||
private readonly Box overlayBackground;
|
||||
private readonly Box background;
|
||||
|
||||
public TaikoPlayfield()
|
||||
{
|
||||
@ -59,7 +62,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
Height = DEFAULT_PLAYFIELD_HEIGHT,
|
||||
Children = new[]
|
||||
{
|
||||
rightBackgroundContainer = new Container
|
||||
backgroundContainer = new Container
|
||||
{
|
||||
Name = "Transparent playfield background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -73,7 +76,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
rightBackground = new Box
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.6f
|
||||
@ -82,24 +85,23 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Transparent playfield elements",
|
||||
Name = "Right area",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = left_area_size },
|
||||
Margin = new MarginPadding { Left = left_area_size },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
Name = "Hit target container",
|
||||
X = hit_target_offset,
|
||||
Name = "Masked elements",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
hitExplosionContainer = new Container<HitExplosion>
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
BlendingMode = BlendingMode.Additive
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
},
|
||||
barLineContainer = new Container<DrawableBarLine>
|
||||
{
|
||||
@ -114,23 +116,32 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
judgementContainer = new Container<DrawableTaikoJudgement>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
BlendingMode = BlendingMode.Additive
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
kiaiExplosionContainer = new Container<KiaiHitExplosion>
|
||||
{
|
||||
Name = "Kiai hit explosions",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
||||
BlendingMode = BlendingMode.Additive
|
||||
},
|
||||
judgementContainer = new Container<DrawableTaikoJudgement>
|
||||
{
|
||||
Name = "Judgements",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
||||
BlendingMode = BlendingMode.Additive
|
||||
},
|
||||
}
|
||||
},
|
||||
leftBackgroundContainer = new Container
|
||||
overlayBackgroundContainer = new Container
|
||||
{
|
||||
Name = "Left overlay",
|
||||
Size = new Vector2(left_area_size, DEFAULT_PLAYFIELD_HEIGHT),
|
||||
BorderThickness = 1,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
leftBackground = new Box
|
||||
overlayBackground = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
@ -164,11 +175,11 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
leftBackgroundContainer.BorderColour = colours.Gray0;
|
||||
leftBackground.Colour = colours.Gray1;
|
||||
overlayBackgroundContainer.BorderColour = colours.Gray0;
|
||||
overlayBackground.Colour = colours.Gray1;
|
||||
|
||||
rightBackgroundContainer.BorderColour = colours.Gray1;
|
||||
rightBackground.Colour = colours.Gray0;
|
||||
backgroundContainer.BorderColour = colours.Gray1;
|
||||
background.Colour = colours.Gray0;
|
||||
}
|
||||
|
||||
public override void Add(DrawableHitObject<TaikoHitObject, TaikoJudgement> h)
|
||||
@ -204,6 +215,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
if (!wasHit)
|
||||
return;
|
||||
|
||||
bool isRim = judgedObject.HitObject is RimHit;
|
||||
|
||||
if (!secondHit)
|
||||
{
|
||||
if (judgedObject.X >= -0.05f && !(judgedObject is DrawableSwell))
|
||||
@ -212,7 +225,11 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
topLevelHitContainer.Add(judgedObject.CreateProxy());
|
||||
}
|
||||
|
||||
hitExplosionContainer.Add(new HitExplosion(judgedObject.Judgement));
|
||||
hitExplosionContainer.Add(new HitExplosion(judgedObject.Judgement, isRim));
|
||||
|
||||
if (judgedObject.HitObject.Kiai)
|
||||
kiaiExplosionContainer.Add(new KiaiHitExplosion(judgedObject.Judgement, isRim));
|
||||
|
||||
}
|
||||
else
|
||||
hitExplosionContainer.Children.FirstOrDefault(e => e.Judgement == judgedObject.Judgement)?.VisualiseSecondHit();
|
||||
@ -221,7 +238,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
/// <summary>
|
||||
/// This is a very special type of container. It serves a similar purpose to <see cref="FillMode.Fit"/>, however unlike <see cref="FillMode.Fit"/>,
|
||||
/// this will only adjust the scale relative to the height of its parent and will maintain the original width relative to its parent.
|
||||
///
|
||||
///
|
||||
/// <para>
|
||||
/// By adjusting the scale relative to the height of its parent, the aspect ratio of this container's children is maintained, however this is undesirable
|
||||
/// in the case where the hit object container should not have its width adjusted by scale. To counteract this, another container is nested inside this
|
||||
|
@ -87,6 +87,7 @@
|
||||
<Compile Include="Scoring\TaikoScoreProcessor.cs" />
|
||||
<Compile Include="UI\HitTarget.cs" />
|
||||
<Compile Include="UI\InputDrum.cs" />
|
||||
<Compile Include="UI\KiaiHitExplosion.cs" />
|
||||
<Compile Include="UI\DrawableTaikoJudgement.cs" />
|
||||
<Compile Include="UI\HitExplosion.cs" />
|
||||
<Compile Include="UI\TaikoHitRenderer.cs" />
|
||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
/// </summary>
|
||||
/// <param name="time">The time to find the timing control point at.</param>
|
||||
/// <returns>The timing control point.</returns>
|
||||
public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time);
|
||||
public TimingControlPoint TimingPointAt(double time) => binarySearch(TimingPoints, time, TimingPoints.FirstOrDefault());
|
||||
|
||||
/// <summary>
|
||||
/// Finds the maximum BPM represented by any timing control point.
|
||||
@ -75,14 +75,21 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
public double BPMMode =>
|
||||
60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength;
|
||||
|
||||
private T binarySearch<T>(SortedList<T> list, double time)
|
||||
/// <summary>
|
||||
/// Binary searches one of the control point lists to find the active control point at <paramref name="time"/>.
|
||||
/// </summary>
|
||||
/// <param name="list">The list to search.</param>
|
||||
/// <param name="time">The time to find the control point at.</param>
|
||||
/// <param name="prePoint">The control point to use when <paramref name="time"/> is before any control points. If null, a new control point will be constructed.</param>
|
||||
/// <returns>The active control point at <paramref name="time"/>.</returns>
|
||||
private T binarySearch<T>(SortedList<T> list, double time, T prePoint = null)
|
||||
where T : ControlPoint, new()
|
||||
{
|
||||
if (list.Count == 0)
|
||||
return new T();
|
||||
|
||||
if (time < list[0].Time)
|
||||
return new T();
|
||||
return prePoint ?? new T();
|
||||
|
||||
int index = list.BinarySearch(new T() { Time = time });
|
||||
|
||||
@ -92,8 +99,8 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
|
||||
index = ~index;
|
||||
|
||||
if (index == list.Count)
|
||||
return list[list.Count - 1];
|
||||
// BinarySearch will return the index of the first element _greater_ than the search
|
||||
// This is the inactive point - the active point is the one before it (index - 1)
|
||||
return list[index - 1];
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
internal class DifficultyColouredContainer : Container, IHasAccentColour
|
||||
public class DifficultyColouredContainer : Container, IHasAccentColour
|
||||
{
|
||||
public Color4 AccentColour { get; set; }
|
||||
|
||||
|
@ -11,7 +11,7 @@ using OpenTK.Graphics;
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
|
||||
internal class DifficultyIcon : DifficultyColouredContainer
|
||||
public class DifficultyIcon : DifficultyColouredContainer
|
||||
{
|
||||
private readonly BeatmapInfo beatmap;
|
||||
|
||||
|
@ -43,6 +43,9 @@ namespace osu.Game.Database
|
||||
[Ignore]
|
||||
public BeatmapMetrics Metrics { get; set; }
|
||||
|
||||
[Ignore]
|
||||
public BeatmapOnlineInfo OnlineInfo { get; set; }
|
||||
|
||||
public string Path { get; set; }
|
||||
|
||||
[JsonProperty("file_md5")]
|
||||
|
38
osu.Game/Database/BeatmapOnlineInfo.cs
Normal file
38
osu.Game/Database/BeatmapOnlineInfo.cs
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
/// <summary>
|
||||
/// Beatmap info retrieved for previewing locally without having the beatmap downloaded.
|
||||
/// </summary>
|
||||
public class BeatmapOnlineInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The different sizes of cover art for this beatmap: cover, cover@2x, card, card@2x, list, list@2x.
|
||||
/// </summary>
|
||||
[JsonProperty(@"covers")]
|
||||
public IEnumerable<string> Covers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A small sample clip of this beatmap's song.
|
||||
/// </summary>
|
||||
[JsonProperty(@"previewUrl")]
|
||||
public string Preview { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of plays this beatmap has.
|
||||
/// </summary>
|
||||
[JsonProperty(@"play_count")]
|
||||
public int PlayCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The amount of people who have favourited this map.
|
||||
/// </summary>
|
||||
[JsonProperty(@"favourite_count")]
|
||||
public int FavouriteCount { get; set; }
|
||||
}
|
||||
}
|
37
osu.Game/Database/OnlineWorkingBeatmap.cs
Normal file
37
osu.Game/Database/OnlineWorkingBeatmap.cs
Normal file
@ -0,0 +1,37 @@
|
||||
// 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.Audio.Track;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
internal class OnlineWorkingBeatmap : WorkingBeatmap
|
||||
{
|
||||
private readonly TextureStore textures;
|
||||
private readonly TrackManager tracks;
|
||||
|
||||
public OnlineWorkingBeatmap(BeatmapInfo beatmapInfo, TextureStore textures, TrackManager tracks) : base(beatmapInfo)
|
||||
{
|
||||
this.textures = textures;
|
||||
this.tracks = tracks;
|
||||
}
|
||||
|
||||
protected override Beatmap GetBeatmap()
|
||||
{
|
||||
return new Beatmap();
|
||||
}
|
||||
|
||||
protected override Texture GetBackground()
|
||||
{
|
||||
return textures.Get(BeatmapInfo.OnlineInfo.Covers.FirstOrDefault());
|
||||
}
|
||||
|
||||
protected override Track GetTrack()
|
||||
{
|
||||
return tracks.Get(BeatmapInfo.OnlineInfo.Preview);
|
||||
}
|
||||
}
|
||||
}
|
23
osu.Game/Database/RankStatus.cs
Normal file
23
osu.Game/Database/RankStatus.cs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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.ComponentModel;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
public enum RankStatus
|
||||
{
|
||||
Any = 7,
|
||||
[Description("Ranked & Approved")]
|
||||
RankedApproved = 0,
|
||||
Approved = 1,
|
||||
Loved = 8,
|
||||
Favourites = 2,
|
||||
[Description("Mod Requests")]
|
||||
ModRequests = 3,
|
||||
Pending = 4,
|
||||
Graveyard = 5,
|
||||
[Description("My Maps")]
|
||||
MyMaps = 6,
|
||||
}
|
||||
}
|
@ -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;
|
||||
@ -44,6 +53,33 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
/// </summary>
|
||||
public bool HideAlphaDiscrepancies = true;
|
||||
|
||||
/// <summary>
|
||||
/// The relative velocity of the triangles. Default is 1.
|
||||
/// </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; }
|
||||
@ -52,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);
|
||||
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;
|
||||
@ -97,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,59 +2,65 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
|
||||
namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
public class BeatSyncedContainer : Container
|
||||
{
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
protected readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private int lastBeat;
|
||||
private TimingControlPoint lastTimingPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of time before a beat we should fire <see cref="OnNewBeat(int, TimingControlPoint, EffectControlPoint, TrackAmplitudes)"/>.
|
||||
/// This allows for adding easing to animations that may be synchronised to the beat.
|
||||
/// </summary>
|
||||
protected double EarlyActivationMilliseconds;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (beatmap.Value?.Track == null)
|
||||
if (Beatmap.Value?.Track == null)
|
||||
return;
|
||||
|
||||
double currentTrackTime = beatmap.Value.Track.CurrentTime;
|
||||
double currentTrackTime = Beatmap.Value.Track.CurrentTime + EarlyActivationMilliseconds;
|
||||
|
||||
TimingControlPoint timingPoint = beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
|
||||
EffectControlPoint effectPoint = beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
|
||||
TimingControlPoint timingPoint = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
|
||||
EffectControlPoint effectPoint = Beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
|
||||
|
||||
if (timingPoint.BeatLength == 0)
|
||||
return;
|
||||
|
||||
int beat = (int)((currentTrackTime - timingPoint.Time) / timingPoint.BeatLength);
|
||||
int beatIndex = (int)((currentTrackTime - timingPoint.Time) / timingPoint.BeatLength);
|
||||
|
||||
// The beats before the start of the first control point are off by 1, this should do the trick
|
||||
if (currentTrackTime < timingPoint.Time)
|
||||
beat--;
|
||||
beatIndex--;
|
||||
|
||||
if (timingPoint == lastTimingPoint && beat == lastBeat)
|
||||
if (timingPoint == lastTimingPoint && beatIndex == lastBeat)
|
||||
return;
|
||||
|
||||
double offsetFromBeat = (timingPoint.Time - currentTrackTime) % timingPoint.BeatLength;
|
||||
|
||||
using (BeginDelayedSequence(offsetFromBeat, true))
|
||||
OnNewBeat(beat, timingPoint.BeatLength, timingPoint.TimeSignature, effectPoint.KiaiMode);
|
||||
OnNewBeat(beatIndex, timingPoint, effectPoint, Beatmap.Value.Track.CurrentAmplitudes);
|
||||
|
||||
lastBeat = beat;
|
||||
lastBeat = beatIndex;
|
||||
lastTimingPoint = timingPoint;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase game)
|
||||
{
|
||||
beatmap.BindTo(game.Beatmap);
|
||||
Beatmap.BindTo(game.Beatmap);
|
||||
}
|
||||
|
||||
protected virtual void OnNewBeat(int newBeat, double beatLength, TimeSignatures timeSignature, bool kiai)
|
||||
protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
public class ReverseDepthFillFlowContainer<T> : FillFlowContainer<T> where T : Drawable
|
||||
{
|
||||
protected override IComparer<Drawable> DepthComparer => new ReverseCreationOrderDepthComparer();
|
||||
protected override IEnumerable<T> FlowingChildren => base.FlowingChildren.Reverse();
|
||||
}
|
||||
}
|
@ -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
|
||||
@ -113,13 +113,13 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
protected class OsuDropdownHeader : DropdownHeader
|
||||
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,
|
||||
|
32
osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs
Normal file
32
osu.Game/Graphics/UserInterface/OsuEnumDropdown.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// 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;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
public class OsuEnumDropdown<T> : OsuDropdown<T>
|
||||
{
|
||||
public OsuEnumDropdown()
|
||||
{
|
||||
if (!typeof(T).IsEnum)
|
||||
throw new InvalidOperationException("OsuEnumDropdown only supports enums as the generic type argument");
|
||||
|
||||
List<KeyValuePair<string, T>> items = new List<KeyValuePair<string, T>>();
|
||||
foreach(var val in (T[])Enum.GetValues(typeof(T)))
|
||||
{
|
||||
var field = typeof(T).GetField(Enum.GetName(typeof(T), val));
|
||||
items.Add(
|
||||
new KeyValuePair<string, T>(
|
||||
field.GetCustomAttribute<DescriptionAttribute>()?.Description ?? Enum.GetName(typeof(T), val),
|
||||
val
|
||||
)
|
||||
);
|
||||
}
|
||||
Items = items;
|
||||
}
|
||||
}
|
||||
}
|
@ -57,9 +57,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
}
|
||||
|
||||
private class OsuTabItem : TabItem<T>
|
||||
public class OsuTabItem : TabItem<T>
|
||||
{
|
||||
private readonly SpriteText text;
|
||||
protected readonly SpriteText Text;
|
||||
private readonly Box box;
|
||||
|
||||
private Color4? accentColour;
|
||||
@ -70,7 +70,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
{
|
||||
accentColour = value;
|
||||
if (!Active)
|
||||
text.Colour = value;
|
||||
Text.Colour = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,13 +94,13 @@ namespace osu.Game.Graphics.UserInterface
|
||||
private void fadeActive()
|
||||
{
|
||||
box.FadeIn(transition_length, EasingTypes.OutQuint);
|
||||
text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint);
|
||||
Text.FadeColour(Color4.White, transition_length, EasingTypes.OutQuint);
|
||||
}
|
||||
|
||||
private void fadeInactive()
|
||||
{
|
||||
box.FadeOut(transition_length, EasingTypes.OutQuint);
|
||||
text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint);
|
||||
Text.FadeColour(AccentColour, transition_length, EasingTypes.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
@ -130,7 +130,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
text = new OsuSpriteText
|
||||
Text = new OsuSpriteText
|
||||
{
|
||||
Margin = new MarginPadding { Top = 5, Bottom = 5 },
|
||||
Origin = Anchor.BottomLeft,
|
||||
|
17
osu.Game/Online/Multiplayer/Room.cs
Normal file
17
osu.Game/Online/Multiplayer/Room.cs
Normal 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>();
|
||||
}
|
||||
}
|
26
osu.Game/Online/Multiplayer/RoomStatus.cs
Normal file
26
osu.Game/Online/Multiplayer/RoomStatus.cs
Normal 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;
|
||||
}
|
||||
}
|
@ -41,6 +41,8 @@ namespace osu.Game
|
||||
|
||||
private DialogOverlay dialogOverlay;
|
||||
|
||||
private DirectOverlay direct;
|
||||
|
||||
private Intro intro
|
||||
{
|
||||
get
|
||||
@ -70,6 +72,8 @@ namespace osu.Game
|
||||
|
||||
public void ToggleSettings() => settings.ToggleVisibility();
|
||||
|
||||
public void ToggleDirect() => direct.ToggleVisibility();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -160,6 +164,7 @@ namespace osu.Game
|
||||
});
|
||||
|
||||
//overlay elements
|
||||
LoadComponentAsync(direct = new DirectOverlay { Depth = -1 }, mainContent.Add);
|
||||
LoadComponentAsync(chat = new ChatOverlay { Depth = -1 }, mainContent.Add);
|
||||
LoadComponentAsync(settings = new SettingsOverlay { Depth = -1 }, overlayContent.Add);
|
||||
LoadComponentAsync(musicController = new MusicController
|
||||
@ -249,6 +254,9 @@ namespace osu.Game
|
||||
case Key.O:
|
||||
settings.ToggleVisibility();
|
||||
return true;
|
||||
case Key.D:
|
||||
direct.ToggleVisibility();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,6 +288,7 @@ namespace osu.Game
|
||||
Toolbar.State = Visibility.Hidden;
|
||||
musicController.State = Visibility.Hidden;
|
||||
chat.State = Visibility.Hidden;
|
||||
direct.State = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
193
osu.Game/Overlays/Direct/DirectGridPanel.cs
Normal file
193
osu.Game/Overlays/Direct/DirectGridPanel.cs
Normal file
@ -0,0 +1,193 @@
|
||||
// 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 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.Graphics.Textures;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
public class DirectGridPanel : DirectPanel
|
||||
{
|
||||
private const float horizontal_padding = 10;
|
||||
private const float vertical_padding = 5;
|
||||
|
||||
private FillFlowContainer bottomPanel;
|
||||
|
||||
public DirectGridPanel(BeatmapSetInfo beatmap) : base(beatmap)
|
||||
{
|
||||
Height = 140 + vertical_padding; //full height of all the elements plus vertical padding (autosize uses the image)
|
||||
CornerRadius = 4;
|
||||
Masking = true;
|
||||
|
||||
EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Offset = new Vector2(0f, 1f),
|
||||
Radius = 3f,
|
||||
Colour = Color4.Black.Opacity(0.25f),
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
FadeInFromZero(200, EasingTypes.Out);
|
||||
bottomPanel.LayoutDuration = 200;
|
||||
bottomPanel.LayoutEasing = EasingTypes.Out;
|
||||
bottomPanel.Origin = Anchor.BottomLeft;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, LocalisationEngine localisation, TextureStore textures)
|
||||
{
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
GetBackground(textures),
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.5f),
|
||||
},
|
||||
bottomPanel = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
Direction = FillDirection.Vertical,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Spacing = new Vector2(0f, vertical_padding),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = horizontal_padding, Right = horizontal_padding },
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = localisation.GetUnicodePreference(SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title),
|
||||
TextSize = 18,
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = localisation.GetUnicodePreference(SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist),
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = vertical_padding,
|
||||
Bottom = vertical_padding,
|
||||
Left = horizontal_padding,
|
||||
Right = horizontal_padding,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "mapped by ",
|
||||
TextSize = 14,
|
||||
Shadow = false,
|
||||
Colour = colours.Gray5,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = SetInfo.Metadata.Author,
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-SemiBoldItalic",
|
||||
Shadow = false,
|
||||
Colour = colours.BlueDark,
|
||||
},
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = 14,
|
||||
Children = new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = $"from {SetInfo.Metadata.Source}",
|
||||
TextSize = 14,
|
||||
Shadow = false,
|
||||
Colour = colours.Gray5,
|
||||
Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f,
|
||||
},
|
||||
},
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = 20,
|
||||
Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding },
|
||||
Children = GetDifficultyIcons(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Margin = new MarginPadding { Top = vertical_padding, Right = vertical_padding },
|
||||
Children = new[]
|
||||
{
|
||||
new Statistic(FontAwesome.fa_play_circle, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.PlayCount ?? 0)
|
||||
{
|
||||
Margin = new MarginPadding { Right = 1 },
|
||||
},
|
||||
new Statistic(FontAwesome.fa_heart, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.FavouriteCount ?? 0),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
197
osu.Game/Overlays/Direct/DirectListPanel.cs
Normal file
197
osu.Game/Overlays/Direct/DirectListPanel.cs
Normal file
@ -0,0 +1,197 @@
|
||||
// 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.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Database;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using System.Linq;
|
||||
using osu.Framework.Input;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
public class DirectListPanel : DirectPanel
|
||||
{
|
||||
private const float horizontal_padding = 10;
|
||||
private const float vertical_padding = 5;
|
||||
private const float height = 70;
|
||||
|
||||
public DirectListPanel(BeatmapSetInfo beatmap) : base(beatmap)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = height;
|
||||
CornerRadius = 5;
|
||||
Masking = true;
|
||||
EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Offset = new Vector2(0f, 1f),
|
||||
Radius = 3f,
|
||||
Colour = Color4.Black.Opacity(0.25f),
|
||||
};
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
FadeInFromZero(200, EasingTypes.Out);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LocalisationEngine localisation, TextureStore textures)
|
||||
{
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black,
|
||||
},
|
||||
GetBackground(textures),
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ColourInfo = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.25f), Color4.Black.Opacity(0.75f)),
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding, Left = horizontal_padding, Right = vertical_padding },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Current = localisation.GetUnicodePreference(SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title),
|
||||
TextSize = 18,
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Current = localisation.GetUnicodePreference(SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist),
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.X,
|
||||
Height = 20,
|
||||
Margin = new MarginPadding { Top = vertical_padding, Bottom = vertical_padding },
|
||||
Children = GetDifficultyIcons(),
|
||||
},
|
||||
},
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Margin = new MarginPadding { Right = height - vertical_padding * 2 + vertical_padding },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Statistic(FontAwesome.fa_play_circle, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.PlayCount ?? 0)
|
||||
{
|
||||
Margin = new MarginPadding { Right = 1 },
|
||||
},
|
||||
new Statistic(FontAwesome.fa_heart, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.FavouriteCount ?? 0),
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "mapped by ",
|
||||
TextSize = 14,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = SetInfo.Metadata.Author,
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-SemiBoldItalic",
|
||||
},
|
||||
},
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = $"from {SetInfo.Metadata.Source}",
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
TextSize = 14,
|
||||
Alpha = string.IsNullOrEmpty(SetInfo.Metadata.Source) ? 0f : 1f,
|
||||
},
|
||||
},
|
||||
},
|
||||
new DownloadButton
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Size = new Vector2(height - vertical_padding * 2),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private class DownloadButton : ClickableContainer
|
||||
{
|
||||
private readonly TextAwesome icon;
|
||||
|
||||
public DownloadButton()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
icon = new TextAwesome
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
UseFullGlyphHeight = false,
|
||||
TextSize = 30,
|
||||
Icon = FontAwesome.fa_osu_chevron_down_o,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
{
|
||||
icon.ScaleTo(0.9f, 1000, EasingTypes.Out);
|
||||
return base.OnMouseDown(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
icon.ScaleTo(1f, 500, EasingTypes.OutElastic);
|
||||
return base.OnMouseUp(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
icon.ScaleTo(1.1f, 500, EasingTypes.OutElastic);
|
||||
return base.OnHover(state);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
icon.ScaleTo(1f, 500, EasingTypes.OutElastic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
88
osu.Game/Overlays/Direct/DirectPanel.cs
Normal file
88
osu.Game/Overlays/Direct/DirectPanel.cs
Normal file
@ -0,0 +1,88 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
public abstract class DirectPanel : Container
|
||||
{
|
||||
protected readonly BeatmapSetInfo SetInfo;
|
||||
|
||||
protected DirectPanel(BeatmapSetInfo setInfo)
|
||||
{
|
||||
SetInfo = setInfo;
|
||||
}
|
||||
|
||||
protected IEnumerable<DifficultyIcon> GetDifficultyIcons()
|
||||
{
|
||||
var icons = new List<DifficultyIcon>();
|
||||
|
||||
foreach (var b in SetInfo.Beatmaps)
|
||||
icons.Add(new DifficultyIcon(b));
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
||||
protected Drawable GetBackground(TextureStore textures)
|
||||
{
|
||||
return new AsyncLoadWrapper(new BeatmapBackgroundSprite(new OnlineWorkingBeatmap(SetInfo.Beatmaps.FirstOrDefault(), textures, null))
|
||||
{
|
||||
FillMode = FillMode.Fill,
|
||||
OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out),
|
||||
}) { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
|
||||
public class Statistic : FillFlowContainer
|
||||
{
|
||||
private readonly SpriteText text;
|
||||
|
||||
private int value;
|
||||
public int Value
|
||||
{
|
||||
get { return value; }
|
||||
set
|
||||
{
|
||||
this.value = value;
|
||||
text.Text = Value.ToString(@"N0");
|
||||
}
|
||||
}
|
||||
|
||||
public Statistic(FontAwesome icon, int value = 0)
|
||||
{
|
||||
Anchor = Anchor.TopRight;
|
||||
Origin = Anchor.TopRight;
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Direction = FillDirection.Horizontal;
|
||||
Spacing = new Vector2(5f, 0f);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
text = new OsuSpriteText
|
||||
{
|
||||
Font = @"Exo2.0-SemiBoldItalic",
|
||||
},
|
||||
new TextAwesome
|
||||
{
|
||||
Icon = icon,
|
||||
Shadow = true,
|
||||
TextSize = 14,
|
||||
Margin = new MarginPadding { Top = 1 },
|
||||
},
|
||||
};
|
||||
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
233
osu.Game/Overlays/Direct/FilterControl.cs
Normal file
233
osu.Game/Overlays/Direct/FilterControl.cs
Normal file
@ -0,0 +1,233 @@
|
||||
// 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.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
public class FilterControl : Container
|
||||
{
|
||||
public static readonly float HEIGHT = 35 + 32 + 30 + padding * 2; // search + mode toggle buttons + sort tabs + padding
|
||||
|
||||
private const float padding = 10;
|
||||
|
||||
private readonly Box tabStrip;
|
||||
private readonly FillFlowContainer<RulesetToggleButton> modeButtons;
|
||||
|
||||
public readonly SearchTextBox Search;
|
||||
public readonly SortTabControl SortTabs;
|
||||
public readonly OsuEnumDropdown<RankStatus> RankStatusDropdown;
|
||||
public readonly Bindable<DirectOverlay.PanelDisplayStyle> DisplayStyle = new Bindable<DirectOverlay.PanelDisplayStyle>();
|
||||
|
||||
protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || RankStatusDropdown.Contains(screenSpacePos);
|
||||
|
||||
public FilterControl()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
DisplayStyle.Value = DirectOverlay.PanelDisplayStyle.Grid;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"384552"),
|
||||
Alpha = 0.9f,
|
||||
},
|
||||
tabStrip = new Box
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Left = DirectOverlay.WIDTH_PADDING, Right = DirectOverlay.WIDTH_PADDING },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Search = new DirectSearchTextBox
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Margin = new MarginPadding { Top = padding },
|
||||
},
|
||||
modeButtons = new FillFlowContainer<RulesetToggleButton>
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(padding, 0f),
|
||||
Margin = new MarginPadding { Top = padding },
|
||||
},
|
||||
SortTabs = new SortTabControl
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
},
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
Spacing = new Vector2(10f, 0f),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Margin = new MarginPadding { Top = HEIGHT - SlimEnumDropdown<DirectTab>.HEIGHT - padding, Right = DirectOverlay.WIDTH_PADDING },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(5f, 0f),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new[]
|
||||
{
|
||||
new DisplayStyleToggleButton(FontAwesome.fa_th_large, DirectOverlay.PanelDisplayStyle.Grid, DisplayStyle),
|
||||
new DisplayStyleToggleButton(FontAwesome.fa_list_ul, DirectOverlay.PanelDisplayStyle.List, DisplayStyle),
|
||||
},
|
||||
},
|
||||
RankStatusDropdown = new SlimEnumDropdown<RankStatus>
|
||||
{
|
||||
RelativeSizeAxes = Axes.None,
|
||||
Width = 160f,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
RankStatusDropdown.Current.Value = RankStatus.RankedApproved;
|
||||
SortTabs.Current.Value = SortCriteria.Title;
|
||||
SortTabs.Current.TriggerChange();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame game, RulesetDatabase rulesets, OsuColour colours)
|
||||
{
|
||||
tabStrip.Colour = colours.Yellow;
|
||||
RankStatusDropdown.AccentColour = colours.BlueDark;
|
||||
|
||||
var b = new Bindable<RulesetInfo>(); //backup bindable incase the game is null
|
||||
foreach (var r in rulesets.AllRulesets)
|
||||
{
|
||||
modeButtons.Add(new RulesetToggleButton(game?.Ruleset ?? b, r));
|
||||
}
|
||||
}
|
||||
|
||||
private class DirectSearchTextBox : SearchTextBox
|
||||
{
|
||||
protected override Color4 BackgroundUnfocused => backgroundColour;
|
||||
protected override Color4 BackgroundFocused => backgroundColour;
|
||||
|
||||
private Color4 backgroundColour;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
backgroundColour = colours.Gray2.Opacity(0.9f);
|
||||
}
|
||||
}
|
||||
|
||||
private class RulesetToggleButton : ClickableContainer
|
||||
{
|
||||
private readonly TextAwesome icon;
|
||||
|
||||
private RulesetInfo ruleset;
|
||||
public RulesetInfo Ruleset
|
||||
{
|
||||
get { return ruleset; }
|
||||
set
|
||||
{
|
||||
ruleset = value;
|
||||
icon.Icon = Ruleset.CreateInstance().Icon;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Bindable<RulesetInfo> bindable;
|
||||
|
||||
private void Bindable_ValueChanged(RulesetInfo obj)
|
||||
{
|
||||
icon.FadeTo(Ruleset.ID == obj?.ID ? 1f : 0.5f, 100);
|
||||
}
|
||||
|
||||
public RulesetToggleButton(Bindable<RulesetInfo> bindable, RulesetInfo ruleset)
|
||||
{
|
||||
this.bindable = bindable;
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
icon = new TextAwesome
|
||||
{
|
||||
Origin = Anchor.TopLeft,
|
||||
Anchor = Anchor.TopLeft,
|
||||
TextSize = 32,
|
||||
}
|
||||
};
|
||||
|
||||
Ruleset = ruleset;
|
||||
bindable.ValueChanged += Bindable_ValueChanged;
|
||||
Bindable_ValueChanged(bindable.Value);
|
||||
Action = () => bindable.Value = Ruleset;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
if (bindable != null)
|
||||
bindable.ValueChanged -= Bindable_ValueChanged;
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
}
|
||||
|
||||
private class DisplayStyleToggleButton : ClickableContainer
|
||||
{
|
||||
private readonly TextAwesome icon;
|
||||
private readonly DirectOverlay.PanelDisplayStyle style;
|
||||
private readonly Bindable<DirectOverlay.PanelDisplayStyle> bindable;
|
||||
|
||||
public DisplayStyleToggleButton(FontAwesome icon, DirectOverlay.PanelDisplayStyle style, Bindable<DirectOverlay.PanelDisplayStyle> bindable)
|
||||
{
|
||||
this.bindable = bindable;
|
||||
this.style = style;
|
||||
Size = new Vector2(SlimEnumDropdown<DirectTab>.HEIGHT);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
this.icon = new TextAwesome
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Icon = icon,
|
||||
TextSize = 18,
|
||||
UseFullGlyphHeight = false,
|
||||
Alpha = 0.5f,
|
||||
},
|
||||
};
|
||||
|
||||
bindable.ValueChanged += Bindable_ValueChanged;
|
||||
Bindable_ValueChanged(bindable.Value);
|
||||
Action = () => bindable.Value = this.style;
|
||||
}
|
||||
|
||||
private void Bindable_ValueChanged(DirectOverlay.PanelDisplayStyle style)
|
||||
{
|
||||
icon.FadeTo(style == this.style ? 1.0f : 0.5f, 100);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
bindable.ValueChanged -= Bindable_ValueChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
osu.Game/Overlays/Direct/Header.cs
Normal file
124
osu.Game/Overlays/Direct/Header.cs
Normal file
@ -0,0 +1,124 @@
|
||||
// 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.ComponentModel;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
using Container = osu.Framework.Graphics.Containers.Container;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
public class Header : Container
|
||||
{
|
||||
public static readonly float HEIGHT = 90;
|
||||
|
||||
private readonly Box tabStrip;
|
||||
|
||||
public readonly OsuTabControl<DirectTab> Tabs;
|
||||
|
||||
public Header()
|
||||
{
|
||||
Height = HEIGHT;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"252f3a"),
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = DirectOverlay.WIDTH_PADDING, Right = DirectOverlay.WIDTH_PADDING },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Position = new Vector2(-35f, 5f),
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(10f, 0f),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new TextAwesome
|
||||
{
|
||||
TextSize = 25,
|
||||
Icon = FontAwesome.fa_osu_chevron_down_o,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
TextSize = 25,
|
||||
Text = @"osu!direct",
|
||||
},
|
||||
},
|
||||
},
|
||||
tabStrip = new Box
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Width = 282, //todo: make this actually match the tab control's width instead of hardcoding
|
||||
Height = 1,
|
||||
},
|
||||
Tabs = new DirectTabControl
|
||||
{
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Tabs.Current.Value = DirectTab.Search;
|
||||
Tabs.Current.TriggerChange();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
tabStrip.Colour = colours.Green;
|
||||
}
|
||||
|
||||
private class DirectTabControl : OsuTabControl<DirectTab>
|
||||
{
|
||||
protected override TabItem<DirectTab> CreateTabItem(DirectTab value) => new DirectTabItem(value);
|
||||
|
||||
public DirectTabControl()
|
||||
{
|
||||
Height = 25;
|
||||
AccentColour = Color4.White;
|
||||
}
|
||||
|
||||
private class DirectTabItem : OsuTabItem
|
||||
{
|
||||
public DirectTabItem(DirectTab value) : base(value)
|
||||
{
|
||||
Text.TextSize = 15;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum DirectTab
|
||||
{
|
||||
Search,
|
||||
[Description("Newest Maps")]
|
||||
NewestMaps,
|
||||
[Description("Top Rated")]
|
||||
TopRated,
|
||||
[Description("Most Played")]
|
||||
MostPlayed
|
||||
}
|
||||
}
|
43
osu.Game/Overlays/Direct/SlimEnumDropdown.cs
Normal file
43
osu.Game/Overlays/Direct/SlimEnumDropdown.cs
Normal file
@ -0,0 +1,43 @@
|
||||
// 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.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
public class SlimEnumDropdown<T> : OsuEnumDropdown<T>
|
||||
{
|
||||
public const float HEIGHT = 25;
|
||||
|
||||
protected override DropdownHeader CreateHeader() => new SlimDropdownHeader { AccentColour = AccentColour };
|
||||
protected override Menu CreateMenu() => new SlimMenu();
|
||||
|
||||
private class SlimDropdownHeader : OsuDropdownHeader
|
||||
{
|
||||
public SlimDropdownHeader()
|
||||
{
|
||||
Height = HEIGHT;
|
||||
Icon.TextSize = 16;
|
||||
Foreground.Padding = new MarginPadding { Top = 4, Bottom = 4, Left = 8, Right = 4 };
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
BackgroundColour = Color4.Black.Opacity(0.25f);
|
||||
}
|
||||
}
|
||||
|
||||
private class SlimMenu : OsuMenu
|
||||
{
|
||||
public SlimMenu()
|
||||
{
|
||||
Background.Colour = Color4.Black.Opacity(0.25f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
osu.Game/Overlays/Direct/SortTabControl.cs
Normal file
117
osu.Game/Overlays/Direct/SortTabControl.cs
Normal file
@ -0,0 +1,117 @@
|
||||
// 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;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
public class SortTabControl : OsuTabControl<SortCriteria>
|
||||
{
|
||||
protected override TabItem<SortCriteria> CreateTabItem(SortCriteria value) => new SortTabItem(value);
|
||||
|
||||
public SortTabControl()
|
||||
{
|
||||
Height = 30;
|
||||
}
|
||||
|
||||
private class SortTabItem : TabItem<SortCriteria>
|
||||
{
|
||||
private const float transition_duration = 100;
|
||||
|
||||
private readonly Box box;
|
||||
|
||||
public override bool Active
|
||||
{
|
||||
get { return base.Active; }
|
||||
set
|
||||
{
|
||||
if (Active == value) return;
|
||||
|
||||
if (value)
|
||||
slideActive();
|
||||
else
|
||||
slideInactive();
|
||||
base.Active = value;
|
||||
}
|
||||
}
|
||||
|
||||
public SortTabItem(SortCriteria value) : base(value)
|
||||
{
|
||||
AutoSizeAxes = Axes.X;
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Margin = new MarginPadding { Top = 8, Bottom = 8 },
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Text = (value as Enum).GetDescription() ?? value.ToString(),
|
||||
TextSize = 14,
|
||||
Font = @"Exo2.0-Bold",
|
||||
},
|
||||
box = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 5,
|
||||
Scale = new Vector2(1f, 0f),
|
||||
Colour = Color4.White,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
box.Colour = colours.Yellow;
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
if (!Active)
|
||||
slideActive();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
if (!Active)
|
||||
slideInactive();
|
||||
}
|
||||
|
||||
private void slideActive()
|
||||
{
|
||||
box.ScaleTo(new Vector2(1f), transition_duration);
|
||||
}
|
||||
|
||||
private void slideInactive()
|
||||
{
|
||||
box.ScaleTo(new Vector2(1f, 0f), transition_duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum SortCriteria
|
||||
{
|
||||
Title,
|
||||
Artist,
|
||||
Creator,
|
||||
Difficulty,
|
||||
Ranked,
|
||||
Rating,
|
||||
}
|
||||
}
|
230
osu.Game/Overlays/DirectOverlay.cs
Normal file
230
osu.Game/Overlays/DirectOverlay.cs
Normal file
@ -0,0 +1,230 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Overlays.Direct;
|
||||
|
||||
using Container = osu.Framework.Graphics.Containers.Container;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
public class DirectOverlay : WaveOverlayContainer
|
||||
{
|
||||
public static readonly int WIDTH_PADDING = 80;
|
||||
private const float panel_padding = 10f;
|
||||
|
||||
private readonly FilterControl filter;
|
||||
private readonly FillFlowContainer resultCountsContainer;
|
||||
private readonly OsuSpriteText resultCountsText;
|
||||
private readonly FillFlowContainer<DirectPanel> panels;
|
||||
|
||||
private IEnumerable<BeatmapSetInfo> beatmapSets;
|
||||
public IEnumerable<BeatmapSetInfo> BeatmapSets
|
||||
{
|
||||
get { return beatmapSets; }
|
||||
set
|
||||
{
|
||||
if (beatmapSets?.Equals(value) ?? false) return;
|
||||
beatmapSets = value;
|
||||
|
||||
recreatePanels(filter.DisplayStyle.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private ResultCounts resultAmounts;
|
||||
public ResultCounts ResultAmounts
|
||||
{
|
||||
get { return resultAmounts; }
|
||||
set
|
||||
{
|
||||
if (value == ResultAmounts) return;
|
||||
resultAmounts = value;
|
||||
|
||||
updateResultCounts();
|
||||
}
|
||||
}
|
||||
|
||||
public DirectOverlay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
// osu!direct colours are not part of the standard palette
|
||||
|
||||
FirstWaveColour = OsuColour.FromHex(@"19b0e2");
|
||||
SecondWaveColour = OsuColour.FromHex(@"2280a2");
|
||||
ThirdWaveColour = OsuColour.FromHex(@"005774");
|
||||
FourthWaveColour = OsuColour.FromHex(@"003a4e");
|
||||
|
||||
Header header;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.FromHex(@"485e74"),
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Children = new[]
|
||||
{
|
||||
new Triangles
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
TriangleScale = 5,
|
||||
ColourLight = OsuColour.FromHex(@"465b71"),
|
||||
ColourDark = OsuColour.FromHex(@"3f5265"),
|
||||
},
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Top = Header.HEIGHT + FilterControl.HEIGHT },
|
||||
Children = new[]
|
||||
{
|
||||
new ScrollContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
ScrollDraggerVisible = false,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
resultCountsContainer = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Margin = new MarginPadding { Left = WIDTH_PADDING, Top = 6 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = "Found ",
|
||||
TextSize = 15,
|
||||
},
|
||||
resultCountsText = new OsuSpriteText
|
||||
{
|
||||
TextSize = 15,
|
||||
Font = @"Exo2.0-Bold",
|
||||
},
|
||||
}
|
||||
},
|
||||
panels = new FillFlowContainer<DirectPanel>
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Top = panel_padding, Bottom = panel_padding, Left = WIDTH_PADDING, Right = WIDTH_PADDING },
|
||||
Spacing = new Vector2(panel_padding),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
filter = new FilterControl
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Margin = new MarginPadding { Top = Header.HEIGHT },
|
||||
},
|
||||
header = new Header
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
};
|
||||
|
||||
header.Tabs.Current.ValueChanged += tab => { if (tab != DirectTab.Search) filter.Search.Current.Value = string.Empty; };
|
||||
|
||||
filter.Search.Exit = Hide;
|
||||
filter.Search.Current.ValueChanged += text => { if (text != string.Empty) header.Tabs.Current.Value = DirectTab.Search; };
|
||||
filter.DisplayStyle.ValueChanged += recreatePanels;
|
||||
|
||||
updateResultCounts();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
resultCountsContainer.Colour = colours.Yellow;
|
||||
}
|
||||
|
||||
private void updateResultCounts()
|
||||
{
|
||||
resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, EasingTypes.Out);
|
||||
if (ResultAmounts == null) return;
|
||||
|
||||
resultCountsText.Text = pluralize("Artist", ResultAmounts.Artists) + ", " +
|
||||
pluralize("Song", ResultAmounts.Songs) + ", " +
|
||||
pluralize("Tag", ResultAmounts.Tags);
|
||||
}
|
||||
|
||||
private string pluralize(string prefix, int value)
|
||||
{
|
||||
return $@"{value} {prefix}" + (value == 1 ? string.Empty : @"s");
|
||||
}
|
||||
|
||||
private void recreatePanels(PanelDisplayStyle displayStyle)
|
||||
{
|
||||
if (BeatmapSets == null) return;
|
||||
panels.Children = BeatmapSets.Select(b => displayStyle == PanelDisplayStyle.Grid ? (DirectPanel)new DirectGridPanel(b) { Width = 400 } : new DirectListPanel(b));
|
||||
}
|
||||
|
||||
protected override bool OnFocus(InputState state)
|
||||
{
|
||||
filter.Search.TriggerFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
base.PopIn();
|
||||
|
||||
filter.Search.HoldFocus = true;
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
|
||||
filter.Search.HoldFocus = false;
|
||||
}
|
||||
|
||||
public class ResultCounts
|
||||
{
|
||||
public readonly int Artists;
|
||||
public readonly int Songs;
|
||||
public readonly int Tags;
|
||||
|
||||
public ResultCounts(int artists, int songs, int tags)
|
||||
{
|
||||
Artists = artists;
|
||||
Songs = songs;
|
||||
Tags = tags;
|
||||
}
|
||||
}
|
||||
|
||||
public enum PanelDisplayStyle
|
||||
{
|
||||
Grid,
|
||||
List,
|
||||
}
|
||||
}
|
||||
}
|
@ -12,15 +12,24 @@ using osu.Game.Graphics.UserInterface;
|
||||
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;
|
||||
|
||||
@ -34,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);
|
||||
}
|
||||
|
||||
@ -49,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;
|
||||
@ -66,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 OsuSpriteText
|
||||
{
|
||||
Text = $"Connected as {api.Username}!",
|
||||
},
|
||||
new OsuButton
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = "Sign out",
|
||||
Action = api.Logout
|
||||
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 },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
panel.Status.BindTo(api.LocalUser.Value.Status);
|
||||
|
||||
dropdown.Current.ValueChanged += newValue =>
|
||||
{
|
||||
switch (newValue)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -170,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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +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 System;
|
||||
using System.Reflection;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
|
||||
namespace osu.Game.Overlays.Settings
|
||||
{
|
||||
public class SettingsEnumDropdown<T> : SettingsDropdown<T>
|
||||
{
|
||||
public SettingsEnumDropdown()
|
||||
protected override Drawable CreateControl() => new OsuEnumDropdown<T>
|
||||
{
|
||||
if (!typeof(T).IsEnum)
|
||||
throw new InvalidOperationException("SettingsDropdown only supports enums as the generic type argument");
|
||||
|
||||
List<KeyValuePair<string, T>> items = new List<KeyValuePair<string, T>>();
|
||||
foreach(var val in (T[])Enum.GetValues(typeof(T)))
|
||||
{
|
||||
var field = typeof(T).GetField(Enum.GetName(typeof(T), val));
|
||||
items.Add(
|
||||
new KeyValuePair<string, T>(
|
||||
field.GetCustomAttribute<DescriptionAttribute>()?.Description ?? Enum.GetName(typeof(T), val),
|
||||
val
|
||||
)
|
||||
);
|
||||
}
|
||||
Items = items;
|
||||
}
|
||||
Margin = new MarginPadding { Top = 5 },
|
||||
RelativeSizeAxes = Axes.X,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ namespace osu.Game.Screens.Menu
|
||||
OnSolo = delegate { Push(consumeSongSelect()); },
|
||||
OnMulti = delegate { Push(new Lobby()); },
|
||||
OnExit = delegate { Exit(); },
|
||||
}
|
||||
},
|
||||
new MenuSideFlashes(),
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -60,6 +61,7 @@ namespace osu.Game.Screens.Menu
|
||||
LoadComponentAsync(background);
|
||||
|
||||
buttons.OnSettings = game.ToggleSettings;
|
||||
buttons.OnDirect = game.ToggleDirect;
|
||||
|
||||
preloadSongSelect();
|
||||
}
|
||||
|
98
osu.Game/Screens/Menu/MenuSideFlashes.cs
Normal file
98
osu.Game/Screens/Menu/MenuSideFlashes.cs
Normal file
@ -0,0 +1,98 @@
|
||||
// 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.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class MenuSideFlashes : BeatSyncedContainer
|
||||
{
|
||||
public override bool HandleInput => false;
|
||||
|
||||
private readonly Bindable<WorkingBeatmap> beatmap = new Bindable<WorkingBeatmap>();
|
||||
|
||||
private readonly Box leftBox;
|
||||
private readonly Box rightBox;
|
||||
|
||||
private const float amplitude_dead_zone = 0.25f;
|
||||
private const float alpha_multiplier = (1 - amplitude_dead_zone) / 0.55f;
|
||||
private const float kiai_multiplier = (1 - amplitude_dead_zone * 0.95f) / 0.8f;
|
||||
|
||||
private const int box_max_alpha = 200;
|
||||
private const double box_fade_in_time = 65;
|
||||
private const int box_width = 200;
|
||||
|
||||
public MenuSideFlashes()
|
||||
{
|
||||
EarlyActivationMilliseconds = box_fade_in_time;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
leftBox = new Box
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
},
|
||||
rightBox = new Box
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = box_width,
|
||||
Alpha = 0,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase game, OsuColour colours)
|
||||
{
|
||||
beatmap.BindTo(game.Beatmap);
|
||||
|
||||
// linear colour looks better in this case, so let's use it for now.
|
||||
Color4 gradientDark = colours.Blue.Opacity(0).ToLinear();
|
||||
Color4 gradientLight = colours.Blue.Opacity(0.3f).ToLinear();
|
||||
|
||||
leftBox.ColourInfo = ColourInfo.GradientHorizontal(gradientLight, gradientDark);
|
||||
rightBox.ColourInfo = ColourInfo.GradientHorizontal(gradientDark, gradientLight);
|
||||
}
|
||||
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
if (beatIndex < 0)
|
||||
return;
|
||||
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 0 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
flash(leftBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
if (effectPoint.KiaiMode ? beatIndex % 2 == 1 : beatIndex % (int)timingPoint.TimeSignature == 0)
|
||||
flash(rightBox, timingPoint.BeatLength, effectPoint.KiaiMode, amplitudes);
|
||||
}
|
||||
|
||||
private void flash(Drawable d, double beatLength, bool kiai, TrackAmplitudes amplitudes)
|
||||
{
|
||||
d.FadeTo(Math.Max(0, ((d.Equals(leftBox) ? amplitudes.LeftChannel : amplitudes.RightChannel) - amplitude_dead_zone) / (kiai ? kiai_multiplier : alpha_multiplier)), box_fade_in_time);
|
||||
using (d.BeginDelayedSequence(box_fade_in_time))
|
||||
d.FadeOut(beatLength, EasingTypes.In);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,13 +5,17 @@ using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
@ -20,19 +24,23 @@ namespace osu.Game.Screens.Menu
|
||||
/// <summary>
|
||||
/// osu! logo and its attachments (pulsing, visualiser etc.)
|
||||
/// </summary>
|
||||
public class OsuLogo : Container
|
||||
public class OsuLogo : BeatSyncedContainer
|
||||
{
|
||||
public readonly Color4 OsuPink = OsuColour.FromHex(@"e967a1");
|
||||
|
||||
private readonly Sprite logo;
|
||||
private readonly CircularContainer logoContainer;
|
||||
private readonly Container logoBounceContainer;
|
||||
private readonly Container logoBeatContainer;
|
||||
private readonly Container logoAmplitudeContainer;
|
||||
private readonly Container logoHoverContainer;
|
||||
|
||||
private SampleChannel sampleClick;
|
||||
|
||||
private readonly Container colourAndTriangles;
|
||||
|
||||
private readonly Triangles triangles;
|
||||
|
||||
public Action Action;
|
||||
|
||||
public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X * 0.74f;
|
||||
@ -67,8 +75,12 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
private const float default_size = 480;
|
||||
|
||||
private const double beat_in_time = 60;
|
||||
|
||||
public OsuLogo()
|
||||
{
|
||||
EarlyActivationMilliseconds = beat_in_time;
|
||||
|
||||
Size = new Vector2(default_size);
|
||||
|
||||
Anchor = Anchor.Centre;
|
||||
@ -78,67 +90,16 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoBounceContainer = new Container
|
||||
logoHoverContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoHoverContainer = new Container
|
||||
logoBounceContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new BufferedContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.88f),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
colourAndTriangles = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuPink,
|
||||
},
|
||||
new Triangles
|
||||
{
|
||||
TriangleScale = 4,
|
||||
ColourLight = OsuColour.FromHex(@"ff7db7"),
|
||||
ColourDark = OsuColour.FromHex(@"de5b95"),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
}
|
||||
},
|
||||
flashLayer = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
logo = new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
}
|
||||
},
|
||||
rippleContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
@ -151,36 +112,101 @@ namespace osu.Game.Screens.Menu
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Alpha = 0.15f
|
||||
Alpha = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
impactContainer = new CircularContainer
|
||||
logoAmplitudeContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
BorderColour = Color4.White,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BorderThickness = 10,
|
||||
Masking = true,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
logoBeatContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new BufferedContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
logoContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.88f),
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
colourAndTriangles = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuPink,
|
||||
},
|
||||
triangles = new Triangles
|
||||
{
|
||||
TriangleScale = 4,
|
||||
ColourLight = OsuColour.FromHex(@"ff7db7"),
|
||||
ColourDark = OsuColour.FromHex(@"de5b95"),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
}
|
||||
},
|
||||
flashLayer = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Colour = Color4.White,
|
||||
Alpha = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
logo = new Sprite
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
}
|
||||
},
|
||||
impactContainer = new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0,
|
||||
BorderColour = Color4.White,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BorderThickness = 10,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
AlwaysPresent = true,
|
||||
Alpha = 0,
|
||||
}
|
||||
}
|
||||
},
|
||||
new MenuVisualisation
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Alpha = 0.2f,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new MenuVisualisation
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
BlendingMode = BlendingMode.Additive,
|
||||
Alpha = 0.2f,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,13 +223,56 @@ namespace osu.Game.Screens.Menu
|
||||
ripple.Texture = textures.Get(@"Menu/logo");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
private int lastBeatIndex;
|
||||
|
||||
ripple.ScaleTo(ripple.Scale * 1.1f, 500);
|
||||
ripple.FadeOut(500);
|
||||
ripple.Loop(300);
|
||||
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
|
||||
{
|
||||
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
|
||||
|
||||
lastBeatIndex = beatIndex;
|
||||
|
||||
var beatLength = timingPoint.BeatLength;
|
||||
|
||||
float amplitudeAdjust = Math.Min(1, 0.4f + amplitudes.Maximum);
|
||||
|
||||
if (beatIndex < 0) return;
|
||||
|
||||
logoBeatContainer.ScaleTo(1 - 0.02f * amplitudeAdjust, beat_in_time, EasingTypes.Out);
|
||||
using (logoBeatContainer.BeginDelayedSequence(beat_in_time))
|
||||
logoBeatContainer.ScaleTo(1, beatLength * 2, EasingTypes.OutQuint);
|
||||
|
||||
ripple.ClearTransforms();
|
||||
|
||||
ripple.ScaleTo(logoAmplitudeContainer.Scale);
|
||||
ripple.Alpha = 0.15f * amplitudeAdjust;
|
||||
|
||||
ripple.ScaleTo(logoAmplitudeContainer.Scale * (1 + 0.04f * amplitudeAdjust), beatLength, EasingTypes.OutQuint);
|
||||
ripple.FadeOut(beatLength, EasingTypes.OutQuint);
|
||||
|
||||
if (effectPoint.KiaiMode && flashLayer.Alpha < 0.4f)
|
||||
{
|
||||
flashLayer.ClearTransforms();
|
||||
|
||||
flashLayer.FadeTo(0.2f * amplitudeAdjust, beat_in_time, EasingTypes.Out);
|
||||
using (flashLayer.BeginDelayedSequence(beat_in_time))
|
||||
flashLayer.FadeOut(beatLength);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
const float scale_adjust_cutoff = 0.4f;
|
||||
const float velocity_adjust_cutoff = 0.98f;
|
||||
|
||||
var maxAmplitude = lastBeatIndex >= 0 ? Beatmap.Value?.Track?.CurrentAmplitudes.Maximum ?? 0 : 0;
|
||||
logoAmplitudeContainer.ScaleTo(1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 75, EasingTypes.OutQuint);
|
||||
|
||||
if (maxAmplitude > velocity_adjust_cutoff)
|
||||
triangles.Velocity = 1 + Math.Max(0, maxAmplitude - velocity_adjust_cutoff) * 50;
|
||||
else
|
||||
triangles.Velocity = (float)Interpolation.Damp(triangles.Velocity, 1, 0.995f, Time.Elapsed);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
@ -254,4 +323,4 @@ namespace osu.Game.Screens.Menu
|
||||
impactContainer.ScaleTo(1.12f, 250);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
259
osu.Game/Screens/Multiplayer/DrawableRoom.cs
Normal file
259
osu.Game/Screens/Multiplayer/DrawableRoom.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -12,6 +11,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Screens.Play.HUD
|
||||
{
|
||||
@ -27,7 +27,7 @@ namespace osu.Game.Screens.Play.HUD
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
iconsContainer = new IconFlow
|
||||
iconsContainer = new ReverseDepthFillFlowContainer<ModIcon>
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
@ -93,12 +93,5 @@ namespace osu.Game.Screens.Play.HUD
|
||||
contract();
|
||||
base.OnHoverLost(state);
|
||||
}
|
||||
|
||||
private class IconFlow : FillFlowContainer<ModIcon>
|
||||
{
|
||||
// just reverses the depth of flow contents.
|
||||
protected override IComparer<Drawable> DepthComparer => new ReverseCreationOrderDepthComparer();
|
||||
protected override IEnumerable<ModIcon> FlowingChildren => base.FlowingChildren.Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,8 +170,8 @@ namespace osu.Game.Screens.Select
|
||||
List<BeatmapGroup> visibleGroups = groups.Where(selectGroup => selectGroup.State != BeatmapGroupState.Hidden).ToList();
|
||||
if (visibleGroups.Count < 1)
|
||||
return;
|
||||
BeatmapGroup group = visibleGroups[RNG.Next(visibleGroups.Count)];
|
||||
|
||||
BeatmapGroup group = visibleGroups[RNG.Next(visibleGroups.Count)];
|
||||
BeatmapPanel panel = group.BeatmapPanels[RNG.Next(group.BeatmapPanels.Count)];
|
||||
|
||||
selectGroup(group, panel);
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -12,6 +10,7 @@ using osu.Game.Graphics;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Input;
|
||||
using osu.Game.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Screens.Select.Options
|
||||
{
|
||||
@ -71,7 +70,7 @@ namespace osu.Game.Screens.Select.Options
|
||||
Scale = new Vector2(1, 0),
|
||||
Colour = Color4.Black.Opacity(0.5f),
|
||||
},
|
||||
buttonsContainer = new ButtonFlow
|
||||
buttonsContainer = new ReverseDepthFillFlowContainer<BeatmapOptionsButton>
|
||||
{
|
||||
Height = height,
|
||||
RelativePositionAxes = Axes.X,
|
||||
@ -109,16 +108,5 @@ namespace osu.Game.Screens.Select.Options
|
||||
HotKey = hotkey
|
||||
});
|
||||
}
|
||||
|
||||
private class ButtonFlow : FillFlowContainer<BeatmapOptionsButton>
|
||||
{
|
||||
protected override IComparer<Drawable> DepthComparer => new ReverseCreationOrderDepthComparer();
|
||||
protected override IEnumerable<BeatmapOptionsButton> FlowingChildren => base.FlowingChildren.Reverse();
|
||||
|
||||
public ButtonFlow()
|
||||
{
|
||||
Direction = FillDirection.Horizontal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -316,11 +316,12 @@ namespace osu.Game.Screens.Select
|
||||
/// </summary>
|
||||
private void selectionChanged(BeatmapInfo beatmap)
|
||||
{
|
||||
bool beatmapSetChange = false;
|
||||
selectionChangedDebounce?.Cancel();
|
||||
|
||||
if (beatmap.Equals(Beatmap?.BeatmapInfo))
|
||||
return;
|
||||
|
||||
bool beatmapSetChange = false;
|
||||
if (beatmap.BeatmapSetInfoID == selectionChangeNoBounce?.BeatmapSetInfoID)
|
||||
sampleChangeDifficulty.Play();
|
||||
else
|
||||
@ -331,7 +332,6 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
selectionChangeNoBounce = beatmap;
|
||||
|
||||
selectionChangedDebounce?.Cancel();
|
||||
selectionChangedDebounce = Scheduler.AddDelayed(delegate
|
||||
{
|
||||
Beatmap = database.GetWorkingBeatmap(beatmap, Beatmap);
|
||||
|
@ -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")]
|
||||
|
214
osu.Game/Users/UserPanel.cs
Normal file
214
osu.Game/Users/UserPanel.cs
Normal file
@ -0,0 +1,214 @@
|
||||
// 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.Configuration;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Users
|
||||
{
|
||||
public class UserPanel : Container
|
||||
{
|
||||
private const float height = 100;
|
||||
private const float content_padding = 10;
|
||||
private const float status_height = 30;
|
||||
|
||||
private OsuColour colours;
|
||||
|
||||
private readonly Container statusBar;
|
||||
private readonly Box statusBg;
|
||||
private readonly OsuSpriteText statusMessage;
|
||||
|
||||
public readonly Bindable<UserStatus> Status = new Bindable<UserStatus>();
|
||||
|
||||
public UserPanel(User user)
|
||||
{
|
||||
Height = height - status_height;
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
EdgeEffect = new EdgeEffect
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Colour = Color4.Black.Opacity(0.25f),
|
||||
Radius = 4,
|
||||
};
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new AsyncLoadWrapper(new CoverBackgroundSprite(user)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
FillMode = FillMode.Fill,
|
||||
OnLoadComplete = d => d.FadeInFromZero(200),
|
||||
}) { 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 EdgeEffect
|
||||
{
|
||||
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",
|
||||
},
|
||||
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?.FlagName ?? @"__")
|
||||
{
|
||||
Width = 30f,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Width = 40f,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Width = 20f,
|
||||
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[]
|
||||
{
|
||||
new TextAwesome
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Icon = FontAwesome.fa_circle_o,
|
||||
Shadow = true,
|
||||
TextSize = 14,
|
||||
},
|
||||
statusMessage = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Font = @"Exo2.0-Semibold",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
const float transition_duration = 500;
|
||||
|
||||
if (status == null)
|
||||
{
|
||||
statusBar.ResizeHeightTo(0f, transition_duration, EasingTypes.OutQuint);
|
||||
statusBar.FadeOut(transition_duration, EasingTypes.OutQuint);
|
||||
ResizeHeightTo(height - status_height, transition_duration, EasingTypes.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
statusBar.ResizeHeightTo(status_height, transition_duration, EasingTypes.OutQuint);
|
||||
statusBar.FadeIn(transition_duration, EasingTypes.OutQuint);
|
||||
ResizeHeightTo(height, transition_duration, EasingTypes.OutQuint);
|
||||
|
||||
statusBg.FadeColour(status.GetAppropriateColour(colours), 500, EasingTypes.OutQuint);
|
||||
statusMessage.Text = status.Message;
|
||||
}
|
||||
}
|
||||
|
||||
private class CoverBackgroundSprite : Sprite
|
||||
{
|
||||
private readonly User user;
|
||||
|
||||
public CoverBackgroundSprite(User user)
|
||||
{
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(user.CoverUrl))
|
||||
Texture = textures.Get(user.CoverUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
osu.Game/Users/UserStatus.cs
Normal file
67
osu.Game/Users/UserStatus.cs
Normal file
@ -0,0 +1,67 @@
|
||||
// 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.Users
|
||||
{
|
||||
public abstract class UserStatus
|
||||
{
|
||||
public abstract string Message { get; }
|
||||
public abstract Color4 GetAppropriateColour(OsuColour colours);
|
||||
}
|
||||
|
||||
public abstract class UserStatusAvailable : UserStatus
|
||||
{
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.BlueDarker;
|
||||
}
|
||||
|
||||
public abstract class UserStatusBusy : UserStatus
|
||||
{
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.YellowDark;
|
||||
}
|
||||
|
||||
public class UserStatusOffline : UserStatus
|
||||
{
|
||||
public override string Message => @"Offline";
|
||||
public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray7;
|
||||
}
|
||||
|
||||
public class UserStatusOnline : UserStatusAvailable
|
||||
{
|
||||
public override string Message => @"Online";
|
||||
}
|
||||
|
||||
public class UserStatusSpectating : UserStatusAvailable
|
||||
{
|
||||
public override string Message => @"Spectating a game";
|
||||
}
|
||||
|
||||
public class UserStatusInLobby : UserStatusAvailable
|
||||
{
|
||||
public override string Message => @"in Multiplayer Lobby";
|
||||
}
|
||||
|
||||
public class UserStatusSoloGame : UserStatusBusy
|
||||
{
|
||||
public override string Message => @"Solo Game";
|
||||
}
|
||||
|
||||
public class UserStatusMultiplayerGame: UserStatusBusy
|
||||
{
|
||||
public override string Message => @"Multiplaying";
|
||||
}
|
||||
|
||||
public class UserStatusModding : UserStatus
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
@ -189,6 +189,7 @@
|
||||
<Compile Include="Database\RulesetDatabase.cs" />
|
||||
<Compile Include="Rulesets\Scoring\Score.cs" />
|
||||
<Compile Include="Rulesets\Scoring\ScoreProcessor.cs" />
|
||||
<Compile Include="Screens\Menu\MenuSideFlashes.cs" />
|
||||
<Compile Include="Screens\Play\HUD\HealthDisplay.cs" />
|
||||
<Compile Include="Screens\Play\HUDOverlay.cs" />
|
||||
<Compile Include="Screens\Play\HUD\StandardHealthDisplay.cs" />
|
||||
@ -431,6 +432,24 @@
|
||||
<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" />
|
||||
<Compile Include="Overlays\Direct\FilterControl.cs" />
|
||||
<Compile Include="Overlays\Direct\Header.cs" />
|
||||
<Compile Include="Overlays\Direct\SortTabControl.cs" />
|
||||
<Compile Include="Graphics\UserInterface\OsuEnumDropdown.cs" />
|
||||
<Compile Include="Overlays\Direct\DirectPanel.cs" />
|
||||
<Compile Include="Overlays\Direct\DirectGridPanel.cs" />
|
||||
<Compile Include="Overlays\Direct\DirectListPanel.cs" />
|
||||
<Compile Include="Database\OnlineWorkingBeatmap.cs" />
|
||||
<Compile Include="Database\BeatmapOnlineInfo.cs" />
|
||||
<Compile Include="Overlays\Direct\SlimEnumDropdown.cs" />
|
||||
<Compile Include="Graphics\Containers\ReverseDepthFillFlowContainer.cs" />
|
||||
<Compile Include="Database\RankStatus.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||
|
Loading…
Reference in New Issue
Block a user