1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-13 10:03:05 +08:00

Merge remote-tracking branch 'origin/master' into netstandard

This commit is contained in:
smoogipoo 2017-11-22 19:46:17 +09:00
commit de7c571be3
26 changed files with 626 additions and 253 deletions

View File

@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu
}; };
public override IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new[] public override IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new[]
{ {
new BeatmapStatistic new BeatmapStatistic
{ {
Name = @"Circle count", Name = @"Circle count",

View File

@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
/// <summary> /// <summary>
/// Taiko fails at the end of the map if the player has not half-filled their HP bar. /// Taiko fails at the end of the map if the player has not half-filled their HP bar.
/// </summary> /// </summary>
protected override bool FailCondition => Hits == MaxHits && Health.Value <= 0.5; protected override bool DefaultFailCondition => Hits == MaxHits && Health.Value <= 0.5;
private double hpIncreaseTick; private double hpIncreaseTick;
private double hpIncreaseGreat; private double hpIncreaseGreat;

View File

@ -0,0 +1,27 @@
// 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;
using osu.Game.Beatmaps;
using osu.Game.Screens.Edit.Components;
using osu.Game.Tests.Beatmaps;
using OpenTK;
namespace osu.Game.Tests.Visual
{
public class TestCasePlaybackControl : OsuTestCase
{
public TestCasePlaybackControl()
{
var playback = new PlaybackControl
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(200,100)
};
playback.Beatmap.Value = new TestWorkingBeatmap(new Beatmap());
Add(playback);
}
}
}

View File

@ -36,7 +36,8 @@ namespace osu.Game.Tests.Visual
Username = @"peppy", Username = @"peppy",
Id = 2, Id = 2,
Country = new Country { FlagName = @"AU" }, Country = new Country { FlagName = @"AU" },
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg" CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
IsSupporter = true,
}) { Width = 300 }, }) { Width = 300 },
}, },
}); });

View File

@ -165,7 +165,7 @@ namespace osu.Game.Beatmaps
catch (Exception e) catch (Exception e)
{ {
e = e.InnerException ?? e; e = e.InnerException ?? e;
Logger.Error(e, @"Could not import beatmap set"); Logger.Error(e, $@"Could not import beatmap set ({Path.GetFileName(path)})");
} }
} }

View File

@ -11,7 +11,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -28,10 +27,8 @@ namespace osu.Game.Beatmaps.Drawables
public Action<BeatmapSetInfo> RestoreHiddenRequested; public Action<BeatmapSetInfo> RestoreHiddenRequested;
private readonly SpriteText title;
private readonly SpriteText artist;
private readonly WorkingBeatmap beatmap; private readonly WorkingBeatmap beatmap;
private readonly FillFlowContainer difficultyIcons; private readonly FillFlowContainer difficultyIcons;
public BeatmapSetHeader(WorkingBeatmap beatmap) public BeatmapSetHeader(WorkingBeatmap beatmap)
@ -41,6 +38,25 @@ namespace osu.Game.Beatmaps.Drawables
this.beatmap = beatmap; this.beatmap = beatmap;
difficultyIcons = new FillFlowContainer
{
Margin = new MarginPadding { Top = 5 },
AutoSizeAxes = Axes.Both,
};
}
protected override void Selected()
{
base.Selected();
GainedSelection?.Invoke(this);
}
[BackgroundDependencyLoader]
private void load(LocalisationEngine localisation)
{
if (localisation == null)
throw new ArgumentNullException(nameof(localisation));
Children = new Drawable[] Children = new Drawable[]
{ {
new DelayedLoadWrapper( new DelayedLoadWrapper(
@ -60,44 +76,26 @@ namespace osu.Game.Beatmaps.Drawables
AutoSizeAxes = Axes.Both, AutoSizeAxes = Axes.Both,
Children = new Drawable[] Children = new Drawable[]
{ {
title = new OsuSpriteText new OsuSpriteText
{ {
Font = @"Exo2.0-BoldItalic", Font = @"Exo2.0-BoldItalic",
Current = localisation.GetUnicodePreference(beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title),
TextSize = 22, TextSize = 22,
Shadow = true, Shadow = true,
}, },
artist = new OsuSpriteText new OsuSpriteText
{ {
Font = @"Exo2.0-SemiBoldItalic", Font = @"Exo2.0-SemiBoldItalic",
Current = localisation.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist),
TextSize = 17, TextSize = 17,
Shadow = true, Shadow = true,
}, },
difficultyIcons = new FillFlowContainer difficultyIcons
{
Margin = new MarginPadding { Top = 5 },
AutoSizeAxes = Axes.Both,
}
} }
} }
}; };
} }
protected override void Selected()
{
base.Selected();
GainedSelection?.Invoke(this);
}
[BackgroundDependencyLoader]
private void load(LocalisationEngine localisation)
{
if (localisation == null)
throw new ArgumentNullException(nameof(localisation));
title.Current = localisation.GetUnicodePreference(beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title);
artist.Current = localisation.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist);
}
private class PanelBackground : BufferedContainer private class PanelBackground : BufferedContainer
{ {
public PanelBackground(WorkingBeatmap working) public PanelBackground(WorkingBeatmap working)
@ -185,4 +183,4 @@ namespace osu.Game.Beatmaps.Drawables
} }
} }
} }
} }

