mirror of
https://github.com/ppy/osu.git
synced 2026-05-14 23:53:20 +08:00
Compare commits
252 Commits
2018.830.0
...
2018.920.0
@@ -24,7 +24,9 @@ Clone the repository including submodules
|
||||
Build and run
|
||||
|
||||
- Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included)
|
||||
- From command line using `dotnet run --project osu.Desktop`
|
||||
- From command line using `dotnet run --project osu.Desktop`. When building for non-development purposes, add `-c Release` to gain higher performance.
|
||||
|
||||
Note: If you run from command line under linux, you will need to prefix the output folder to your `LD_LIBRARY_PATH`. See `.vscode/launch.json` for an example
|
||||
|
||||
If you run into issues building you may need to restore nuget packages (commonly via `dotnet restore`). Visual Studio Code users must run `Restore` task from debug tab before attempt to build.
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -32,7 +31,7 @@ namespace osu.Desktop.Overlays
|
||||
public override bool HandleMouseInput => false;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host)
|
||||
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config, GameHost host)
|
||||
{
|
||||
notificationOverlay = notification;
|
||||
this.config = config;
|
||||
@@ -87,7 +86,7 @@ namespace osu.Desktop.Overlays
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Texture = await textures.GetAsync(@"Menu/dev-build-footer"),
|
||||
Texture = textures.Get(@"Menu/dev-build-footer"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Package References">
|
||||
<PackageReference Include="System.IO.Packaging" Version="4.5.0" />
|
||||
<PackageReference Include="ppy.squirrel.windows" Version="1.8.0.5" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.2" />
|
||||
<PackageReference Include="ppy.squirrel.windows" Version="1.8.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.3" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="Resources">
|
||||
<EmbeddedResource Include="lazer.ico" />
|
||||
|
||||
@@ -74,42 +74,42 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
|
||||
private void initialiseHyperDash(List<CatchHitObject> objects)
|
||||
{
|
||||
// todo: add difficulty adjust.
|
||||
double halfCatcherWidth = CatcherArea.CATCHER_SIZE * (objects.FirstOrDefault()?.Scale ?? 1) / CatchPlayfield.BASE_WIDTH / 2;
|
||||
List<CatchHitObject> objectWithDroplets = new List<CatchHitObject>();
|
||||
|
||||
foreach (var currentObject in objects)
|
||||
{
|
||||
if (currentObject is Fruit)
|
||||
objectWithDroplets.Add(currentObject);
|
||||
if (currentObject is JuiceStream)
|
||||
foreach (var currentJuiceElement in currentObject.NestedHitObjects)
|
||||
if (!(currentJuiceElement is TinyDroplet))
|
||||
objectWithDroplets.Add((CatchHitObject)currentJuiceElement);
|
||||
}
|
||||
|
||||
objectWithDroplets.Sort((h1, h2) => h1.StartTime.CompareTo(h2.StartTime));
|
||||
|
||||
double halfCatcherWidth = CatcherArea.GetCatcherSize(Beatmap.BeatmapInfo.BaseDifficulty) / 2;
|
||||
int lastDirection = 0;
|
||||
double lastExcess = halfCatcherWidth;
|
||||
|
||||
int objCount = objects.Count;
|
||||
|
||||
for (int i = 0; i < objCount - 1; i++)
|
||||
for (int i = 0; i < objectWithDroplets.Count - 1; i++)
|
||||
{
|
||||
CatchHitObject currentObject = objects[i];
|
||||
|
||||
// not needed?
|
||||
// if (currentObject is TinyDroplet) continue;
|
||||
|
||||
CatchHitObject nextObject = objects[i + 1];
|
||||
|
||||
// while (nextObject is TinyDroplet)
|
||||
// {
|
||||
// if (++i == objCount - 1) break;
|
||||
// nextObject = objects[i + 1];
|
||||
// }
|
||||
CatchHitObject currentObject = objectWithDroplets[i];
|
||||
CatchHitObject nextObject = objectWithDroplets[i + 1];
|
||||
|
||||
int thisDirection = nextObject.X > currentObject.X ? 1 : -1;
|
||||
double timeToNext = nextObject.StartTime - ((currentObject as IHasEndTime)?.EndTime ?? currentObject.StartTime) - 4;
|
||||
double timeToNext = nextObject.StartTime - currentObject.StartTime;
|
||||
double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth);
|
||||
|
||||
if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext)
|
||||
float distanceToHyper = (float)(timeToNext * CatcherArea.Catcher.BASE_SPEED - distanceToNext);
|
||||
if (distanceToHyper < 0)
|
||||
{
|
||||
currentObject.HyperDashTarget = nextObject;
|
||||
lastExcess = halfCatcherWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
//currentObject.DistanceToHyperDash = timeToNext - distanceToNext;
|
||||
lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, halfCatcherWidth);
|
||||
currentObject.DistanceToHyperDash = distanceToHyper;
|
||||
lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth);
|
||||
}
|
||||
|
||||
lastDirection = thisDirection;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
|
||||
public int IndexInBeatmap { get; set; }
|
||||
|
||||
public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(IndexInBeatmap % 4);
|
||||
public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(ComboIndex % 4);
|
||||
|
||||
public virtual bool NewCombo { get; set; }
|
||||
|
||||
@@ -27,7 +27,9 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The distance for a fruit to to next hyper if it's not a hyper.
|
||||
/// Difference between the distance to the next object
|
||||
/// and the distance that would have triggered a hyper dash.
|
||||
/// A value close to 0 indicates a difficult jump (for difficulty calculation).
|
||||
/// </summary>
|
||||
public float DistanceToHyperDash { get; set; }
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
private readonly CatcherArea catcherArea;
|
||||
|
||||
protected override bool UserScrollSpeedAdjustment => false;
|
||||
|
||||
public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation)
|
||||
: base(BASE_WIDTH)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -108,6 +107,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj);
|
||||
|
||||
public static float GetCatcherSize(BeatmapDifficulty difficulty)
|
||||
{
|
||||
return CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5);
|
||||
}
|
||||
|
||||
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
||||
{
|
||||
/// <summary>
|
||||
@@ -408,9 +412,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
/// </summary>
|
||||
public void Explode()
|
||||
{
|
||||
var fruit = caughtFruit.ToArray();
|
||||
|
||||
foreach (var f in fruit)
|
||||
foreach (var f in caughtFruit.ToArray())
|
||||
Explode(f);
|
||||
}
|
||||
|
||||
@@ -423,15 +425,15 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
fruit.Anchor = Anchor.TopLeft;
|
||||
fruit.Position = caughtFruit.ToSpaceOfOtherDrawable(fruit.DrawPosition, ExplodingFruitTarget);
|
||||
|
||||
caughtFruit.Remove(fruit);
|
||||
if (!caughtFruit.Remove(fruit))
|
||||
// we may have already been removed by a previous operation (due to the weird OnLoadComplete scheduling).
|
||||
// this avoids a crash on potentially attempting to Add a fruit to ExplodingFruitTarget twice.
|
||||
return;
|
||||
|
||||
ExplodingFruitTarget.Add(fruit);
|
||||
}
|
||||
|
||||
fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine)
|
||||
.Then()
|
||||
.MoveToY(fruit.Y + 50, 500, Easing.InSine);
|
||||
|
||||
fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine).Then().MoveToY(fruit.Y + 50, 500, Easing.InSine);
|
||||
fruit.MoveToX(fruit.X + originalX * 6, 1000);
|
||||
fruit.FadeOut(750);
|
||||
|
||||
@@ -449,9 +451,9 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Texture = await textures.GetAsync(@"Play/Catch/fruit-catcher-idle");
|
||||
Texture = textures.Get(@"Play/Catch/fruit-catcher-idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2;
|
||||
}
|
||||
|
||||
protected void BeginHold()
|
||||
{
|
||||
holdStartTime = Time.Current;
|
||||
bodyPiece.Hitting = true;
|
||||
}
|
||||
|
||||
protected void EndHold()
|
||||
{
|
||||
holdStartTime = null;
|
||||
bodyPiece.Hitting = false;
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
// Make sure the action happened within the body of the hold note
|
||||
@@ -123,8 +135,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
// The user has pressed during the body of the hold note, after the head note and its hit windows have passed
|
||||
// and within the limited range of the above if-statement. This state will be managed by the head note if the
|
||||
// user has pressed during the hit windows of the head note.
|
||||
holdStartTime = Time.Current;
|
||||
|
||||
BeginHold();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,7 +148,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
if (action != Action.Value)
|
||||
return false;
|
||||
|
||||
holdStartTime = null;
|
||||
EndHold();
|
||||
|
||||
// If the key has been released too early, the user should not receive full score for the release
|
||||
if (!Tail.IsHit)
|
||||
@@ -170,7 +181,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
// The head note also handles early hits before the body, but we want accurate early hits to count as the body being held
|
||||
// The body doesn't handle these early early hits, so we have to explicitly set the holding state here
|
||||
holdNote.holdStartTime = Time.Current;
|
||||
holdNote.BeginHold();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||
foreground = new BufferedContainer
|
||||
{
|
||||
Blending = BlendingMode.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CacheDrawnFrameBuffer = true,
|
||||
Children = new Drawable[]
|
||||
@@ -73,6 +74,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get { return accentColour; }
|
||||
@@ -86,6 +88,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
public bool Hitting
|
||||
{
|
||||
get { return hitting; }
|
||||
set
|
||||
{
|
||||
hitting = value;
|
||||
updateAccentColour();
|
||||
}
|
||||
}
|
||||
|
||||
private Cached subtractionCache = new Cached();
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
@@ -118,13 +130,26 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
private bool hitting;
|
||||
|
||||
private void updateAccentColour()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
foreground.Colour = AccentColour.Opacity(0.9f);
|
||||
background.Colour = AccentColour.Opacity(0.6f);
|
||||
foreground.Colour = AccentColour.Opacity(0.5f);
|
||||
background.Colour = AccentColour.Opacity(0.7f);
|
||||
|
||||
const float animation_length = 50;
|
||||
|
||||
foreground.ClearTransforms(false, nameof(foreground.Colour));
|
||||
if (hitting)
|
||||
{
|
||||
// wait for the next sync point
|
||||
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
||||
using (foreground.BeginDelayedSequence(synchronisedOffset))
|
||||
foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(foreground.Colour, animation_length).Loop();
|
||||
}
|
||||
|
||||
subtractionCache.Invalidate();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@@ -77,7 +76,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
wasLeft = !wasLeft;
|
||||
}
|
||||
|
||||
osuInputManager.HandleCustomInput(new InputState(), state);
|
||||
state.Apply(osuInputManager.CurrentState, osuInputManager);
|
||||
}
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<OsuHitObject> rulesetContainer)
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects
|
||||
{
|
||||
public override string Name => "Transform";
|
||||
public override string ShortenedName => "TR";
|
||||
public override FontAwesome Icon => FontAwesome.fa_arrows;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "Everything rotates. EVERYTHING.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModWiggle) };
|
||||
|
||||
private float theta;
|
||||
|
||||
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||
{
|
||||
foreach (var drawable in drawables)
|
||||
{
|
||||
var hitObject = (OsuHitObject) drawable.HitObject;
|
||||
|
||||
float appearDistance = (float)(hitObject.TimePreempt - hitObject.TimeFadeIn) / 2;
|
||||
|
||||
Vector2 originalPosition = drawable.Position;
|
||||
Vector2 appearOffset = new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta)) * appearDistance;
|
||||
|
||||
//the - 1 and + 1 prevents the hit objects to appear in the wrong position.
|
||||
double appearTime = hitObject.StartTime - hitObject.TimePreempt - 1;
|
||||
double moveDuration = hitObject.TimePreempt + 1;
|
||||
|
||||
using (drawable.BeginAbsoluteSequence(appearTime, true))
|
||||
{
|
||||
drawable
|
||||
.MoveToOffset(appearOffset)
|
||||
.MoveTo(originalPosition, moveDuration, Easing.InOutSine);
|
||||
}
|
||||
|
||||
theta += (float) hitObject.TimeFadeIn / 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects
|
||||
{
|
||||
public override string Name => "Wiggle";
|
||||
public override string ShortenedName => "WG";
|
||||
public override FontAwesome Icon => FontAwesome.fa_certificate;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "They just won't stay still...";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModTransform) };
|
||||
|
||||
private const int wiggle_duration = 90; // (ms) Higher = fewer wiggles
|
||||
private const int wiggle_strength = 10; // Higher = stronger wiggles
|
||||
|
||||
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||
{
|
||||
foreach (var drawable in drawables)
|
||||
drawable.ApplyCustomUpdateState += drawableOnApplyCustomUpdateState;
|
||||
}
|
||||
|
||||
private void drawableOnApplyCustomUpdateState(DrawableHitObject drawable, ArmedState state)
|
||||
{
|
||||
var osuObject = (OsuHitObject)drawable.HitObject;
|
||||
Vector2 origin = drawable.Position;
|
||||
|
||||
Random objRand = new Random((int)osuObject.StartTime);
|
||||
|
||||
// Wiggle all objects during TimePreempt
|
||||
int amountWiggles = (int)osuObject.TimePreempt / wiggle_duration;
|
||||
|
||||
void wiggle()
|
||||
{
|
||||
float nextAngle = (float)(objRand.NextDouble() * 2 * Math.PI);
|
||||
float nextDist = (float)(objRand.NextDouble() * wiggle_strength);
|
||||
drawable.MoveTo(new Vector2((float)(nextDist * Math.Cos(nextAngle) + origin.X), (float)(nextDist * Math.Sin(nextAngle) + origin.Y)), wiggle_duration);
|
||||
}
|
||||
|
||||
for (int i = 0; i < amountWiggles; i++)
|
||||
using (drawable.BeginAbsoluteSequence(osuObject.StartTime - osuObject.TimePreempt + i * wiggle_duration, true))
|
||||
wiggle();
|
||||
|
||||
// Keep wiggling sliders and spinners for their duration
|
||||
if (!(osuObject is IHasEndTime endTime))
|
||||
return;
|
||||
|
||||
amountWiggles = (int)(endTime.Duration / wiggle_duration);
|
||||
|
||||
for (int i = 0; i < amountWiggles; i++)
|
||||
using (drawable.BeginAbsoluteSequence(osuObject.StartTime + i * wiggle_duration, true))
|
||||
wiggle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject>
|
||||
{
|
||||
public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt;
|
||||
public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Clock?.CurrentTime >= HitObject.StartTime - HitObject.TimePreempt;
|
||||
|
||||
private readonly ShakeContainer shakeContainer;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -13,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
public class DefaultCirclePiece : Container
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Children = new Drawable[]
|
||||
@@ -22,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Texture = await textures.GetAsync(@"Play/osu/disc"),
|
||||
Texture = textures.Get(@"Play/osu/disc"),
|
||||
},
|
||||
new TrianglesPiece
|
||||
{
|
||||
|
||||
@@ -7,14 +7,15 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.ES30;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
@@ -43,6 +44,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
public double? SnakedEnd { get; private set; }
|
||||
|
||||
private Color4 accentColour = Color4.White;
|
||||
|
||||
/// <summary>
|
||||
/// Used to colour the path.
|
||||
/// </summary>
|
||||
@@ -61,6 +63,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
|
||||
private Color4 borderColour = Color4.White;
|
||||
|
||||
/// <summary>
|
||||
/// Used to colour the path border.
|
||||
/// </summary>
|
||||
@@ -85,6 +88,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
private Vector2 topLeftOffset;
|
||||
|
||||
private readonly Slider slider;
|
||||
|
||||
public SliderBody(Slider s)
|
||||
{
|
||||
slider = s;
|
||||
@@ -139,8 +143,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
var texture = new Texture(textureWidth, 1);
|
||||
|
||||
//initialise background
|
||||
var raw = new RawTexture(textureWidth, 1);
|
||||
var bytes = raw.Data;
|
||||
var raw = new Image<Rgba32>(textureWidth, 1);
|
||||
|
||||
const float aa_portion = 0.02f;
|
||||
const float border_portion = 0.128f;
|
||||
@@ -155,19 +158,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
|
||||
if (progress <= border_portion)
|
||||
{
|
||||
bytes[i * 4] = (byte)(BorderColour.R * 255);
|
||||
bytes[i * 4 + 1] = (byte)(BorderColour.G * 255);
|
||||
bytes[i * 4 + 2] = (byte)(BorderColour.B * 255);
|
||||
bytes[i * 4 + 3] = (byte)(Math.Min(progress / aa_portion, 1) * (BorderColour.A * 255));
|
||||
raw[i, 0] = new Rgba32(BorderColour.R, BorderColour.G, BorderColour.B, Math.Min(progress / aa_portion, 1) * BorderColour.A);
|
||||
}
|
||||
else
|
||||
{
|
||||
progress -= border_portion;
|
||||
|
||||
bytes[i * 4] = (byte)(AccentColour.R * 255);
|
||||
bytes[i * 4 + 1] = (byte)(AccentColour.G * 255);
|
||||
bytes[i * 4 + 2] = (byte)(AccentColour.B * 255);
|
||||
bytes[i * 4 + 3] = (byte)((opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * (AccentColour.A * 255));
|
||||
raw[i, 0] = new Rgba32(AccentColour.R, AccentColour.G, AccentColour.B,
|
||||
(opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * AccentColour.A);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModRelax(),
|
||||
new OsuModAutopilot(),
|
||||
};
|
||||
case ModType.Fun:
|
||||
return new Mod[] {
|
||||
new OsuModTransform(),
|
||||
new OsuModWiggle(),
|
||||
};
|
||||
default:
|
||||
return new Mod[] { };
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.OpenGL.Buffers;
|
||||
@@ -80,10 +79,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(ShaderManager shaders, TextureStore textures)
|
||||
private void load(ShaderManager shaders, TextureStore textures)
|
||||
{
|
||||
shader = shaders?.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE);
|
||||
texture = await textures.GetAsync(@"Cursor/cursortrail");
|
||||
texture = textures.Get(@"Cursor/cursortrail");
|
||||
Scale = new Vector2(1 / texture.ScaleAdjust);
|
||||
}
|
||||
|
||||
@@ -217,7 +216,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
Texture.DrawQuad(
|
||||
new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y),
|
||||
DrawInfo.Colour,
|
||||
DrawColourInfo.Colour,
|
||||
null,
|
||||
v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using OpenTK;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -131,12 +130,12 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures, OsuColour colours)
|
||||
private void load(TextureStore textures, OsuColour colours)
|
||||
{
|
||||
rim.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-outer");
|
||||
rimHit.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-outer-hit");
|
||||
centre.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-inner");
|
||||
centreHit.Texture = await textures.GetAsync(@"Play/Taiko/taiko-drum-inner-hit");
|
||||
rim.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer");
|
||||
rimHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-outer-hit");
|
||||
centre.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner");
|
||||
centreHit.Texture = textures.Get(@"Play/Taiko/taiko-drum-inner-hit");
|
||||
|
||||
rimHit.Colour = colours.Blue;
|
||||
centreHit.Colour = colours.Pink;
|
||||
|
||||
@@ -8,14 +8,14 @@ using System.Linq;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.EventArgs;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Screens.Play;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[Description("player pause/fail screens")]
|
||||
public class TestCaseGameplayMenuOverlay : OsuTestCase
|
||||
public class TestCaseGameplayMenuOverlay : ManualInputManagerTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(FailOverlay), typeof(PauseContainer) };
|
||||
|
||||
@@ -73,12 +73,18 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
AddStep("Hover first button", () => failOverlay.Buttons.First().TriggerOnMouseMove(null));
|
||||
AddStep("Hover first button", () => InputManager.MoveMouseTo(failOverlay.Buttons.First()));
|
||||
AddStep("Hide overlay", () => failOverlay.Hide());
|
||||
|
||||
AddAssert("Overlay state is reset", () => !failOverlay.Buttons.Any(b => b.Selected));
|
||||
}
|
||||
|
||||
private void press(Key key)
|
||||
{
|
||||
InputManager.PressKey(key);
|
||||
InputManager.ReleaseKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that pressing enter after an overlay shows doesn't trigger an event because a selection hasn't occurred.
|
||||
/// </summary>
|
||||
@@ -86,7 +92,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
AddStep("Press enter", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Enter }));
|
||||
AddStep("Press enter", () => press(Key.Enter));
|
||||
AddAssert("Overlay still open", () => pauseOverlay.State == Visibility.Visible);
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
@@ -99,7 +105,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
AddStep("Up arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up }));
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => pauseOverlay.Buttons.Last().Selected);
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
@@ -112,7 +118,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
|
||||
AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }));
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected);
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
@@ -125,11 +131,11 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up }));
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected);
|
||||
AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up }));
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected);
|
||||
AddStep("Up arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up }));
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected);
|
||||
|
||||
AddStep("Hide overlay", () => failOverlay.Hide());
|
||||
@@ -142,11 +148,11 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
AddStep("Show overlay", () => failOverlay.Show());
|
||||
|
||||
AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }));
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected);
|
||||
AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }));
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("Last button selected", () => failOverlay.Buttons.Last().Selected);
|
||||
AddStep("Down arrow", () => failOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }));
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => failOverlay.Buttons.First().Selected);
|
||||
|
||||
AddStep("Hide overlay", () => failOverlay.Hide());
|
||||
@@ -161,8 +167,8 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
var secondButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
|
||||
AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }));
|
||||
AddStep("Hover second button", () => secondButton.TriggerOnMouseMove(null));
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton));
|
||||
AddAssert("First button not selected", () => !pauseOverlay.Buttons.First().Selected);
|
||||
AddAssert("Second button selected", () => secondButton.Selected);
|
||||
|
||||
@@ -174,12 +180,16 @@ namespace osu.Game.Tests.Visual
|
||||
/// </summary>
|
||||
private void testKeySelectionAfterMouseSelection()
|
||||
{
|
||||
AddStep("Show overlay", () => pauseOverlay.Show());
|
||||
AddStep("Show overlay", () =>
|
||||
{
|
||||
pauseOverlay.Show();
|
||||
InputManager.MoveMouseTo(Vector2.Zero);
|
||||
});
|
||||
|
||||
var secondButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
|
||||
AddStep("Hover second button", () => secondButton.TriggerOnMouseMove(null));
|
||||
AddStep("Up arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Up }));
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton));
|
||||
AddStep("Up arrow", () => press(Key.Up));
|
||||
AddAssert("Second button not selected", () => !secondButton.Selected);
|
||||
AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected);
|
||||
|
||||
@@ -195,9 +205,9 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
var secondButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
|
||||
AddStep("Hover second button", () => secondButton.TriggerOnMouseMove(null));
|
||||
AddStep("Unhover second button", () => secondButton.TriggerOnHoverLost(null));
|
||||
AddStep("Down arrow", () => pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down }));
|
||||
AddStep("Hover second button", () => InputManager.MoveMouseTo(secondButton));
|
||||
AddStep("Unhover second button", () => InputManager.MoveMouseTo(Vector2.Zero));
|
||||
AddStep("Down arrow", () => press(Key.Down));
|
||||
AddAssert("First button selected", () => pauseOverlay.Buttons.First().Selected); // Initial state condition
|
||||
|
||||
AddStep("Hide overlay", () => pauseOverlay.Hide());
|
||||
@@ -218,7 +228,7 @@ namespace osu.Game.Tests.Visual
|
||||
var lastAction = pauseOverlay.OnRetry;
|
||||
pauseOverlay.OnRetry = () => triggered = true;
|
||||
|
||||
retryButton.TriggerOnClick();
|
||||
retryButton.Click();
|
||||
pauseOverlay.OnRetry = lastAction;
|
||||
});
|
||||
|
||||
@@ -235,23 +245,28 @@ namespace osu.Game.Tests.Visual
|
||||
|
||||
AddStep("Select second button", () =>
|
||||
{
|
||||
pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down });
|
||||
pauseOverlay.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Down });
|
||||
press(Key.Down);
|
||||
press(Key.Down);
|
||||
});
|
||||
|
||||
var retryButton = pauseOverlay.Buttons.Skip(1).First();
|
||||
|
||||
bool triggered = false;
|
||||
Action lastAction = null;
|
||||
AddStep("Press enter", () =>
|
||||
{
|
||||
var lastAction = pauseOverlay.OnRetry;
|
||||
lastAction = pauseOverlay.OnRetry;
|
||||
pauseOverlay.OnRetry = () => triggered = true;
|
||||
|
||||
retryButton.TriggerOnKeyDown(null, new KeyDownEventArgs { Key = Key.Enter });
|
||||
pauseOverlay.OnRetry = lastAction;
|
||||
press(Key.Enter);
|
||||
});
|
||||
|
||||
AddAssert("Action was triggered", () => triggered);
|
||||
AddAssert("Action was triggered", () =>
|
||||
{
|
||||
if (lastAction != null)
|
||||
{
|
||||
pauseOverlay.OnRetry = lastAction;
|
||||
lastAction = null;
|
||||
}
|
||||
return triggered;
|
||||
});
|
||||
AddAssert("Overlay is closed", () => pauseOverlay.State == Visibility.Hidden);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,45 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Screens.Play;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseKeyCounter : OsuTestCase
|
||||
public class TestCaseKeyCounter : ManualInputManagerTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(KeyCounterKeyboard),
|
||||
typeof(KeyCounterMouse),
|
||||
typeof(KeyCounterCollection)
|
||||
};
|
||||
|
||||
public TestCaseKeyCounter()
|
||||
{
|
||||
KeyCounterKeyboard rewindTestKeyCounterKeyboard;
|
||||
KeyCounterCollection kc = new KeyCounterCollection
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Children = new KeyCounter[]
|
||||
{
|
||||
new KeyCounterKeyboard(Key.Z),
|
||||
rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(Key.X),
|
||||
new KeyCounterKeyboard(Key.X),
|
||||
new KeyCounterMouse(MouseButton.Left),
|
||||
new KeyCounterMouse(MouseButton.Right),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
AddStep("Add random", () =>
|
||||
{
|
||||
Key key = (Key)((int)Key.A + RNG.Next(26));
|
||||
@@ -34,7 +47,57 @@ namespace osu.Game.Tests.Visual
|
||||
});
|
||||
AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v);
|
||||
|
||||
Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key;
|
||||
double time1 = 0;
|
||||
|
||||
AddStep($"Press {testKey} key", () =>
|
||||
{
|
||||
InputManager.PressKey(testKey);
|
||||
InputManager.ReleaseKey(testKey);
|
||||
});
|
||||
|
||||
AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1);
|
||||
|
||||
AddStep($"Press {testKey} key", () =>
|
||||
{
|
||||
InputManager.PressKey(testKey);
|
||||
InputManager.ReleaseKey(testKey);
|
||||
time1 = Clock.CurrentTime;
|
||||
});
|
||||
|
||||
AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 2);
|
||||
|
||||
IFrameBasedClock oldClock = null;
|
||||
|
||||
AddStep($"Rewind {testKey} counter once", () =>
|
||||
{
|
||||
oldClock = rewindTestKeyCounterKeyboard.Clock;
|
||||
rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(time1 - 10));
|
||||
});
|
||||
|
||||
AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 1);
|
||||
|
||||
AddStep($"Rewind {testKey} counter to zero", () => rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(0)));
|
||||
|
||||
AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 0);
|
||||
|
||||
AddStep("Restore clock", () => rewindTestKeyCounterKeyboard.Clock = oldClock);
|
||||
|
||||
Add(kc);
|
||||
}
|
||||
|
||||
private class FixedClock : IClock
|
||||
{
|
||||
private readonly double time;
|
||||
|
||||
public FixedClock(double time)
|
||||
{
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public double CurrentTime => time;
|
||||
public double Rate => 1;
|
||||
public bool IsRunning => false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,13 +27,15 @@ namespace osu.Game.Beatmaps
|
||||
[JsonProperty("id")]
|
||||
public int? OnlineBeatmapID
|
||||
{
|
||||
get { return onlineBeatmapID; }
|
||||
set { onlineBeatmapID = value > 0 ? value : null; }
|
||||
get => onlineBeatmapID;
|
||||
set => onlineBeatmapID = value > 0 ? value : null;
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public int BeatmapSetInfoID { get; set; }
|
||||
|
||||
public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None;
|
||||
|
||||
[Required]
|
||||
public BeatmapSetInfo BeatmapSet { get; set; }
|
||||
|
||||
@@ -82,7 +84,7 @@ namespace osu.Game.Beatmaps
|
||||
[JsonIgnore]
|
||||
public string StoredBookmarks
|
||||
{
|
||||
get { return string.Join(",", Bookmarks); }
|
||||
get => string.Join(",", Bookmarks);
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
@@ -93,8 +95,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
Bookmarks = value.Split(',').Select(v =>
|
||||
{
|
||||
int val;
|
||||
bool result = int.TryParse(v, out val);
|
||||
bool result = int.TryParse(v, out int val);
|
||||
return new { result, val };
|
||||
}).Where(p => p.result).Select(p => p.val).ToArray();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
@@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
@@ -62,6 +63,8 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public override string[] HandledExtensions => new[] { ".osz" };
|
||||
|
||||
protected override string ImportFromStablePath => "Songs";
|
||||
|
||||
private readonly RulesetStore rulesets;
|
||||
|
||||
private readonly BeatmapStore beatmaps;
|
||||
@@ -72,11 +75,6 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
private readonly List<DownloadBeatmapSetRequest> currentDownloads = new List<DownloadBeatmapSetRequest>();
|
||||
|
||||
/// <summary>
|
||||
/// Set a storage with access to an osu-stable install for import purposes.
|
||||
/// </summary>
|
||||
public Func<Storage> GetStableStorage { private get; set; }
|
||||
|
||||
public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, AudioManager audioManager, IIpcHost importHost = null)
|
||||
: base(storage, contextFactory, new BeatmapStore(contextFactory), importHost)
|
||||
{
|
||||
@@ -103,6 +101,11 @@ namespace osu.Game.Beatmaps
|
||||
b.BeatmapSet = beatmapSet;
|
||||
}
|
||||
|
||||
validateOnlineIds(beatmapSet.Beatmaps);
|
||||
|
||||
foreach (BeatmapInfo b in beatmapSet.Beatmaps)
|
||||
fetchAndPopulateOnlineValues(b, beatmapSet.Beatmaps);
|
||||
|
||||
// check if a set already exists with the same online id, delete if it does.
|
||||
if (beatmapSet.OnlineBeatmapSetID != null)
|
||||
{
|
||||
@@ -114,11 +117,6 @@ namespace osu.Game.Beatmaps
|
||||
Logger.Log($"Found existing beatmap set with same OnlineBeatmapSetID ({beatmapSet.OnlineBeatmapSetID}). It has been purged.", LoggingTarget.Database);
|
||||
}
|
||||
}
|
||||
|
||||
validateOnlineIds(beatmapSet.Beatmaps);
|
||||
|
||||
foreach (BeatmapInfo b in beatmapSet.Beatmaps)
|
||||
fetchAndPopulateOnlineIDs(b, beatmapSet.Beatmaps);
|
||||
}
|
||||
|
||||
private void validateOnlineIds(List<BeatmapInfo> beatmaps)
|
||||
@@ -195,7 +193,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
downloadNotification.CompletionClickAction = () =>
|
||||
{
|
||||
PresentBeatmap?.Invoke(importedBeatmap);
|
||||
PresentCompletedImport(importedBeatmap.Yield());
|
||||
return true;
|
||||
};
|
||||
downloadNotification.State = ProgressNotificationState.Completed;
|
||||
@@ -231,6 +229,12 @@ namespace osu.Game.Beatmaps
|
||||
BeatmapDownloadBegan?.Invoke(request);
|
||||
}
|
||||
|
||||
protected override void PresentCompletedImport(IEnumerable<BeatmapSetInfo> imported)
|
||||
{
|
||||
base.PresentCompletedImport(imported);
|
||||
PresentBeatmap?.Invoke(imported.LastOrDefault());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an existing download request if it exists.
|
||||
/// </summary>
|
||||
@@ -311,27 +315,6 @@ namespace osu.Game.Beatmaps
|
||||
/// <returns>Results from the provided query.</returns>
|
||||
public IQueryable<BeatmapInfo> QueryBeatmaps(Expression<Func<BeatmapInfo, bool>> query) => beatmaps.Beatmaps.AsNoTracking().Where(query);
|
||||
|
||||
/// <summary>
|
||||
/// Denotes whether an osu-stable installation is present to perform automated imports from.
|
||||
/// </summary>
|
||||
public bool StableInstallationAvailable => GetStableStorage?.Invoke() != null;
|
||||
|
||||
/// <summary>
|
||||
/// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future.
|
||||
/// </summary>
|
||||
public Task ImportFromStable()
|
||||
{
|
||||
var stable = GetStableStorage?.Invoke();
|
||||
|
||||
if (stable == null)
|
||||
{
|
||||
Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
return Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs").Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a SHA-2 hash from the provided archive based on contained beatmap (.osu) file content.
|
||||
/// </summary>
|
||||
@@ -405,21 +388,22 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query the API to populate mising OnlineBeatmapID / OnlineBeatmapSetID properties.
|
||||
/// Query the API to populate missing values like OnlineBeatmapID / OnlineBeatmapSetID or (Rank-)Status.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to populate.</param>
|
||||
/// <param name="otherBeatmaps">The other beatmaps contained within this set.</param>
|
||||
/// <param name="force">Whether to re-query if the provided beatmap already has populated values.</param>
|
||||
/// <returns>True if population was successful.</returns>
|
||||
private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, IEnumerable<BeatmapInfo> otherBeatmaps, bool force = false)
|
||||
private bool fetchAndPopulateOnlineValues(BeatmapInfo beatmap, IEnumerable<BeatmapInfo> otherBeatmaps, bool force = false)
|
||||
{
|
||||
if (api?.State != APIState.Online)
|
||||
return false;
|
||||
|
||||
if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null)
|
||||
if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null
|
||||
&& beatmap.Status != BeatmapSetOnlineStatus.None && beatmap.BeatmapSet.Status != BeatmapSetOnlineStatus.None)
|
||||
return true;
|
||||
|
||||
Logger.Log("Attempting online lookup for IDs...", LoggingTarget.Database);
|
||||
Logger.Log("Attempting online lookup for the missing values...", LoggingTarget.Database);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -431,6 +415,9 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
Logger.Log($"Successfully mapped to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.", LoggingTarget.Database);
|
||||
|
||||
beatmap.Status = res.Status;
|
||||
beatmap.BeatmapSet.Status = res.BeatmapSet.Status;
|
||||
|
||||
if (otherBeatmaps.Any(b => b.OnlineBeatmapID == res.OnlineBeatmapID))
|
||||
{
|
||||
Logger.Log("Another beatmap in the same set already mapped to this ID. We'll skip adding it this time.", LoggingTarget.Database);
|
||||
@@ -439,6 +426,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID;
|
||||
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -10,7 +10,6 @@ using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.Graphics.Textures;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Storyboards;
|
||||
|
||||
@@ -45,6 +44,10 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath;
|
||||
|
||||
private LargeTextureStore textureStore;
|
||||
|
||||
protected override bool BackgroundStillValid(Texture b) => false; // bypass lazy logic. we want to return a new background each time for refcounting purposes.
|
||||
|
||||
protected override Texture GetBackground()
|
||||
{
|
||||
if (Metadata?.BackgroundFile == null)
|
||||
@@ -52,7 +55,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
try
|
||||
{
|
||||
return new LargeTextureStore(new RawTextureLoaderStore(store)).Get(getPathForFile(Metadata.BackgroundFile));
|
||||
return (textureStore ?? (textureStore = new LargeTextureStore(new TextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -73,6 +76,14 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
public override void TransferTo(WorkingBeatmap other)
|
||||
{
|
||||
base.TransferTo(other);
|
||||
|
||||
if (other is BeatmapManagerWorkingBeatmap owb && textureStore != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo))
|
||||
owb.textureStore = textureStore;
|
||||
}
|
||||
|
||||
protected override Waveform GetWaveform()
|
||||
{
|
||||
try
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
@@ -44,6 +45,25 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public virtual void PostProcess()
|
||||
{
|
||||
void updateNestedCombo(HitObject obj, int comboIndex, int indexInCurrentCombo)
|
||||
{
|
||||
if (obj is IHasComboInformation objectComboInfo)
|
||||
{
|
||||
objectComboInfo.ComboIndex = comboIndex;
|
||||
objectComboInfo.IndexInCurrentCombo = indexInCurrentCombo;
|
||||
foreach (var nestedObject in obj.NestedHitObjects)
|
||||
updateNestedCombo(nestedObject, comboIndex, indexInCurrentCombo);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var hitObject in Beatmap.HitObjects)
|
||||
{
|
||||
if (hitObject is IHasComboInformation objectComboInfo)
|
||||
{
|
||||
foreach (var nested in hitObject.NestedHitObjects)
|
||||
updateNestedCombo(nested, objectComboInfo.ComboIndex, objectComboInfo.IndexInCurrentCombo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public int? OnlineBeatmapSetID
|
||||
{
|
||||
get { return onlineBeatmapSetID; }
|
||||
set { onlineBeatmapSetID = value > 0 ? value : null; }
|
||||
get => onlineBeatmapSetID;
|
||||
set => onlineBeatmapSetID = value > 0 ? value : null;
|
||||
}
|
||||
|
||||
public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None;
|
||||
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
|
||||
public List<BeatmapInfo> Beatmaps { get; set; }
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
@@ -24,7 +23,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
string resource = null;
|
||||
|
||||
@@ -42,7 +41,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
}
|
||||
|
||||
if (resource != null)
|
||||
Texture = await textures.GetAsync(resource);
|
||||
Texture = textures.Get(resource);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@@ -14,20 +13,35 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
private readonly OsuSpriteText statusText;
|
||||
|
||||
private BeatmapSetOnlineStatus status = BeatmapSetOnlineStatus.None;
|
||||
private BeatmapSetOnlineStatus status;
|
||||
|
||||
public BeatmapSetOnlineStatus Status
|
||||
{
|
||||
get { return status; }
|
||||
get => status;
|
||||
set
|
||||
{
|
||||
if (value == status) return;
|
||||
if (status == value)
|
||||
return;
|
||||
status = value;
|
||||
|
||||
statusText.Text = Enum.GetName(typeof(BeatmapSetOnlineStatus), Status)?.ToUpperInvariant();
|
||||
Alpha = value == BeatmapSetOnlineStatus.None ? 0 : 1;
|
||||
statusText.Text = value.ToString().ToUpperInvariant();
|
||||
}
|
||||
}
|
||||
|
||||
public BeatmapSetOnlineStatusPill(float textSize, MarginPadding textPadding)
|
||||
public float TextSize
|
||||
{
|
||||
get => statusText.TextSize;
|
||||
set => statusText.TextSize = value;
|
||||
}
|
||||
|
||||
public MarginPadding TextPadding
|
||||
{
|
||||
get => statusText.Padding;
|
||||
set => statusText.Padding = value;
|
||||
}
|
||||
|
||||
public BeatmapSetOnlineStatusPill()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Masking = true;
|
||||
@@ -45,10 +59,10 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = @"Exo2.0-Bold",
|
||||
TextSize = textSize,
|
||||
Padding = textPadding,
|
||||
},
|
||||
};
|
||||
|
||||
Status = BeatmapSetOnlineStatus.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@ using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Game.Storyboards;
|
||||
using osu.Framework.IO.File;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
@@ -38,12 +38,26 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
Mods.ValueChanged += mods => applyRateAdjustments();
|
||||
|
||||
beatmap = new AsyncLazy<IBeatmap>(populateBeatmap);
|
||||
background = new AsyncLazy<Texture>(populateBackground, b => b == null || !b.IsDisposed);
|
||||
track = new AsyncLazy<Track>(populateTrack);
|
||||
waveform = new AsyncLazy<Waveform>(populateWaveform);
|
||||
storyboard = new AsyncLazy<Storyboard>(populateStoryboard);
|
||||
skin = new AsyncLazy<Skin>(populateSkin);
|
||||
beatmap = new RecyclableLazy<IBeatmap>(() =>
|
||||
{
|
||||
var b = GetBeatmap() ?? new Beatmap();
|
||||
// use the database-backed info.
|
||||
b.BeatmapInfo = BeatmapInfo;
|
||||
return b;
|
||||
});
|
||||
|
||||
track = new RecyclableLazy<Track>(() =>
|
||||
{
|
||||
// we want to ensure that we always have a track, even if it's a fake one.
|
||||
var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap);
|
||||
applyRateAdjustments(t);
|
||||
return t;
|
||||
});
|
||||
|
||||
background = new RecyclableLazy<Texture>(GetBackground, BackgroundStillValid);
|
||||
waveform = new RecyclableLazy<Waveform>(GetWaveform);
|
||||
storyboard = new RecyclableLazy<Storyboard>(GetStoryboard);
|
||||
skin = new RecyclableLazy<Skin>(GetSkin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,28 +72,6 @@ namespace osu.Game.Beatmaps
|
||||
return path;
|
||||
}
|
||||
|
||||
protected abstract IBeatmap GetBeatmap();
|
||||
protected abstract Texture GetBackground();
|
||||
protected abstract Track GetTrack();
|
||||
protected virtual Skin GetSkin() => new DefaultSkin();
|
||||
protected virtual Waveform GetWaveform() => new Waveform();
|
||||
protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo };
|
||||
|
||||
public bool BeatmapLoaded => beatmap.IsResultAvailable;
|
||||
public IBeatmap Beatmap => beatmap.Value.Result;
|
||||
public Task<IBeatmap> GetBeatmapAsync() => beatmap.Value;
|
||||
private readonly AsyncLazy<IBeatmap> beatmap;
|
||||
|
||||
private IBeatmap populateBeatmap()
|
||||
{
|
||||
var b = GetBeatmap() ?? new Beatmap();
|
||||
|
||||
// use the database-backed info.
|
||||
b.BeatmapInfo = BeatmapInfo;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a playable <see cref="IBeatmap"/> from <see cref="Beatmap"/> using the applicable converters for a specific <see cref="RulesetInfo"/>.
|
||||
/// <para>
|
||||
@@ -136,62 +128,53 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public override string ToString() => BeatmapInfo.ToString();
|
||||
|
||||
public bool BackgroundLoaded => background.IsResultAvailable;
|
||||
public Texture Background => background.Value.Result;
|
||||
public Task<Texture> GetBackgroundAsync() => background.Value;
|
||||
private AsyncLazy<Texture> background;
|
||||
public bool BeatmapLoaded => beatmap.IsResultAvailable;
|
||||
public IBeatmap Beatmap => beatmap.Value;
|
||||
protected abstract IBeatmap GetBeatmap();
|
||||
private readonly RecyclableLazy<IBeatmap> beatmap;
|
||||
|
||||
private Texture populateBackground() => GetBackground();
|
||||
public bool BackgroundLoaded => background.IsResultAvailable;
|
||||
public Texture Background => background.Value;
|
||||
protected virtual bool BackgroundStillValid(Texture b) => b == null || b.Available;
|
||||
protected abstract Texture GetBackground();
|
||||
private readonly RecyclableLazy<Texture> background;
|
||||
|
||||
public bool TrackLoaded => track.IsResultAvailable;
|
||||
public Track Track => track.Value.Result;
|
||||
public Task<Track> GetTrackAsync() => track.Value;
|
||||
private AsyncLazy<Track> track;
|
||||
|
||||
private Track populateTrack()
|
||||
{
|
||||
// we want to ensure that we always have a track, even if it's a fake one.
|
||||
var t = GetTrack() ?? new VirtualBeatmapTrack(Beatmap);
|
||||
applyRateAdjustments(t);
|
||||
return t;
|
||||
}
|
||||
public Track Track => track.Value;
|
||||
protected abstract Track GetTrack();
|
||||
private RecyclableLazy<Track> track;
|
||||
|
||||
public bool WaveformLoaded => waveform.IsResultAvailable;
|
||||
public Waveform Waveform => waveform.Value.Result;
|
||||
public Task<Waveform> GetWaveformAsync() => waveform.Value;
|
||||
private readonly AsyncLazy<Waveform> waveform;
|
||||
|
||||
private Waveform populateWaveform() => GetWaveform();
|
||||
public Waveform Waveform => waveform.Value;
|
||||
protected virtual Waveform GetWaveform() => new Waveform();
|
||||
private readonly RecyclableLazy<Waveform> waveform;
|
||||
|
||||
public bool StoryboardLoaded => storyboard.IsResultAvailable;
|
||||
public Storyboard Storyboard => storyboard.Value.Result;
|
||||
public Task<Storyboard> GetStoryboardAsync() => storyboard.Value;
|
||||
private readonly AsyncLazy<Storyboard> storyboard;
|
||||
|
||||
private Storyboard populateStoryboard() => GetStoryboard();
|
||||
public Storyboard Storyboard => storyboard.Value;
|
||||
protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo };
|
||||
private readonly RecyclableLazy<Storyboard> storyboard;
|
||||
|
||||
public bool SkinLoaded => skin.IsResultAvailable;
|
||||
public Skin Skin => skin.Value.Result;
|
||||
public Task<Skin> GetSkinAsync() => skin.Value;
|
||||
private readonly AsyncLazy<Skin> skin;
|
||||
public Skin Skin => skin.Value;
|
||||
protected virtual Skin GetSkin() => new DefaultSkin();
|
||||
private readonly RecyclableLazy<Skin> skin;
|
||||
|
||||
private Skin populateSkin() => GetSkin();
|
||||
|
||||
public void TransferTo(WorkingBeatmap other)
|
||||
/// <summary>
|
||||
/// Transfer pieces of a beatmap to a new one, where possible, to save on loading.
|
||||
/// </summary>
|
||||
/// <param name="other">The new beatmap which is being switched to.</param>
|
||||
public virtual void TransferTo(WorkingBeatmap other)
|
||||
{
|
||||
if (track.IsResultAvailable && Track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo))
|
||||
other.track = track;
|
||||
|
||||
if (background.IsResultAvailable && Background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo))
|
||||
other.background = background;
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (BackgroundLoaded) Background?.Dispose();
|
||||
if (WaveformLoaded) Waveform?.Dispose();
|
||||
if (StoryboardLoaded) Storyboard?.Dispose();
|
||||
if (SkinLoaded) Skin?.Dispose();
|
||||
background.Recycle();
|
||||
waveform.Recycle();
|
||||
storyboard.Recycle();
|
||||
skin.Recycle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -210,15 +193,15 @@ namespace osu.Game.Beatmaps
|
||||
mod.ApplyToClock(t);
|
||||
}
|
||||
|
||||
public class AsyncLazy<T>
|
||||
public class RecyclableLazy<T>
|
||||
{
|
||||
private Lazy<Task<T>> lazy;
|
||||
private Lazy<T> lazy;
|
||||
private readonly Func<T> valueFactory;
|
||||
private readonly Func<T, bool> stillValidFunction;
|
||||
|
||||
private readonly object initLock = new object();
|
||||
private readonly object fetchLock = new object();
|
||||
|
||||
public AsyncLazy(Func<T> valueFactory, Func<T, bool> stillValidFunction = null)
|
||||
public RecyclableLazy(Func<T> valueFactory, Func<T, bool> stillValidFunction = null)
|
||||
{
|
||||
this.valueFactory = valueFactory;
|
||||
this.stillValidFunction = stillValidFunction;
|
||||
@@ -230,45 +213,28 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
if (!IsResultAvailable) return;
|
||||
|
||||
(lazy.Value.Result as IDisposable)?.Dispose();
|
||||
(lazy.Value as IDisposable)?.Dispose();
|
||||
recreate();
|
||||
}
|
||||
|
||||
public bool IsResultAvailable
|
||||
public bool IsResultAvailable => stillValid;
|
||||
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
recreateIfInvalid();
|
||||
return lazy.Value.IsCompleted;
|
||||
lock (fetchLock)
|
||||
{
|
||||
if (!stillValid)
|
||||
recreate();
|
||||
return lazy.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task<T> Value
|
||||
{
|
||||
get
|
||||
{
|
||||
recreateIfInvalid();
|
||||
return lazy.Value;
|
||||
}
|
||||
}
|
||||
private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true);
|
||||
|
||||
private void recreateIfInvalid()
|
||||
{
|
||||
lock (initLock)
|
||||
{
|
||||
if (!lazy.IsValueCreated || !lazy.Value.IsCompleted)
|
||||
// we have not yet been initialised or haven't run the task.
|
||||
return;
|
||||
|
||||
if (stillValidFunction?.Invoke(lazy.Value.Result) ?? true)
|
||||
// we are still in a valid state.
|
||||
return;
|
||||
|
||||
recreate();
|
||||
}
|
||||
}
|
||||
|
||||
private void recreate() => lazy = new Lazy<Task<T>>(() => Task.Run(valueFactory));
|
||||
private void recreate() => lazy = new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.IO.File;
|
||||
@@ -58,7 +59,7 @@ namespace osu.Game.Database
|
||||
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
|
||||
private ArchiveImportIPCChannel ipc;
|
||||
|
||||
private readonly List<Action> cachedEvents = new List<Action>();
|
||||
private readonly List<Action> queuedEvents = new List<Action>();
|
||||
|
||||
/// <summary>
|
||||
/// Allows delaying of outwards events until an operation is confirmed (at a database level).
|
||||
@@ -76,20 +77,26 @@ namespace osu.Game.Database
|
||||
/// <param name="perform">Whether the flushed events should be performed.</param>
|
||||
private void flushEvents(bool perform)
|
||||
{
|
||||
Action[] events;
|
||||
lock (queuedEvents)
|
||||
{
|
||||
events = queuedEvents.ToArray();
|
||||
queuedEvents.Clear();
|
||||
}
|
||||
|
||||
if (perform)
|
||||
{
|
||||
foreach (var a in cachedEvents)
|
||||
foreach (var a in events)
|
||||
a.Invoke();
|
||||
}
|
||||
|
||||
cachedEvents.Clear();
|
||||
delayingEvents = false;
|
||||
}
|
||||
|
||||
private void handleEvent(Action a)
|
||||
{
|
||||
if (delayingEvents)
|
||||
cachedEvents.Add(a);
|
||||
lock (queuedEvents) queuedEvents.Add(a);
|
||||
else
|
||||
a.Invoke();
|
||||
}
|
||||
@@ -129,7 +136,6 @@ namespace osu.Game.Database
|
||||
List<TModel> imported = new List<TModel>();
|
||||
|
||||
int current = 0;
|
||||
int errors = 0;
|
||||
foreach (string path in paths)
|
||||
{
|
||||
if (notification.State == ProgressNotificationState.Cancelled)
|
||||
@@ -162,12 +168,29 @@ namespace osu.Game.Database
|
||||
{
|
||||
e = e.InnerException ?? e;
|
||||
Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})");
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
notification.Text = errors > 0 ? $"Import complete with {errors} errors" : "Import successful!";
|
||||
notification.State = ProgressNotificationState.Completed;
|
||||
if (imported.Count == 0)
|
||||
{
|
||||
notification.Text = "Import failed!";
|
||||
notification.State = ProgressNotificationState.Cancelled;
|
||||
}
|
||||
else
|
||||
{
|
||||
notification.CompletionText = $"Imported {current} {typeof(TModel).Name.Replace("Info", "").ToLower()}s!";
|
||||
notification.CompletionClickAction += () =>
|
||||
{
|
||||
if (imported.Count > 0)
|
||||
PresentCompletedImport(imported);
|
||||
return true;
|
||||
};
|
||||
notification.State = ProgressNotificationState.Completed;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void PresentCompletedImport(IEnumerable<TModel> imported)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -283,7 +306,7 @@ namespace osu.Game.Database
|
||||
var notification = new ProgressNotification
|
||||
{
|
||||
Progress = 0,
|
||||
CompletionText = "Deleted all beatmaps!",
|
||||
CompletionText = $"Deleted all {typeof(TModel).Name.Replace("Info", "").ToLower()}s!",
|
||||
State = ProgressNotificationState.Active,
|
||||
};
|
||||
|
||||
@@ -385,6 +408,41 @@ namespace osu.Game.Database
|
||||
return fileInfos;
|
||||
}
|
||||
|
||||
#region osu-stable import
|
||||
|
||||
/// <summary>
|
||||
/// Set a storage with access to an osu-stable install for import purposes.
|
||||
/// </summary>
|
||||
public Func<Storage> GetStableStorage { private get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Denotes whether an osu-stable installation is present to perform automated imports from.
|
||||
/// </summary>
|
||||
public bool StableInstallationAvailable => GetStableStorage?.Invoke() != null;
|
||||
|
||||
/// <summary>
|
||||
/// The relative path from osu-stable's data directory to import items from.
|
||||
/// </summary>
|
||||
protected virtual string ImportFromStablePath => null;
|
||||
|
||||
/// <summary>
|
||||
/// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future.
|
||||
/// </summary>
|
||||
public Task ImportFromStableAsync()
|
||||
{
|
||||
var stable = GetStableStorage?.Invoke();
|
||||
|
||||
if (stable == null)
|
||||
{
|
||||
Logger.Log("No osu!stable installation available!", LoggingTarget.Information, LogLevel.Error);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
return Task.Factory.StartNew(() => Import(stable.GetDirectories(ImportFromStablePath).Select(f => stable.GetFullPath(f)).ToArray()), TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Create a barebones model from the provided archive.
|
||||
/// Actual expensive population should be done in <see cref="Populate"/>; this should just prepare for duplicate checking.
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Graphics.Textures;
|
||||
|
||||
namespace osu.Game.Graphics.Backgrounds
|
||||
{
|
||||
@@ -35,10 +34,10 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(LargeTextureStore textures)
|
||||
private void load(LargeTextureStore textures)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(textureName))
|
||||
Sprite.Texture = await textures.GetAsync(textureName);
|
||||
Sprite.Texture = textures.Get(textureName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
|
||||
float adjustedAlpha = HideAlphaDiscrepancies ?
|
||||
// Cubically scale alpha to make it drop off more sharply.
|
||||
(float)Math.Pow(DrawInfo.Colour.AverageColour.Linear.A, 3) :
|
||||
(float)Math.Pow(DrawColourInfo.Colour.AverageColour.Linear.A, 3) :
|
||||
1;
|
||||
|
||||
float elapsedSeconds = (float)Time.Elapsed / 1000;
|
||||
@@ -235,7 +235,7 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
Vector2Extensions.Transform(particle.Position * Size + new Vector2(-offset.X, offset.Y), DrawInfo.Matrix)
|
||||
);
|
||||
|
||||
ColourInfo colourInfo = DrawInfo.Colour;
|
||||
ColourInfo colourInfo = DrawColourInfo.Colour;
|
||||
colourInfo.ApplyChild(particle.Colour);
|
||||
|
||||
Texture.DrawTriangle(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@@ -38,15 +37,15 @@ namespace osu.Game.Graphics.Containers
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private async Task load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager)
|
||||
private void load(OsuGame osuGame, AudioManager audio, PreviewTrackManager previewTrackManager)
|
||||
{
|
||||
this.previewTrackManager = previewTrackManager;
|
||||
|
||||
if (osuGame != null)
|
||||
OverlayActivationMode.BindTo(osuGame.OverlayActivationMode);
|
||||
|
||||
samplePopIn = await audio.Sample.GetAsync(@"UI/overlay-pop-in");
|
||||
samplePopOut = await audio.Sample.GetAsync(@"UI/overlay-pop-out");
|
||||
samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in");
|
||||
samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out");
|
||||
|
||||
StateChanged += onStateChanged;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Configuration;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input.EventArgs;
|
||||
@@ -133,7 +132,7 @@ namespace osu.Game.Graphics.Cursor
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(OsuConfigManager config, TextureStore textures, OsuColour colour)
|
||||
private void load(OsuConfigManager config, TextureStore textures, OsuColour colour)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@@ -144,14 +143,14 @@ namespace osu.Game.Graphics.Cursor
|
||||
{
|
||||
new Sprite
|
||||
{
|
||||
Texture = await textures.GetAsync(@"Cursor/menu-cursor"),
|
||||
Texture = textures.Get(@"Cursor/menu-cursor"),
|
||||
},
|
||||
AdditiveLayer = new Sprite
|
||||
{
|
||||
Blending = BlendingMode.Additive,
|
||||
Colour = colour.Pink,
|
||||
Alpha = 0,
|
||||
Texture = await textures.GetAsync(@"Cursor/menu-cursor-additive"),
|
||||
Texture = textures.Get(@"Cursor/menu-cursor-additive"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using Humanizer;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
|
||||
@@ -16,7 +15,6 @@ namespace osu.Game.Graphics
|
||||
|
||||
public DrawableDate(DateTimeOffset date)
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Font = "Exo2.0-RegularItalic";
|
||||
|
||||
Date = date.ToLocalTime();
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace osu.Game.Graphics
|
||||
private SampleChannel shutter;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio)
|
||||
private void load(GameHost host, OsuConfigManager config, Storage storage, NotificationOverlay notificationOverlay, AudioManager audio)
|
||||
{
|
||||
this.host = host;
|
||||
this.storage = storage.GetStorageForDirectory(@"screenshots");
|
||||
@@ -51,7 +51,7 @@ namespace osu.Game.Graphics
|
||||
screenshotFormat = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat);
|
||||
captureMenuCursor = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor);
|
||||
|
||||
shutter = await audio.Sample.GetAsync("UI/shutter");
|
||||
shutter = audio.Sample.Get("UI/shutter");
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
@@ -25,7 +24,7 @@ namespace osu.Game.Graphics
|
||||
private FontStore store;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(FontStore store)
|
||||
private void load(FontStore store)
|
||||
{
|
||||
this.store = store;
|
||||
|
||||
@@ -56,23 +55,23 @@ namespace osu.Game.Graphics
|
||||
},
|
||||
};
|
||||
|
||||
await updateTexture();
|
||||
updateTexture();
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateTexture().Wait();
|
||||
updateTexture();
|
||||
}
|
||||
|
||||
private FontAwesome loadedIcon;
|
||||
private async Task updateTexture()
|
||||
private void updateTexture()
|
||||
{
|
||||
var loadableIcon = icon;
|
||||
|
||||
if (loadableIcon == loadedIcon) return;
|
||||
|
||||
var texture = await store.GetAsync(((char)loadableIcon).ToString());
|
||||
var texture = store.Get(((char)loadableIcon).ToString());
|
||||
|
||||
spriteMain.Texture = texture;
|
||||
spriteShadow.Texture = texture;
|
||||
@@ -96,7 +95,7 @@ namespace osu.Game.Graphics
|
||||
{
|
||||
//adjust shadow alpha based on highest component intensity to avoid muddy display of darker text.
|
||||
//squared result for quadratic fall-off seems to give the best result.
|
||||
var avgColour = (Color4)DrawInfo.Colour.AverageColour;
|
||||
var avgColour = (Color4)DrawColourInfo.Colour.AverageColour;
|
||||
|
||||
spriteShadow.Alpha = (float)Math.Pow(Math.Max(Math.Max(avgColour.R, avgColour.G), avgColour.B), 2);
|
||||
|
||||
@@ -131,7 +130,7 @@ namespace osu.Game.Graphics
|
||||
|
||||
icon = value;
|
||||
if (LoadState == LoadState.Loaded)
|
||||
updateTexture().Wait();
|
||||
updateTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.MathUtils;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Transforms;
|
||||
|
||||
namespace osu.Game.Graphics.Sprites
|
||||
@@ -19,27 +16,6 @@ namespace osu.Game.Graphics.Sprites
|
||||
Shadow = true;
|
||||
TextSize = FONT_SIZE;
|
||||
}
|
||||
|
||||
protected override Drawable CreateFallbackCharacterDrawable()
|
||||
{
|
||||
var tex = GetTextureForCharacter('?').Result;
|
||||
|
||||
if (tex != null)
|
||||
{
|
||||
float adjust = (RNG.NextSingle() - 0.5f) * 2;
|
||||
return new Sprite
|
||||
{
|
||||
Texture = tex,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Scale = new Vector2(1 + adjust * 0.2f),
|
||||
Rotation = adjust * 15,
|
||||
Colour = Color4.White,
|
||||
};
|
||||
}
|
||||
|
||||
return base.CreateFallbackCharacterDrawable();
|
||||
}
|
||||
}
|
||||
|
||||
public static class OsuSpriteTextTransformExtensions
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
|
||||
namespace osu.Game.Graphics.Textures
|
||||
{
|
||||
/// <summary>
|
||||
/// A texture store that bypasses atlasing.
|
||||
/// </summary>
|
||||
public class LargeTextureStore : TextureStore
|
||||
{
|
||||
public LargeTextureStore(IResourceStore<RawTexture> store = null) : base(store, false)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@@ -29,9 +28,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(AudioManager audio)
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleClick = await audio.Sample.GetAsync($@"UI/generic-select{SampleSet.GetDescription()}");
|
||||
sampleClick = audio.Sample.Get($@"UI/generic-select{SampleSet.GetDescription()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@@ -36,9 +35,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(AudioManager audio)
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = await audio.Sample.GetAsync($@"UI/generic-hover{SampleSet.GetDescription()}");
|
||||
sampleHover = audio.Sample.Get($@"UI/generic-hover{SampleSet.GetDescription()}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@@ -111,10 +110,10 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(AudioManager audio)
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleChecked = await audio.Sample.GetAsync(@"UI/check-on");
|
||||
sampleUnchecked = await audio.Sample.GetAsync(@"UI/check-off");
|
||||
sampleChecked = audio.Sample.Get(@"UI/check-on");
|
||||
sampleUnchecked = audio.Sample.Get(@"UI/check-off");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@@ -70,10 +69,10 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(AudioManager audio)
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = await audio.Sample.GetAsync(@"UI/generic-hover");
|
||||
sampleClick = await audio.Sample.GetAsync(@"UI/generic-select");
|
||||
sampleHover = audio.Sample.Get(@"UI/generic-hover");
|
||||
sampleClick = audio.Sample.Get(@"UI/generic-select");
|
||||
|
||||
BackgroundColour = Color4.Transparent;
|
||||
BackgroundColourHover = OsuColour.FromHex(@"172023");
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -120,9 +119,9 @@ namespace osu.Game.Graphics.UserInterface
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(AudioManager audio, OsuColour colours)
|
||||
private void load(AudioManager audio, OsuColour colours)
|
||||
{
|
||||
sample = await audio.Sample.GetAsync(@"UI/sliderbar-notch");
|
||||
sample = audio.Sample.Get(@"UI/sliderbar-notch");
|
||||
AccentColour = colours.Pink;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Input.Handlers;
|
||||
using osu.Framework.Input.StateChanges;
|
||||
using osu.Framework.Input.StateChanges.Events;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Input.Handlers
|
||||
@@ -40,7 +43,29 @@ namespace osu.Game.Input.Handlers
|
||||
|
||||
public void Apply(InputState state, IInputStateChangeHandler handler)
|
||||
{
|
||||
handler.HandleCustomInput(state, this);
|
||||
if (!(state is RulesetInputManagerInputState<T> inputState))
|
||||
throw new InvalidOperationException($"{nameof(ReplayState<T>)} should only be applied to a {nameof(RulesetInputManagerInputState<T>)}");
|
||||
|
||||
var lastPressed = inputState.LastReplayState?.PressedActions ?? new List<T>();
|
||||
var released = lastPressed.Except(PressedActions).ToArray();
|
||||
var pressed = PressedActions.Except(lastPressed).ToArray();
|
||||
|
||||
inputState.LastReplayState = this;
|
||||
|
||||
handler.HandleInputStateChange(new ReplayStateChangeEvent<T>(state, this, released, pressed));
|
||||
}
|
||||
}
|
||||
|
||||
public class ReplayStateChangeEvent<T> : InputStateChangeEvent
|
||||
{
|
||||
public readonly T[] ReleasedActions;
|
||||
public readonly T[] PressedActions;
|
||||
|
||||
public ReplayStateChangeEvent(InputState state, IInput input, T[] releasedActions, T[] pressedActions)
|
||||
: base(state, input)
|
||||
{
|
||||
ReleasedActions = releasedActions;
|
||||
PressedActions = pressedActions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
[DbContext(typeof(OsuDbContext))]
|
||||
[Migration("20180913080842_AddRankStatus")]
|
||||
partial class AddRankStatus
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.2-rtm-30932");
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<float>("ApproachRate");
|
||||
|
||||
b.Property<float>("CircleSize");
|
||||
|
||||
b.Property<float>("DrainRate");
|
||||
|
||||
b.Property<float>("OverallDifficulty");
|
||||
|
||||
b.Property<double>("SliderMultiplier");
|
||||
|
||||
b.Property<double>("SliderTickRate");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapDifficulty");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("AudioLeadIn");
|
||||
|
||||
b.Property<int>("BaseDifficultyID");
|
||||
|
||||
b.Property<int>("BeatDivisor");
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<bool>("Countdown");
|
||||
|
||||
b.Property<double>("DistanceSpacing");
|
||||
|
||||
b.Property<int>("GridSize");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<bool>("Hidden");
|
||||
|
||||
b.Property<bool>("LetterboxInBreaks");
|
||||
|
||||
b.Property<string>("MD5Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapID");
|
||||
|
||||
b.Property<string>("Path");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<bool>("SpecialStyle");
|
||||
|
||||
b.Property<float>("StackLeniency");
|
||||
|
||||
b.Property<double>("StarDifficulty");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.Property<string>("StoredBookmarks");
|
||||
|
||||
b.Property<double>("TimelineZoom");
|
||||
|
||||
b.Property<string>("Version");
|
||||
|
||||
b.Property<bool>("WidescreenStoryboard");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BaseDifficultyID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("Hash");
|
||||
|
||||
b.HasIndex("MD5Hash");
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("BeatmapInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Artist");
|
||||
|
||||
b.Property<string>("ArtistUnicode");
|
||||
|
||||
b.Property<string>("AudioFile");
|
||||
|
||||
b.Property<string>("AuthorString")
|
||||
.HasColumnName("Author");
|
||||
|
||||
b.Property<string>("BackgroundFile");
|
||||
|
||||
b.Property<int>("PreviewTime");
|
||||
|
||||
b.Property<string>("Source");
|
||||
|
||||
b.Property<string>("Tags");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("TitleUnicode");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapMetadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.ToTable("BeatmapSetFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapSetID");
|
||||
|
||||
b.Property<bool>("Protected");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapSetID")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BeatmapSetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntKey")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<string>("StringValue")
|
||||
.HasColumnName("Value");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntAction")
|
||||
.HasColumnName("Action");
|
||||
|
||||
b.Property<string>("KeysString")
|
||||
.HasColumnName("Keys");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("IntAction");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("KeyBinding");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("ReferenceCount");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ReferenceCount");
|
||||
|
||||
b.ToTable("FileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
|
||||
{
|
||||
b.Property<int?>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Available");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("ShortName");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Available");
|
||||
|
||||
b.HasIndex("ShortName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RulesetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SkinInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.ToTable("SkinFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Creator");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("SkinInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||
.WithMany()
|
||||
.HasForeignKey("BaseDifficultyID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("MetadataID");
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("BeatmapSets")
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("SkinInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
public partial class AddRankStatus : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Status",
|
||||
table: "BeatmapSetInfo",
|
||||
nullable: false,
|
||||
defaultValue: -3); // NONE
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Status",
|
||||
table: "BeatmapInfo",
|
||||
nullable: false,
|
||||
defaultValue: -3); // NONE
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Status",
|
||||
table: "BeatmapSetInfo");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Status",
|
||||
table: "BeatmapInfo");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// <auto-generated />
|
||||
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
@@ -13,7 +14,7 @@ namespace osu.Game.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.1.1-rtm-30846");
|
||||
.HasAnnotation("ProductVersion", "2.1.2-rtm-30932");
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||
{
|
||||
@@ -78,6 +79,8 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.Property<double>("StarDifficulty");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.Property<string>("StoredBookmarks");
|
||||
|
||||
b.Property<double>("TimelineZoom");
|
||||
@@ -173,6 +176,8 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.Property<bool>("Protected");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Logging;
|
||||
@@ -26,7 +24,7 @@ namespace osu.Game.Online.API
|
||||
private const string client_id = @"5";
|
||||
private const string client_secret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk";
|
||||
|
||||
private ConcurrentQueue<APIRequest> queue = new ConcurrentQueue<APIRequest>();
|
||||
private readonly Queue<APIRequest> queue = new Queue<APIRequest>();
|
||||
|
||||
/// <summary>
|
||||
/// The username/email provided by the user when initiating a login.
|
||||
@@ -55,7 +53,13 @@ namespace osu.Game.Online.API
|
||||
authentication.TokenString = config.Get<string>(OsuSetting.Token);
|
||||
authentication.Token.ValueChanged += onTokenChanged;
|
||||
|
||||
Task.Factory.StartNew(run, cancellationToken.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||
var thread = new Thread(run)
|
||||
{
|
||||
Name = "APIAccess",
|
||||
IsBackground = true
|
||||
};
|
||||
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
private void onTokenChanged(OAuthToken token) => config.Set(OsuSetting.Token, config.Get<bool>(OsuSetting.SavePassword) ? authentication.TokenString : string.Empty);
|
||||
@@ -75,10 +79,7 @@ namespace osu.Game.Online.API
|
||||
|
||||
public void Unregister(IOnlineComponent component)
|
||||
{
|
||||
Scheduler.Add(delegate
|
||||
{
|
||||
components.Remove(component);
|
||||
});
|
||||
Scheduler.Add(delegate { components.Remove(component); });
|
||||
}
|
||||
|
||||
public string AccessToken => authentication.RequestAccessToken();
|
||||
@@ -103,6 +104,7 @@ namespace osu.Game.Online.API
|
||||
log.Add(@"Queueing a ping request");
|
||||
Queue(new ListChannelsRequest { Timeout = 5000 });
|
||||
}
|
||||
|
||||
break;
|
||||
case APIState.Offline:
|
||||
case APIState.Connecting:
|
||||
@@ -161,18 +163,21 @@ namespace osu.Game.Online.API
|
||||
continue;
|
||||
}
|
||||
|
||||
//process the request queue.
|
||||
APIRequest req;
|
||||
while (queue.TryPeek(out req))
|
||||
while (true)
|
||||
{
|
||||
if (handleRequest(req))
|
||||
APIRequest req;
|
||||
|
||||
lock (queue)
|
||||
{
|
||||
//we have succeeded, so let's unqueue.
|
||||
queue.TryDequeue(out req);
|
||||
if (queue.Count == 0) break;
|
||||
req = queue.Dequeue();
|
||||
}
|
||||
|
||||
// TODO: handle failures better
|
||||
handleRequest(req);
|
||||
}
|
||||
|
||||
Thread.Sleep(1);
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +210,8 @@ namespace osu.Game.Online.API
|
||||
}
|
||||
catch (WebException we)
|
||||
{
|
||||
HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode ?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout);
|
||||
HttpStatusCode statusCode = (we.Response as HttpWebResponse)?.StatusCode
|
||||
?? (we.Status == WebExceptionStatus.UnknownError ? HttpStatusCode.NotAcceptable : HttpStatusCode.RequestTimeout);
|
||||
|
||||
// special cases for un-typed but useful message responses.
|
||||
switch (we.Message)
|
||||
@@ -247,6 +253,7 @@ namespace osu.Game.Online.API
|
||||
}
|
||||
|
||||
private APIState state;
|
||||
|
||||
public APIState State
|
||||
{
|
||||
get { return state; }
|
||||
@@ -271,7 +278,10 @@ namespace osu.Game.Online.API
|
||||
|
||||
public bool IsLoggedIn => LocalUser.Value.Id > 1;
|
||||
|
||||
public void Queue(APIRequest request) => queue.Enqueue(request);
|
||||
public void Queue(APIRequest request)
|
||||
{
|
||||
lock (queue) queue.Enqueue(request);
|
||||
}
|
||||
|
||||
public event StateChangeDelegate OnStateChange;
|
||||
|
||||
@@ -279,16 +289,17 @@ namespace osu.Game.Online.API
|
||||
|
||||
private void flushQueue(bool failOldRequests = true)
|
||||
{
|
||||
var oldQueue = queue;
|
||||
|
||||
//flush the queue.
|
||||
queue = new ConcurrentQueue<APIRequest>();
|
||||
|
||||
if (failOldRequests)
|
||||
lock (queue)
|
||||
{
|
||||
APIRequest req;
|
||||
while (oldQueue.TryDequeue(out req))
|
||||
req.Fail(new WebException(@"Disconnected from server"));
|
||||
var oldQueueRequests = queue.ToArray();
|
||||
|
||||
queue.Clear();
|
||||
|
||||
if (failOldRequests)
|
||||
{
|
||||
foreach (var req in oldQueueRequests)
|
||||
req.Fail(new WebException(@"Disconnected from server"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,12 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"beatmapset_id")]
|
||||
public int OnlineBeatmapSetID { get; set; }
|
||||
|
||||
[JsonProperty(@"status")]
|
||||
public BeatmapSetOnlineStatus Status { get; set; }
|
||||
|
||||
[JsonProperty(@"beatmapset")]
|
||||
public APIBeatmapSet BeatmapSet { get; set; }
|
||||
|
||||
[JsonProperty(@"playcount")]
|
||||
private int playCount { get; set; }
|
||||
|
||||
@@ -59,11 +65,13 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
Ruleset = rulesets.GetRuleset(ruleset),
|
||||
StarDifficulty = starDifficulty,
|
||||
OnlineBeatmapID = OnlineBeatmapID,
|
||||
Version = version,
|
||||
Status = Status,
|
||||
BeatmapSet = new BeatmapSetInfo
|
||||
{
|
||||
OnlineBeatmapSetID = OnlineBeatmapSetID,
|
||||
Status = BeatmapSet?.Status ?? BeatmapSetOnlineStatus.None
|
||||
},
|
||||
Version = version,
|
||||
BaseDifficulty = new BeatmapDifficulty
|
||||
{
|
||||
DrainRate = drainRate,
|
||||
|
||||
@@ -20,10 +20,13 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"id")]
|
||||
public int? OnlineBeatmapSetID
|
||||
{
|
||||
get { return onlineBeatmapSetID; }
|
||||
set { onlineBeatmapSetID = value > 0 ? value : null; }
|
||||
get => onlineBeatmapSetID;
|
||||
set => onlineBeatmapSetID = value > 0 ? value : null;
|
||||
}
|
||||
|
||||
[JsonProperty(@"status")]
|
||||
public BeatmapSetOnlineStatus Status { get; set; }
|
||||
|
||||
[JsonProperty(@"preview_url")]
|
||||
private string preview { get; set; }
|
||||
|
||||
@@ -42,9 +45,6 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"storyboard")]
|
||||
private bool hasStoryboard { get; set; }
|
||||
|
||||
[JsonProperty(@"status")]
|
||||
private BeatmapSetOnlineStatus status { get; set; }
|
||||
|
||||
[JsonProperty(@"submitted_date")]
|
||||
private DateTimeOffset submitted { get; set; }
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"user_id")]
|
||||
private long creatorId
|
||||
{
|
||||
set { Author.Id = value; }
|
||||
set => Author.Id = value;
|
||||
}
|
||||
|
||||
[JsonProperty(@"beatmaps")]
|
||||
@@ -69,6 +69,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
OnlineBeatmapSetID = OnlineBeatmapSetID,
|
||||
Metadata = this,
|
||||
Status = Status,
|
||||
OnlineInfo = new BeatmapSetOnlineInfo
|
||||
{
|
||||
Covers = covers,
|
||||
@@ -76,7 +77,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
PlayCount = playCount,
|
||||
FavouriteCount = favouriteCount,
|
||||
BPM = bpm,
|
||||
Status = status,
|
||||
Status = Status,
|
||||
HasVideo = hasVideo,
|
||||
HasStoryboard = hasStoryboard,
|
||||
Submitted = submitted,
|
||||
|
||||
@@ -15,11 +15,7 @@ namespace osu.Game.Online.Chat
|
||||
Timestamp = DateTimeOffset.Now;
|
||||
Content = message;
|
||||
|
||||
Sender = new User
|
||||
{
|
||||
Username = @"system",
|
||||
Colour = @"0000ff",
|
||||
};
|
||||
Sender = User.SYSTEM_USER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-17
@@ -75,10 +75,10 @@ namespace osu.Game
|
||||
{
|
||||
get
|
||||
{
|
||||
Screen s = screenStack;
|
||||
while (s != null && !(s is Intro))
|
||||
s = s.ChildScreen;
|
||||
return s as Intro;
|
||||
Screen screen = screenStack;
|
||||
while (screen != null && !(screen is Intro))
|
||||
screen = screen.ChildScreen;
|
||||
return screen as Intro;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,8 +126,8 @@ namespace osu.Game
|
||||
/// <param name="toolbar">Whether the toolbar should also be hidden.</param>
|
||||
public void CloseAllOverlays(bool toolbar = true)
|
||||
{
|
||||
foreach (var o in overlays)
|
||||
o.State = Visibility.Hidden;
|
||||
foreach (var overlay in overlays)
|
||||
overlay.State = Visibility.Hidden;
|
||||
if (toolbar) Toolbar.State = Visibility.Hidden;
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace osu.Game
|
||||
/// <param name="beatmapId">The beatmap to show.</param>
|
||||
public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId);
|
||||
|
||||
protected void LoadScore(Score s)
|
||||
protected void LoadScore(Score score)
|
||||
{
|
||||
scoreLoad?.Cancel();
|
||||
|
||||
@@ -252,18 +252,18 @@ namespace osu.Game
|
||||
|
||||
if (menu == null)
|
||||
{
|
||||
scoreLoad = Schedule(() => LoadScore(s));
|
||||
scoreLoad = Schedule(() => LoadScore(score));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!menu.IsCurrentScreen)
|
||||
{
|
||||
menu.MakeCurrent();
|
||||
this.Delay(500).Schedule(() => LoadScore(s), out scoreLoad);
|
||||
this.Delay(500).Schedule(() => LoadScore(score), out scoreLoad);
|
||||
return;
|
||||
}
|
||||
|
||||
if (s.Beatmap == null)
|
||||
if (score.Beatmap == null)
|
||||
{
|
||||
notifications.Post(new SimpleNotification
|
||||
{
|
||||
@@ -273,12 +273,12 @@ namespace osu.Game
|
||||
return;
|
||||
}
|
||||
|
||||
ruleset.Value = s.Ruleset;
|
||||
ruleset.Value = score.Ruleset;
|
||||
|
||||
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(s.Beatmap);
|
||||
Beatmap.Value.Mods.Value = s.Mods;
|
||||
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(score.Beatmap);
|
||||
Beatmap.Value.Mods.Value = score.Mods;
|
||||
|
||||
menu.Push(new PlayerLoader(new ReplayPlayer(s.Replay)));
|
||||
menu.Push(new PlayerLoader(new ReplayPlayer(score.Replay)));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
@@ -299,11 +299,13 @@ namespace osu.Game
|
||||
// This prevents the cursor from showing until we have a screen with CursorVisible = true
|
||||
MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
||||
|
||||
// hook up notifications to components.
|
||||
// todo: all archive managers should be able to be looped here.
|
||||
SkinManager.PostNotification = n => notifications?.Post(n);
|
||||
BeatmapManager.PostNotification = n => notifications?.Post(n);
|
||||
SkinManager.GetStableStorage = GetStorageForStableInstall;
|
||||
|
||||
BeatmapManager.PostNotification = n => notifications?.Post(n);
|
||||
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
||||
|
||||
BeatmapManager.PresentBeatmap = PresentBeatmap;
|
||||
|
||||
AddRange(new Drawable[]
|
||||
@@ -353,7 +355,7 @@ namespace osu.Game
|
||||
loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay { Depth = -3 }, mainContent.Add);
|
||||
loadComponentSingleFile(musicController = new MusicController
|
||||
{
|
||||
Depth = -4,
|
||||
Depth = -5,
|
||||
Position = new Vector2(0, Toolbar.HEIGHT),
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
|
||||
+29
-29
@@ -24,7 +24,6 @@ using osu.Framework.Input;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.Textures;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.IO;
|
||||
@@ -109,11 +108,39 @@ namespace osu.Game
|
||||
|
||||
dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage));
|
||||
|
||||
dependencies.Cache(new LargeTextureStore(new RawTextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures"))));
|
||||
var largeStore = new LargeTextureStore(new TextureLoaderStore(new NamespacedResourceStore<byte[]>(Resources, @"Textures")));
|
||||
largeStore.AddStore(new TextureLoaderStore(new OnlineStore()));
|
||||
dependencies.Cache(largeStore);
|
||||
|
||||
dependencies.CacheAs(this);
|
||||
dependencies.Cache(LocalConfig);
|
||||
|
||||
//this completely overrides the framework default. will need to change once we make a proper FontStore.
|
||||
dependencies.Cache(Fonts = new FontStore(new GlyphStore(Resources, @"Fonts/FontAwesome")));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic"));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Basic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Hangul"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Basic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Compatibility"));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Regular"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-RegularItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBold"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBoldItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Bold"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BoldItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Light"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-LightItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Black"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BlackItalic"));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Light"));
|
||||
|
||||
runMigrations();
|
||||
|
||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
||||
@@ -137,33 +164,6 @@ namespace osu.Game
|
||||
fileImporters.Add(ScoreStore);
|
||||
fileImporters.Add(SkinManager);
|
||||
|
||||
//this completely overrides the framework default. will need to change once we make a proper FontStore.
|
||||
dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 });
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/FontAwesome"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/osuFont"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Medium"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-MediumItalic"));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Basic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-Hangul"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Basic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Noto-CJK-Compatibility"));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Regular"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-RegularItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBold"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-SemiBoldItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Bold"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BoldItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Light"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-LightItalic"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-Black"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Exo2.0-BlackItalic"));
|
||||
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera"));
|
||||
Fonts.AddStore(new GlyphStore(Resources, @"Fonts/Venera-Light"));
|
||||
|
||||
var defaultBeatmap = new DummyWorkingBeatmap(this);
|
||||
beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio);
|
||||
BeatmapManager.DefaultBeatmap = defaultBeatmap;
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
|
||||
},
|
||||
};
|
||||
|
||||
Action = () => playButton.TriggerOnClick();
|
||||
Action = () => playButton.Click();
|
||||
Playing.ValueChanged += newValue => progress.FadeTo(newValue ? 1 : 0, 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -230,10 +230,12 @@ namespace osu.Game.Overlays.BeatmapSet
|
||||
Spacing = new Vector2(10),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
onlineStatusPill = new BeatmapSetOnlineStatusPill(14, new MarginPadding { Horizontal = 25, Vertical = 8 })
|
||||
onlineStatusPill = new BeatmapSetOnlineStatusPill
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
TextSize = 14,
|
||||
TextPadding = new MarginPadding { Horizontal = 25, Vertical = 8 }
|
||||
},
|
||||
Details = new Details(),
|
||||
},
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
loading = true;
|
||||
|
||||
getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset);
|
||||
getScoresRequest.Success += r => Scores = r.Scores;
|
||||
getScoresRequest.Success += r => Schedule(() => Scores = r.Scores);
|
||||
api.Queue(getScoresRequest);
|
||||
}
|
||||
}
|
||||
@@ -134,5 +134,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
this.api = api;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
getScoresRequest?.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Chat;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Configuration;
|
||||
using System;
|
||||
@@ -143,6 +144,17 @@ namespace osu.Game.Overlays.Chat
|
||||
textBold.FadeOut(transition_length, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
if (args.Button == MouseButton.Middle)
|
||||
{
|
||||
closeButton.Action();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
if (IsRemovable)
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace osu.Game.Overlays.Dialog
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.Select:
|
||||
Buttons.OfType<PopupDialogOkButton>().FirstOrDefault()?.TriggerOnClick();
|
||||
Buttons.OfType<PopupDialogOkButton>().FirstOrDefault()?.Click();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ namespace osu.Game.Overlays.Dialog
|
||||
if (!actionInvoked)
|
||||
// In the case a user did not choose an action before a hide was triggered, press the last button.
|
||||
// This is presumed to always be a sane default "cancel" action.
|
||||
buttonsContainer.Last().TriggerOnClick();
|
||||
buttonsContainer.Last().Click();
|
||||
|
||||
base.PopOut();
|
||||
content.FadeOut(EXIT_DURATION, Easing.InSine);
|
||||
@@ -261,7 +261,7 @@ namespace osu.Game.Overlays.Dialog
|
||||
private void pressButtonAtIndex(int index)
|
||||
{
|
||||
if (index < Buttons.Count())
|
||||
Buttons.Skip(index).First().TriggerOnClick();
|
||||
Buttons.Skip(index).First().Click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace osu.Game.Overlays.Direct
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, LocalisationEngine localisation)
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Content.CornerRadius = 4;
|
||||
|
||||
@@ -74,13 +74,13 @@ namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = localisation.GetUnicodePreference(SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title),
|
||||
Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)),
|
||||
TextSize = 18,
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = localisation.GetUnicodePreference(SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist),
|
||||
Text = new LocalisedString((SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist)),
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
},
|
||||
@@ -217,8 +217,10 @@ namespace osu.Game.Overlays.Direct
|
||||
statusContainer.Add(new IconPill(FontAwesome.fa_image));
|
||||
}
|
||||
|
||||
statusContainer.Add(new BeatmapSetOnlineStatusPill(12, new MarginPadding { Horizontal = 10, Vertical = 5 })
|
||||
statusContainer.Add(new BeatmapSetOnlineStatusPill
|
||||
{
|
||||
TextSize = 12,
|
||||
TextPadding = new MarginPadding { Horizontal = 10, Vertical = 5 },
|
||||
Status = SetInfo.OnlineInfo?.Status ?? BeatmapSetOnlineStatus.None,
|
||||
});
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ using osu.Framework.Graphics.Colour;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Overlays.Direct
|
||||
@@ -39,7 +39,7 @@ namespace osu.Game.Overlays.Direct
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LocalisationEngine localisation, OsuColour colours)
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Content.CornerRadius = 5;
|
||||
|
||||
@@ -94,13 +94,13 @@ namespace osu.Game.Overlays.Direct
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Current = localisation.GetUnicodePreference(SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title),
|
||||
Text = new LocalisedString((SetInfo.Metadata.TitleUnicode, SetInfo.Metadata.Title)),
|
||||
TextSize = 18,
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Current = localisation.GetUnicodePreference(SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist),
|
||||
Text = new LocalisedString((SetInfo.Metadata.ArtistUnicode, SetInfo.Metadata.Artist)),
|
||||
Font = @"Exo2.0-BoldItalic",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -104,8 +104,6 @@ namespace osu.Game.Overlays.Direct
|
||||
beatmaps.ItemAdded += setAdded;
|
||||
}
|
||||
|
||||
public override bool DisposeOnDeathRemoval => true;
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
@@ -187,7 +185,7 @@ namespace osu.Game.Overlays.Direct
|
||||
base.LoadComplete();
|
||||
this.FadeInFromZero(200, Easing.Out);
|
||||
|
||||
PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered ? 1 : 0, 120, Easing.InOutQuint);
|
||||
PreviewPlaying.ValueChanged += newValue => PlayButton.FadeTo(newValue || IsHovered || !FadePlayButton ? 1 : 0, 120, Easing.InOutQuint);
|
||||
PreviewPlaying.ValueChanged += newValue => PreviewBar.FadeTo(newValue ? 1 : 0, 120, Easing.InOutQuint);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
|
||||
private FillFlowContainer<KeyButton> buttons;
|
||||
|
||||
public IEnumerable<string> FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend(text.Text);
|
||||
public IEnumerable<string> FilterTerms => bindings.Select(b => b.KeyCombination.ReadableString()).Prepend((string)text.Text);
|
||||
|
||||
public KeyBindingRow(object action, IEnumerable<Framework.Input.Bindings.KeyBinding> bindings)
|
||||
{
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace osu.Game.Overlays
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.Back:
|
||||
TriggerOnClick();
|
||||
Click();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ using OpenTK.Input;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Framework.MathUtils;
|
||||
|
||||
@@ -144,10 +143,10 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(OsuColour colours, TextureStore textures, AudioManager audio)
|
||||
private void load(OsuColour colours, TextureStore textures, AudioManager audio)
|
||||
{
|
||||
getSample = await audio.Sample.GetAsync(@"MedalSplash/medal-get");
|
||||
innerSpin.Texture = outerSpin.Texture = await textures.GetAsync(@"MedalSplash/disc-spin");
|
||||
getSample = audio.Sample.Get(@"MedalSplash/medal-get");
|
||||
innerSpin.Texture = outerSpin.Texture = textures.Get(@"MedalSplash/disc-spin");
|
||||
|
||||
disc.EdgeEffect = leftStrip.EdgeEffect = rightStrip.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework;
|
||||
using OpenTK;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -119,10 +118,10 @@ namespace osu.Game.Overlays.MedalSplash
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(OsuColour colours, TextureStore textures)
|
||||
private void load(OsuColour colours, TextureStore textures, LargeTextureStore largeTextures)
|
||||
{
|
||||
medalSprite.Texture = await textures.GetAsync(medal.ImageUrl);
|
||||
medalGlow.Texture = await textures.GetAsync(@"MedalSplash/medal-glow");
|
||||
medalSprite.Texture = largeTextures.Get(medal.ImageUrl);
|
||||
medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow");
|
||||
description.Colour = colours.BlueLight;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@@ -50,7 +49,7 @@ namespace osu.Game.Overlays.Mods
|
||||
protected readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private async Task load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IEnumerable<Mod>> selectedMods)
|
||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IEnumerable<Mod>> selectedMods)
|
||||
{
|
||||
LowMultiplierColour = colours.Red;
|
||||
HighMultiplierColour = colours.Green;
|
||||
@@ -59,8 +58,8 @@ namespace osu.Game.Overlays.Mods
|
||||
Ruleset.BindTo(ruleset);
|
||||
if (selectedMods != null) SelectedMods.BindTo(selectedMods);
|
||||
|
||||
sampleOn = await audio.Sample.GetAsync(@"UI/check-on");
|
||||
sampleOff = await audio.Sample.GetAsync(@"UI/check-off");
|
||||
sampleOn = audio.Sample.Get(@"UI/check-on");
|
||||
sampleOff = audio.Sample.Get(@"UI/check-off");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace osu.Game.Overlays.Music
|
||||
private SpriteIcon handle;
|
||||
private TextFlowContainer text;
|
||||
private IEnumerable<SpriteText> titleSprites;
|
||||
private UnicodeBindableString titleBind;
|
||||
private UnicodeBindableString artistBind;
|
||||
private ILocalisedBindableString titleBind;
|
||||
private ILocalisedBindableString artistBind;
|
||||
|
||||
public readonly BeatmapSetInfo BeatmapSetInfo;
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace osu.Game.Overlays.Music
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, LocalisationEngine localisation)
|
||||
private void load(OsuColour colours, LocalisationManager localisation)
|
||||
{
|
||||
hoverColour = colours.Yellow;
|
||||
artistColour = colours.Gray9;
|
||||
@@ -97,11 +97,10 @@ namespace osu.Game.Overlays.Music
|
||||
},
|
||||
};
|
||||
|
||||
titleBind = localisation.GetUnicodePreference(metadata.TitleUnicode, metadata.Title);
|
||||
artistBind = localisation.GetUnicodePreference(metadata.ArtistUnicode, metadata.Artist);
|
||||
titleBind = localisation.GetLocalisedString(new LocalisedString((metadata.TitleUnicode, metadata.Title)));
|
||||
artistBind = localisation.GetLocalisedString(new LocalisedString((metadata.ArtistUnicode, metadata.Artist)));
|
||||
|
||||
artistBind.ValueChanged += newText => recreateText();
|
||||
artistBind.TriggerChange();
|
||||
artistBind.BindValueChanged(newText => recreateText(), true);
|
||||
}
|
||||
|
||||
private void recreateText()
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace osu.Game.Overlays
|
||||
private PlaylistOverlay playlist;
|
||||
|
||||
private BeatmapManager beatmaps;
|
||||
private LocalisationEngine localisation;
|
||||
|
||||
private List<BeatmapSetInfo> beatmapSets;
|
||||
private BeatmapSetInfo currentSet;
|
||||
@@ -67,11 +66,10 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(BindableBeatmap beatmap, BeatmapManager beatmaps, OsuColour colours, LocalisationEngine localisation)
|
||||
private void load(BindableBeatmap beatmap, BeatmapManager beatmaps, OsuColour colours)
|
||||
{
|
||||
this.beatmap.BindTo(beatmap);
|
||||
this.beatmaps = beatmaps;
|
||||
this.localisation = localisation;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@@ -351,17 +349,14 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
if (beatmap?.Beatmap == null) //this is not needed if a placeholder exists
|
||||
{
|
||||
title.Current = null;
|
||||
title.Text = @"Nothing to play";
|
||||
|
||||
artist.Current = null;
|
||||
artist.Text = @"Nothing to play";
|
||||
}
|
||||
else
|
||||
{
|
||||
BeatmapMetadata metadata = beatmap.Metadata;
|
||||
title.Current = localisation.GetUnicodePreference(metadata.TitleUnicode, metadata.Title);
|
||||
artist.Current = localisation.GetUnicodePreference(metadata.ArtistUnicode, metadata.Artist);
|
||||
title.Text = new LocalisedString((metadata.TitleUnicode, metadata.Title));
|
||||
artist.Text = new LocalisedString((metadata.ArtistUnicode, metadata.Artist));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -454,9 +449,9 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
sprite.Texture = beatmap?.Background ?? await textures.GetAsync(@"Backgrounds/bg4");
|
||||
sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg4");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ namespace osu.Game.Overlays.Notifications
|
||||
public Action<Notification> CompletionTarget { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An action to complete when the completion notification is clicked.
|
||||
/// An action to complete when the completion notification is clicked. Return true to close.
|
||||
/// </summary>
|
||||
public Func<bool> CompletionClickAction;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -43,9 +42,9 @@ namespace osu.Game.Overlays.Profile.Components
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
badge.Texture = await textures.GetAsync($"Grades/{grade}");
|
||||
badge.Texture = textures.Get($"Grades/{grade}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -177,13 +176,13 @@ namespace osu.Game.Overlays.Profile.Header
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(LargeTextureStore textures)
|
||||
{
|
||||
Child = new Sprite
|
||||
{
|
||||
FillMode = FillMode.Fit,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = await textures.GetAsync(badge.ImageUrl),
|
||||
Texture = textures.Get(badge.ImageUrl),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -312,9 +311,9 @@ namespace osu.Game.Overlays.Profile
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
levelBadge.Texture = await textures.GetAsync(@"Profile/levelbadge");
|
||||
levelBadge.Texture = textures.Get(@"Profile/levelbadge");
|
||||
}
|
||||
|
||||
private User user;
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Sections
|
||||
public string TooltipText { get; }
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(LocalisationEngine locale, BeatmapSetOverlay beatmapSetOverlay)
|
||||
private void load(BeatmapSetOverlay beatmapSetOverlay)
|
||||
{
|
||||
Action = () =>
|
||||
{
|
||||
@@ -46,16 +46,14 @@ namespace osu.Game.Overlays.Profile.Sections
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
Current = locale.GetUnicodePreference(
|
||||
$"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ",
|
||||
$"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] "
|
||||
),
|
||||
Text = new LocalisedString(($"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ",
|
||||
$"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")),
|
||||
TextSize = 15,
|
||||
Font = "Exo2.0-SemiBoldItalic",
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Current = locale.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist),
|
||||
Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)),
|
||||
TextSize = 12,
|
||||
Padding = new MarginPadding { Top = 3 },
|
||||
Font = "Exo2.0-RegularItalic",
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
||||
public class PaginatedBeatmapContainer : PaginatedContainer
|
||||
{
|
||||
private const float panel_padding = 10f;
|
||||
|
||||
private readonly BeatmapSetType type;
|
||||
private GetUserBeatmapsRequest request;
|
||||
|
||||
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<User> user, string header, string missing = "None... yet.")
|
||||
: base(user, header, missing)
|
||||
@@ -31,9 +31,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
var req = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||
|
||||
req.Success += sets =>
|
||||
request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += sets => Schedule(() =>
|
||||
{
|
||||
ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
|
||||
ShowMoreLoading.Hide();
|
||||
@@ -52,9 +51,15 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
||||
var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets));
|
||||
ItemsContainer.Add(panel);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Api.Queue(req);
|
||||
Api.Queue(request);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
request?.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-5
@@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
||||
{
|
||||
public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer
|
||||
{
|
||||
private GetUserMostPlayedBeatmapsRequest request;
|
||||
|
||||
public PaginatedMostPlayedBeatmapContainer(Bindable<User> user)
|
||||
:base(user, "Most Played Beatmaps", "No records. :(")
|
||||
{
|
||||
@@ -24,9 +26,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
var req = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||
|
||||
req.Success += beatmaps =>
|
||||
request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += beatmaps => Schedule(() =>
|
||||
{
|
||||
ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
|
||||
ShowMoreLoading.Hide();
|
||||
@@ -43,9 +44,16 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
||||
{
|
||||
ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Api.Queue(req);
|
||||
Api.Queue(request);
|
||||
}
|
||||
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
request?.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections
|
||||
protected readonly Bindable<User> User = new Bindable<User>();
|
||||
|
||||
protected APIAccess Api;
|
||||
protected APIRequest RetrievalRequest;
|
||||
protected RulesetStore Rulesets;
|
||||
|
||||
public PaginatedContainer(Bindable<User> user, string header, string missing)
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
{
|
||||
private readonly bool includeWeight;
|
||||
private readonly ScoreType type;
|
||||
private GetUserScoresRequest request;
|
||||
|
||||
public PaginatedScoreContainer(ScoreType type, Bindable<User> user, string header, string missing, bool includeWeight = false)
|
||||
: base(user, header, missing)
|
||||
@@ -32,9 +33,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
var req = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||
|
||||
req.Success += scores =>
|
||||
request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += scores => Schedule(() =>
|
||||
{
|
||||
foreach (var s in scores)
|
||||
s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID));
|
||||
@@ -66,9 +66,15 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
|
||||
ItemsContainer.Add(drawableScore);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Api.Queue(req);
|
||||
Api.Queue(request);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
request?.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -31,9 +30,9 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(LargeTextureStore textures)
|
||||
{
|
||||
sprite.Texture = await textures.GetAsync(url);
|
||||
sprite.Texture = textures.Get(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
{
|
||||
public class PaginatedRecentActivityContainer : PaginatedContainer
|
||||
{
|
||||
private GetUserRecentActivitiesRequest request;
|
||||
|
||||
public PaginatedRecentActivityContainer(Bindable<User> user, string header, string missing)
|
||||
: base(user, header, missing)
|
||||
{
|
||||
@@ -22,9 +24,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
var req = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||
|
||||
req.Success += activities =>
|
||||
request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += activities => Schedule(() =>
|
||||
{
|
||||
ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
|
||||
ShowMoreLoading.Hide();
|
||||
@@ -41,9 +42,15 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
{
|
||||
ItemsContainer.Add(new DrawableRecentActivity(activity));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Api.Queue(req);
|
||||
Api.Queue(request);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
request?.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
@@ -15,21 +19,36 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
private FillFlowContainer letterboxSettings;
|
||||
|
||||
private Bindable<bool> letterboxing;
|
||||
private Bindable<Size> sizeFullscreen;
|
||||
|
||||
private OsuGameBase game;
|
||||
private SettingsDropdown<Size> resolutionDropdown;
|
||||
private SettingsEnumDropdown<WindowMode> windowModeDropdown;
|
||||
|
||||
private const int transition_duration = 400;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(FrameworkConfigManager config)
|
||||
private void load(FrameworkConfigManager config, OsuGameBase game)
|
||||
{
|
||||
this.game = game;
|
||||
|
||||
letterboxing = config.GetBindable<bool>(FrameworkSetting.Letterboxing);
|
||||
sizeFullscreen = config.GetBindable<Size>(FrameworkSetting.SizeFullscreen);
|
||||
|
||||
Container resolutionSettingsContainer;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsEnumDropdown<WindowMode>
|
||||
windowModeDropdown = new SettingsEnumDropdown<WindowMode>
|
||||
{
|
||||
LabelText = "Screen mode",
|
||||
Bindable = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
|
||||
},
|
||||
resolutionSettingsContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Letterboxing",
|
||||
@@ -62,15 +81,52 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
},
|
||||
};
|
||||
|
||||
letterboxing.ValueChanged += isVisible =>
|
||||
var resolutions = getResolutions();
|
||||
|
||||
if (resolutions.Count > 1)
|
||||
{
|
||||
resolutionSettingsContainer.Child = resolutionDropdown = new SettingsDropdown<Size>
|
||||
{
|
||||
LabelText = "Resolution",
|
||||
ShowsDefaultIndicator = false,
|
||||
Items = resolutions,
|
||||
Bindable = sizeFullscreen
|
||||
};
|
||||
|
||||
windowModeDropdown.Bindable.BindValueChanged(windowMode =>
|
||||
{
|
||||
if (windowMode == WindowMode.Fullscreen)
|
||||
{
|
||||
resolutionDropdown.Show();
|
||||
sizeFullscreen.TriggerChange();
|
||||
}
|
||||
else
|
||||
resolutionDropdown.Hide();
|
||||
});
|
||||
}
|
||||
|
||||
letterboxing.BindValueChanged(isVisible =>
|
||||
{
|
||||
letterboxSettings.ClearTransforms();
|
||||
letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None;
|
||||
|
||||
if (!isVisible)
|
||||
letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint);
|
||||
};
|
||||
letterboxing.TriggerChange();
|
||||
}, true);
|
||||
}
|
||||
|
||||
private IReadOnlyList<KeyValuePair<string, Size>> getResolutions()
|
||||
{
|
||||
var resolutions = new KeyValuePair<string, Size>("Default", new Size(9999, 9999)).Yield();
|
||||
|
||||
if (game.Window != null)
|
||||
resolutions = resolutions.Concat(game.Window.AvailableResolutions
|
||||
.Where(r => r.Width >= 800 && r.Height >= 600)
|
||||
.OrderByDescending(r => r.Width)
|
||||
.ThenByDescending(r => r.Height)
|
||||
.Select(res => new KeyValuePair<string, Size>($"{res.Width}x{res.Height}", new Size(res.Width, res.Height)))
|
||||
.Distinct());
|
||||
return resolutions.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
{
|
||||
@@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
protected override string Header => "General";
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(BeatmapManager beatmaps, DialogOverlay dialogOverlay)
|
||||
private void load(BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
@@ -30,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
Action = () =>
|
||||
{
|
||||
importButton.Enabled.Value = false;
|
||||
beatmaps.ImportFromStable().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true));
|
||||
beatmaps.ImportFromStableAsync().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true));
|
||||
}
|
||||
},
|
||||
deleteButton = new DangerousSettingsButton
|
||||
@@ -45,6 +46,27 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
}));
|
||||
}
|
||||
},
|
||||
importButton = new SettingsButton
|
||||
{
|
||||
Text = "Import skins from stable",
|
||||
Action = () =>
|
||||
{
|
||||
importButton.Enabled.Value = false;
|
||||
skins.ImportFromStableAsync().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true));
|
||||
}
|
||||
},
|
||||
deleteButton = new DangerousSettingsButton
|
||||
{
|
||||
Text = "Delete ALL skins",
|
||||
Action = () =>
|
||||
{
|
||||
dialogOverlay?.Push(new DeleteAllBeatmapsDialog(() =>
|
||||
{
|
||||
deleteButton.Enabled.Value = false;
|
||||
Task.Run(() => skins.Delete(skins.GetAllUserSkins())).ContinueWith(t => Schedule(() => deleteButton.Enabled.Value = true));
|
||||
}));
|
||||
}
|
||||
},
|
||||
restoreButton = new SettingsButton
|
||||
{
|
||||
Text = "Restore all hidden difficulties",
|
||||
|
||||
@@ -51,10 +51,10 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
},
|
||||
};
|
||||
|
||||
skins.ItemAdded += onItemsChanged;
|
||||
skins.ItemRemoved += onItemsChanged;
|
||||
skins.ItemAdded += itemAdded;
|
||||
skins.ItemRemoved += itemRemoved;
|
||||
|
||||
reloadSkins();
|
||||
skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair<string, int>(s.ToString(), s.ID));
|
||||
|
||||
var skinBindable = config.GetBindable<int>(OsuSetting.Skin);
|
||||
|
||||
@@ -65,9 +65,8 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
skinDropdown.Bindable = skinBindable;
|
||||
}
|
||||
|
||||
private void reloadSkins() => skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair<string, int>(s.ToString(), s.ID));
|
||||
|
||||
private void onItemsChanged(SkinInfo _) => Schedule(reloadSkins);
|
||||
private void itemRemoved(SkinInfo s) => skinDropdown.Items = skinDropdown.Items.Where(i => i.Value != s.ID);
|
||||
private void itemAdded(SkinInfo s) => skinDropdown.Items = skinDropdown.Items.Append(new KeyValuePair<string, int>(s.ToString(), s.ID));
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
@@ -75,8 +74,8 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
|
||||
if (skins != null)
|
||||
{
|
||||
skins.ItemAdded -= onItemsChanged;
|
||||
skins.ItemRemoved -= onItemsChanged;
|
||||
skins.ItemAdded -= itemAdded;
|
||||
skins.ItemRemoved -= itemRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Settings
|
||||
},
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new[]
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new OsuSpriteText
|
||||
{
|
||||
|
||||
@@ -83,14 +83,14 @@ namespace osu.Game.Overlays.Toolbar
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame osuGame)
|
||||
{
|
||||
if (osuGame != null)
|
||||
overlayActivationMode.BindTo(osuGame.OverlayActivationMode);
|
||||
|
||||
StateChanged += visibility =>
|
||||
{
|
||||
if (overlayActivationMode == OverlayActivation.Disabled)
|
||||
State = Visibility.Hidden;
|
||||
};
|
||||
|
||||
if (osuGame != null)
|
||||
overlayActivationMode.BindTo(osuGame.OverlayActivationMode);
|
||||
}
|
||||
|
||||
public class ToolbarBackground : Container
|
||||
|
||||
@@ -73,16 +73,17 @@ namespace osu.Game.Overlays
|
||||
FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out);
|
||||
}
|
||||
|
||||
public void ShowUser(long userId)
|
||||
{
|
||||
if (userId == Header.User.Id)
|
||||
return;
|
||||
|
||||
ShowUser(new User { Id = userId });
|
||||
}
|
||||
public void ShowUser(long userId) => ShowUser(new User { Id = userId });
|
||||
|
||||
public void ShowUser(User user, bool fetchOnline = true)
|
||||
{
|
||||
if (user == User.SYSTEM_USER) return;
|
||||
|
||||
Show();
|
||||
|
||||
if (user.Id == Header?.User?.Id)
|
||||
return;
|
||||
|
||||
userReq?.Cancel();
|
||||
Clear();
|
||||
lastSection = null;
|
||||
@@ -97,6 +98,7 @@ namespace osu.Game.Overlays
|
||||
new BeatmapsSection(),
|
||||
new KudosuSection()
|
||||
};
|
||||
|
||||
tabs = new ProfileTabControl
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
@@ -161,7 +163,6 @@ namespace osu.Game.Overlays
|
||||
userLoadComplete(user);
|
||||
}
|
||||
|
||||
Show();
|
||||
sectionsContainer.ScrollToTop();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Extensions.TypeExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
@@ -165,6 +167,14 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
public override bool UpdateSubTreeMasking(Drawable source, RectangleF maskingBounds)
|
||||
{
|
||||
if (!AllJudged)
|
||||
return false;
|
||||
|
||||
return base.UpdateSubTreeMasking(source, maskingBounds);
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
@@ -10,7 +9,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.EventArgs;
|
||||
using osu.Framework.Input.StateChanges;
|
||||
using osu.Framework.Input.StateChanges.Events;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Configuration;
|
||||
@@ -56,33 +55,20 @@ namespace osu.Game.Rulesets.UI
|
||||
|
||||
#region Action mapping (for replays)
|
||||
|
||||
private List<T> lastPressedActions = new List<T>();
|
||||
|
||||
public override void HandleCustomInput(InputState state, IInput input)
|
||||
public override void HandleInputStateChange(InputStateChangeEvent inputStateChange)
|
||||
{
|
||||
if (!(input is ReplayState<T> replayState))
|
||||
if (inputStateChange is ReplayStateChangeEvent<T> replayStateChanged)
|
||||
{
|
||||
base.HandleCustomInput(state, input);
|
||||
return;
|
||||
}
|
||||
foreach (var action in replayStateChanged.ReleasedActions)
|
||||
KeyBindingContainer.TriggerReleased(action);
|
||||
|
||||
if (state is RulesetInputManagerInputState<T> inputState)
|
||||
foreach (var action in replayStateChanged.PressedActions)
|
||||
KeyBindingContainer.TriggerPressed(action);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputState.LastReplayState = replayState;
|
||||
base.HandleInputStateChange(inputStateChange);
|
||||
}
|
||||
|
||||
// Here we handle states specifically coming from a replay source.
|
||||
// These have extra action information rather than keyboard keys or mouse buttons.
|
||||
|
||||
List<T> newActions = replayState.PressedActions;
|
||||
|
||||
foreach (var released in lastPressedActions.Except(newActions))
|
||||
KeyBindingContainer.TriggerReleased(released);
|
||||
|
||||
foreach (var pressed in newActions.Except(lastPressedActions))
|
||||
KeyBindingContainer.TriggerPressed(pressed);
|
||||
|
||||
lastPressedActions = newActions;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
@@ -76,9 +75,9 @@ namespace osu.Game.Screens.Backgrounds
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Sprite.Texture = beatmap?.Background ?? await textures.GetAsync(@"Backgrounds/bg1");
|
||||
Sprite.Texture = beatmap?.Background ?? textures.Get(@"Backgrounds/bg1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
@@ -180,11 +179,11 @@ namespace osu.Game.Screens.Menu
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(AudioManager audio)
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = await audio.Sample.GetAsync(@"Menu/button-hover");
|
||||
sampleHover = audio.Sample.Get(@"Menu/button-hover");
|
||||
if (!string.IsNullOrEmpty(sampleName))
|
||||
sampleClick = await audio.Sample.GetAsync($@"Menu/{sampleName}");
|
||||
sampleClick = audio.Sample.Get($@"Menu/{sampleName}");
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
@@ -103,10 +102,10 @@ namespace osu.Game.Screens.Menu
|
||||
private OsuGame game;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private async Task load(AudioManager audio, OsuGame game)
|
||||
private void load(AudioManager audio, OsuGame game)
|
||||
{
|
||||
this.game = game;
|
||||
sampleBack = await audio.Sample.GetAsync(@"Menu/button-back-select");
|
||||
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
@@ -116,7 +115,7 @@ namespace osu.Game.Screens.Menu
|
||||
case GlobalAction.Back:
|
||||
return goBack();
|
||||
case GlobalAction.Select:
|
||||
logo?.TriggerOnClick();
|
||||
logo?.Click();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -134,7 +133,7 @@ namespace osu.Game.Screens.Menu
|
||||
sampleBack?.Play();
|
||||
return true;
|
||||
case ButtonSystemState.Play:
|
||||
backButton.TriggerOnClick();
|
||||
backButton.Click();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -151,10 +150,10 @@ namespace osu.Game.Screens.Menu
|
||||
State = ButtonSystemState.TopLevel;
|
||||
return true;
|
||||
case ButtonSystemState.TopLevel:
|
||||
buttonsTopLevel.First().TriggerOnClick();
|
||||
buttonsTopLevel.First().Click();
|
||||
return false;
|
||||
case ButtonSystemState.Play:
|
||||
buttonsPlay.First().TriggerOnClick();
|
||||
buttonsPlay.First().Click();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@@ -48,7 +47,7 @@ namespace osu.Game.Screens.Menu
|
||||
private WorkingBeatmap introBeatmap;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap)
|
||||
private void load(AudioManager audio, OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, BindableBeatmap beatmap)
|
||||
{
|
||||
this.beatmap.BindTo(beatmap);
|
||||
|
||||
@@ -81,8 +80,8 @@ namespace osu.Game.Screens.Menu
|
||||
introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
||||
track = introBeatmap.Track;
|
||||
|
||||
welcome = await audio.Sample.GetAsync(@"welcome");
|
||||
seeya = await audio.Sample.GetAsync(@"seeya");
|
||||
welcome = audio.Sample.Get(@"welcome");
|
||||
seeya = audio.Sample.Get(@"seeya");
|
||||
}
|
||||
|
||||
private const double delay_step_one = 2300;
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy;
|
||||
|
||||
ColourInfo colourInfo = DrawInfo.Colour;
|
||||
ColourInfo colourInfo = DrawColourInfo.Colour;
|
||||
colourInfo.ApplyChild(Colour);
|
||||
|
||||
if (AudioData != null)
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
@@ -85,11 +84,10 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
private const double early_activation = 60;
|
||||
|
||||
public override bool IsPresent => base.IsPresent || Scheduler.HasPendingTasks;
|
||||
|
||||
public OsuLogo()
|
||||
{
|
||||
// Required to make Schedule calls run in OsuScreen even when we are not visible.
|
||||
AlwaysPresent = true;
|
||||
|
||||
EarlyActivationMilliseconds = early_activation;
|
||||
|
||||
Size = new Vector2(default_size);
|
||||
@@ -254,13 +252,13 @@ namespace osu.Game.Screens.Menu
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures, AudioManager audio)
|
||||
private void load(TextureStore textures, AudioManager audio)
|
||||
{
|
||||
sampleClick = await audio.Sample.GetAsync(@"Menu/osu-logo-select");
|
||||
sampleBeat = await audio.Sample.GetAsync(@"Menu/osu-logo-heartbeat");
|
||||
sampleClick = audio.Sample.Get(@"Menu/osu-logo-select");
|
||||
sampleBeat = audio.Sample.Get(@"Menu/osu-logo-heartbeat");
|
||||
|
||||
logo.Texture = await textures.GetAsync(@"Menu/logo");
|
||||
ripple.Texture = await textures.GetAsync(@"Menu/logo");
|
||||
logo.Texture = textures.Get(@"Menu/logo");
|
||||
ripple.Texture = textures.Get(@"Menu/logo");
|
||||
}
|
||||
|
||||
private int lastBeatIndex;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
@@ -14,8 +13,6 @@ namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
private readonly OsuSpriteText beatmapTitle, beatmapDash, beatmapArtist;
|
||||
|
||||
private LocalisationEngine localisation;
|
||||
|
||||
public float TextSize
|
||||
{
|
||||
set { beatmapTitle.TextSize = beatmapDash.TextSize = beatmapArtist.TextSize = value; }
|
||||
@@ -48,12 +45,6 @@ namespace osu.Game.Screens.Multi.Components
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(LocalisationEngine localisation)
|
||||
{
|
||||
this.localisation = localisation;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@@ -64,15 +55,14 @@ namespace osu.Game.Screens.Multi.Components
|
||||
{
|
||||
if (beatmap == null)
|
||||
{
|
||||
beatmapTitle.Current = beatmapArtist.Current = null;
|
||||
beatmapTitle.Text = "Changing map";
|
||||
beatmapDash.Text = beatmapArtist.Text = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
beatmapTitle.Current = localisation.GetUnicodePreference(beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title);
|
||||
beatmapTitle.Text = new LocalisedString((beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title));
|
||||
beatmapDash.Text = @" - ";
|
||||
beatmapArtist.Current = localisation.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist);
|
||||
beatmapArtist.Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
@@ -81,7 +80,7 @@ namespace osu.Game.Screens
|
||||
private SampleChannel sampleExit;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private async Task load(BindableBeatmap beatmap, OsuGame osu, AudioManager audio, Bindable<RulesetInfo> ruleset)
|
||||
private void load(BindableBeatmap beatmap, OsuGame osu, AudioManager audio, Bindable<RulesetInfo> ruleset)
|
||||
{
|
||||
Beatmap.BindTo(beatmap);
|
||||
Ruleset.BindTo(ruleset);
|
||||
@@ -99,7 +98,7 @@ namespace osu.Game.Screens
|
||||
};
|
||||
}
|
||||
|
||||
sampleExit = await audio.Sample.GetAsync(@"UI/screen-back");
|
||||
sampleExit = audio.Sample.Get(@"UI/screen-back");
|
||||
}
|
||||
|
||||
public virtual bool OnPressed(GlobalAction action)
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play
|
||||
/// <summary>
|
||||
/// Action that is invoked when <see cref="GlobalAction.Back"/> is triggered.
|
||||
/// </summary>
|
||||
protected virtual Action BackAction => () => InternalButtons.Children.Last().TriggerOnClick();
|
||||
protected virtual Action BackAction => () => InternalButtons.Children.Last().Click();
|
||||
|
||||
public abstract string Header { get; }
|
||||
public abstract string Description { get; }
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace osu.Game.Screens.Play
|
||||
Direction = FillDirection.Vertical,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
KeyCounter = CreateKeyCounter(),
|
||||
KeyCounter = CreateKeyCounter(adjustableClock as IFrameBasedClock),
|
||||
HoldToQuit = CreateQuitButton(),
|
||||
}
|
||||
}
|
||||
@@ -194,12 +194,13 @@ namespace osu.Game.Screens.Play
|
||||
Margin = new MarginPadding { Top = 20 }
|
||||
};
|
||||
|
||||
protected virtual KeyCounterCollection CreateKeyCounter() => new KeyCounterCollection
|
||||
protected virtual KeyCounterCollection CreateKeyCounter(IFrameBasedClock offsetClock) => new KeyCounterCollection
|
||||
{
|
||||
FadeTime = 50,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
Margin = new MarginPadding(10),
|
||||
AudioClock = offsetClock
|
||||
};
|
||||
|
||||
protected virtual ScoreCounter CreateScoreCounter() => new ScoreCounter(6)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -20,6 +21,9 @@ namespace osu.Game.Screens.Play
|
||||
private Container textLayer;
|
||||
private SpriteText countSpriteText;
|
||||
|
||||
private readonly List<KeyCounterState> states = new List<KeyCounterState>();
|
||||
private KeyCounterState currentState;
|
||||
|
||||
public bool IsCounting { get; set; } = true;
|
||||
private int countPresses;
|
||||
public int CountPresses
|
||||
@@ -46,7 +50,10 @@ namespace osu.Game.Screens.Play
|
||||
isLit = value;
|
||||
updateGlowSprite(value);
|
||||
if (value && IsCounting)
|
||||
{
|
||||
CountPresses++;
|
||||
saveState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,19 +69,19 @@ namespace osu.Game.Screens.Play
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private async Task load(TextureStore textures)
|
||||
private void load(TextureStore textures)
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
buttonSprite = new Sprite
|
||||
{
|
||||
Texture = await textures.GetAsync(@"KeyCounter/key-up"),
|
||||
Texture = textures.Get(@"KeyCounter/key-up"),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
},
|
||||
glowSprite = new Sprite
|
||||
{
|
||||
Texture = await textures.GetAsync(@"KeyCounter/key-glow"),
|
||||
Texture = textures.Get(@"KeyCounter/key-glow"),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Alpha = 0
|
||||
@@ -129,6 +136,32 @@ namespace osu.Game.Screens.Play
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetCount() => CountPresses = 0;
|
||||
public void ResetCount()
|
||||
{
|
||||
CountPresses = 0;
|
||||
states.Clear();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (currentState?.Time > Clock.CurrentTime)
|
||||
restoreStateTo(Clock.CurrentTime);
|
||||
}
|
||||
|
||||
private void saveState()
|
||||
{
|
||||
if (currentState == null || currentState.Time < Clock.CurrentTime)
|
||||
states.Add(currentState = new KeyCounterState(Clock.CurrentTime, CountPresses));
|
||||
}
|
||||
|
||||
private void restoreStateTo(double time)
|
||||
{
|
||||
states.RemoveAll(state => state.Time > time);
|
||||
|
||||
currentState = states.LastOrDefault();
|
||||
CountPresses = currentState?.Count ?? 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Input.EventArgs;
|
||||
using osu.Framework.Input.States;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Configuration;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
@@ -37,6 +37,9 @@ namespace osu.Game.Screens.Play
|
||||
key.FadeTime = FadeTime;
|
||||
key.KeyDownTextColor = KeyDownTextColor;
|
||||
key.KeyUpTextColor = KeyUpTextColor;
|
||||
// Use the same clock object as SongProgress for saving KeyCounter state
|
||||
if (AudioClock != null)
|
||||
key.Clock = AudioClock;
|
||||
}
|
||||
|
||||
public void ResetCount()
|
||||
@@ -118,6 +121,8 @@ namespace osu.Game.Screens.Play
|
||||
public override bool HandleKeyboardInput => receptor == null;
|
||||
public override bool HandleMouseInput => receptor == null;
|
||||
|
||||
public IFrameBasedClock AudioClock { get; set; }
|
||||
|
||||
private Receptor receptor;
|
||||
|
||||
public Receptor GetReceptor()
|
||||
@@ -146,13 +151,18 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;
|
||||
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyDown(state, args));
|
||||
|
||||
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args) => Target.Children.Any(c => c.TriggerOnKeyUp(state, args));
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => Target.Children.Any(c => c.TriggerOnMouseDown(state, args));
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => Target.Children.Any(c => c.TriggerOnMouseUp(state, args));
|
||||
protected override bool Handle(UIEvent e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case KeyDownEvent _:
|
||||
case KeyUpEvent _:
|
||||
case MouseDownEvent _:
|
||||
case MouseUpEvent _:
|
||||
return Target.Children.Any(c => c.TriggerEvent(e));
|
||||
}
|
||||
return base.Handle(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class KeyCounterState
|
||||
{
|
||||
public KeyCounterState(double time, int count)
|
||||
{
|
||||
Time = time;
|
||||
Count = count;
|
||||
}
|
||||
|
||||
public readonly double Time;
|
||||
public readonly int Count;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user