mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 19:22:54 +08:00
Merge remote-tracking branch 'origin/deflate-branch' into deflate-branch
This commit is contained in:
commit
cf8e6cf0ec
@ -24,7 +24,9 @@ Clone the repository including submodules
|
|||||||
Build and run
|
Build and run
|
||||||
|
|
||||||
- Using Visual Studio 2017, Rider or Visual Studio Code (configurations are included)
|
- 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.
|
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.
|
||||||
|
|
||||||
|
@ -74,42 +74,42 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
|
|
||||||
private void initialiseHyperDash(List<CatchHitObject> objects)
|
private void initialiseHyperDash(List<CatchHitObject> objects)
|
||||||
{
|
{
|
||||||
// todo: add difficulty adjust.
|
List<CatchHitObject> objectWithDroplets = new List<CatchHitObject>();
|
||||||
double halfCatcherWidth = CatcherArea.CATCHER_SIZE * (objects.FirstOrDefault()?.Scale ?? 1) / CatchPlayfield.BASE_WIDTH / 2;
|
|
||||||
|
|
||||||
|
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;
|
int lastDirection = 0;
|
||||||
double lastExcess = halfCatcherWidth;
|
double lastExcess = halfCatcherWidth;
|
||||||
|
|
||||||
int objCount = objects.Count;
|
for (int i = 0; i < objectWithDroplets.Count - 1; i++)
|
||||||
|
|
||||||
for (int i = 0; i < objCount - 1; i++)
|
|
||||||
{
|
{
|
||||||
CatchHitObject currentObject = objects[i];
|
CatchHitObject currentObject = objectWithDroplets[i];
|
||||||
|
CatchHitObject nextObject = objectWithDroplets[i + 1];
|
||||||
// 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];
|
|
||||||
// }
|
|
||||||
|
|
||||||
int thisDirection = nextObject.X > currentObject.X ? 1 : -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);
|
double distanceToNext = Math.Abs(nextObject.X - currentObject.X) - (lastDirection == thisDirection ? lastExcess : halfCatcherWidth);
|
||||||
|
float distanceToHyper = (float)(timeToNext * CatcherArea.Catcher.BASE_SPEED - distanceToNext);
|
||||||
if (timeToNext * CatcherArea.Catcher.BASE_SPEED < distanceToNext)
|
if (distanceToHyper < 0)
|
||||||
{
|
{
|
||||||
currentObject.HyperDashTarget = nextObject;
|
currentObject.HyperDashTarget = nextObject;
|
||||||
lastExcess = halfCatcherWidth;
|
lastExcess = halfCatcherWidth;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//currentObject.DistanceToHyperDash = timeToNext - distanceToNext;
|
currentObject.DistanceToHyperDash = distanceToHyper;
|
||||||
lastExcess = MathHelper.Clamp(timeToNext - distanceToNext, 0, halfCatcherWidth);
|
lastExcess = MathHelper.Clamp(distanceToHyper, 0, halfCatcherWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastDirection = thisDirection;
|
lastDirection = thisDirection;
|
||||||
|
@ -27,7 +27,9 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
public int ComboIndex { get; set; }
|
public int ComboIndex { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public float DistanceToHyperDash { get; set; }
|
public float DistanceToHyperDash { get; set; }
|
||||||
|
|
||||||
|
@ -107,6 +107,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj);
|
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>
|
public class Catcher : Container, IKeyBindingHandler<CatchAction>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -111,6 +111,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
bodyPiece.Height = DrawHeight - Head.Height / 2 + Tail.Height / 2;
|
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)
|
public bool OnPressed(ManiaAction action)
|
||||||
{
|
{
|
||||||
// Make sure the action happened within the body of the hold note
|
// 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
|
// 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
|
// 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.
|
// user has pressed during the hit windows of the head note.
|
||||||
holdStartTime = Time.Current;
|
BeginHold();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +148,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
if (action != Action.Value)
|
if (action != Action.Value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
holdStartTime = null;
|
EndHold();
|
||||||
|
|
||||||
// If the key has been released too early, the user should not receive full score for the release
|
// If the key has been released too early, the user should not receive full score for the release
|
||||||
if (!Tail.IsHit)
|
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 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
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
background = new Box { RelativeSizeAxes = Axes.Both },
|
background = new Box { RelativeSizeAxes = Axes.Both },
|
||||||
foreground = new BufferedContainer
|
foreground = new BufferedContainer
|
||||||
{
|
{
|
||||||
|
Blending = BlendingMode.Additive,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
CacheDrawnFrameBuffer = true,
|
CacheDrawnFrameBuffer = true,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
@ -73,6 +74,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Color4 accentColour;
|
private Color4 accentColour;
|
||||||
|
|
||||||
public Color4 AccentColour
|
public Color4 AccentColour
|
||||||
{
|
{
|
||||||
get { return 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();
|
private Cached subtractionCache = new Cached();
|
||||||
|
|
||||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
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()
|
private void updateAccentColour()
|
||||||
{
|
{
|
||||||
if (!IsLoaded)
|
if (!IsLoaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreground.Colour = AccentColour.Opacity(0.9f);
|
foreground.Colour = AccentColour.Opacity(0.5f);
|
||||||
background.Colour = AccentColour.Opacity(0.6f);
|
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();
|
subtractionCache.Invalidate();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
public class DrawableOsuHitObject : DrawableHitObject<OsuHitObject>
|
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;
|
private readonly ShakeContainer shakeContainer;
|
||||||
|
|
||||||
|
@ -7,14 +7,15 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.OpenGL.Textures;
|
|
||||||
using osu.Framework.Graphics.Lines;
|
using osu.Framework.Graphics.Lines;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Graphics.ES30;
|
using OpenTK.Graphics.ES30;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Framework.Graphics.Primitives;
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using OpenTK;
|
||||||
|
using SixLabors.ImageSharp;
|
||||||
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
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; }
|
public double? SnakedEnd { get; private set; }
|
||||||
|
|
||||||
private Color4 accentColour = Color4.White;
|
private Color4 accentColour = Color4.White;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to colour the path.
|
/// Used to colour the path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -61,6 +63,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Color4 borderColour = Color4.White;
|
private Color4 borderColour = Color4.White;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to colour the path border.
|
/// Used to colour the path border.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -85,6 +88,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
private Vector2 topLeftOffset;
|
private Vector2 topLeftOffset;
|
||||||
|
|
||||||
private readonly Slider slider;
|
private readonly Slider slider;
|
||||||
|
|
||||||
public SliderBody(Slider s)
|
public SliderBody(Slider s)
|
||||||
{
|
{
|
||||||
slider = s;
|
slider = s;
|
||||||
@ -139,8 +143,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
var texture = new Texture(textureWidth, 1);
|
var texture = new Texture(textureWidth, 1);
|
||||||
|
|
||||||
//initialise background
|
//initialise background
|
||||||
var raw = new RawTexture(textureWidth, 1);
|
var raw = new Image<Rgba32>(textureWidth, 1);
|
||||||
var bytes = raw.Data;
|
|
||||||
|
|
||||||
const float aa_portion = 0.02f;
|
const float aa_portion = 0.02f;
|
||||||
const float border_portion = 0.128f;
|
const float border_portion = 0.128f;
|
||||||
@ -155,19 +158,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
if (progress <= border_portion)
|
if (progress <= border_portion)
|
||||||
{
|
{
|
||||||
bytes[i * 4] = (byte)(BorderColour.R * 255);
|
raw[i, 0] = new Rgba32(BorderColour.R, BorderColour.G, BorderColour.B, Math.Min(progress / aa_portion, 1) * BorderColour.A);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
progress -= border_portion;
|
progress -= border_portion;
|
||||||
|
raw[i, 0] = new Rgba32(AccentColour.R, AccentColour.G, AccentColour.B,
|
||||||
bytes[i * 4] = (byte)(AccentColour.R * 255);
|
(opacity_at_edge - (opacity_at_edge - opacity_at_centre) * progress / gradient_portion) * AccentColour.A);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
|
|
||||||
Texture.DrawQuad(
|
Texture.DrawQuad(
|
||||||
new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y),
|
new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y),
|
||||||
DrawInfo.Colour,
|
DrawColourInfo.Colour,
|
||||||
null,
|
null,
|
||||||
v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex
|
v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
@ -62,6 +63,8 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public override string[] HandledExtensions => new[] { ".osz" };
|
public override string[] HandledExtensions => new[] { ".osz" };
|
||||||
|
|
||||||
|
protected override string ImportFromStablePath => "Songs";
|
||||||
|
|
||||||
private readonly RulesetStore rulesets;
|
private readonly RulesetStore rulesets;
|
||||||
|
|
||||||
private readonly BeatmapStore beatmaps;
|
private readonly BeatmapStore beatmaps;
|
||||||
@ -72,11 +75,6 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
private readonly List<DownloadBeatmapSetRequest> currentDownloads = new List<DownloadBeatmapSetRequest>();
|
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)
|
public BeatmapManager(Storage storage, IDatabaseContextFactory contextFactory, RulesetStore rulesets, APIAccess api, AudioManager audioManager, IIpcHost importHost = null)
|
||||||
: base(storage, contextFactory, new BeatmapStore(contextFactory), importHost)
|
: base(storage, contextFactory, new BeatmapStore(contextFactory), importHost)
|
||||||
{
|
{
|
||||||
@ -195,7 +193,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
downloadNotification.CompletionClickAction = () =>
|
downloadNotification.CompletionClickAction = () =>
|
||||||
{
|
{
|
||||||
PresentBeatmap?.Invoke(importedBeatmap);
|
PresentCompletedImport(importedBeatmap.Yield());
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
downloadNotification.State = ProgressNotificationState.Completed;
|
downloadNotification.State = ProgressNotificationState.Completed;
|
||||||
@ -231,6 +229,12 @@ namespace osu.Game.Beatmaps
|
|||||||
BeatmapDownloadBegan?.Invoke(request);
|
BeatmapDownloadBegan?.Invoke(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void PresentCompletedImport(IEnumerable<BeatmapSetInfo> imported)
|
||||||
|
{
|
||||||
|
base.PresentCompletedImport(imported);
|
||||||
|
PresentBeatmap?.Invoke(imported.LastOrDefault());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get an existing download request if it exists.
|
/// Get an existing download request if it exists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -311,27 +315,6 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <returns>Results from the provided query.</returns>
|
/// <returns>Results from the provided query.</returns>
|
||||||
public IQueryable<BeatmapInfo> QueryBeatmaps(Expression<Func<BeatmapInfo, bool>> query) => beatmaps.Beatmaps.AsNoTracking().Where(query);
|
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>
|
/// <summary>
|
||||||
/// Create a SHA-2 hash from the provided archive based on contained beatmap (.osu) file content.
|
/// Create a SHA-2 hash from the provided archive based on contained beatmap (.osu) file content.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -10,7 +10,6 @@ using osu.Framework.Graphics.Textures;
|
|||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Beatmaps.Formats;
|
using osu.Game.Beatmaps.Formats;
|
||||||
using osu.Game.Graphics.Textures;
|
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using osu.Game.Storyboards;
|
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 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()
|
protected override Texture GetBackground()
|
||||||
{
|
{
|
||||||
if (Metadata?.BackgroundFile == null)
|
if (Metadata?.BackgroundFile == null)
|
||||||
@ -52,7 +55,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new LargeTextureStore(new RawTextureLoaderStore(store)).Get(getPathForFile(Metadata.BackgroundFile));
|
return (textureStore ?? (textureStore = new LargeTextureStore(new TextureLoaderStore(store)))).Get(getPathForFile(Metadata.BackgroundFile));
|
||||||
}
|
}
|
||||||
catch
|
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()
|
protected override Waveform GetWaveform()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -8,10 +8,10 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using osu.Game.Storyboards;
|
using osu.Game.Storyboards;
|
||||||
using osu.Framework.IO.File;
|
using osu.Framework.IO.File;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
using osu.Game.IO.Serialization;
|
using osu.Game.IO.Serialization;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
@ -38,12 +38,26 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
Mods.ValueChanged += mods => applyRateAdjustments();
|
Mods.ValueChanged += mods => applyRateAdjustments();
|
||||||
|
|
||||||
beatmap = new AsyncLazy<IBeatmap>(populateBeatmap);
|
beatmap = new RecyclableLazy<IBeatmap>(() =>
|
||||||
background = new AsyncLazy<Texture>(populateBackground, b => b == null || !b.IsDisposed);
|
{
|
||||||
track = new AsyncLazy<Track>(populateTrack);
|
var b = GetBeatmap() ?? new Beatmap();
|
||||||
waveform = new AsyncLazy<Waveform>(populateWaveform);
|
// use the database-backed info.
|
||||||
storyboard = new AsyncLazy<Storyboard>(populateStoryboard);
|
b.BeatmapInfo = BeatmapInfo;
|
||||||
skin = new AsyncLazy<Skin>(populateSkin);
|
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>
|
/// <summary>
|
||||||
@ -58,28 +72,6 @@ namespace osu.Game.Beatmaps
|
|||||||
return path;
|
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>
|
/// <summary>
|
||||||
/// Constructs a playable <see cref="IBeatmap"/> from <see cref="Beatmap"/> using the applicable converters for a specific <see cref="RulesetInfo"/>.
|
/// Constructs a playable <see cref="IBeatmap"/> from <see cref="Beatmap"/> using the applicable converters for a specific <see cref="RulesetInfo"/>.
|
||||||
/// <para>
|
/// <para>
|
||||||
@ -136,62 +128,53 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
public override string ToString() => BeatmapInfo.ToString();
|
public override string ToString() => BeatmapInfo.ToString();
|
||||||
|
|
||||||
public bool BackgroundLoaded => background.IsResultAvailable;
|
public bool BeatmapLoaded => beatmap.IsResultAvailable;
|
||||||
public Texture Background => background.Value.Result;
|
public IBeatmap Beatmap => beatmap.Value;
|
||||||
public Task<Texture> GetBackgroundAsync() => background.Value;
|
protected abstract IBeatmap GetBeatmap();
|
||||||
private AsyncLazy<Texture> background;
|
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 bool TrackLoaded => track.IsResultAvailable;
|
||||||
public Track Track => track.Value.Result;
|
public Track Track => track.Value;
|
||||||
public Task<Track> GetTrackAsync() => track.Value;
|
protected abstract Track GetTrack();
|
||||||
private AsyncLazy<Track> track;
|
private RecyclableLazy<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 bool WaveformLoaded => waveform.IsResultAvailable;
|
public bool WaveformLoaded => waveform.IsResultAvailable;
|
||||||
public Waveform Waveform => waveform.Value.Result;
|
public Waveform Waveform => waveform.Value;
|
||||||
public Task<Waveform> GetWaveformAsync() => waveform.Value;
|
protected virtual Waveform GetWaveform() => new Waveform();
|
||||||
private readonly AsyncLazy<Waveform> waveform;
|
private readonly RecyclableLazy<Waveform> waveform;
|
||||||
|
|
||||||
private Waveform populateWaveform() => GetWaveform();
|
|
||||||
|
|
||||||
public bool StoryboardLoaded => storyboard.IsResultAvailable;
|
public bool StoryboardLoaded => storyboard.IsResultAvailable;
|
||||||
public Storyboard Storyboard => storyboard.Value.Result;
|
public Storyboard Storyboard => storyboard.Value;
|
||||||
public Task<Storyboard> GetStoryboardAsync() => storyboard.Value;
|
protected virtual Storyboard GetStoryboard() => new Storyboard { BeatmapInfo = BeatmapInfo };
|
||||||
private readonly AsyncLazy<Storyboard> storyboard;
|
private readonly RecyclableLazy<Storyboard> storyboard;
|
||||||
|
|
||||||
private Storyboard populateStoryboard() => GetStoryboard();
|
|
||||||
|
|
||||||
public bool SkinLoaded => skin.IsResultAvailable;
|
public bool SkinLoaded => skin.IsResultAvailable;
|
||||||
public Skin Skin => skin.Value.Result;
|
public Skin Skin => skin.Value;
|
||||||
public Task<Skin> GetSkinAsync() => skin.Value;
|
protected virtual Skin GetSkin() => new DefaultSkin();
|
||||||
private readonly AsyncLazy<Skin> skin;
|
private readonly RecyclableLazy<Skin> skin;
|
||||||
|
|
||||||
private Skin populateSkin() => GetSkin();
|
/// <summary>
|
||||||
|
/// Transfer pieces of a beatmap to a new one, where possible, to save on loading.
|
||||||
public void TransferTo(WorkingBeatmap other)
|
/// </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))
|
if (track.IsResultAvailable && Track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo))
|
||||||
other.track = track;
|
other.track = track;
|
||||||
|
|
||||||
if (background.IsResultAvailable && Background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo))
|
|
||||||
other.background = background;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
if (BackgroundLoaded) Background?.Dispose();
|
background.Recycle();
|
||||||
if (WaveformLoaded) Waveform?.Dispose();
|
waveform.Recycle();
|
||||||
if (StoryboardLoaded) Storyboard?.Dispose();
|
storyboard.Recycle();
|
||||||
if (SkinLoaded) Skin?.Dispose();
|
skin.Recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -210,15 +193,15 @@ namespace osu.Game.Beatmaps
|
|||||||
mod.ApplyToClock(t);
|
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> valueFactory;
|
||||||
private readonly Func<T, bool> stillValidFunction;
|
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.valueFactory = valueFactory;
|
||||||
this.stillValidFunction = stillValidFunction;
|
this.stillValidFunction = stillValidFunction;
|
||||||
@ -230,45 +213,28 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
if (!IsResultAvailable) return;
|
if (!IsResultAvailable) return;
|
||||||
|
|
||||||
(lazy.Value.Result as IDisposable)?.Dispose();
|
(lazy.Value as IDisposable)?.Dispose();
|
||||||
recreate();
|
recreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsResultAvailable
|
public bool IsResultAvailable => stillValid;
|
||||||
|
|
||||||
|
public T Value
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
recreateIfInvalid();
|
lock (fetchLock)
|
||||||
return lazy.Value.IsCompleted;
|
{
|
||||||
|
if (!stillValid)
|
||||||
|
recreate();
|
||||||
|
return lazy.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<T> Value
|
private bool stillValid => lazy.IsValueCreated && (stillValidFunction?.Invoke(lazy.Value) ?? true);
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
recreateIfInvalid();
|
|
||||||
return lazy.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recreateIfInvalid()
|
private void recreate() => lazy = new Lazy<T>(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication);
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using osu.Framework.IO.File;
|
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)
|
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
|
||||||
private ArchiveImportIPCChannel ipc;
|
private ArchiveImportIPCChannel ipc;
|
||||||
|
|
||||||
private readonly List<Action> cachedEvents = new List<Action>();
|
private readonly List<Action> queuedEvents = new List<Action>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows delaying of outwards events until an operation is confirmed (at a database level).
|
/// 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>
|
/// <param name="perform">Whether the flushed events should be performed.</param>
|
||||||
private void flushEvents(bool perform)
|
private void flushEvents(bool perform)
|
||||||
{
|
{
|
||||||
|
Action[] events;
|
||||||
|
lock (queuedEvents)
|
||||||
|
{
|
||||||
|
events = queuedEvents.ToArray();
|
||||||
|
queuedEvents.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
if (perform)
|
if (perform)
|
||||||
{
|
{
|
||||||
foreach (var a in cachedEvents)
|
foreach (var a in events)
|
||||||
a.Invoke();
|
a.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedEvents.Clear();
|
|
||||||
delayingEvents = false;
|
delayingEvents = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEvent(Action a)
|
private void handleEvent(Action a)
|
||||||
{
|
{
|
||||||
if (delayingEvents)
|
if (delayingEvents)
|
||||||
cachedEvents.Add(a);
|
lock (queuedEvents) queuedEvents.Add(a);
|
||||||
else
|
else
|
||||||
a.Invoke();
|
a.Invoke();
|
||||||
}
|
}
|
||||||
@ -129,7 +136,6 @@ namespace osu.Game.Database
|
|||||||
List<TModel> imported = new List<TModel>();
|
List<TModel> imported = new List<TModel>();
|
||||||
|
|
||||||
int current = 0;
|
int current = 0;
|
||||||
int errors = 0;
|
|
||||||
foreach (string path in paths)
|
foreach (string path in paths)
|
||||||
{
|
{
|
||||||
if (notification.State == ProgressNotificationState.Cancelled)
|
if (notification.State == ProgressNotificationState.Cancelled)
|
||||||
@ -162,12 +168,29 @@ namespace osu.Game.Database
|
|||||||
{
|
{
|
||||||
e = e.InnerException ?? e;
|
e = e.InnerException ?? e;
|
||||||
Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})");
|
Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})");
|
||||||
errors++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.Text = errors > 0 ? $"Import complete with {errors} errors" : "Import successful!";
|
if (imported.Count == 0)
|
||||||
notification.State = ProgressNotificationState.Completed;
|
{
|
||||||
|
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>
|
/// <summary>
|
||||||
@ -283,7 +306,7 @@ namespace osu.Game.Database
|
|||||||
var notification = new ProgressNotification
|
var notification = new ProgressNotification
|
||||||
{
|
{
|
||||||
Progress = 0,
|
Progress = 0,
|
||||||
CompletionText = "Deleted all beatmaps!",
|
CompletionText = $"Deleted all {typeof(TModel).Name.Replace("Info", "").ToLower()}s!",
|
||||||
State = ProgressNotificationState.Active,
|
State = ProgressNotificationState.Active,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -385,6 +408,41 @@ namespace osu.Game.Database
|
|||||||
return fileInfos;
|
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>
|
/// <summary>
|
||||||
/// Create a barebones model from the provided archive.
|
/// 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.
|
/// Actual expensive population should be done in <see cref="Populate"/>; this should just prepare for duplicate checking.
|
||||||
|
@ -5,8 +5,8 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Textures;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Game.Graphics.Textures;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Backgrounds
|
namespace osu.Game.Graphics.Backgrounds
|
||||||
{
|
{
|
||||||
|
@ -116,7 +116,7 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
|
|
||||||
float adjustedAlpha = HideAlphaDiscrepancies ?
|
float adjustedAlpha = HideAlphaDiscrepancies ?
|
||||||
// Cubically scale alpha to make it drop off more sharply.
|
// 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;
|
1;
|
||||||
|
|
||||||
float elapsedSeconds = (float)Time.Elapsed / 1000;
|
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)
|
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);
|
colourInfo.ApplyChild(particle.Colour);
|
||||||
|
|
||||||
Texture.DrawTriangle(
|
Texture.DrawTriangle(
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
@ -16,7 +15,6 @@ namespace osu.Game.Graphics
|
|||||||
|
|
||||||
public DrawableDate(DateTimeOffset date)
|
public DrawableDate(DateTimeOffset date)
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
|
||||||
Font = "Exo2.0-RegularItalic";
|
Font = "Exo2.0-RegularItalic";
|
||||||
|
|
||||||
Date = date.ToLocalTime();
|
Date = date.ToLocalTime();
|
||||||
|
@ -95,7 +95,7 @@ namespace osu.Game.Graphics
|
|||||||
{
|
{
|
||||||
//adjust shadow alpha based on highest component intensity to avoid muddy display of darker text.
|
//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.
|
//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);
|
spriteShadow.Alpha = (float)Math.Pow(Math.Max(Math.Max(avgColour.R, avgColour.G), avgColour.B), 2);
|
||||||
|
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.MathUtils;
|
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Graphics;
|
|
||||||
using osu.Framework.Graphics.Transforms;
|
using osu.Framework.Graphics.Transforms;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Sprites
|
namespace osu.Game.Graphics.Sprites
|
||||||
@ -19,27 +16,6 @@ namespace osu.Game.Graphics.Sprites
|
|||||||
Shadow = true;
|
Shadow = true;
|
||||||
TextSize = FONT_SIZE;
|
TextSize = FONT_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateFallbackCharacterDrawable()
|
|
||||||
{
|
|
||||||
var tex = GetTextureForCharacter('?');
|
|
||||||
|
|
||||||
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
|
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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,12 +2,10 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
@ -26,7 +24,7 @@ namespace osu.Game.Online.API
|
|||||||
private const string client_id = @"5";
|
private const string client_id = @"5";
|
||||||
private const string client_secret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk";
|
private const string client_secret = @"FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk";
|
||||||
|
|
||||||
private ConcurrentQueue<APIRequest> queue = new ConcurrentQueue<APIRequest>();
|
private readonly Queue<APIRequest> queue = new Queue<APIRequest>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The username/email provided by the user when initiating a login.
|
/// 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.TokenString = config.Get<string>(OsuSetting.Token);
|
||||||
authentication.Token.ValueChanged += onTokenChanged;
|
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);
|
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)
|
public void Unregister(IOnlineComponent component)
|
||||||
{
|
{
|
||||||
Scheduler.Add(delegate
|
Scheduler.Add(delegate { components.Remove(component); });
|
||||||
{
|
|
||||||
components.Remove(component);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string AccessToken => authentication.RequestAccessToken();
|
public string AccessToken => authentication.RequestAccessToken();
|
||||||
@ -103,6 +104,7 @@ namespace osu.Game.Online.API
|
|||||||
log.Add(@"Queueing a ping request");
|
log.Add(@"Queueing a ping request");
|
||||||
Queue(new ListChannelsRequest { Timeout = 5000 });
|
Queue(new ListChannelsRequest { Timeout = 5000 });
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case APIState.Offline:
|
case APIState.Offline:
|
||||||
case APIState.Connecting:
|
case APIState.Connecting:
|
||||||
@ -161,18 +163,21 @@ namespace osu.Game.Online.API
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//process the request queue.
|
while (true)
|
||||||
APIRequest req;
|
|
||||||
while (queue.TryPeek(out req))
|
|
||||||
{
|
{
|
||||||
if (handleRequest(req))
|
APIRequest req;
|
||||||
|
|
||||||
|
lock (queue)
|
||||||
{
|
{
|
||||||
//we have succeeded, so let's unqueue.
|
if (queue.Count == 0) break;
|
||||||
queue.TryDequeue(out req);
|
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)
|
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.
|
// special cases for un-typed but useful message responses.
|
||||||
switch (we.Message)
|
switch (we.Message)
|
||||||
@ -247,6 +253,7 @@ namespace osu.Game.Online.API
|
|||||||
}
|
}
|
||||||
|
|
||||||
private APIState state;
|
private APIState state;
|
||||||
|
|
||||||
public APIState State
|
public APIState State
|
||||||
{
|
{
|
||||||
get { return state; }
|
get { return state; }
|
||||||
@ -271,7 +278,10 @@ namespace osu.Game.Online.API
|
|||||||
|
|
||||||
public bool IsLoggedIn => LocalUser.Value.Id > 1;
|
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;
|
public event StateChangeDelegate OnStateChange;
|
||||||
|
|
||||||
@ -279,16 +289,17 @@ namespace osu.Game.Online.API
|
|||||||
|
|
||||||
private void flushQueue(bool failOldRequests = true)
|
private void flushQueue(bool failOldRequests = true)
|
||||||
{
|
{
|
||||||
var oldQueue = queue;
|
lock (queue)
|
||||||
|
|
||||||
//flush the queue.
|
|
||||||
queue = new ConcurrentQueue<APIRequest>();
|
|
||||||
|
|
||||||
if (failOldRequests)
|
|
||||||
{
|
{
|
||||||
APIRequest req;
|
var oldQueueRequests = queue.ToArray();
|
||||||
while (oldQueue.TryDequeue(out req))
|
|
||||||
req.Fail(new WebException(@"Disconnected from server"));
|
queue.Clear();
|
||||||
|
|
||||||
|
if (failOldRequests)
|
||||||
|
{
|
||||||
|
foreach (var req in oldQueueRequests)
|
||||||
|
req.Fail(new WebException(@"Disconnected from server"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,11 +299,13 @@ namespace osu.Game
|
|||||||
// This prevents the cursor from showing until we have a screen with CursorVisible = true
|
// This prevents the cursor from showing until we have a screen with CursorVisible = true
|
||||||
MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
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);
|
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.GetStableStorage = GetStorageForStableInstall;
|
||||||
|
|
||||||
BeatmapManager.PresentBeatmap = PresentBeatmap;
|
BeatmapManager.PresentBeatmap = PresentBeatmap;
|
||||||
|
|
||||||
AddRange(new Drawable[]
|
AddRange(new Drawable[]
|
||||||
|
@ -24,7 +24,6 @@ using osu.Framework.Input;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics.Textures;
|
|
||||||
using osu.Game.Input;
|
using osu.Game.Input;
|
||||||
using osu.Game.Input.Bindings;
|
using osu.Game.Input.Bindings;
|
||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
@ -109,11 +108,39 @@ namespace osu.Game
|
|||||||
|
|
||||||
dependencies.Cache(contextFactory = new DatabaseContextFactory(Host.Storage));
|
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.CacheAs(this);
|
||||||
dependencies.Cache(LocalConfig);
|
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();
|
runMigrations();
|
||||||
|
|
||||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
||||||
@ -137,33 +164,6 @@ namespace osu.Game
|
|||||||
fileImporters.Add(ScoreStore);
|
fileImporters.Add(ScoreStore);
|
||||||
fileImporters.Add(SkinManager);
|
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);
|
var defaultBeatmap = new DummyWorkingBeatmap(this);
|
||||||
beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio);
|
beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio);
|
||||||
BeatmapManager.DefaultBeatmap = defaultBeatmap;
|
BeatmapManager.DefaultBeatmap = defaultBeatmap;
|
||||||
|
@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset);
|
getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset);
|
||||||
getScoresRequest.Success += r => Scores = r.Scores;
|
getScoresRequest.Success += r => Schedule(() => Scores = r.Scores);
|
||||||
api.Queue(getScoresRequest);
|
api.Queue(getScoresRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,5 +134,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
this.api = api;
|
this.api = api;
|
||||||
updateDisplay();
|
updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
getScoresRequest?.Cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,6 @@ namespace osu.Game.Overlays.Direct
|
|||||||
beatmaps.ItemAdded += setAdded;
|
beatmaps.ItemAdded += setAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool DisposeOnDeathRemoval => true;
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
|
@ -118,9 +118,9 @@ namespace osu.Game.Overlays.MedalSplash
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours, TextureStore textures)
|
private void load(OsuColour colours, TextureStore textures, LargeTextureStore largeTextures)
|
||||||
{
|
{
|
||||||
medalSprite.Texture = textures.Get(medal.ImageUrl);
|
medalSprite.Texture = largeTextures.Get(medal.ImageUrl);
|
||||||
medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow");
|
medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow");
|
||||||
description.Colour = colours.BlueLight;
|
description.Colour = colours.BlueLight;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ namespace osu.Game.Overlays.Notifications
|
|||||||
public Action<Notification> CompletionTarget { get; set; }
|
public Action<Notification> CompletionTarget { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public Func<bool> CompletionClickAction;
|
public Func<bool> CompletionClickAction;
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ namespace osu.Game.Overlays.Profile.Header
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
Child = new Sprite
|
Child = new Sprite
|
||||||
{
|
{
|
||||||
|
@ -14,8 +14,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
|||||||
public class PaginatedBeatmapContainer : PaginatedContainer
|
public class PaginatedBeatmapContainer : PaginatedContainer
|
||||||
{
|
{
|
||||||
private const float panel_padding = 10f;
|
private const float panel_padding = 10f;
|
||||||
|
|
||||||
private readonly BeatmapSetType type;
|
private readonly BeatmapSetType type;
|
||||||
|
private GetUserBeatmapsRequest request;
|
||||||
|
|
||||||
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<User> user, string header, string missing = "None... yet.")
|
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<User> user, string header, string missing = "None... yet.")
|
||||||
: base(user, header, missing)
|
: base(user, header, missing)
|
||||||
@ -31,9 +31,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
|||||||
{
|
{
|
||||||
base.ShowMore();
|
base.ShowMore();
|
||||||
|
|
||||||
var req = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||||
|
request.Success += sets => Schedule(() =>
|
||||||
req.Success += sets =>
|
|
||||||
{
|
{
|
||||||
ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
|
ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
|
||||||
ShowMoreLoading.Hide();
|
ShowMoreLoading.Hide();
|
||||||
@ -52,9 +51,15 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
|||||||
var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets));
|
var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets));
|
||||||
ItemsContainer.Add(panel);
|
ItemsContainer.Add(panel);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
Api.Queue(req);
|
Api.Queue(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
request?.Cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
|||||||
{
|
{
|
||||||
public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer
|
public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer
|
||||||
{
|
{
|
||||||
|
private GetUserMostPlayedBeatmapsRequest request;
|
||||||
|
|
||||||
public PaginatedMostPlayedBeatmapContainer(Bindable<User> user)
|
public PaginatedMostPlayedBeatmapContainer(Bindable<User> user)
|
||||||
:base(user, "Most Played Beatmaps", "No records. :(")
|
:base(user, "Most Played Beatmaps", "No records. :(")
|
||||||
{
|
{
|
||||||
@ -24,9 +26,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
|||||||
{
|
{
|
||||||
base.ShowMore();
|
base.ShowMore();
|
||||||
|
|
||||||
var req = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||||
|
request.Success += beatmaps => Schedule(() =>
|
||||||
req.Success += beatmaps =>
|
|
||||||
{
|
{
|
||||||
ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
|
ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
|
||||||
ShowMoreLoading.Hide();
|
ShowMoreLoading.Hide();
|
||||||
@ -43,9 +44,16 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
|||||||
{
|
{
|
||||||
ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount));
|
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 readonly Bindable<User> User = new Bindable<User>();
|
||||||
|
|
||||||
protected APIAccess Api;
|
protected APIAccess Api;
|
||||||
|
protected APIRequest RetrievalRequest;
|
||||||
protected RulesetStore Rulesets;
|
protected RulesetStore Rulesets;
|
||||||
|
|
||||||
public PaginatedContainer(Bindable<User> user, string header, string missing)
|
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 bool includeWeight;
|
||||||
private readonly ScoreType type;
|
private readonly ScoreType type;
|
||||||
|
private GetUserScoresRequest request;
|
||||||
|
|
||||||
public PaginatedScoreContainer(ScoreType type, Bindable<User> user, string header, string missing, bool includeWeight = false)
|
public PaginatedScoreContainer(ScoreType type, Bindable<User> user, string header, string missing, bool includeWeight = false)
|
||||||
: base(user, header, missing)
|
: base(user, header, missing)
|
||||||
@ -32,9 +33,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
{
|
{
|
||||||
base.ShowMore();
|
base.ShowMore();
|
||||||
|
|
||||||
var req = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||||
|
request.Success += scores => Schedule(() =>
|
||||||
req.Success += scores =>
|
|
||||||
{
|
{
|
||||||
foreach (var s in scores)
|
foreach (var s in scores)
|
||||||
s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID));
|
s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID));
|
||||||
@ -66,9 +66,15 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
|
|
||||||
ItemsContainer.Add(drawableScore);
|
ItemsContainer.Add(drawableScore);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
Api.Queue(req);
|
Api.Queue(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
request?.Cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
sprite.Texture = textures.Get(url);
|
sprite.Texture = textures.Get(url);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
|||||||
{
|
{
|
||||||
public class PaginatedRecentActivityContainer : PaginatedContainer
|
public class PaginatedRecentActivityContainer : PaginatedContainer
|
||||||
{
|
{
|
||||||
|
private GetUserRecentActivitiesRequest request;
|
||||||
|
|
||||||
public PaginatedRecentActivityContainer(Bindable<User> user, string header, string missing)
|
public PaginatedRecentActivityContainer(Bindable<User> user, string header, string missing)
|
||||||
: base(user, header, missing)
|
: base(user, header, missing)
|
||||||
{
|
{
|
||||||
@ -22,9 +24,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
|||||||
{
|
{
|
||||||
base.ShowMore();
|
base.ShowMore();
|
||||||
|
|
||||||
var req = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||||
|
request.Success += activities => Schedule(() =>
|
||||||
req.Success += activities =>
|
|
||||||
{
|
{
|
||||||
ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
|
ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
|
||||||
ShowMoreLoading.Hide();
|
ShowMoreLoading.Hide();
|
||||||
@ -41,9 +42,15 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
|||||||
{
|
{
|
||||||
ItemsContainer.Add(new DrawableRecentActivity(activity));
|
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>.
|
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
|
||||||
@ -15,21 +19,36 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
|||||||
private FillFlowContainer letterboxSettings;
|
private FillFlowContainer letterboxSettings;
|
||||||
|
|
||||||
private Bindable<bool> letterboxing;
|
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;
|
private const int transition_duration = 400;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(FrameworkConfigManager config)
|
private void load(FrameworkConfigManager config, OsuGameBase game)
|
||||||
{
|
{
|
||||||
|
this.game = game;
|
||||||
|
|
||||||
letterboxing = config.GetBindable<bool>(FrameworkSetting.Letterboxing);
|
letterboxing = config.GetBindable<bool>(FrameworkSetting.Letterboxing);
|
||||||
|
sizeFullscreen = config.GetBindable<Size>(FrameworkSetting.SizeFullscreen);
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new SettingsEnumDropdown<WindowMode>
|
windowModeDropdown = new SettingsEnumDropdown<WindowMode>
|
||||||
{
|
{
|
||||||
LabelText = "Screen mode",
|
LabelText = "Screen mode",
|
||||||
Bindable = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
|
Bindable = config.GetBindable<WindowMode>(FrameworkSetting.WindowMode),
|
||||||
},
|
},
|
||||||
|
resolutionDropdown = new SettingsDropdown<Size>
|
||||||
|
{
|
||||||
|
LabelText = "Resolution",
|
||||||
|
ShowsDefaultIndicator = false,
|
||||||
|
Items = getResolutions(),
|
||||||
|
Bindable = sizeFullscreen
|
||||||
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
LabelText = "Letterboxing",
|
LabelText = "Letterboxing",
|
||||||
@ -62,15 +81,39 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
letterboxing.ValueChanged += isVisible =>
|
windowModeDropdown.Bindable.BindValueChanged(windowMode =>
|
||||||
|
{
|
||||||
|
if (windowMode == WindowMode.Fullscreen)
|
||||||
|
{
|
||||||
|
resolutionDropdown.Show();
|
||||||
|
sizeFullscreen.TriggerChange();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
resolutionDropdown.Hide();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
letterboxing.BindValueChanged(isVisible =>
|
||||||
{
|
{
|
||||||
letterboxSettings.ClearTransforms();
|
letterboxSettings.ClearTransforms();
|
||||||
letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None;
|
letterboxSettings.AutoSizeAxes = isVisible ? Axes.Y : Axes.None;
|
||||||
|
|
||||||
if (!isVisible)
|
if (!isVisible)
|
||||||
letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint);
|
letterboxSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint);
|
||||||
};
|
}, true);
|
||||||
letterboxing.TriggerChange();
|
}
|
||||||
|
|
||||||
|
private IEnumerable<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()).ToList();
|
||||||
|
return resolutions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||||
{
|
{
|
||||||
@ -20,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
|||||||
protected override string Header => "General";
|
protected override string Header => "General";
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(BeatmapManager beatmaps, DialogOverlay dialogOverlay)
|
private void load(BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay)
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -30,7 +31,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
|||||||
Action = () =>
|
Action = () =>
|
||||||
{
|
{
|
||||||
importButton.Enabled.Value = false;
|
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
|
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
|
restoreButton = new SettingsButton
|
||||||
{
|
{
|
||||||
Text = "Restore all hidden difficulties",
|
Text = "Restore all hidden difficulties",
|
||||||
|
@ -51,10 +51,10 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
skins.ItemAdded += onItemsChanged;
|
skins.ItemAdded += itemAdded;
|
||||||
skins.ItemRemoved += onItemsChanged;
|
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);
|
var skinBindable = config.GetBindable<int>(OsuSetting.Skin);
|
||||||
|
|
||||||
@ -65,9 +65,8 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
skinDropdown.Bindable = skinBindable;
|
skinDropdown.Bindable = skinBindable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reloadSkins() => skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair<string, int>(s.ToString(), s.ID));
|
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));
|
||||||
private void onItemsChanged(SkinInfo _) => Schedule(reloadSkins);
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
@ -75,8 +74,8 @@ namespace osu.Game.Overlays.Settings.Sections
|
|||||||
|
|
||||||
if (skins != null)
|
if (skins != null)
|
||||||
{
|
{
|
||||||
skins.ItemAdded -= onItemsChanged;
|
skins.ItemAdded -= itemAdded;
|
||||||
skins.ItemRemoved -= onItemsChanged;
|
skins.ItemRemoved -= itemRemoved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Settings
|
|||||||
},
|
},
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Children = new[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
|
@ -83,14 +83,14 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(OsuGame osuGame)
|
private void load(OsuGame osuGame)
|
||||||
{
|
{
|
||||||
if (osuGame != null)
|
|
||||||
overlayActivationMode.BindTo(osuGame.OverlayActivationMode);
|
|
||||||
|
|
||||||
StateChanged += visibility =>
|
StateChanged += visibility =>
|
||||||
{
|
{
|
||||||
if (overlayActivationMode == OverlayActivation.Disabled)
|
if (overlayActivationMode == OverlayActivation.Disabled)
|
||||||
State = Visibility.Hidden;
|
State = Visibility.Hidden;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (osuGame != null)
|
||||||
|
overlayActivationMode.BindTo(osuGame.OverlayActivationMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ToolbarBackground : Container
|
public class ToolbarBackground : Container
|
||||||
|
@ -73,16 +73,15 @@ namespace osu.Game.Overlays
|
|||||||
FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out);
|
FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowUser(long userId)
|
public void ShowUser(long userId) => ShowUser(new User { Id = userId });
|
||||||
{
|
|
||||||
if (userId == Header.User.Id)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ShowUser(new User { Id = userId });
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowUser(User user, bool fetchOnline = true)
|
public void ShowUser(User user, bool fetchOnline = true)
|
||||||
{
|
{
|
||||||
|
Show();
|
||||||
|
|
||||||
|
if (user.Id == Header?.User.Id)
|
||||||
|
return;
|
||||||
|
|
||||||
userReq?.Cancel();
|
userReq?.Cancel();
|
||||||
Clear();
|
Clear();
|
||||||
lastSection = null;
|
lastSection = null;
|
||||||
@ -97,6 +96,7 @@ namespace osu.Game.Overlays
|
|||||||
new BeatmapsSection(),
|
new BeatmapsSection(),
|
||||||
new KudosuSection()
|
new KudosuSection()
|
||||||
};
|
};
|
||||||
|
|
||||||
tabs = new ProfileTabControl
|
tabs = new ProfileTabControl
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
@ -161,7 +161,6 @@ namespace osu.Game.Overlays
|
|||||||
userLoadComplete(user);
|
userLoadComplete(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
Show();
|
|
||||||
sectionsContainer.ScrollToTop();
|
sectionsContainer.ScrollToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ using System.Linq;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Configuration;
|
using osu.Framework.Configuration;
|
||||||
using osu.Framework.Extensions.TypeExtensions;
|
using osu.Framework.Extensions.TypeExtensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Primitives;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Judgements;
|
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()
|
protected override void UpdateAfterChildren()
|
||||||
{
|
{
|
||||||
base.UpdateAfterChildren();
|
base.UpdateAfterChildren();
|
||||||
|
@ -176,7 +176,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy;
|
Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy;
|
||||||
|
|
||||||
ColourInfo colourInfo = DrawInfo.Colour;
|
ColourInfo colourInfo = DrawColourInfo.Colour;
|
||||||
colourInfo.ApplyChild(Colour);
|
colourInfo.ApplyChild(Colour);
|
||||||
|
|
||||||
if (AudioData != null)
|
if (AudioData != null)
|
||||||
|
@ -29,6 +29,7 @@ namespace osu.Game.Screens.Ranking
|
|||||||
{
|
{
|
||||||
public class ResultsPageScore : ResultsPage
|
public class ResultsPageScore : ResultsPage
|
||||||
{
|
{
|
||||||
|
private Container scoreContainer;
|
||||||
private ScoreCounter scoreCounter;
|
private ScoreCounter scoreCounter;
|
||||||
|
|
||||||
public ResultsPageScore(Score score, WorkingBeatmap beatmap) : base(score, beatmap) { }
|
public ResultsPageScore(Score score, WorkingBeatmap beatmap) : base(score, beatmap) { }
|
||||||
@ -76,7 +77,7 @@ namespace osu.Game.Screens.Ranking
|
|||||||
Size = new Vector2(150, 60),
|
Size = new Vector2(150, 60),
|
||||||
Margin = new MarginPadding(20),
|
Margin = new MarginPadding(20),
|
||||||
},
|
},
|
||||||
new Container
|
scoreContainer = new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
@ -92,8 +93,8 @@ namespace osu.Game.Screens.Ranking
|
|||||||
},
|
},
|
||||||
scoreCounter = new SlowScoreCounter(6)
|
scoreCounter = new SlowScoreCounter(6)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.Centre,
|
||||||
Colour = colours.PinkDarker,
|
Colour = colours.PinkDarker,
|
||||||
Y = 10,
|
Y = 10,
|
||||||
TextSize = 56,
|
TextSize = 56,
|
||||||
@ -185,6 +186,13 @@ namespace osu.Game.Screens.Ranking
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void UpdateAfterChildren()
|
||||||
|
{
|
||||||
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
|
scoreCounter.Scale = new Vector2(Math.Min(1f, (scoreContainer.DrawWidth - 20) / scoreCounter.DrawWidth));
|
||||||
|
}
|
||||||
|
|
||||||
private class DrawableScoreStatistic : Container
|
private class DrawableScoreStatistic : Container
|
||||||
{
|
{
|
||||||
private readonly KeyValuePair<HitResult, object> statistic;
|
private readonly KeyValuePair<HitResult, object> statistic;
|
||||||
@ -368,7 +376,7 @@ namespace osu.Game.Screens.Ranking
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(user.CoverUrl))
|
if (!string.IsNullOrEmpty(user.CoverUrl))
|
||||||
cover.Texture = textures.Get(user.CoverUrl);
|
cover.Texture = textures.Get(user.CoverUrl);
|
||||||
|
@ -486,6 +486,15 @@ namespace osu.Game.Screens.Select
|
|||||||
updateItem(p, halfHeight);
|
updateItem(p, halfHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
|
||||||
|
// aggressively dispose "off-screen" items to reduce GC pressure.
|
||||||
|
foreach (var i in Items)
|
||||||
|
i.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
private CarouselBeatmapSet createCarouselSet(BeatmapSetInfo beatmapSet)
|
private CarouselBeatmapSet createCarouselSet(BeatmapSetInfo beatmapSet)
|
||||||
{
|
{
|
||||||
if (beatmapSet.Beatmaps.All(b => b.Hidden))
|
if (beatmapSet.Beatmaps.All(b => b.Hidden))
|
||||||
|
@ -50,12 +50,12 @@ namespace osu.Game.Screens.Select.Carousel
|
|||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new DelayedLoadWrapper(
|
new DelayedLoadUnloadWrapper(() =>
|
||||||
new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault()))
|
new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault()))
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint),
|
OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint),
|
||||||
}, 300
|
}, 300, 5000
|
||||||
),
|
),
|
||||||
new FillFlowContainer
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Screens.Select
|
|||||||
public ImportFromStablePopup(Action importFromStable)
|
public ImportFromStablePopup(Action importFromStable)
|
||||||
{
|
{
|
||||||
HeaderText = @"You have no beatmaps!";
|
HeaderText = @"You have no beatmaps!";
|
||||||
BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps?";
|
BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps (and skins)?";
|
||||||
|
|
||||||
Icon = FontAwesome.fa_plane;
|
Icon = FontAwesome.fa_plane;
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
@ -20,6 +19,7 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
namespace osu.Game.Screens.Select
|
||||||
{
|
{
|
||||||
@ -55,7 +55,7 @@ namespace osu.Game.Screens.Select
|
|||||||
private readonly Bindable<IEnumerable<Mod>> selectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
|
private readonly Bindable<IEnumerable<Mod>> selectedMods = new Bindable<IEnumerable<Mod>>(new Mod[] { });
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay, Bindable<IEnumerable<Mod>> selectedMods)
|
private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, SkinManager skins, DialogOverlay dialogOverlay, Bindable<IEnumerable<Mod>> selectedMods)
|
||||||
{
|
{
|
||||||
if (selectedMods != null) this.selectedMods.BindTo(selectedMods);
|
if (selectedMods != null) this.selectedMods.BindTo(selectedMods);
|
||||||
|
|
||||||
@ -78,7 +78,10 @@ namespace osu.Game.Screens.Select
|
|||||||
// if we have no beatmaps but osu-stable is found, let's prompt the user to import.
|
// if we have no beatmaps but osu-stable is found, let's prompt the user to import.
|
||||||
if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable)
|
if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable)
|
||||||
dialogOverlay.Push(new ImportFromStablePopup(() =>
|
dialogOverlay.Push(new ImportFromStablePopup(() =>
|
||||||
Task.Factory.StartNew(beatmaps.ImportFromStable, TaskCreationOptions.LongRunning)));
|
{
|
||||||
|
beatmaps.ImportFromStableAsync();
|
||||||
|
skins.ImportFromStableAsync();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ namespace osu.Game.Screens.Tournament
|
|||||||
|
|
||||||
TextureStore flagStore = new TextureStore();
|
TextureStore flagStore = new TextureStore();
|
||||||
// Local flag store
|
// Local flag store
|
||||||
flagStore.AddStore(new RawTextureLoaderStore(new NamespacedResourceStore<byte[]>(new StorageBackedResourceStore(storage), "Drawings")));
|
flagStore.AddStore(new TextureLoaderStore(new NamespacedResourceStore<byte[]>(new StorageBackedResourceStore(storage), "Drawings")));
|
||||||
// Default texture store
|
// Default texture store
|
||||||
flagStore.AddStore(textures);
|
flagStore.AddStore(textures);
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Skinning
|
|||||||
Configuration = new SkinConfiguration();
|
Configuration = new SkinConfiguration();
|
||||||
|
|
||||||
Samples = audioManager.GetSampleManager(storage);
|
Samples = audioManager.GetSampleManager(storage);
|
||||||
Textures = new TextureStore(new RawTextureLoaderStore(storage));
|
Textures = new TextureStore(new TextureLoaderStore(storage));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Drawable GetDrawableComponent(string componentName)
|
public override Drawable GetDrawableComponent(string componentName)
|
||||||
|
@ -26,17 +26,25 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
public override string[] HandledExtensions => new[] { ".osk" };
|
public override string[] HandledExtensions => new[] { ".osk" };
|
||||||
|
|
||||||
|
protected override string ImportFromStablePath => "Skins";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of all usable <see cref="SkinInfo"/>s.
|
/// Returns a list of all usable <see cref="SkinInfo"/>s. Includes the special default skin plus all skins from <see cref="GetAllUserSkins"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A list of available <see cref="SkinInfo"/>.</returns>
|
/// <returns>A list of available <see cref="SkinInfo"/>.</returns>
|
||||||
public List<SkinInfo> GetAllUsableSkins()
|
public List<SkinInfo> GetAllUsableSkins()
|
||||||
{
|
{
|
||||||
var userSkins = ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList();
|
var userSkins = GetAllUserSkins();
|
||||||
userSkins.Insert(0, SkinInfo.Default);
|
userSkins.Insert(0, SkinInfo.Default);
|
||||||
return userSkins;
|
return userSkins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all usable <see cref="SkinInfo"/>s that have been loaded by the user.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of available <see cref="SkinInfo"/>.</returns>
|
||||||
|
public List<SkinInfo> GetAllUserSkins() => ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList();
|
||||||
|
|
||||||
protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo
|
protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo
|
||||||
{
|
{
|
||||||
Name = archive.Name
|
Name = archive.Name
|
||||||
@ -85,6 +93,13 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
this.audio = audio;
|
this.audio = audio;
|
||||||
|
|
||||||
|
ItemRemoved += removedInfo =>
|
||||||
|
{
|
||||||
|
// check the removed skin is not the current user choice. if it is, switch back to default.
|
||||||
|
if (removedInfo.ID == CurrentSkinInfo.Value.ID)
|
||||||
|
CurrentSkinInfo.Value = SkinInfo.Default;
|
||||||
|
};
|
||||||
|
|
||||||
CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = GetSkin(info);
|
CurrentSkinInfo.ValueChanged += info => CurrentSkin.Value = GetSkin(info);
|
||||||
CurrentSkin.ValueChanged += skin =>
|
CurrentSkin.ValueChanged += skin =>
|
||||||
{
|
{
|
||||||
@ -93,16 +108,6 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
SourceChanged?.Invoke();
|
SourceChanged?.Invoke();
|
||||||
};
|
};
|
||||||
|
|
||||||
// migrate older imports which didn't have access to skin.ini
|
|
||||||
using (ContextFactory.GetForWrite())
|
|
||||||
{
|
|
||||||
foreach (var skinInfo in ModelStore.ConsumableItems.Where(s => s.Name.EndsWith(".osk")))
|
|
||||||
{
|
|
||||||
populate(skinInfo);
|
|
||||||
Update(skinInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Storyboards.Drawables
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(FileStore fileStore)
|
private void load(FileStore fileStore)
|
||||||
{
|
{
|
||||||
dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, });
|
dependencies.Cache(new TextureStore(new TextureLoaderStore(fileStore.Store), false, scaleAdjust: 1));
|
||||||
|
|
||||||
foreach (var layer in Storyboard.Layers)
|
foreach (var layer in Storyboard.Layers)
|
||||||
Add(layer.CreateDrawable());
|
Add(layer.CreateDrawable());
|
||||||
|
@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
AddStep(r.Name, () => p = loadPlayerFor(r));
|
AddStep(r.Name, () => p = loadPlayerFor(r));
|
||||||
AddUntilStep(() => ContinueCondition(p));
|
AddUntilStep(() => ContinueCondition(p));
|
||||||
|
|
||||||
AddAssert("no leaked beatmaps", () =>
|
AddUntilStep(() =>
|
||||||
{
|
{
|
||||||
p = null;
|
p = null;
|
||||||
|
|
||||||
@ -64,9 +64,9 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
workingWeakReferences.ForEachAlive(_ => count++);
|
workingWeakReferences.ForEachAlive(_ => count++);
|
||||||
return count == 1;
|
return count == 1;
|
||||||
});
|
}, "no leaked beatmaps");
|
||||||
|
|
||||||
AddAssert("no leaked players", () =>
|
AddUntilStep(() =>
|
||||||
{
|
{
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
GC.WaitForPendingFinalizers();
|
||||||
@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
playerWeakReferences.ForEachAlive(_ => count++);
|
playerWeakReferences.ForEachAlive(_ => count++);
|
||||||
return count == 1;
|
return count == 1;
|
||||||
});
|
}, "no leaked players");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Users
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
if (textures == null)
|
if (textures == null)
|
||||||
throw new ArgumentNullException(nameof(textures));
|
throw new ArgumentNullException(nameof(textures));
|
||||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Users
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(LargeTextureStore textures)
|
||||||
{
|
{
|
||||||
if (textures == null)
|
if (textures == null)
|
||||||
throw new ArgumentNullException(nameof(textures));
|
throw new ArgumentNullException(nameof(textures));
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.1.2" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2018.901.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2018.913.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.22.0" />
|
<PackageReference Include="SharpCompress" Version="0.22.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.10.1" />
|
<PackageReference Include="NUnit" Version="3.10.1" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
Loading…
Reference in New Issue
Block a user