View File

@ -8,6 +8,7 @@ using osu.Game.Rulesets.Mods;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
@ -29,10 +30,10 @@ namespace osu.Game.Beatmaps
Mods.ValueChanged += mods => applyRateAdjustments(); Mods.ValueChanged += mods => applyRateAdjustments();
beatmap = new Lazy<Beatmap>(populateBeatmap); beatmap = new AsyncLazy<Beatmap>(populateBeatmap);
background = new Lazy<Texture>(populateBackground); background = new AsyncLazy<Texture>(populateBackground);
track = new Lazy<Track>(populateTrack); track = new AsyncLazy<Track>(populateTrack);
waveform = new Lazy<Waveform>(populateWaveform); waveform = new AsyncLazy<Waveform>(populateWaveform);
} }
protected abstract Beatmap GetBeatmap(); protected abstract Beatmap GetBeatmap();
@ -41,8 +42,10 @@ namespace osu.Game.Beatmaps
protected virtual Waveform GetWaveform() => new Waveform(); protected virtual Waveform GetWaveform() => new Waveform();
public bool BeatmapLoaded => beatmap.IsValueCreated; public bool BeatmapLoaded => beatmap.IsValueCreated;
public Beatmap Beatmap => beatmap.Value; public Beatmap Beatmap => beatmap.Value.Result;
private readonly Lazy<Beatmap> beatmap; public async Task<Beatmap> GetBeatmapAsync() => await beatmap.Value;
private readonly AsyncLazy<Beatmap> beatmap;
private Beatmap populateBeatmap() private Beatmap populateBeatmap()
{ {
@ -55,14 +58,16 @@ namespace osu.Game.Beatmaps
} }
public bool BackgroundLoaded => background.IsValueCreated; public bool BackgroundLoaded => background.IsValueCreated;
public Texture Background => background.Value; public Texture Background => background.Value.Result;
private Lazy<Texture> background; public async Task<Texture> GetBackgroundAsync() => await background.Value;
private AsyncLazy<Texture> background;
private Texture populateBackground() => GetBackground(); private Texture populateBackground() => GetBackground();
public bool TrackLoaded => track.IsValueCreated; public bool TrackLoaded => track.IsValueCreated;
public Track Track => track.Value; public Track Track => track.Value.Result;
private Lazy<Track> track; public async Task<Track> GetTrackAsync() => await track.Value;
private AsyncLazy<Track> track;
private Track populateTrack() private Track populateTrack()
{ {
@ -73,8 +78,9 @@ namespace osu.Game.Beatmaps
} }
public bool WaveformLoaded => waveform.IsValueCreated; public bool WaveformLoaded => waveform.IsValueCreated;
public Waveform Waveform => waveform.Value; public Waveform Waveform => waveform.Value.Result;
private readonly Lazy<Waveform> waveform; public async Task<Waveform> GetWaveformAsync() => await waveform.Value;
private readonly AsyncLazy<Waveform> waveform;
private Waveform populateWaveform() => GetWaveform(); private Waveform populateWaveform() => GetWaveform();
@ -107,5 +113,13 @@ namespace osu.Game.Beatmaps
foreach (var mod in Mods.Value.OfType<IApplicableToClock>()) foreach (var mod in Mods.Value.OfType<IApplicableToClock>())
mod.ApplyToClock(t); mod.ApplyToClock(t);
} }
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<T> valueFactory)
: base(() => Task.Run(valueFactory))
{
}
}
} }
} }

View File

@ -45,8 +45,8 @@ namespace osu.Game.Graphics.Containers
double currentTrackTime = track.Length > 0 ? track.CurrentTime + EarlyActivationMilliseconds : Clock.CurrentTime; double currentTrackTime = track.Length > 0 ? track.CurrentTime + EarlyActivationMilliseconds : Clock.CurrentTime;
TimingControlPoint timingPoint = Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(currentTrackTime); TimingControlPoint timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
EffectControlPoint effectPoint = Beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(currentTrackTime); EffectControlPoint effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
if (timingPoint.BeatLength == 0) if (timingPoint.BeatLength == 0)
return; return;
@ -67,7 +67,7 @@ namespace osu.Game.Graphics.Containers
return; return;
using (BeginDelayedSequence(-TimeSinceLastBeat, true)) using (BeginDelayedSequence(-TimeSinceLastBeat, true))
OnNewBeat(beatIndex, timingPoint, effectPoint, Beatmap.Value.Track.CurrentAmplitudes); OnNewBeat(beatIndex, timingPoint, effectPoint, track.CurrentAmplitudes);
lastBeat = beatIndex; lastBeat = beatIndex;
lastTimingPoint = timingPoint; lastTimingPoint = timingPoint;

View File

@ -109,7 +109,7 @@ namespace osu.Game
dependencies.Cache(this); dependencies.Cache(this);
configRuleset = LocalConfig.GetBindable<int>(OsuSetting.Ruleset); configRuleset = LocalConfig.GetBindable<int>(OsuSetting.Ruleset);
Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value); Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First();
Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0; Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0;
} }

View File

@ -37,7 +37,7 @@ namespace osu.Game.Overlays
private const float bottom_black_area_height = 55; private const float bottom_black_area_height = 55;
private Drawable currentBackground; private Drawable background;
private ProgressBar progressBar; private ProgressBar progressBar;
private IconButton prevButton; private IconButton prevButton;
@ -121,7 +121,7 @@ namespace osu.Game.Overlays
}, },
Children = new[] Children = new[]
{ {
currentBackground = new Background(), background = new Background(),
title = new OsuSpriteText title = new OsuSpriteText
{ {
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
@ -335,6 +335,7 @@ namespace osu.Game.Overlays
pendingBeatmapSwitch = Schedule(delegate pendingBeatmapSwitch = Schedule(delegate
{ {
// todo: this can likely be replaced with WorkingBeatmap.GetBeatmapAsync()
Task.Run(() => Task.Run(() =>
{ {
if (beatmap?.Beatmap == null) //this is not needed if a placeholder exists if (beatmap?.Beatmap == null) //this is not needed if a placeholder exists
@ -353,29 +354,26 @@ namespace osu.Game.Overlays
} }
}); });
playerContainer.Add(new AsyncLoadWrapper(new Background(beatmap) LoadComponentAsync(new Background(beatmap) { Depth = float.MaxValue }, newBackground =>
{ {
OnLoadComplete = newBackground => switch (direction)
{ {
switch (direction) case TransformDirection.Next:
{ newBackground.Position = new Vector2(400, 0);
case TransformDirection.Next: newBackground.MoveToX(0, 500, Easing.OutCubic);
newBackground.Position = new Vector2(400, 0); background.MoveToX(-400, 500, Easing.OutCubic);
newBackground.MoveToX(0, 500, Easing.OutCubic); break;
currentBackground.MoveToX(-400, 500, Easing.OutCubic); case TransformDirection.Prev:
break; newBackground.Position = new Vector2(-400, 0);
case TransformDirection.Prev: newBackground.MoveToX(0, 500, Easing.OutCubic);
newBackground.Position = new Vector2(-400, 0); background.MoveToX(400, 500, Easing.OutCubic);
newBackground.MoveToX(0, 500, Easing.OutCubic); break;
currentBackground.MoveToX(400, 500, Easing.OutCubic);
break;
}
currentBackground.Expire();
currentBackground = newBackground;
} }
})
{ background.Expire();
Depth = float.MaxValue, background = newBackground;
playerContainer.Add(newBackground);
}); });
}); });
} }

View File

@ -0,0 +1,15 @@
// 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.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for mods that make general adjustments to score processor.
/// </summary>
public interface IApplicableToScoreProcessor
{
void ApplyToScoreProcessor(ScoreProcessor scoreProcessor);
}
}

View File

@ -1,6 +1,8 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
public abstract class ModPerfect : ModSuddenDeath public abstract class ModPerfect : ModSuddenDeath
@ -8,5 +10,7 @@ namespace osu.Game.Rulesets.Mods
public override string Name => "Perfect"; public override string Name => "Perfect";
public override string ShortenedName => "PF"; public override string ShortenedName => "PF";
public override string Description => "SS or quit."; public override string Description => "SS or quit.";
protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1;
} }
} }

View File

@ -3,10 +3,11 @@
using System; using System;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
public abstract class ModSuddenDeath : Mod public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor
{ {
public override string Name => "Sudden Death"; public override string Name => "Sudden Death";
public override string ShortenedName => "SD"; public override string ShortenedName => "SD";
@ -16,5 +17,12 @@ namespace osu.Game.Rulesets.Mods
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) };
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
{
scoreProcessor.FailConditions += FailCondition;
}
protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0;
} }
} }

View File

@ -31,6 +31,11 @@ namespace osu.Game.Rulesets.Scoring
/// </summary> /// </summary>
public event Action<Judgement> NewJudgement; public event Action<Judgement> NewJudgement;
/// <summary>
/// Additional conditions on top of <see cref="DefaultFailCondition"/> that cause a failing state.
/// </summary>
public event Func<ScoreProcessor, bool> FailConditions;
/// <summary> /// <summary>
/// The current total score. /// The current total score.
/// </summary> /// </summary>
@ -72,9 +77,9 @@ namespace osu.Game.Rulesets.Scoring
public virtual bool HasFailed { get; private set; } public virtual bool HasFailed { get; private set; }
/// <summary> /// <summary>
/// The conditions for failing. /// The default conditions for failing.
/// </summary> /// </summary>
protected virtual bool FailCondition => Health.Value == Health.MinValue; protected virtual bool DefaultFailCondition => Health.Value == Health.MinValue;
protected ScoreProcessor() protected ScoreProcessor()
{ {
@ -121,7 +126,10 @@ namespace osu.Game.Rulesets.Scoring
/// </summary> /// </summary>
protected void UpdateFailed() protected void UpdateFailed()
{ {
if (HasFailed || !FailCondition) if (HasFailed)
return;
if (!DefaultFailCondition && FailConditions?.Invoke(this) != true)
return; return;
if (Failed?.Invoke() != false) if (Failed?.Invoke() != false)
@ -216,8 +224,8 @@ namespace osu.Game.Rulesets.Scoring
OnNewJudgement(judgement); OnNewJudgement(judgement);
updateScore(); updateScore();
NotifyNewJudgement(judgement);
UpdateFailed(); UpdateFailed();
NotifyNewJudgement(judgement);
} }
protected void RemoveJudgement(Judgement judgement) protected void RemoveJudgement(Judgement judgement)

View File

@ -32,9 +32,7 @@ namespace osu.Game.Screens.Backgrounds
Schedule(() => Schedule(() =>
{ {
var newBackground = new BeatmapBackground(beatmap); LoadComponentAsync(new BeatmapBackground(beatmap), b =>
LoadComponentAsync(newBackground, delegate
{ {
float newDepth = 0; float newDepth = 0;
if (background != null) if (background != null)
@ -45,8 +43,8 @@ namespace osu.Game.Screens.Backgrounds
background.Expire(); background.Expire();
} }
newBackground.Depth = newDepth; b.Depth = newDepth;
Add(background = newBackground); Add(background = b);
background.BlurSigma = blurTarget; background.BlurSigma = blurTarget;
}); });
}); });

View File

@ -0,0 +1,50 @@
// 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.Allocation;
using osu.Framework.Audio.Track;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
namespace osu.Game.Screens.Edit.Components
{
public class BottomBarContainer : Container
{
private const float corner_radius = 5;
private const float contents_padding = 15;
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
protected Track Track => Beatmap.Value.Track;
private readonly Drawable background;
private readonly Container content;
protected override Container<Drawable> Content => content;
public BottomBarContainer()
{
Masking = true;
CornerRadius = corner_radius;
InternalChildren = new[]
{
background = new Box { RelativeSizeAxes = Axes.Both },
content = new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Horizontal = contents_padding },
}
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
background.Colour = colours.Gray1;
}
}
}

View File

@ -0,0 +1,154 @@
// 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.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
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.Screens.Edit.Components
{
public class PlaybackControl : BottomBarContainer
{
private readonly IconButton playButton;
public PlaybackControl()
{
PlaybackTabControl tabs;
Children = new Drawable[]
{
playButton = new IconButton
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.Centre,
Scale = new Vector2(1.4f),
IconScale = new Vector2(1.4f),
Icon = FontAwesome.fa_play_circle_o,
Action = togglePause,
Padding = new MarginPadding { Left = 20 }
},
new OsuSpriteText
{
Origin = Anchor.BottomLeft,
Text = "Playback Speed",
RelativePositionAxes = Axes.Y,
Y = 0.5f,
Padding = new MarginPadding { Left = 45 }
},
new Container
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
RelativeSizeAxes = Axes.Both,
Height = 0.5f,
Padding = new MarginPadding { Left = 45 },
Child = tabs = new PlaybackTabControl(),
}
};
tabs.Current.ValueChanged += newValue => Track.Tempo.Value = newValue;
}
private void togglePause()
{
if (Track.IsRunning)
Track.Stop();
else
Track.Start();
}
protected override void Update()
{
base.Update();
playButton.Icon = Track.IsRunning ? FontAwesome.fa_pause_circle_o : FontAwesome.fa_play_circle_o;
}
private class PlaybackTabControl : OsuTabControl<double>
{
private static readonly double[] tempo_values = { 0.5, 0.75, 1 };
protected override TabItem<double> CreateTabItem(double value) => new PlaybackTabItem(value);
protected override Dropdown<double> CreateDropdown() => null;
public PlaybackTabControl()
{
RelativeSizeAxes = Axes.Both;
TabContainer.Spacing = Vector2.Zero;
tempo_values.ForEach(AddItem);
}
public class PlaybackTabItem : TabItem<double>
{
private const float fade_duration = 200;
private readonly OsuSpriteText text;
private readonly OsuSpriteText textBold;
public PlaybackTabItem(double value) : base(value)
{
RelativeSizeAxes = Axes.Both;
Width = 1f / tempo_values.Length;
Children = new Drawable[]
{
text = new OsuSpriteText
{
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Text = $"{value:0%}",
TextSize = 14,
},
textBold = new OsuSpriteText
{
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Text = $"{value:0%}",
TextSize = 14,
Font = @"Exo2.0-Bold",
Alpha = 0,
},
};
}
private Color4 hoveredColour;
private Color4 normalColour;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
text.Colour = normalColour = colours.YellowDarker;
textBold.Colour = hoveredColour = colours.Yellow;
}
protected override bool OnHover(InputState state)
{
updateState();
return true;
}
protected override void OnHoverLost(InputState state) => updateState();
protected override void OnActivated() => updateState();
protected override void OnDeactivated() => updateState();
private void updateState()
{
text.FadeColour(Active || IsHovered ? hoveredColour : normalColour, fade_duration, Easing.OutQuint);
text.FadeTo(Active ? 0 : 1, fade_duration, Easing.OutQuint);
textBold.FadeTo(Active ? 1 : 0, fade_duration, Easing.OutQuint);
}
}
}
}
}

View 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 osu.Framework.Graphics;
using osu.Game.Graphics.Sprites;
using System;
namespace osu.Game.Screens.Edit.Components
{
public class TimeInfoContainer : BottomBarContainer
{
private const int count_duration = 150;
private readonly OsuSpriteText trackTimer;
public TimeInfoContainer()
{
Children = new Drawable[]
{
trackTimer = new OsuSpriteText
{
Origin = Anchor.BottomLeft,
RelativePositionAxes = Axes.Y,
TextSize = 22,
FixedWidth = true,
Y = 0.5f,
}
};
}
protected override void Update()
{
base.Update();
trackTimer.Text = TimeSpan.FromMilliseconds(Track.CurrentTime).ToString(@"mm\:ss\:fff");
}
}
}

View File

@ -3,11 +3,9 @@
using OpenTK; using OpenTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts; using osu.Game.Screens.Edit.Components.Timelines.Summary.Parts;
@ -16,83 +14,64 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
/// <summary> /// <summary>
/// The timeline that sits at the bottom of the editor. /// The timeline that sits at the bottom of the editor.
/// </summary> /// </summary>
public class SummaryTimeline : CompositeDrawable public class SummaryTimeline : BottomBarContainer
{ {
private const float corner_radius = 5;
private const float contents_padding = 15;
public Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
private readonly Drawable background;
private readonly Drawable timelineBar; private readonly Drawable timelineBar;
public SummaryTimeline() public SummaryTimeline()
{ {
Masking = true;
CornerRadius = corner_radius;
TimelinePart markerPart, controlPointPart, bookmarkPart, breakPart; TimelinePart markerPart, controlPointPart, bookmarkPart, breakPart;
InternalChildren = new[] Children = new[]
{ {
background = new Box { RelativeSizeAxes = Axes.Both }, markerPart = new MarkerPart { RelativeSizeAxes = Axes.Both },
new Container controlPointPart = new ControlPointPart
{
Anchor = Anchor.Centre,
Origin = Anchor.BottomCentre,
RelativeSizeAxes = Axes.Both,
Height = 0.35f
},
bookmarkPart = new BookmarkPart
{
Anchor = Anchor.Centre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Both,
Height = 0.35f
},
timelineBar = new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = contents_padding, Right = contents_padding }, Children = new Drawable[]
Children = new[]
{ {
markerPart = new MarkerPart { RelativeSizeAxes = Axes.Both }, new Circle
controlPointPart = new ControlPointPart
{ {
Anchor = Anchor.Centre, Anchor = Anchor.CentreLeft,
Origin = Anchor.BottomCentre, Origin = Anchor.CentreRight,
RelativeSizeAxes = Axes.Both, Size = new Vector2(5)
Height = 0.35f
}, },
bookmarkPart = new BookmarkPart new Box
{ {
Anchor = Anchor.Centre, Anchor = Anchor.CentreLeft,
Origin = Anchor.TopCentre, Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.X,
Height = 0.35f Height = 1,
EdgeSmoothness = new Vector2(0, 1),
}, },
timelineBar = new Container new Circle
{ {
RelativeSizeAxes = Axes.Both, Anchor = Anchor.CentreRight,
Children = new Drawable[] Origin = Anchor.CentreLeft,
{ Size = new Vector2(5)
new Circle
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreRight,
Size = new Vector2(5)
},
new Box
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
RelativeSizeAxes = Axes.X,
Height = 1,
EdgeSmoothness = new Vector2(0, 1),
},
new Circle
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreLeft,
Size = new Vector2(5)
},
}
}, },
breakPart = new BreakPart
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Height = 0.25f
}
} }
},
breakPart = new BreakPart
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Height = 0.25f
} }
}; };
@ -105,7 +84,6 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours) private void load(OsuColour colours)
{ {
background.Colour = colours.Gray1;
timelineBar.Colour = colours.Gray5; timelineBar.Colour = colours.Gray5;
} }
} }

View File

@ -10,13 +10,13 @@ using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Screens.Edit.Menus; using osu.Game.Screens.Edit.Menus;
using osu.Game.Screens.Edit.Components.Timelines.Summary; using osu.Game.Screens.Edit.Components.Timelines.Summary;
using OpenTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Screens.Edit.Screens; using osu.Game.Screens.Edit.Screens;
using osu.Game.Screens.Edit.Screens.Compose; using osu.Game.Screens.Edit.Screens.Compose;
using osu.Game.Screens.Edit.Screens.Design; using osu.Game.Screens.Edit.Screens.Design;
using osu.Game.Screens.Edit.Components;
namespace osu.Game.Screens.Edit namespace osu.Game.Screens.Edit
{ {
@ -34,7 +34,9 @@ namespace osu.Game.Screens.Edit
public Editor() public Editor()
{ {
EditorMenuBar menuBar; EditorMenuBar menuBar;
TimeInfoContainer timeInfo;
SummaryTimeline timeline; SummaryTimeline timeline;
PlaybackControl playback;
Children = new[] Children = new[]
{ {
@ -84,30 +86,47 @@ namespace osu.Game.Screens.Edit
new Container new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Top = 5, Bottom = 5, Left = 10, Right = 10 }, Padding = new MarginPadding { Vertical = 5, Horizontal = 10 },
Child = new FillFlowContainer Child = new GridContainer
{ {
Name = "Bottom bar",
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal, ColumnDimensions = new[]
Spacing = new Vector2(10, 0),
Children = new[]
{ {
timeline = new SummaryTimeline new Dimension(GridSizeMode.Absolute, 220),
new Dimension(),
new Dimension(GridSizeMode.Absolute, 220)
},
Content = new[]
{
new Drawable[]
{ {
Anchor = Anchor.Centre, new Container
Origin = Anchor.Centre, {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Width = 0.65f Padding = new MarginPadding { Right = 10 },
} Child = timeInfo = new TimeInfoContainer { RelativeSizeAxes = Axes.Both },
},
timeline = new SummaryTimeline
{
RelativeSizeAxes = Axes.Both,
},
new Container
{
RelativeSizeAxes = Axes.Both,
Padding = new MarginPadding { Left = 10 },
Child = playback = new PlaybackControl { RelativeSizeAxes = Axes.Both },
}
},
} }
} },
} }
} }
}, },
}; };
timeInfo.Beatmap.BindTo(Beatmap);
timeline.Beatmap.BindTo(Beatmap); timeline.Beatmap.BindTo(Beatmap);
playback.Beatmap.BindTo(Beatmap);
menuBar.Mode.ValueChanged += onModeChanged; menuBar.Mode.ValueChanged += onModeChanged;
} }
@ -154,7 +173,11 @@ namespace osu.Game.Screens.Edit
protected override bool OnExiting(Screen next) protected override bool OnExiting(Screen next)
{ {
Background.FadeColour(Color4.White, 500); Background.FadeColour(Color4.White, 500);
Beatmap.Value.Track?.Start(); if (Beatmap.Value.Track != null)
{
Beatmap.Value.Track.Tempo.Value = 1;
Beatmap.Value.Track.Start();
}
return base.OnExiting(next); return base.OnExiting(next);
} }
} }

View File

@ -85,12 +85,11 @@ namespace osu.Game.Screens.Menu
private void updateAmplitudes() private void updateAmplitudes()
{ {
var track = beatmap.Value.Track; var track = beatmap.Value.TrackLoaded ? beatmap.Value.Track : null;
var effect = beatmap.Value.BeatmapLoaded ? beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current) : null;
float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256]; float[] temporalAmplitudes = track?.CurrentAmplitudes.FrequencyAmplitudes ?? new float[256];
var effect = beatmap.Value.Beatmap.ControlPointInfo.EffectPointAt(track?.CurrentTime ?? Time.Current);
for (int i = 0; i < bars_per_visualiser; i++) for (int i = 0; i < bars_per_visualiser; i++)
{ {
if (track?.IsRunning ?? false) if (track?.IsRunning ?? false)

View File

@ -227,6 +227,9 @@ namespace osu.Game.Screens.Play
// Bind ScoreProcessor to ourselves // Bind ScoreProcessor to ourselves
scoreProcessor.AllJudged += onCompletion; scoreProcessor.AllJudged += onCompletion;
scoreProcessor.Failed += onFail; scoreProcessor.Failed += onFail;
foreach (var mod in Beatmap.Value.Mods.Value.OfType<IApplicableToScoreProcessor>())
mod.ApplyToScoreProcessor(scoreProcessor);
} }
private void applyRateFromMods() private void applyRateFromMods()

View File

@ -572,7 +572,18 @@ namespace osu.Game.Screens.Select
// Makes sure headers are always _below_ panels, // Makes sure headers are always _below_ panels,
// and depth flows downward. // and depth flows downward.
panel.Depth = i + (panel is BeatmapSetHeader ? panels.Count : 0); panel.Depth = i + (panel is BeatmapSetHeader ? panels.Count : 0);
scrollableContent.Add(panel);
switch (panel.LoadState)
{
case LoadState.NotLoaded:
LoadComponentAsync(panel);
break;
case LoadState.Loading:
break;
default:
scrollableContent.Add(panel);
break;
}
} }
} }

View File

@ -26,7 +26,7 @@ namespace osu.Game.Screens.Select
{ {
private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0); private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0);
private Drawable beatmapInfoContainer; private Drawable info;
public BeatmapInfoWedge() public BeatmapInfoWedge()
{ {
@ -43,12 +43,6 @@ namespace osu.Game.Screens.Select
}; };
} }
protected override void LoadComplete()
{
base.LoadComplete();
AlwaysPresent = true;
}
protected override bool BlockPassThroughMouse => false; protected override bool BlockPassThroughMouse => false;
protected override void PopIn() protected override void PopIn()
@ -65,56 +59,62 @@ namespace osu.Game.Screens.Select
public void UpdateBeatmap(WorkingBeatmap beatmap) public void UpdateBeatmap(WorkingBeatmap beatmap)
{ {
var lastContainer = beatmapInfoContainer; LoadComponentAsync(new BufferedWedgeInfo(beatmap)
float newDepth = lastContainer?.Depth + 1 ?? 0;
Add(beatmapInfoContainer = new AsyncLoadWrapper(
new BufferedWedgeInfo(beatmap)
{
Shear = -Shear,
OnLoadComplete = d =>
{
this.FadeIn(250);
lastContainer?.FadeOut(250);
lastContainer?.Expire();
}
})
{ {
Depth = newDepth, Shear = -Shear,
Depth = info?.Depth + 1 ?? 0,
}, newInfo =>
{
// ensure we ourselves are visible if not already.
if (!IsPresent)
this.FadeIn(250);
info?.FadeOut(250);
info?.Expire();
Add(info = newInfo);
}); });
} }
public class BufferedWedgeInfo : BufferedContainer public class BufferedWedgeInfo : BufferedContainer
{ {
public BufferedWedgeInfo(WorkingBeatmap beatmap) private readonly WorkingBeatmap working;
public BufferedWedgeInfo(WorkingBeatmap working)
{ {
BeatmapInfo beatmapInfo = beatmap.BeatmapInfo; this.working = working;
BeatmapMetadata metadata = beatmapInfo.Metadata ?? beatmap.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); }
[BackgroundDependencyLoader]
private void load()
{
BeatmapInfo beatmapInfo = working.BeatmapInfo;
BeatmapMetadata metadata = beatmapInfo.Metadata ?? working.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
Beatmap beatmap = working.Beatmap;
List<InfoLabel> labels = new List<InfoLabel>(); List<InfoLabel> labels = new List<InfoLabel>();
if (beatmap.Beatmap != null) if (beatmap != null)
{ {
HitObject lastObject = beatmap.Beatmap.HitObjects.LastOrDefault(); HitObject lastObject = beatmap.HitObjects.LastOrDefault();
double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0; double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0;
labels.Add(new InfoLabel(new BeatmapStatistic labels.Add(new InfoLabel(new BeatmapStatistic
{ {
Name = "Length", Name = "Length",
Icon = FontAwesome.fa_clock_o, Icon = FontAwesome.fa_clock_o,
Content = beatmap.Beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(endTime - beatmap.Beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"), Content = beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(endTime - beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"),
})); }));
labels.Add(new InfoLabel(new BeatmapStatistic labels.Add(new InfoLabel(new BeatmapStatistic
{ {
Name = "BPM", Name = "BPM",
Icon = FontAwesome.fa_circle, Icon = FontAwesome.fa_circle,
Content = getBPMRange(beatmap.Beatmap), Content = getBPMRange(beatmap),
})); }));
//get statistics from the current ruleset. //get statistics from the current ruleset.
labels.AddRange(beatmapInfo.Ruleset.CreateInstance().GetBeatmapStatistics(beatmap).Select(s => new InfoLabel(s))); labels.AddRange(beatmapInfo.Ruleset.CreateInstance().GetBeatmapStatistics(working).Select(s => new InfoLabel(s)));
} }
PixelSnapping = true; PixelSnapping = true;
@ -140,7 +140,7 @@ namespace osu.Game.Screens.Select
Children = new[] Children = new[]
{ {
// Zoomed-in and cropped beatmap background // Zoomed-in and cropped beatmap background
new BeatmapBackgroundSprite(beatmap) new BeatmapBackgroundSprite(working)
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
@ -149,7 +149,7 @@ namespace osu.Game.Screens.Select
}, },
}, },
}, },
new DifficultyColourBar(beatmap.BeatmapInfo) new DifficultyColourBar(beatmapInfo)
{ {
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
Width = 20, Width = 20,
@ -206,13 +206,13 @@ namespace osu.Game.Screens.Select
Font = @"Exo2.0-Medium", Font = @"Exo2.0-Medium",
Text = "mapped by ", Text = "mapped by ",
TextSize = 15, TextSize = 15,
}, },
new OsuSpriteText new OsuSpriteText
{ {
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
Text = metadata.Author.Username, Text = metadata.Author.Username,
TextSize = 15, TextSize = 15,
}, },
} }
}, },
new FillFlowContainer new FillFlowContainer
@ -244,38 +244,39 @@ namespace osu.Game.Screens.Select
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
Children = new Drawable[] Children = new Drawable[]
{ {
new SpriteIcon new SpriteIcon
{ {
Icon = FontAwesome.fa_square, Icon = FontAwesome.fa_square,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Colour = new Color4(68, 17, 136, 255), Colour = new Color4(68, 17, 136, 255),
Rotation = 45, Rotation = 45,
Size = new Vector2(20), Size = new Vector2(20),
}, },
new SpriteIcon new SpriteIcon
{ {
Icon = statistic.Icon, Icon = statistic.Icon,
Origin = Anchor.Centre, Origin = Anchor.Centre,
Colour = new Color4(255, 221, 85, 255), Colour = new Color4(255, 221, 85, 255),
Scale = new Vector2(0.8f), Scale = new Vector2(0.8f),
Size = new Vector2(20), Size = new Vector2(20),
}, },
new OsuSpriteText new OsuSpriteText
{ {
Margin = new MarginPadding { Left = 13 }, Margin = new MarginPadding { Left = 13 },
Font = @"Exo2.0-Bold", Font = @"Exo2.0-Bold",
Colour = new Color4(255, 221, 85, 255), Colour = new Color4(255, 221, 85, 255),
Text = statistic.Content, Text = statistic.Content,
TextSize = 17, TextSize = 17,
Origin = Anchor.CentreLeft Origin = Anchor.CentreLeft
}, },
}; };
} }
} }
private class DifficultyColourBar : DifficultyColouredContainer private class DifficultyColourBar : DifficultyColouredContainer
{ {
public DifficultyColourBar(BeatmapInfo beatmap) : base(beatmap) public DifficultyColourBar(BeatmapInfo beatmap)
: base(beatmap)
{ {
} }
@ -286,21 +287,21 @@ namespace osu.Game.Screens.Select
Children = new Drawable[] Children = new Drawable[]
{ {
new Box new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = AccentColour, Colour = AccentColour,
Width = full_opacity_ratio, Width = full_opacity_ratio,
}, },
new Box new Box
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
RelativePositionAxes = Axes.Both, RelativePositionAxes = Axes.Both,
Colour = AccentColour, Colour = AccentColour,
Alpha = 0.5f, Alpha = 0.5f,
X = full_opacity_ratio, X = full_opacity_ratio,
Width = 1 - full_opacity_ratio, Width = 1 - full_opacity_ratio,
} }
}; };
} }
} }

View File

@ -1,7 +1,6 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq; using System.Linq;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -24,8 +23,6 @@ namespace osu.Game.Screens.Select.Leaderboards
{ {
public static readonly float HEIGHT = 60; public static readonly float HEIGHT = 60;
public event Action<Visibility> StateChanged;
public readonly int RankPosition; public readonly int RankPosition;
public readonly Score Score; public readonly Score Score;

View File

@ -16,6 +16,7 @@ using osu.Game.Overlays;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Game.Graphics.Backgrounds;
namespace osu.Game.Users namespace osu.Game.Users
{ {
@ -43,6 +44,8 @@ namespace osu.Game.Users
this.user = user; this.user = user;
FillFlowContainer infoContainer;
Height = height - status_height; Height = height - status_height;
Masking = true; Masking = true;
CornerRadius = 5; CornerRadius = 5;
@ -100,7 +103,7 @@ namespace osu.Game.Users
TextSize = 18, TextSize = 18,
Font = @"Exo2.0-SemiBoldItalic", Font = @"Exo2.0-SemiBoldItalic",
}, },
new FillFlowContainer infoContainer = new FillFlowContainer
{ {
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft, Origin = Anchor.BottomLeft,
@ -115,16 +118,6 @@ namespace osu.Game.Users
Width = 30f, Width = 30f,
RelativeSizeAxes = Axes.Y, RelativeSizeAxes = Axes.Y,
}, },
new Container
{
Width = 40f,
RelativeSizeAxes = Axes.Y,
},
new CircularContainer
{
Width = 20f,
RelativeSizeAxes = Axes.Y,
},
}, },
}, },
}, },
@ -171,6 +164,13 @@ namespace osu.Game.Users
}, },
}, },
}; };
if (user.IsSupporter)
infoContainer.Add(new SupporterIcon
{
RelativeSizeAxes = Axes.Y,
Width = 20f,
});
} }
[BackgroundDependencyLoader(permitNulls: true)] [BackgroundDependencyLoader(permitNulls: true)]
@ -219,5 +219,53 @@ namespace osu.Game.Users
{ {
new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile), new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile),
}; };
private class SupporterIcon : CircularContainer
{
private readonly Box background;
public SupporterIcon()
{
Masking = true;
Children = new Drawable[]
{
new Box { RelativeSizeAxes = Axes.Both },
new CircularContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.8f),
Masking = true,
Children = new Drawable[]
{
background = new Box { RelativeSizeAxes = Axes.Both },
new Triangles
{
TriangleScale = 0.2f,
ColourLight = OsuColour.FromHex(@"ff7db7"),
ColourDark = OsuColour.FromHex(@"de5b95"),
RelativeSizeAxes = Axes.Both,
Velocity = 0.3f,
},
}
},
new SpriteIcon
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Icon = FontAwesome.fa_heart,
Scale = new Vector2(0.45f),
}
};
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
background.Colour = colours.Pink;
}
}
} }
} }