mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 06:03:08 +08:00
Merge branch 'master' into selection-update
This commit is contained in:
commit
d7cb932606
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
custom: https://osu.ppy.sh/home/support
|
21
README.md
21
README.md
@ -10,6 +10,8 @@ This project is still heavily under development, but is in a state where users a
|
||||
|
||||
We are accepting bug reports (please report with as much detail as possible). Feature requests are welcome as long as you read and understand the contribution guidelines listed below.
|
||||
|
||||
Detailed changelogs are published on the [official osu! site](https://osu.ppy.sh/home/changelog).
|
||||
|
||||
## Requirements
|
||||
|
||||
- A desktop platform with the [.NET Core SDK 2.2](https://www.microsoft.com/net/learn/get-started) or higher installed.
|
||||
@ -20,17 +22,24 @@ We are accepting bug reports (please report with as much detail as possible). Fe
|
||||
|
||||
### Releases
|
||||
|
||||
If you are not interested in developing the game, please head over to the [releases](https://github.com/ppy/osu/releases) to download a precompiled build with automatic updating enabled.
|
||||
![](https://puu.sh/DCmvA/f6a74f5fbb.png)
|
||||
|
||||
- Windows (x64) users should download and run `install.exe`.
|
||||
- macOS users (10.12 "Sierra" and higher) should download and run `osu.app.zip`.
|
||||
- iOS users can join the [TestFlight beta program](https://t.co/xQJmHkfC18).
|
||||
If you are not interested in developing the game, you can consume our [binary releases](https://github.com/ppy/osu/releases).
|
||||
|
||||
**Latest build:***
|
||||
|
||||
| [Windows (x64)](https://github.com/ppy/osu/releases/latest/download/install.exe) | [macOS 10.12+](https://github.com/ppy/osu/releases/latest/download/osu.app.zip) |
|
||||
| ------------- | ------------- |
|
||||
|
||||
- **Linux** users are recommended to self-compile until we have official deployment in place.
|
||||
- **iOS** users can join the [TestFlight beta program](https://t.co/xQJmHkfC18) (note that due to high demand this is regularly full).
|
||||
- **Android** users can self-compile, and expect a public beta soon.
|
||||
|
||||
If your platform is not listed above, there is still a chance you can manually build it by following the instructions below.
|
||||
|
||||
### Downloading the source code
|
||||
|
||||
Clone the repository **including submodules**:
|
||||
Clone the repository:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/ppy/osu
|
||||
@ -45,7 +54,7 @@ git pull
|
||||
|
||||
### Building
|
||||
|
||||
Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this provided below.
|
||||
Build configurations for the recommended IDEs (listed above) are included. You should use the provided Build/Run functionality of your IDE to get things going. When testing or building new components, it's highly encouraged you use the `VisualTests` project/configuration. More information on this provided [below](#contributing).
|
||||
|
||||
> Visual Studio Code users must run the `Restore` task before any build attempt.
|
||||
|
||||
|
@ -20,14 +20,14 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6, SliderMultiplier = 3 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -29,14 +29,14 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,14 +16,14 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -23,13 +23,13 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
AddAssert("First note is hyperdash", () => Beatmap.Value.Beatmap.HitObjects[0] is Fruit f && f.HyperDash);
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
Ruleset = ruleset.RulesetInfo,
|
||||
Ruleset = ruleset,
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 3.6f }
|
||||
}
|
||||
};
|
||||
|
@ -17,14 +17,14 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmap(Ruleset ruleset)
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
{
|
||||
BaseDifficulty = new BeatmapDifficulty { CircleSize = 6 },
|
||||
Ruleset = ruleset.RulesetInfo
|
||||
Ruleset = ruleset
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,6 @@ using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
@ -299,7 +298,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
AddStep("load player", () =>
|
||||
{
|
||||
Beatmap.Value = new TestWorkingBeatmap(new Beatmap<OsuHitObject>
|
||||
Beatmap.Value = CreateWorkingBeatmap(new Beatmap<OsuHitObject>
|
||||
{
|
||||
HitObjects =
|
||||
{
|
||||
@ -323,7 +322,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 3 },
|
||||
Ruleset = new OsuRuleset().RulesetInfo
|
||||
},
|
||||
}, Clock);
|
||||
});
|
||||
|
||||
var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } });
|
||||
|
||||
|
@ -2,13 +2,10 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Graphics.ES30;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
{
|
||||
@ -19,8 +16,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
private readonly SliderPath path;
|
||||
protected Path Path => path;
|
||||
|
||||
private readonly BufferedContainer container;
|
||||
|
||||
public float PathRadius
|
||||
{
|
||||
get => path.PathRadius;
|
||||
@ -44,8 +39,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return;
|
||||
|
||||
path.AccentColour = value;
|
||||
|
||||
container.ForceRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,8 +54,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return;
|
||||
|
||||
path.BorderColour = value;
|
||||
|
||||
container.ForceRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,23 +69,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return;
|
||||
|
||||
path.BorderSize = value;
|
||||
|
||||
container.ForceRedraw();
|
||||
}
|
||||
}
|
||||
|
||||
public Quad PathDrawQuad => container.ScreenSpaceDrawQuad;
|
||||
|
||||
protected SliderBody()
|
||||
{
|
||||
InternalChild = container = new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CacheDrawnFrameBuffer = true,
|
||||
Child = path = new SliderPath { Blending = BlendingMode.None }
|
||||
};
|
||||
|
||||
container.Attach(RenderbufferInternalFormat.DepthComponent16);
|
||||
InternalChild = path = new SliderPath();
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos);
|
||||
@ -103,11 +83,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
/// Sets the vertices of the path which should be drawn by this <see cref="SliderBody"/>.
|
||||
/// </summary>
|
||||
/// <param name="vertices">The vertices</param>
|
||||
protected void SetVertices(IReadOnlyList<Vector2> vertices)
|
||||
{
|
||||
path.Vertices = vertices;
|
||||
container.ForceRedraw();
|
||||
}
|
||||
protected void SetVertices(IReadOnlyList<Vector2> vertices) => path.Vertices = vertices;
|
||||
|
||||
private class SliderPath : SmoothPath
|
||||
{
|
||||
|
@ -54,7 +54,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
for (int i = 0; i < max_sprites; i++)
|
||||
{
|
||||
parts[i].InvalidationID = 0;
|
||||
// InvalidationID 1 forces an update of each part of the cursor trail the first time ApplyState is run on the draw node
|
||||
// This is to prevent garbage data from being sent to the vertex shader, resulting in visual issues on some platforms
|
||||
parts[i].InvalidationID = 1;
|
||||
parts[i].WasUpdated = true;
|
||||
}
|
||||
}
|
||||
@ -210,7 +212,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
Vector2 pos = parts[i].Position;
|
||||
float localTime = parts[i].Time;
|
||||
|
||||
texture.DrawQuad(
|
||||
DrawQuad(
|
||||
texture,
|
||||
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
|
||||
DrawColourInfo.Colour,
|
||||
null,
|
||||
|
@ -18,7 +18,6 @@ using osu.Game.Rulesets.Taiko.Judgements;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
@ -64,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
var controlPointInfo = new ControlPointInfo();
|
||||
controlPointInfo.TimingPoints.Add(new TimingControlPoint());
|
||||
|
||||
WorkingBeatmap beatmap = new TestWorkingBeatmap(new Beatmap
|
||||
WorkingBeatmap beatmap = CreateWorkingBeatmap(new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject> { new CentreHit() },
|
||||
BeatmapInfo = new BeatmapInfo
|
||||
@ -79,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
Ruleset = new TaikoRuleset().RulesetInfo
|
||||
},
|
||||
ControlPointInfo = controlPointInfo
|
||||
}, Clock);
|
||||
});
|
||||
|
||||
Add(playfieldContainer = new Container
|
||||
{
|
||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Events;
|
||||
@ -54,7 +55,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
private RulesetStore rulesets;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(GameHost host)
|
||||
private void load(GameHost host, AudioManager audio)
|
||||
{
|
||||
factory = new DatabaseContextFactory(LocalStorage);
|
||||
factory.ResetDatabase();
|
||||
@ -68,7 +69,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
usage.Migrate();
|
||||
|
||||
Dependencies.Cache(rulesets = new RulesetStore(factory));
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, host, Beatmap.Default));
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, Beatmap.Default));
|
||||
Dependencies.Cache(new OsuConfigManager(LocalStorage));
|
||||
|
||||
manager.Import(TestResources.GetTestBeatmapForImport());
|
||||
|
@ -111,16 +111,19 @@ namespace osu.Game.Tests.Visual.Components
|
||||
|
||||
private class TestPreviewTrackManager : PreviewTrackManager
|
||||
{
|
||||
protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) => new TestPreviewTrack(beatmapSetInfo, trackManager);
|
||||
protected override TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TestPreviewTrack(beatmapSetInfo, trackStore);
|
||||
|
||||
protected class TestPreviewTrack : TrackManagerPreviewTrack
|
||||
{
|
||||
public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager)
|
||||
private readonly ITrackStore trackManager;
|
||||
|
||||
public TestPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager)
|
||||
: base(beatmapSetInfo, trackManager)
|
||||
{
|
||||
this.trackManager = trackManager;
|
||||
}
|
||||
|
||||
protected override Track GetTrack() => new TrackVirtual { Length = 100000 };
|
||||
protected override Track GetTrack() => trackManager.GetVirtual(100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Edit.Compose;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
{
|
||||
@ -19,7 +18,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, Clock);
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
Child = new ComposeScreen();
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@ -30,9 +31,9 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
Beatmap.Value = new WaveformTestBeatmap();
|
||||
Beatmap.Value = new WaveformTestBeatmap(audio);
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
@ -10,7 +10,6 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -48,7 +47,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
}
|
||||
};
|
||||
|
||||
Beatmap.Value = new TestWorkingBeatmap(testBeatmap, Clock);
|
||||
Beatmap.Value = CreateWorkingBeatmap(testBeatmap);
|
||||
|
||||
Child = new TimingPointVisualiser(testBeatmap, 5000) { Clock = Clock };
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Screens.Edit.Components.Timelines.Summary;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
@ -21,7 +20,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Beatmap.Value = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null);
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
|
||||
Add(new SummaryTimeline
|
||||
{
|
||||
|
@ -18,7 +18,6 @@ using osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Screens.Edit.Compose;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
@ -45,7 +44,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Beatmap.Value = new TestWorkingBeatmap(new Beatmap
|
||||
Beatmap.Value = CreateWorkingBeatmap(new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
@ -7,7 +7,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Edit.Components;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
@ -29,7 +28,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
Size = new Vector2(200, 100)
|
||||
};
|
||||
|
||||
Beatmap.Value = new TestWorkingBeatmap(new Beatmap(), Clock);
|
||||
Beatmap.Value = CreateWorkingBeatmap(new Beatmap());
|
||||
|
||||
Child = playback;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Audio;
|
||||
@ -10,6 +11,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Editor
|
||||
@ -20,9 +22,9 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
private WorkingBeatmap waveformBeatmap;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
waveformBeatmap = new WaveformTestBeatmap();
|
||||
waveformBeatmap = new WaveformTestBeatmap(audio);
|
||||
}
|
||||
|
||||
[TestCase(1f)]
|
||||
@ -91,7 +93,7 @@ namespace osu.Game.Tests.Visual.Editor
|
||||
Child = graph = new TestWaveformGraph
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Waveform = new DummyWorkingBeatmap().Waveform,
|
||||
Waveform = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo).Waveform,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
50
osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs
Normal file
50
osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
public class TestSceneFailAnimation : AllPlayersTestScene
|
||||
{
|
||||
protected override Player CreatePlayer(Ruleset ruleset)
|
||||
{
|
||||
Mods.Value = Array.Empty<Mod>();
|
||||
return new FailPlayer();
|
||||
}
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(AllPlayersTestScene),
|
||||
typeof(TestPlayer),
|
||||
typeof(Player),
|
||||
};
|
||||
|
||||
protected override void AddCheckSteps()
|
||||
{
|
||||
AddUntilStep("wait for fail", () => Player.HasFailed);
|
||||
AddUntilStep("wait for fail overlay", () => ((FailPlayer)Player).FailOverlay.State == Visibility.Visible);
|
||||
}
|
||||
|
||||
private class FailPlayer : TestPlayer
|
||||
{
|
||||
public new FailOverlay FailOverlay => base.FailOverlay;
|
||||
|
||||
public FailPlayer()
|
||||
: base(false, false)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
ScoreProcessor.FailConditions += _ => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public void TestPauseAfterFail()
|
||||
{
|
||||
AddUntilStep("wait for fail", () => Player.HasFailed);
|
||||
AddAssert("fail overlay shown", () => Player.FailOverlayVisible);
|
||||
AddUntilStep("fail overlay shown", () => Player.FailOverlayVisible);
|
||||
|
||||
confirmClockRunning(false);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
@ -16,7 +16,6 @@ using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
@ -29,7 +28,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
InputManager.Child = stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both };
|
||||
Beatmap.Value = new TestWorkingBeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo), Clock);
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
});
|
||||
|
||||
[Test]
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Lists;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Play;
|
||||
@ -43,9 +42,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
});
|
||||
}
|
||||
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, IFrameBasedClock clock)
|
||||
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
var working = base.CreateWorkingBeatmap(beatmap, clock);
|
||||
var working = base.CreateWorkingBeatmap(beatmap);
|
||||
workingWeakReferences.Add(working);
|
||||
return working;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
@ -57,7 +56,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddStep("set name", () => Room.Name.Value = "Room name");
|
||||
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
|
||||
|
||||
AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = new DummyWorkingBeatmap().BeatmapInfo }));
|
||||
AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = CreateBeatmap(Ruleset.Value).BeatmapInfo }));
|
||||
AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value);
|
||||
|
||||
AddStep("clear name", () => Room.Name.Value = "");
|
||||
|
@ -8,7 +8,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Overlays.Direct;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
@ -25,7 +24,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
var beatmap = new TestWorkingBeatmap(new OsuRuleset().RulesetInfo, null);
|
||||
var beatmap = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
beatmap.BeatmapSetInfo.OnlineInfo.HasVideo = true;
|
||||
beatmap.BeatmapSetInfo.OnlineInfo.HasStoryboard = true;
|
||||
|
||||
|
@ -157,7 +157,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
FlagName = @"TH",
|
||||
},
|
||||
},
|
||||
Rank = ScoreRank.F,
|
||||
Rank = ScoreRank.D,
|
||||
PP = 160,
|
||||
MaxCombo = 1234,
|
||||
TotalScore = 123456,
|
||||
|
55
osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs
Normal file
55
osu.Game.Tests/Visual/Online/TestSceneShowMoreButton.cs
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Overlays.Profile.Sections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public class TestSceneShowMoreButton : OsuTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ShowMoreButton),
|
||||
};
|
||||
|
||||
public TestSceneShowMoreButton()
|
||||
{
|
||||
ShowMoreButton button = null;
|
||||
|
||||
int fireCount = 0;
|
||||
|
||||
Add(button = new ShowMoreButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Action = () =>
|
||||
{
|
||||
fireCount++;
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
Scheduler.AddDelayed(() => button.IsLoading = false, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("click button", () => button.Click());
|
||||
|
||||
AddAssert("action fired once", () => fireCount == 1);
|
||||
AddAssert("is in loading state", () => button.IsLoading);
|
||||
|
||||
AddStep("click button", () => button.Click());
|
||||
|
||||
AddAssert("action not fired", () => fireCount == 1);
|
||||
AddAssert("is in loading state", () => button.IsLoading);
|
||||
|
||||
AddUntilStep("wait for loaded", () => !button.IsLoading);
|
||||
|
||||
AddStep("click button", () => button.Click());
|
||||
|
||||
AddAssert("action fired twice", () => fireCount == 2);
|
||||
AddAssert("is in loading state", () => button.IsLoading);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Screens.Select;
|
||||
@ -18,7 +19,8 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(BeatmapDetails) };
|
||||
|
||||
public TestSceneBeatmapDetailArea()
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase game)
|
||||
{
|
||||
BeatmapDetailArea detailsArea;
|
||||
Add(detailsArea = new BeatmapDetailArea
|
||||
@ -28,7 +30,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
Size = new Vector2(550f, 450f),
|
||||
});
|
||||
|
||||
AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap
|
||||
AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
@ -56,7 +58,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}
|
||||
);
|
||||
|
||||
AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap
|
||||
AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
@ -82,7 +84,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap
|
||||
AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
@ -107,7 +109,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap
|
||||
AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
@ -133,7 +135,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}
|
||||
});
|
||||
|
||||
AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap
|
||||
AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null)
|
||||
{
|
||||
BeatmapInfo =
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
@ -18,7 +18,6 @@ using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Screens.Select;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.SongSelect
|
||||
@ -136,7 +135,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
AddStep($"select {b?.Metadata.Title ?? "null"} beatmap", () =>
|
||||
{
|
||||
infoBefore = infoWedge.Info;
|
||||
infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : new TestWorkingBeatmap(b);
|
||||
infoWedge.Beatmap = Beatmap.Value = b == null ? Beatmap.Default : CreateWorkingBeatmap(b);
|
||||
});
|
||||
|
||||
AddUntilStep("wait for async load", () => infoWedge.Info != infoBefore);
|
||||
|
@ -188,7 +188,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.F,
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.6025,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
@ -206,7 +206,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.F,
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.5140,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
},
|
||||
new ScoreInfo
|
||||
{
|
||||
Rank = ScoreRank.F,
|
||||
Rank = ScoreRank.D,
|
||||
Accuracy = 0.4222,
|
||||
MaxCombo = 244,
|
||||
TotalScore = 1707827,
|
||||
|
@ -8,6 +8,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.MathUtils;
|
||||
@ -79,7 +80,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(GameHost host)
|
||||
private void load(GameHost host, AudioManager audio)
|
||||
{
|
||||
factory = new DatabaseContextFactory(LocalStorage);
|
||||
factory.ResetDatabase();
|
||||
@ -93,7 +94,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
usage.Migrate();
|
||||
|
||||
Dependencies.Cache(rulesets = new RulesetStore(factory));
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, null, host, defaultBeatmap = Beatmap.Default));
|
||||
Dependencies.Cache(manager = new BeatmapManager(LocalStorage, factory, rulesets, null, audio, host, defaultBeatmap = Beatmap.Default));
|
||||
|
||||
Beatmap.SetDefault();
|
||||
}
|
||||
|
50
osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs
Normal file
50
osu.Game.Tests/Visual/UserInterface/OsuGridTestScene.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// An abstract test case which exposes small cells arranged in a grid.
|
||||
/// Useful for displaying multiple configurations of a tested component at a glance.
|
||||
/// </summary>
|
||||
public abstract class OsuGridTestScene : OsuTestScene
|
||||
{
|
||||
private readonly Drawable[,] cells;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of rows in the grid.
|
||||
/// </summary>
|
||||
protected readonly int Rows;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of columns in the grid.
|
||||
/// </summary>
|
||||
protected readonly int Cols;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a grid test case with the given dimensions.
|
||||
/// </summary>
|
||||
protected OsuGridTestScene(int rows, int cols)
|
||||
{
|
||||
Rows = rows;
|
||||
Cols = cols;
|
||||
|
||||
GridContainer testContainer;
|
||||
Add(testContainer = new GridContainer { RelativeSizeAxes = Axes.Both });
|
||||
|
||||
cells = new Drawable[rows, cols];
|
||||
for (int r = 0; r < rows; r++)
|
||||
for (int c = 0; c < cols; c++)
|
||||
cells[r, c] = new Container { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
testContainer.Content = cells.ToJagged();
|
||||
}
|
||||
|
||||
protected Container Cell(int index) => (Container)cells[index / Cols, index % Cols];
|
||||
protected Container Cell(int row, int col) => (Container)cells[row, col];
|
||||
}
|
||||
}
|
@ -84,7 +84,6 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
testLocalCursor();
|
||||
testUserCursorOverride();
|
||||
testMultipleLocalCursors();
|
||||
ReturnUserInput();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3,13 +3,12 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneLoadingAnimation : GridTestScene //todo: this should be an OsuTestScene
|
||||
public class TestSceneLoadingAnimation : OsuGridTestScene
|
||||
{
|
||||
public TestSceneLoadingAnimation()
|
||||
: base(2, 2)
|
||||
|
@ -0,0 +1,72 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public class TestSceneOsuAnimatedButton : OsuGridTestScene
|
||||
{
|
||||
public TestSceneOsuAnimatedButton()
|
||||
: base(3, 2)
|
||||
{
|
||||
Cell(0).Add(new BaseContainer("relative sized")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
|
||||
Cell(1).Add(new BaseContainer("auto sized")
|
||||
{
|
||||
AutoSizeAxes = Axes.Both
|
||||
});
|
||||
|
||||
Cell(2).Add(new BaseContainer("relative Y auto X")
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X
|
||||
});
|
||||
|
||||
Cell(3).Add(new BaseContainer("relative X auto Y")
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y
|
||||
});
|
||||
|
||||
Cell(4).Add(new BaseContainer("fixed")
|
||||
{
|
||||
Size = new Vector2(100),
|
||||
});
|
||||
|
||||
Cell(5).Add(new BaseContainer("fixed")
|
||||
{
|
||||
Size = new Vector2(100, 50),
|
||||
});
|
||||
|
||||
AddToggleStep("toggle enabled", toggle =>
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
((BaseContainer)Cell(i).Child).Action = toggle ? () => { } : (Action)null;
|
||||
});
|
||||
}
|
||||
|
||||
public class BaseContainer : OsuAnimatedButton
|
||||
{
|
||||
public BaseContainer(string text)
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Add(new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = text
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneOsuHoverContainer : ManualInputManagerTestScene
|
||||
{
|
||||
private OsuHoverTestContainer hoverContainer;
|
||||
private Box colourContainer;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
Child = hoverContainer = new OsuHoverTestContainer
|
||||
{
|
||||
Enabled = { Value = true },
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(100),
|
||||
Child = colourContainer = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
};
|
||||
|
||||
doMoveOut();
|
||||
});
|
||||
|
||||
[Description("Checks IsHovered property value on a container when it is hovered/unhovered.")]
|
||||
[TestCase(true, TestName = "Enabled_Check_IsHovered")]
|
||||
[TestCase(false, TestName = "Disabled_Check_IsHovered")]
|
||||
public void TestIsHoveredHasProperValue(bool isEnabled)
|
||||
{
|
||||
setContainerEnabledTo(isEnabled);
|
||||
|
||||
checkNotHovered();
|
||||
|
||||
moveToText();
|
||||
checkHovered();
|
||||
|
||||
moveOut();
|
||||
checkNotHovered();
|
||||
|
||||
moveToText();
|
||||
checkHovered();
|
||||
|
||||
moveOut();
|
||||
checkNotHovered();
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Checks colour fading on an enabled container when it is hovered/unhovered.")]
|
||||
public void TestTransitionWhileEnabled()
|
||||
{
|
||||
enableContainer();
|
||||
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveToText();
|
||||
waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR);
|
||||
|
||||
moveOut();
|
||||
waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveToText();
|
||||
waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR);
|
||||
|
||||
moveOut();
|
||||
waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Checks colour fading on a disabled container when it is hovered/unhovered.")]
|
||||
public void TestNoTransitionWhileDisabled()
|
||||
{
|
||||
disableContainer();
|
||||
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveToText();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveOut();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveToText();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveOut();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Checks that when a disabled & hovered container gets enabled, colour fading happens")]
|
||||
public void TestBecomesEnabledTransition()
|
||||
{
|
||||
disableContainer();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveToText();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
enableContainer();
|
||||
waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Checks that when an enabled & hovered container gets disabled, colour fading happens")]
|
||||
public void TestBecomesDisabledTransition()
|
||||
{
|
||||
enableContainer();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveToText();
|
||||
waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR);
|
||||
|
||||
disableContainer();
|
||||
waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Description("Checks that when a hovered container gets enabled and disabled multiple times, colour fading happens")]
|
||||
public void TestDisabledChangesMultipleTimes()
|
||||
{
|
||||
enableContainer();
|
||||
checkColour(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
moveToText();
|
||||
waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR);
|
||||
|
||||
disableContainer();
|
||||
waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
|
||||
enableContainer();
|
||||
waitUntilColourIs(OsuHoverTestContainer.HOVER_COLOUR);
|
||||
|
||||
disableContainer();
|
||||
waitUntilColourIs(OsuHoverTestContainer.IDLE_COLOUR);
|
||||
}
|
||||
|
||||
private void enableContainer() => setContainerEnabledTo(true);
|
||||
|
||||
private void disableContainer() => setContainerEnabledTo(false);
|
||||
|
||||
private void setContainerEnabledTo(bool newValue)
|
||||
{
|
||||
string word = newValue ? "Enable" : "Disable";
|
||||
AddStep($"{word} container", () => hoverContainer.Enabled.Value = newValue);
|
||||
}
|
||||
|
||||
private void moveToText() => AddStep("Move mouse to text", () => InputManager.MoveMouseTo(hoverContainer));
|
||||
|
||||
private void moveOut() => AddStep("Move out", doMoveOut);
|
||||
|
||||
private void checkHovered() => AddAssert("Check hovered", () => hoverContainer.IsHovered);
|
||||
|
||||
private void checkNotHovered() => AddAssert("Check not hovered", () => !hoverContainer.IsHovered);
|
||||
|
||||
private void checkColour(ColourInfo expectedColour)
|
||||
=> AddAssert($"Check colour to be '{expectedColour}'", () => currentColour.Equals(expectedColour));
|
||||
|
||||
private void waitUntilColourIs(ColourInfo expectedColour)
|
||||
=> AddUntilStep($"Wait until hover colour is {expectedColour}", () => currentColour.Equals(expectedColour));
|
||||
|
||||
private ColourInfo currentColour => colourContainer.DrawColourInfo.Colour;
|
||||
|
||||
/// <summary>
|
||||
/// Moves the cursor to top left corner of the screen
|
||||
/// </summary>
|
||||
private void doMoveOut()
|
||||
=> InputManager.MoveMouseTo(new Vector2(InputManager.ScreenSpaceDrawQuad.TopLeft.X, InputManager.ScreenSpaceDrawQuad.TopLeft.Y));
|
||||
|
||||
private sealed class OsuHoverTestContainer : OsuHoverContainer
|
||||
{
|
||||
public static readonly Color4 HOVER_COLOUR = Color4.Red;
|
||||
public static readonly Color4 IDLE_COLOUR = Color4.Green;
|
||||
|
||||
public OsuHoverTestContainer()
|
||||
{
|
||||
HoverColour = HOVER_COLOUR;
|
||||
IdleColour = IDLE_COLOUR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
TestUpdateableBeatmapBackgroundSprite background = null;
|
||||
|
||||
AddStep("load null beatmap", () => Child = background = new TestUpdateableBeatmapBackgroundSprite { RelativeSizeAxes = Axes.Both });
|
||||
AddUntilStep("wait for load", () => background.ContentLoaded);
|
||||
AddUntilStep("content loaded", () => background.ContentLoaded);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -19,12 +20,14 @@ namespace osu.Game.Tests
|
||||
{
|
||||
private readonly ZipArchiveReader reader;
|
||||
private readonly Stream stream;
|
||||
private readonly ITrackStore trackStore;
|
||||
|
||||
public WaveformTestBeatmap()
|
||||
: base(new BeatmapInfo())
|
||||
public WaveformTestBeatmap(AudioManager audioManager)
|
||||
: base(new BeatmapInfo(), audioManager)
|
||||
{
|
||||
stream = TestResources.GetTestBeatmapStream();
|
||||
reader = new ZipArchiveReader(stream);
|
||||
trackStore = audioManager.GetTrackStore(reader);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
@ -32,17 +35,19 @@ namespace osu.Game.Tests
|
||||
base.Dispose();
|
||||
stream?.Dispose();
|
||||
reader?.Dispose();
|
||||
trackStore?.Dispose();
|
||||
}
|
||||
|
||||
protected override IBeatmap GetBeatmap() => createTestBeatmap();
|
||||
|
||||
protected override Texture GetBackground() => null;
|
||||
|
||||
protected override Waveform GetWaveform() => new Waveform(getAudioStream());
|
||||
protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile));
|
||||
|
||||
protected override Track GetTrack() => new TrackBass(getAudioStream());
|
||||
protected override Track GetTrack() => trackStore.Get(firstAudioFile);
|
||||
|
||||
private string firstAudioFile => reader.Filenames.First(f => f.EndsWith(".mp3"));
|
||||
|
||||
private Stream getAudioStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".mp3")));
|
||||
private Stream getBeatmapStream() => reader.GetStream(reader.Filenames.First(f => f.EndsWith(".osu")));
|
||||
|
||||
private Beatmap createTestBeatmap()
|
||||
|
@ -1,6 +1,10 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
@ -12,27 +16,28 @@ using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Audio
|
||||
{
|
||||
/// <summary>
|
||||
/// A central store for the retrieval of <see cref="PreviewTrack"/>s.
|
||||
/// </summary>
|
||||
public class PreviewTrackManager : Component
|
||||
{
|
||||
private readonly BindableDouble muteBindable = new BindableDouble();
|
||||
|
||||
private AudioManager audio;
|
||||
private TrackManager trackManager;
|
||||
private PreviewTrackStore trackStore;
|
||||
|
||||
private TrackManagerPreviewTrack current;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, FrameworkConfigManager config)
|
||||
{
|
||||
trackManager = new TrackManager(new OnlineStore());
|
||||
// this is a temporary solution to get around muting ourselves.
|
||||
// todo: update this once we have a BackgroundTrackManager or similar.
|
||||
trackStore = new PreviewTrackStore(new OnlineStore());
|
||||
|
||||
audio.AddItem(trackStore);
|
||||
trackStore.AddAdjustment(AdjustableProperty.Volume, audio.VolumeTrack);
|
||||
|
||||
this.audio = audio;
|
||||
audio.AddItem(trackManager);
|
||||
|
||||
config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume);
|
||||
config.BindWith(FrameworkSetting.VolumeMusic, trackStore.Volume);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -42,19 +47,19 @@ namespace osu.Game.Audio
|
||||
/// <returns>The playable <see cref="PreviewTrack"/>.</returns>
|
||||
public PreviewTrack Get(BeatmapSetInfo beatmapSetInfo)
|
||||
{
|
||||
var track = CreatePreviewTrack(beatmapSetInfo, trackManager);
|
||||
var track = CreatePreviewTrack(beatmapSetInfo, trackStore);
|
||||
|
||||
track.Started += () =>
|
||||
{
|
||||
current?.Stop();
|
||||
current = track;
|
||||
audio.Track.AddAdjustment(AdjustableProperty.Volume, muteBindable);
|
||||
audio.Tracks.AddAdjustment(AdjustableProperty.Volume, muteBindable);
|
||||
};
|
||||
|
||||
track.Stopped += () =>
|
||||
{
|
||||
current = null;
|
||||
audio.Track.RemoveAdjustment(AdjustableProperty.Volume, muteBindable);
|
||||
audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, muteBindable);
|
||||
};
|
||||
|
||||
return track;
|
||||
@ -81,16 +86,16 @@ namespace osu.Game.Audio
|
||||
/// <summary>
|
||||
/// Creates the <see cref="TrackManagerPreviewTrack"/>.
|
||||
/// </summary>
|
||||
protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager) => new TrackManagerPreviewTrack(beatmapSetInfo, trackManager);
|
||||
protected virtual TrackManagerPreviewTrack CreatePreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackStore) => new TrackManagerPreviewTrack(beatmapSetInfo, trackStore);
|
||||
|
||||
protected class TrackManagerPreviewTrack : PreviewTrack
|
||||
{
|
||||
public IPreviewTrackOwner Owner { get; private set; }
|
||||
|
||||
private readonly BeatmapSetInfo beatmapSetInfo;
|
||||
private readonly TrackManager trackManager;
|
||||
private readonly ITrackStore trackManager;
|
||||
|
||||
public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, TrackManager trackManager)
|
||||
public TrackManagerPreviewTrack(BeatmapSetInfo beatmapSetInfo, ITrackStore trackManager)
|
||||
{
|
||||
this.beatmapSetInfo = beatmapSetInfo;
|
||||
this.trackManager = trackManager;
|
||||
@ -104,5 +109,46 @@ namespace osu.Game.Audio
|
||||
|
||||
protected override Track GetTrack() => trackManager.Get($"https://b.ppy.sh/preview/{beatmapSetInfo?.OnlineBeatmapSetID}.mp3");
|
||||
}
|
||||
|
||||
private class PreviewTrackStore : AudioCollectionManager<AdjustableAudioComponent>, ITrackStore
|
||||
{
|
||||
private readonly IResourceStore<byte[]> store;
|
||||
|
||||
internal PreviewTrackStore(IResourceStore<byte[]> store)
|
||||
{
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public Track GetVirtual(double length = double.PositiveInfinity)
|
||||
{
|
||||
if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(PreviewTrackStore)}");
|
||||
|
||||
var track = new TrackVirtual(length);
|
||||
AddItem(track);
|
||||
return track;
|
||||
}
|
||||
|
||||
public Track Get(string name)
|
||||
{
|
||||
if (IsDisposed) throw new ObjectDisposedException($"Cannot retrieve items for an already disposed {nameof(PreviewTrackStore)}");
|
||||
|
||||
if (string.IsNullOrEmpty(name)) return null;
|
||||
|
||||
var dataStream = store.GetStream(name);
|
||||
|
||||
if (dataStream == null)
|
||||
return null;
|
||||
|
||||
Track track = new TrackBass(dataStream);
|
||||
AddItem(track);
|
||||
return track;
|
||||
}
|
||||
|
||||
public Task<Track> GetAsync(string name) => Task.Run(() => Get(name));
|
||||
|
||||
public Stream GetStream(string name) => store.GetStream(name);
|
||||
|
||||
public IEnumerable<string> GetAvailableResources() => store.GetAvailableResources();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,6 +342,7 @@ namespace osu.Game.Beatmaps
|
||||
OnlineBeatmapSetID = beatmap.BeatmapInfo.BeatmapSet?.OnlineBeatmapSetID,
|
||||
Beatmaps = new List<BeatmapInfo>(),
|
||||
Metadata = beatmap.Metadata,
|
||||
DateAdded = DateTimeOffset.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
@ -429,7 +430,7 @@ namespace osu.Game.Beatmaps
|
||||
private readonly IBeatmap beatmap;
|
||||
|
||||
public DummyConversionBeatmap(IBeatmap beatmap)
|
||||
: base(beatmap.BeatmapInfo)
|
||||
: base(beatmap.BeatmapInfo, null)
|
||||
{
|
||||
this.beatmap = beatmap;
|
||||
}
|
||||
|
@ -20,14 +20,12 @@ namespace osu.Game.Beatmaps
|
||||
protected class BeatmapManagerWorkingBeatmap : WorkingBeatmap
|
||||
{
|
||||
private readonly IResourceStore<byte[]> store;
|
||||
private readonly AudioManager audioManager;
|
||||
|
||||
public BeatmapManagerWorkingBeatmap(IResourceStore<byte[]> store, TextureStore textureStore, BeatmapInfo beatmapInfo, AudioManager audioManager)
|
||||
: base(beatmapInfo)
|
||||
: base(beatmapInfo, audioManager)
|
||||
{
|
||||
this.store = store;
|
||||
this.textureStore = textureStore;
|
||||
this.audioManager = audioManager;
|
||||
}
|
||||
|
||||
protected override IBeatmap GetBeatmap()
|
||||
@ -47,6 +45,8 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
private TextureStore textureStore;
|
||||
|
||||
private ITrackStore trackStore;
|
||||
|
||||
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()
|
||||
@ -68,8 +68,7 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
try
|
||||
{
|
||||
var trackData = store.GetStream(getPathForFile(Metadata.AudioFile));
|
||||
return trackData == null ? null : new TrackBass(trackData);
|
||||
return (trackStore ?? (trackStore = AudioManager.GetTrackStore(store))).Get(getPathForFile(Metadata.AudioFile));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -77,6 +76,14 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
}
|
||||
|
||||
public override void RecycleTrack()
|
||||
{
|
||||
base.RecycleTrack();
|
||||
|
||||
trackStore?.Dispose();
|
||||
trackStore = null;
|
||||
}
|
||||
|
||||
public override void TransferTo(WorkingBeatmap other)
|
||||
{
|
||||
base.TransferTo(other);
|
||||
@ -135,7 +142,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
try
|
||||
{
|
||||
skin = new LegacyBeatmapSkin(BeatmapInfo, store, audioManager);
|
||||
skin = new LegacyBeatmapSkin(BeatmapInfo, store, AudioManager);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
@ -20,6 +21,8 @@ namespace osu.Game.Beatmaps
|
||||
set => onlineBeatmapSetID = value > 0 ? value : null;
|
||||
}
|
||||
|
||||
public DateTimeOffset DateAdded { get; set; }
|
||||
|
||||
public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None;
|
||||
|
||||
public BeatmapMetadata Metadata { get; set; }
|
||||
|
@ -1,11 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
@ -16,32 +12,15 @@ namespace osu.Game.Beatmaps
|
||||
/// </summary>
|
||||
public abstract class BindableBeatmap : NonNullableBindable<WorkingBeatmap>
|
||||
{
|
||||
private AudioManager audioManager;
|
||||
private WorkingBeatmap lastBeatmap;
|
||||
|
||||
protected BindableBeatmap(WorkingBeatmap defaultValue)
|
||||
: base(defaultValue)
|
||||
{
|
||||
BindValueChanged(b => updateAudioTrack(b.NewValue), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an <see cref="AudioManager"/> for <see cref="Track"/>s to be added to.
|
||||
/// </summary>
|
||||
/// <param name="audioManager">The <see cref="AudioManager"/> to register.</param>
|
||||
protected void RegisterAudioManager([NotNull] AudioManager audioManager)
|
||||
{
|
||||
if (this.audioManager != null) throw new InvalidOperationException($"Cannot register multiple {nameof(AudioManager)}s.");
|
||||
|
||||
this.audioManager = audioManager;
|
||||
|
||||
ValueChanged += b => registerAudioTrack(b.NewValue);
|
||||
|
||||
// If the track has changed prior to this being called, let's register it
|
||||
if (Value != Default)
|
||||
registerAudioTrack(Value);
|
||||
}
|
||||
|
||||
private void registerAudioTrack(WorkingBeatmap beatmap)
|
||||
private void updateAudioTrack(WorkingBeatmap beatmap)
|
||||
{
|
||||
var trackLoaded = lastBeatmap?.TrackLoaded ?? false;
|
||||
|
||||
@ -55,18 +34,9 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
lastBeatmap.RecycleTrack();
|
||||
}
|
||||
|
||||
audioManager.Track.AddItem(beatmap.Track);
|
||||
}
|
||||
|
||||
lastBeatmap = beatmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a new <see cref="BindableBeatmap"/> instance weakly bound to this <see cref="BindableBeatmap"/>.
|
||||
/// If you are further binding to events of the retrieved <see cref="BindableBeatmap"/>, ensure a local reference is held.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public new abstract BindableBeatmap GetBoundCopy();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -31,24 +32,8 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
/// </summary>
|
||||
protected virtual double UnloadDelay => 10000;
|
||||
|
||||
private BeatmapInfo lastModel;
|
||||
private bool firstLoad = true;
|
||||
|
||||
protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Drawable content, double timeBeforeLoad)
|
||||
{
|
||||
return new DelayedLoadUnloadWrapper(() =>
|
||||
{
|
||||
// If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was
|
||||
// previously UNLOADED and thus its children have been disposed of, so we need to recreate them here.
|
||||
if (!firstLoad && lastModel == Beatmap.Value)
|
||||
return CreateDrawable(Beatmap.Value);
|
||||
|
||||
// If the model has changed since the previous unload (or if there was no load), then we can safely use the given content
|
||||
lastModel = Beatmap.Value;
|
||||
firstLoad = false;
|
||||
return content;
|
||||
}, timeBeforeLoad, UnloadDelay);
|
||||
}
|
||||
protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func<Drawable> createContentFunc, double timeBeforeLoad)
|
||||
=> new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad, UnloadDelay);
|
||||
|
||||
protected override Drawable CreateDrawable(BeatmapInfo model)
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
@ -16,9 +17,9 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
public class DummyWorkingBeatmap : WorkingBeatmap
|
||||
{
|
||||
private readonly OsuGameBase game;
|
||||
private readonly TextureStore textures;
|
||||
|
||||
public DummyWorkingBeatmap(OsuGameBase game = null)
|
||||
public DummyWorkingBeatmap(AudioManager audio, TextureStore textures)
|
||||
: base(new BeatmapInfo
|
||||
{
|
||||
Metadata = new BeatmapMetadata
|
||||
@ -34,16 +35,16 @@ namespace osu.Game.Beatmaps
|
||||
OverallDifficulty = 0,
|
||||
},
|
||||
Ruleset = new DummyRulesetInfo()
|
||||
})
|
||||
}, audio)
|
||||
{
|
||||
this.game = game;
|
||||
this.textures = textures;
|
||||
}
|
||||
|
||||
protected override IBeatmap GetBeatmap() => new Beatmap();
|
||||
|
||||
protected override Texture GetBackground() => game?.Textures.Get(@"Backgrounds/bg4");
|
||||
protected override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4");
|
||||
|
||||
protected override Track GetTrack() => new TrackVirtual { Length = 1000 };
|
||||
protected override Track GetTrack() => GetVirtualTrack();
|
||||
|
||||
private class DummyRulesetInfo : RulesetInfo
|
||||
{
|
||||
|
@ -11,15 +11,17 @@ using osu.Framework.IO.File;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Game.IO.Serialization;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
public abstract partial class WorkingBeatmap : IDisposable
|
||||
public abstract class WorkingBeatmap : IDisposable
|
||||
{
|
||||
public readonly BeatmapInfo BeatmapInfo;
|
||||
|
||||
@ -27,8 +29,11 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public readonly BeatmapMetadata Metadata;
|
||||
|
||||
protected WorkingBeatmap(BeatmapInfo beatmapInfo)
|
||||
protected AudioManager AudioManager { get; }
|
||||
|
||||
protected WorkingBeatmap(BeatmapInfo beatmapInfo, AudioManager audioManager)
|
||||
{
|
||||
AudioManager = audioManager;
|
||||
BeatmapInfo = beatmapInfo;
|
||||
BeatmapSetInfo = beatmapInfo.BeatmapSet;
|
||||
Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
|
||||
@ -46,13 +51,39 @@ namespace osu.Game.Beatmaps
|
||||
return b;
|
||||
});
|
||||
|
||||
track = new RecyclableLazy<Track>(() => GetTrack() ?? new VirtualBeatmapTrack(Beatmap));
|
||||
track = new RecyclableLazy<Track>(() => GetTrack() ?? GetVirtualTrack());
|
||||
background = new RecyclableLazy<Texture>(GetBackground, BackgroundStillValid);
|
||||
waveform = new RecyclableLazy<Waveform>(GetWaveform);
|
||||
storyboard = new RecyclableLazy<Storyboard>(GetStoryboard);
|
||||
skin = new RecyclableLazy<Skin>(GetSkin);
|
||||
}
|
||||
|
||||
protected virtual Track GetVirtualTrack()
|
||||
{
|
||||
const double excess_length = 1000;
|
||||
|
||||
var lastObject = Beatmap.HitObjects.LastOrDefault();
|
||||
|
||||
double length;
|
||||
|
||||
switch (lastObject)
|
||||
{
|
||||
case null:
|
||||
length = excess_length;
|
||||
break;
|
||||
|
||||
case IHasEndTime endTime:
|
||||
length = endTime.EndTime + excess_length;
|
||||
break;
|
||||
|
||||
default:
|
||||
length = lastObject.StartTime + excess_length;
|
||||
break;
|
||||
}
|
||||
|
||||
return AudioManager.Tracks.GetVirtual(length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the <see cref="Beatmaps.Beatmap"/>.
|
||||
/// </summary>
|
||||
@ -150,6 +181,7 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
public bool SkinLoaded => skin.IsResultAvailable;
|
||||
public Skin Skin => skin.Value;
|
||||
|
||||
protected virtual Skin GetSkin() => new DefaultSkin();
|
||||
private readonly RecyclableLazy<Skin> skin;
|
||||
|
||||
@ -175,7 +207,7 @@ namespace osu.Game.Beatmaps
|
||||
/// Eagerly dispose of the audio track associated with this <see cref="WorkingBeatmap"/> (if any).
|
||||
/// Accessing track again will load a fresh instance.
|
||||
/// </summary>
|
||||
public void RecycleTrack() => track.Recycle();
|
||||
public virtual void RecycleTrack() => track.Recycle();
|
||||
|
||||
public class RecyclableLazy<T>
|
||||
{
|
||||
|
@ -1,41 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
{
|
||||
public partial class WorkingBeatmap
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of <see cref="TrackVirtual"/> which provides a valid length based on the <see cref="HitObject"/>s of an <see cref="IBeatmap"/>.
|
||||
/// </summary>
|
||||
protected class VirtualBeatmapTrack : TrackVirtual
|
||||
{
|
||||
private const double excess_length = 1000;
|
||||
|
||||
public VirtualBeatmapTrack(IBeatmap beatmap)
|
||||
{
|
||||
var lastObject = beatmap.HitObjects.LastOrDefault();
|
||||
|
||||
switch (lastObject)
|
||||
{
|
||||
case null:
|
||||
Length = excess_length;
|
||||
break;
|
||||
|
||||
case IHasEndTime endTime:
|
||||
Length = endTime.EndTime + excess_length;
|
||||
break;
|
||||
|
||||
default:
|
||||
Length = lastObject.StartTime + excess_length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,8 @@ namespace osu.Game.Configuration
|
||||
|
||||
public int? Variant { get; set; }
|
||||
|
||||
public int? SkinInfoID { get; set; }
|
||||
|
||||
[Column("Key")]
|
||||
public string Key { get; set; }
|
||||
|
||||
|
@ -214,7 +214,6 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
base.Draw(vertexAction);
|
||||
|
||||
shader.Bind();
|
||||
texture.TextureGL.Bind();
|
||||
|
||||
Vector2 localInflationAmount = edge_smoothness * DrawInfo.MatrixInverse.ExtractScale().Xy;
|
||||
|
||||
@ -231,7 +230,8 @@ namespace osu.Game.Graphics.Backgrounds
|
||||
ColourInfo colourInfo = DrawColourInfo.Colour;
|
||||
colourInfo.ApplyChild(particle.Colour);
|
||||
|
||||
texture.DrawTriangle(
|
||||
DrawTriangle(
|
||||
texture,
|
||||
triangle,
|
||||
colourInfo,
|
||||
null,
|
||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
if (AutoSizeAxes != Axes.None)
|
||||
{
|
||||
content.RelativeSizeAxes = RelativeSizeAxes;
|
||||
content.RelativeSizeAxes = (Axes.Both & ~AutoSizeAxes);
|
||||
content.AutoSizeAxes = AutoSizeAxes;
|
||||
}
|
||||
|
||||
|
@ -51,8 +51,8 @@ namespace osu.Game.Graphics.Containers
|
||||
if (osuGame != null)
|
||||
OverlayActivationMode.BindTo(osuGame.OverlayActivationMode);
|
||||
|
||||
samplePopIn = audio.Sample.Get(@"UI/overlay-pop-in");
|
||||
samplePopOut = audio.Sample.Get(@"UI/overlay-pop-out");
|
||||
samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in");
|
||||
samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out");
|
||||
|
||||
StateChanged += onStateChanged;
|
||||
}
|
||||
|
@ -24,7 +24,13 @@ namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
Enabled.ValueChanged += e =>
|
||||
{
|
||||
if (!e.NewValue) unhover();
|
||||
if (isHovered)
|
||||
{
|
||||
if (e.NewValue)
|
||||
fadeIn();
|
||||
else
|
||||
fadeOut();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -32,27 +38,28 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
if (isHovered)
|
||||
return false;
|
||||
|
||||
isHovered = true;
|
||||
|
||||
if (!Enabled.Value)
|
||||
return false;
|
||||
|
||||
EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint));
|
||||
isHovered = true;
|
||||
fadeIn();
|
||||
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
unhover();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
private void unhover()
|
||||
{
|
||||
if (!isHovered) return;
|
||||
if (!isHovered)
|
||||
return;
|
||||
|
||||
isHovered = false;
|
||||
EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint));
|
||||
fadeOut();
|
||||
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -67,5 +74,9 @@ namespace osu.Game.Graphics.Containers
|
||||
base.LoadComplete();
|
||||
EffectTargets.ForEach(d => d.FadeColour(IdleColour));
|
||||
}
|
||||
|
||||
private void fadeIn() => EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint));
|
||||
|
||||
private void fadeOut() => EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint));
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace osu.Game.Graphics
|
||||
screenshotFormat = config.GetBindable<ScreenshotFormat>(OsuSetting.ScreenshotFormat);
|
||||
captureMenuCursor = config.GetBindable<bool>(OsuSetting.ScreenshotCaptureMenuCursor);
|
||||
|
||||
shutter = audio.Sample.Get("UI/shutter");
|
||||
shutter = audio.Samples.Get("UI/shutter");
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleClick = audio.Sample.Get($@"UI/generic-select{SampleSet.GetDescription()}");
|
||||
sampleClick = audio.Samples.Get($@"UI/generic-select{SampleSet.GetDescription()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = audio.Sample.Get($@"UI/generic-hover{SampleSet.GetDescription()}");
|
||||
sampleHover = audio.Samples.Get($@"UI/generic-hover{SampleSet.GetDescription()}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
set
|
||||
{
|
||||
Content.RelativeSizeAxes = Axes.None;
|
||||
Content.AutoSizeAxes = Axes.None;
|
||||
Content.Size = value;
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,12 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
if (AutoSizeAxes != Axes.None)
|
||||
{
|
||||
content.RelativeSizeAxes = (Axes.Both & ~AutoSizeAxes);
|
||||
content.AutoSizeAxes = AutoSizeAxes;
|
||||
}
|
||||
|
||||
Enabled.BindValueChanged(enabled => this.FadeColour(enabled.NewValue ? Color4.White : colours.Gray9, 200, Easing.OutQuint), true);
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@ namespace osu.Game.Graphics.UserInterface
|
||||
/// <summary>
|
||||
/// A button with added default sound effects.
|
||||
/// </summary>
|
||||
public class OsuButton : Button
|
||||
public abstract class OsuButton : Button
|
||||
{
|
||||
private Box hover;
|
||||
|
||||
public OsuButton()
|
||||
protected OsuButton()
|
||||
{
|
||||
Height = 40;
|
||||
|
||||
|
@ -112,8 +112,8 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleChecked = audio.Sample.Get(@"UI/check-on");
|
||||
sampleUnchecked = audio.Sample.Get(@"UI/check-off");
|
||||
sampleChecked = audio.Samples.Get(@"UI/check-on");
|
||||
sampleUnchecked = audio.Samples.Get(@"UI/check-off");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,8 +71,8 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = audio.Sample.Get(@"UI/generic-hover");
|
||||
sampleClick = audio.Sample.Get(@"UI/generic-select");
|
||||
sampleHover = audio.Samples.Get(@"UI/generic-hover");
|
||||
sampleClick = audio.Samples.Get(@"UI/generic-select");
|
||||
|
||||
BackgroundColour = Color4.Transparent;
|
||||
BackgroundColourHover = OsuColour.FromHex(@"172023");
|
||||
|
@ -86,7 +86,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, OsuColour colours)
|
||||
{
|
||||
sample = audio.Sample.Get(@"UI/sliderbar-notch");
|
||||
sample = audio.Samples.Get(@"UI/sliderbar-notch");
|
||||
AccentColour = colours.Pink;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@ namespace osu.Game.IO.Archives
|
||||
/// </summary>
|
||||
public abstract Stream GetStream(string name);
|
||||
|
||||
public IEnumerable<string> GetAvailableResources() => Filenames;
|
||||
|
||||
public abstract void Dispose();
|
||||
|
||||
/// <summary>
|
||||
|
498
osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs
generated
Normal file
498
osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs
generated
Normal file
@ -0,0 +1,498 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
[DbContext(typeof(OsuDbContext))]
|
||||
[Migration("20190525060824_SkinSettings")]
|
||||
partial class SkinSettings
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<float>("ApproachRate");
|
||||
|
||||
b.Property<float>("CircleSize");
|
||||
|
||||
b.Property<float>("DrainRate");
|
||||
|
||||
b.Property<float>("OverallDifficulty");
|
||||
|
||||
b.Property<double>("SliderMultiplier");
|
||||
|
||||
b.Property<double>("SliderTickRate");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapDifficulty");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("AudioLeadIn");
|
||||
|
||||
b.Property<int>("BaseDifficultyID");
|
||||
|
||||
b.Property<int>("BeatDivisor");
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<bool>("Countdown");
|
||||
|
||||
b.Property<double>("DistanceSpacing");
|
||||
|
||||
b.Property<int>("GridSize");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<bool>("Hidden");
|
||||
|
||||
b.Property<bool>("LetterboxInBreaks");
|
||||
|
||||
b.Property<string>("MD5Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapID");
|
||||
|
||||
b.Property<string>("Path");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<bool>("SpecialStyle");
|
||||
|
||||
b.Property<float>("StackLeniency");
|
||||
|
||||
b.Property<double>("StarDifficulty");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.Property<string>("StoredBookmarks");
|
||||
|
||||
b.Property<double>("TimelineZoom");
|
||||
|
||||
b.Property<string>("Version");
|
||||
|
||||
b.Property<bool>("WidescreenStoryboard");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BaseDifficultyID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("Hash");
|
||||
|
||||
b.HasIndex("MD5Hash");
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("BeatmapInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Artist");
|
||||
|
||||
b.Property<string>("ArtistUnicode");
|
||||
|
||||
b.Property<string>("AudioFile");
|
||||
|
||||
b.Property<string>("AuthorString")
|
||||
.HasColumnName("Author");
|
||||
|
||||
b.Property<string>("BackgroundFile");
|
||||
|
||||
b.Property<int>("PreviewTime");
|
||||
|
||||
b.Property<string>("Source");
|
||||
|
||||
b.Property<string>("Tags");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("TitleUnicode");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapMetadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.ToTable("BeatmapSetFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapSetID");
|
||||
|
||||
b.Property<bool>("Protected");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapSetID")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BeatmapSetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("SkinInfoID");
|
||||
|
||||
b.Property<string>("StringValue")
|
||||
.HasColumnName("Value");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("ReferenceCount");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ReferenceCount");
|
||||
|
||||
b.ToTable("FileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntAction")
|
||||
.HasColumnName("Action");
|
||||
|
||||
b.Property<string>("KeysString")
|
||||
.HasColumnName("Keys");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("IntAction");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("KeyBinding");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
|
||||
{
|
||||
b.Property<int?>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Available");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("ShortName");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Available");
|
||||
|
||||
b.HasIndex("ShortName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RulesetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("ScoreInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("ScoreInfoID");
|
||||
|
||||
b.ToTable("ScoreFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<double>("Accuracy")
|
||||
.HasColumnType("DECIMAL(1,4)");
|
||||
|
||||
b.Property<int>("BeatmapInfoID");
|
||||
|
||||
b.Property<int>("Combo");
|
||||
|
||||
b.Property<DateTimeOffset>("Date");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("MaxCombo");
|
||||
|
||||
b.Property<string>("ModsJson")
|
||||
.HasColumnName("Mods");
|
||||
|
||||
b.Property<long?>("OnlineScoreID");
|
||||
|
||||
b.Property<double?>("PP");
|
||||
|
||||
b.Property<int>("Rank");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<string>("StatisticsJson")
|
||||
.HasColumnName("Statistics");
|
||||
|
||||
b.Property<long>("TotalScore");
|
||||
|
||||
b.Property<long?>("UserID")
|
||||
.HasColumnName("UserID");
|
||||
|
||||
b.Property<string>("UserString")
|
||||
.HasColumnName("User");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapInfoID");
|
||||
|
||||
b.HasIndex("OnlineScoreID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("ScoreInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SkinInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.ToTable("SkinFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Creator");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SkinInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||
.WithMany()
|
||||
.HasForeignKey("BaseDifficultyID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("MetadataID");
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("BeatmapSets")
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Settings")
|
||||
.HasForeignKey("SkinInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Scoring.ScoreInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("ScoreInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap")
|
||||
.WithMany("Scores")
|
||||
.HasForeignKey("BeatmapInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("SkinInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
54
osu.Game/Migrations/20190525060824_SkinSettings.cs
Normal file
54
osu.Game/Migrations/20190525060824_SkinSettings.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
public partial class SkinSettings : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql(@"create table Settings_dg_tmp
|
||||
(
|
||||
ID INTEGER not null
|
||||
constraint PK_Settings
|
||||
primary key autoincrement,
|
||||
Key TEXT not null,
|
||||
RulesetID INTEGER,
|
||||
Value TEXT,
|
||||
Variant INTEGER,
|
||||
SkinInfoID int
|
||||
constraint Settings_SkinInfo_ID_fk
|
||||
references SkinInfo
|
||||
on delete restrict
|
||||
);
|
||||
|
||||
insert into Settings_dg_tmp(ID, Key, RulesetID, Value, Variant) select ID, Key, RulesetID, Value, Variant from Settings;
|
||||
|
||||
drop table Settings;
|
||||
|
||||
alter table Settings_dg_tmp rename to Settings;
|
||||
|
||||
create index IX_Settings_RulesetID_Variant
|
||||
on Settings (RulesetID, Variant);
|
||||
|
||||
create index Settings_SkinInfoID_index
|
||||
on Settings (SkinInfoID);
|
||||
|
||||
");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Settings_SkinInfo_SkinInfoID",
|
||||
table: "Settings");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Settings_SkinInfoID",
|
||||
table: "Settings");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SkinInfoID",
|
||||
table: "Settings");
|
||||
}
|
||||
}
|
||||
}
|
489
osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs
generated
Normal file
489
osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs
generated
Normal file
@ -0,0 +1,489 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
[DbContext(typeof(OsuDbContext))]
|
||||
[Migration("20190605091246_AddDateAddedColumnToBeatmapSet")]
|
||||
partial class AddDateAddedColumnToBeatmapSet
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<float>("ApproachRate");
|
||||
|
||||
b.Property<float>("CircleSize");
|
||||
|
||||
b.Property<float>("DrainRate");
|
||||
|
||||
b.Property<float>("OverallDifficulty");
|
||||
|
||||
b.Property<double>("SliderMultiplier");
|
||||
|
||||
b.Property<double>("SliderTickRate");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapDifficulty");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("AudioLeadIn");
|
||||
|
||||
b.Property<int>("BaseDifficultyID");
|
||||
|
||||
b.Property<int>("BeatDivisor");
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<bool>("Countdown");
|
||||
|
||||
b.Property<double>("DistanceSpacing");
|
||||
|
||||
b.Property<int>("GridSize");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<bool>("Hidden");
|
||||
|
||||
b.Property<bool>("LetterboxInBreaks");
|
||||
|
||||
b.Property<string>("MD5Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapID");
|
||||
|
||||
b.Property<string>("Path");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<bool>("SpecialStyle");
|
||||
|
||||
b.Property<float>("StackLeniency");
|
||||
|
||||
b.Property<double>("StarDifficulty");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.Property<string>("StoredBookmarks");
|
||||
|
||||
b.Property<double>("TimelineZoom");
|
||||
|
||||
b.Property<string>("Version");
|
||||
|
||||
b.Property<bool>("WidescreenStoryboard");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BaseDifficultyID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("Hash");
|
||||
|
||||
b.HasIndex("MD5Hash");
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("BeatmapInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Artist");
|
||||
|
||||
b.Property<string>("ArtistUnicode");
|
||||
|
||||
b.Property<string>("AudioFile");
|
||||
|
||||
b.Property<string>("AuthorString")
|
||||
.HasColumnName("Author");
|
||||
|
||||
b.Property<string>("BackgroundFile");
|
||||
|
||||
b.Property<int>("PreviewTime");
|
||||
|
||||
b.Property<string>("Source");
|
||||
|
||||
b.Property<string>("Tags");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.Property<string>("TitleUnicode");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("BeatmapMetadata");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("BeatmapSetInfoID");
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapSetInfoID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.ToTable("BeatmapSetFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTimeOffset>("DateAdded");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int?>("MetadataID");
|
||||
|
||||
b.Property<int?>("OnlineBeatmapSetID");
|
||||
|
||||
b.Property<bool>("Protected");
|
||||
|
||||
b.Property<int>("Status");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapSetID")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BeatmapSetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Key")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<string>("StringValue")
|
||||
.HasColumnName("Value");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("ReferenceCount");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ReferenceCount");
|
||||
|
||||
b.ToTable("FileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntAction")
|
||||
.HasColumnName("Action");
|
||||
|
||||
b.Property<string>("KeysString")
|
||||
.HasColumnName("Keys");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("IntAction");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("KeyBinding");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
|
||||
{
|
||||
b.Property<int?>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Available");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("ShortName");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Available");
|
||||
|
||||
b.HasIndex("ShortName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RulesetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("ScoreInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("ScoreInfoID");
|
||||
|
||||
b.ToTable("ScoreFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<double>("Accuracy")
|
||||
.HasColumnType("DECIMAL(1,4)");
|
||||
|
||||
b.Property<int>("BeatmapInfoID");
|
||||
|
||||
b.Property<int>("Combo");
|
||||
|
||||
b.Property<DateTimeOffset>("Date");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("MaxCombo");
|
||||
|
||||
b.Property<string>("ModsJson")
|
||||
.HasColumnName("Mods");
|
||||
|
||||
b.Property<long?>("OnlineScoreID");
|
||||
|
||||
b.Property<double?>("PP");
|
||||
|
||||
b.Property<int>("Rank");
|
||||
|
||||
b.Property<int>("RulesetID");
|
||||
|
||||
b.Property<string>("StatisticsJson")
|
||||
.HasColumnName("Statistics");
|
||||
|
||||
b.Property<long>("TotalScore");
|
||||
|
||||
b.Property<long?>("UserID")
|
||||
.HasColumnName("UserID");
|
||||
|
||||
b.Property<string>("UserString")
|
||||
.HasColumnName("User");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("BeatmapInfoID");
|
||||
|
||||
b.HasIndex("OnlineScoreID")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RulesetID");
|
||||
|
||||
b.ToTable("ScoreInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SkinInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.ToTable("SkinFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Creator");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("SkinInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||
.WithMany()
|
||||
.HasForeignKey("BaseDifficultyID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("MetadataID");
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("BeatmapSets")
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Scoring.ScoreInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("ScoreInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap")
|
||||
.WithMany("Scores")
|
||||
.HasForeignKey("BeatmapInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("SkinInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
public partial class AddDateAddedColumnToBeatmapSet : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "DateAdded",
|
||||
table: "BeatmapSetInfo",
|
||||
nullable: false,
|
||||
defaultValue: new DateTimeOffset(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0)));
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DateAdded",
|
||||
table: "BeatmapSetInfo");
|
||||
}
|
||||
}
|
||||
}
|
@ -166,6 +166,8 @@ namespace osu.Game.Migrations
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTimeOffset>("DateAdded");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Hash");
|
||||
@ -203,6 +205,8 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("SkinInfoID");
|
||||
|
||||
b.Property<string>("StringValue")
|
||||
.HasColumnName("Value");
|
||||
|
||||
@ -210,6 +214,8 @@ namespace osu.Game.Migrations
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("Settings");
|
||||
@ -442,6 +448,13 @@ namespace osu.Game.Migrations
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Settings")
|
||||
.HasForeignKey("SkinInfoID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
public string MessageHtml { get; set; }
|
||||
|
||||
[JsonProperty("major")]
|
||||
public bool? Major { get; set; }
|
||||
public bool Major { get; set; }
|
||||
|
||||
[JsonProperty("created_at")]
|
||||
public DateTimeOffset? CreatedAt { get; set; }
|
||||
|
@ -81,6 +81,9 @@ namespace osu.Game.Online.Chat
|
||||
if (user == null)
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
|
||||
if (user.Id == api.LocalUser.Value.Id)
|
||||
return;
|
||||
|
||||
CurrentChannel.Value = JoinedChannels.FirstOrDefault(c => c.Type == ChannelType.PM && c.Users.Count == 1 && c.Users.Any(u => u.Id == user.Id))
|
||||
?? new Channel(user);
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ namespace osu.Game
|
||||
|
||||
dependencies.CacheAs<IAPIProvider>(API);
|
||||
|
||||
var defaultBeatmap = new DummyWorkingBeatmap(this);
|
||||
var defaultBeatmap = new DummyWorkingBeatmap(Audio, Textures);
|
||||
|
||||
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory));
|
||||
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
|
||||
@ -193,9 +193,9 @@ namespace osu.Game
|
||||
|
||||
// tracks play so loud our samples can't keep up.
|
||||
// this adds a global reduction of track volume for the time being.
|
||||
Audio.Track.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));
|
||||
Audio.Tracks.AddAdjustment(AdjustableProperty.Volume, new BindableDouble(0.8));
|
||||
|
||||
beatmap = new OsuBindableBeatmap(defaultBeatmap, Audio);
|
||||
beatmap = new OsuBindableBeatmap(defaultBeatmap);
|
||||
|
||||
dependencies.CacheAs<IBindable<WorkingBeatmap>>(beatmap);
|
||||
dependencies.CacheAs(beatmap);
|
||||
@ -281,23 +281,10 @@ namespace osu.Game
|
||||
|
||||
private class OsuBindableBeatmap : BindableBeatmap
|
||||
{
|
||||
public OsuBindableBeatmap(WorkingBeatmap defaultValue, AudioManager audioManager)
|
||||
: this(defaultValue)
|
||||
{
|
||||
RegisterAudioManager(audioManager);
|
||||
}
|
||||
|
||||
public OsuBindableBeatmap(WorkingBeatmap defaultValue)
|
||||
: base(defaultValue)
|
||||
{
|
||||
}
|
||||
|
||||
public override BindableBeatmap GetBoundCopy()
|
||||
{
|
||||
var copy = new OsuBindableBeatmap(Default);
|
||||
copy.BindTo(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
private class OsuUserInputManager : UserInputManager
|
||||
|
@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
Text = "#1",
|
||||
Font = OsuFont.GetFont(size: 30, weight: FontWeight.Bold, italics: true)
|
||||
},
|
||||
rank = new DrawableRank(ScoreRank.F)
|
||||
rank = new DrawableRank(ScoreRank.D)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
|
@ -13,6 +13,7 @@ using System.Text.RegularExpressions;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Users;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Overlays.Changelog
|
||||
{
|
||||
@ -45,8 +46,12 @@ namespace osu.Game.Overlays.Changelog
|
||||
Direction = FillDirection.Vertical,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var categoryEntries in build.ChangelogEntries.GroupBy(b => b.Category).OrderBy(c => c.Key))
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
foreach (var categoryEntries in Build.ChangelogEntries.GroupBy(b => b.Category).OrderBy(c => c.Key))
|
||||
{
|
||||
ChangelogEntries.Add(new OsuSpriteText
|
||||
{
|
||||
@ -69,34 +74,69 @@ namespace osu.Game.Overlays.Changelog
|
||||
Margin = new MarginPadding { Vertical = 5 },
|
||||
};
|
||||
|
||||
var entryColour = entry.Major ? colours.YellowLight : Color4.White;
|
||||
|
||||
title.AddIcon(FontAwesome.Solid.Check, t =>
|
||||
{
|
||||
t.Font = fontSmall;
|
||||
t.Colour = entryColour;
|
||||
t.Padding = new MarginPadding { Left = -17, Right = 5 };
|
||||
});
|
||||
|
||||
title.AddText(entry.Title, t => { t.Font = fontLarge; });
|
||||
title.AddText(entry.Title, t =>
|
||||
{
|
||||
t.Font = fontLarge;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
|
||||
if (!string.IsNullOrEmpty(entry.Repository))
|
||||
{
|
||||
title.AddText(" (", t => t.Font = fontLarge);
|
||||
title.AddText(" (", t =>
|
||||
{
|
||||
t.Font = fontLarge;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
title.AddLink($"{entry.Repository.Replace("ppy/", "")}#{entry.GithubPullRequestId}", entry.GithubUrl, Online.Chat.LinkAction.External,
|
||||
creationParameters: t => { t.Font = fontLarge; });
|
||||
title.AddText(")", t => t.Font = fontLarge);
|
||||
creationParameters: t =>
|
||||
{
|
||||
t.Font = fontLarge;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
title.AddText(")", t =>
|
||||
{
|
||||
t.Font = fontLarge;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
}
|
||||
|
||||
title.AddText(" by ", t => t.Font = fontMedium);
|
||||
title.AddText(" by ", t =>
|
||||
{
|
||||
t.Font = fontMedium;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
|
||||
if (entry.GithubUser.UserId != null)
|
||||
title.AddUserLink(new User
|
||||
{
|
||||
Username = entry.GithubUser.OsuUsername,
|
||||
Id = entry.GithubUser.UserId.Value
|
||||
}, t => t.Font = fontMedium);
|
||||
}, t =>
|
||||
{
|
||||
t.Font = fontMedium;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
else if (entry.GithubUser.GithubUrl != null)
|
||||
title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t => t.Font = fontMedium);
|
||||
title.AddLink(entry.GithubUser.DisplayName, entry.GithubUser.GithubUrl, Online.Chat.LinkAction.External, null, null, t =>
|
||||
{
|
||||
t.Font = fontMedium;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
else
|
||||
title.AddText(entry.GithubUser.DisplayName, t => t.Font = fontSmall);
|
||||
title.AddText(entry.GithubUser.DisplayName, t =>
|
||||
{
|
||||
t.Font = fontSmall;
|
||||
t.Colour = entryColour;
|
||||
});
|
||||
|
||||
ChangelogEntries.Add(title);
|
||||
|
||||
|
@ -90,8 +90,8 @@ namespace osu.Game.Overlays.Changelog
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleClick = audio.Sample.Get(@"UI/generic-select-soft");
|
||||
sampleHover = audio.Sample.Get(@"UI/generic-hover-soft");
|
||||
sampleClick = audio.Samples.Get(@"UI/generic-select-soft");
|
||||
sampleHover = audio.Samples.Get(@"UI/generic-hover-soft");
|
||||
}
|
||||
|
||||
protected override void OnActivated() => updateState();
|
||||
|
@ -76,7 +76,7 @@ namespace osu.Game.Overlays
|
||||
},
|
||||
};
|
||||
|
||||
sampleBack = audio.Sample.Get(@"UI/generic-select-soft");
|
||||
sampleBack = audio.Samples.Get(@"UI/generic-select-soft");
|
||||
|
||||
header.Current.BindTo(Current);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
@ -14,6 +15,7 @@ using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Chat;
|
||||
using osu.Game.Users;
|
||||
using osuTK;
|
||||
@ -201,6 +203,9 @@ namespace osu.Game.Overlays.Chat
|
||||
|
||||
private Action startChatAction;
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
public MessageSender(User sender)
|
||||
{
|
||||
this.sender = sender;
|
||||
@ -213,11 +218,21 @@ namespace osu.Game.Overlays.Chat
|
||||
startChatAction = () => chatManager?.OpenPrivateChannel(sender);
|
||||
}
|
||||
|
||||
public MenuItem[] ContextMenuItems => new MenuItem[]
|
||||
public MenuItem[] ContextMenuItems
|
||||
{
|
||||
new OsuMenuItem("View Profile", MenuItemType.Highlighted, Action),
|
||||
new OsuMenuItem("Start Chat", MenuItemType.Standard, startChatAction),
|
||||
};
|
||||
get
|
||||
{
|
||||
List<MenuItem> items = new List<MenuItem>
|
||||
{
|
||||
new OsuMenuItem("View Profile", MenuItemType.Highlighted, Action)
|
||||
};
|
||||
|
||||
if (sender.Id != api.LocalUser.Value.Id)
|
||||
items.Add(new OsuMenuItem("Start Chat", MenuItemType.Standard, startChatAction));
|
||||
|
||||
return items.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Color4[] username_colours =
|
||||
|
@ -2,6 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@ -17,6 +19,11 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
private Box overlay;
|
||||
|
||||
private readonly BindableDouble audioVolume = new BindableDouble(1);
|
||||
|
||||
[Resolved]
|
||||
private AudioManager audio { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -33,7 +40,19 @@ namespace osu.Game.Overlays
|
||||
}
|
||||
};
|
||||
|
||||
Progress.ValueChanged += p => overlay.Alpha = (float)p.NewValue;
|
||||
Progress.ValueChanged += p =>
|
||||
{
|
||||
audioVolume.Value = 1 - p.NewValue;
|
||||
overlay.Alpha = (float)p.NewValue;
|
||||
};
|
||||
|
||||
audio.Tracks.AddAdjustment(AdjustableProperty.Volume, audioVolume);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
audio.Tracks.RemoveAdjustment(AdjustableProperty.Volume, audioVolume);
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ namespace osu.Game.Overlays
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours, TextureStore textures, AudioManager audio)
|
||||
{
|
||||
getSample = audio.Sample.Get(@"MedalSplash/medal-get");
|
||||
getSample = audio.Samples.Get(@"MedalSplash/medal-get");
|
||||
innerSpin.Texture = outerSpin.Texture = textures.Get(@"MedalSplash/disc-spin");
|
||||
|
||||
disc.EdgeEffect = leftStrip.EdgeEffect = rightStrip.EdgeEffect = new EdgeEffectParameters
|
||||
|
@ -1,40 +1,40 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays.Mods.Sections;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Overlays.Mods
|
||||
{
|
||||
public class ModSelectOverlay : WaveOverlayContainer
|
||||
{
|
||||
private const float content_width = 0.8f;
|
||||
|
||||
protected Color4 LowMultiplierColour, HighMultiplierColour;
|
||||
|
||||
protected readonly TriangleButton DeselectAllButton;
|
||||
protected readonly OsuSpriteText MultiplierLabel, UnrankedLabel;
|
||||
private readonly FillFlowContainer footerContainer;
|
||||
protected readonly TriangleButton CloseButton;
|
||||
|
||||
protected readonly OsuSpriteText MultiplierLabel;
|
||||
protected readonly OsuSpriteText UnrankedLabel;
|
||||
|
||||
protected override bool BlockNonPositionalInput => false;
|
||||
|
||||
@ -46,154 +46,14 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
protected readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
LowMultiplierColour = colours.Red;
|
||||
HighMultiplierColour = colours.Green;
|
||||
UnrankedLabel.Colour = colours.Blue;
|
||||
protected Color4 LowMultiplierColour;
|
||||
protected Color4 HighMultiplierColour;
|
||||
|
||||
Ruleset.BindTo(ruleset);
|
||||
if (mods != null) SelectedMods.BindTo(mods);
|
||||
|
||||
sampleOn = audio.Sample.Get(@"UI/check-on");
|
||||
sampleOff = audio.Sample.Get(@"UI/check-off");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Ruleset.BindValueChanged(rulesetChanged, true);
|
||||
SelectedMods.BindValueChanged(selectedModsChanged, true);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
Ruleset.UnbindAll();
|
||||
SelectedMods.UnbindAll();
|
||||
}
|
||||
|
||||
private void rulesetChanged(ValueChangedEvent<RulesetInfo> e)
|
||||
{
|
||||
if (e.NewValue == null) return;
|
||||
|
||||
var instance = e.NewValue.CreateInstance();
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.Mods = instance.GetModsFor(section.ModType);
|
||||
|
||||
// attempt to re-select any already selected mods.
|
||||
// this may be the first time we are receiving the ruleset, in which case they will still match.
|
||||
selectedModsChanged(new ValueChangedEvent<IReadOnlyList<Mod>>(SelectedMods.Value, SelectedMods.Value));
|
||||
|
||||
// write the mods back to the SelectedMods bindable in the case a change was not applicable.
|
||||
// this generally isn't required as the previous line will perform deselection; just here for safety.
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> e)
|
||||
{
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList());
|
||||
|
||||
updateMods();
|
||||
}
|
||||
|
||||
private void updateMods()
|
||||
{
|
||||
double multiplier = 1.0;
|
||||
bool ranked = true;
|
||||
|
||||
foreach (Mod mod in SelectedMods.Value)
|
||||
{
|
||||
multiplier *= mod.ScoreMultiplier;
|
||||
ranked &= mod.Ranked;
|
||||
}
|
||||
|
||||
MultiplierLabel.Text = $"{multiplier:N2}x";
|
||||
if (multiplier > 1.0)
|
||||
MultiplierLabel.FadeColour(HighMultiplierColour, 200);
|
||||
else if (multiplier < 1.0)
|
||||
MultiplierLabel.FadeColour(LowMultiplierColour, 200);
|
||||
else
|
||||
MultiplierLabel.FadeColour(Color4.White, 200);
|
||||
|
||||
UnrankedLabel.FadeTo(ranked ? 0 : 1, 200);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
|
||||
footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
base.PopIn();
|
||||
|
||||
footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
public void DeselectAll()
|
||||
{
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.DeselectAll();
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect one or more mods.
|
||||
/// </summary>
|
||||
/// <param name="modTypes">The types of <see cref="Mod"/>s which should be deselected.</param>
|
||||
/// <param name="immediate">Set to true to bypass animations and update selections immediately.</param>
|
||||
public void DeselectTypes(Type[] modTypes, bool immediate = false)
|
||||
{
|
||||
if (modTypes.Length == 0) return;
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
section.DeselectTypes(modTypes, immediate);
|
||||
}
|
||||
private const float content_width = 0.8f;
|
||||
private readonly FillFlowContainer footerContainer;
|
||||
|
||||
private SampleChannel sampleOn, sampleOff;
|
||||
|
||||
private void modButtonPressed(Mod selectedMod)
|
||||
{
|
||||
if (selectedMod != null)
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOn?.Play();
|
||||
DeselectTypes(selectedMod.IncompatibleMods, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOff?.Play();
|
||||
}
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
|
||||
public ModSelectOverlay()
|
||||
{
|
||||
Waves.FirstWaveColour = OsuColour.FromHex(@"19b0e2");
|
||||
@ -364,6 +224,16 @@ namespace osu.Game.Overlays.Mods
|
||||
Right = 20
|
||||
}
|
||||
},
|
||||
CloseButton = new TriangleButton
|
||||
{
|
||||
Width = 180,
|
||||
Text = "Close",
|
||||
Action = Hide,
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Right = 20
|
||||
}
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = @"Score Multiplier:",
|
||||
@ -401,5 +271,171 @@ namespace osu.Game.Overlays.Mods
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuColour colours, IBindable<RulesetInfo> ruleset, AudioManager audio, Bindable<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
LowMultiplierColour = colours.Red;
|
||||
HighMultiplierColour = colours.Green;
|
||||
UnrankedLabel.Colour = colours.Blue;
|
||||
|
||||
Ruleset.BindTo(ruleset);
|
||||
if (mods != null) SelectedMods.BindTo(mods);
|
||||
|
||||
sampleOn = audio.Samples.Get(@"UI/check-on");
|
||||
sampleOff = audio.Samples.Get(@"UI/check-off");
|
||||
}
|
||||
|
||||
public void DeselectAll()
|
||||
{
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.DeselectAll();
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect one or more mods.
|
||||
/// </summary>
|
||||
/// <param name="modTypes">The types of <see cref="Mod"/>s which should be deselected.</param>
|
||||
/// <param name="immediate">Set to true to bypass animations and update selections immediately.</param>
|
||||
public void DeselectTypes(Type[] modTypes, bool immediate = false)
|
||||
{
|
||||
if (modTypes.Length == 0) return;
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.DeselectTypes(modTypes, immediate);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Ruleset.BindValueChanged(rulesetChanged, true);
|
||||
SelectedMods.BindValueChanged(selectedModsChanged, true);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
base.PopOut();
|
||||
|
||||
footerContainer.MoveToX(footerContainer.DrawSize.X, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
footerContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(100f, 0f), WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.MoveToX(100f, WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
section.ButtonsContainer.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.InSine);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
base.PopIn();
|
||||
|
||||
footerContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
footerContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
{
|
||||
section.ButtonsContainer.TransformSpacingTo(new Vector2(50f, 0f), WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
section.ButtonsContainer.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnKeyDown(KeyDownEvent e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Number1:
|
||||
DeselectAllButton.Click();
|
||||
return true;
|
||||
|
||||
case Key.Number2:
|
||||
CloseButton.Click();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
private void rulesetChanged(ValueChangedEvent<RulesetInfo> e)
|
||||
{
|
||||
if (e.NewValue == null) return;
|
||||
|
||||
var instance = e.NewValue.CreateInstance();
|
||||
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.Mods = instance.GetModsFor(section.ModType);
|
||||
|
||||
// attempt to re-select any already selected mods.
|
||||
// this may be the first time we are receiving the ruleset, in which case they will still match.
|
||||
selectedModsChanged(new ValueChangedEvent<IReadOnlyList<Mod>>(SelectedMods.Value, SelectedMods.Value));
|
||||
|
||||
// write the mods back to the SelectedMods bindable in the case a change was not applicable.
|
||||
// this generally isn't required as the previous line will perform deselection; just here for safety.
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void selectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> e)
|
||||
{
|
||||
foreach (var section in ModSectionsContainer.Children)
|
||||
section.SelectTypes(e.NewValue.Select(m => m.GetType()).ToList());
|
||||
|
||||
updateMods();
|
||||
}
|
||||
|
||||
private void updateMods()
|
||||
{
|
||||
var multiplier = 1.0;
|
||||
var ranked = true;
|
||||
|
||||
foreach (var mod in SelectedMods.Value)
|
||||
{
|
||||
multiplier *= mod.ScoreMultiplier;
|
||||
ranked &= mod.Ranked;
|
||||
}
|
||||
|
||||
MultiplierLabel.Text = $"{multiplier:N2}x";
|
||||
if (multiplier > 1.0)
|
||||
MultiplierLabel.FadeColour(HighMultiplierColour, 200);
|
||||
else if (multiplier < 1.0)
|
||||
MultiplierLabel.FadeColour(LowMultiplierColour, 200);
|
||||
else
|
||||
MultiplierLabel.FadeColour(Color4.White, 200);
|
||||
|
||||
UnrankedLabel.FadeTo(ranked ? 0 : 1, 200);
|
||||
}
|
||||
|
||||
private void modButtonPressed(Mod selectedMod)
|
||||
{
|
||||
if (selectedMod != null)
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOn?.Play();
|
||||
DeselectTypes(selectedMod.IncompatibleMods, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (State == Visibility.Visible) sampleOff?.Play();
|
||||
}
|
||||
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
|
||||
#region Disposal
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
Ruleset.UnbindAll();
|
||||
SelectedMods.UnbindAll();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +350,7 @@ namespace osu.Game.Overlays
|
||||
direction = last > next ? TransformDirection.Prev : TransformDirection.Next;
|
||||
}
|
||||
|
||||
current.Track.Completed -= currentTrackCompleted;
|
||||
//current.Track.Completed -= currentTrackCompleted;
|
||||
}
|
||||
|
||||
current = beatmap.NewValue;
|
||||
|
@ -29,13 +29,11 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
|
||||
|
||||
protected override void ShowMore()
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += sets => Schedule(() =>
|
||||
{
|
||||
ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
|
||||
ShowMoreLoading.Hide();
|
||||
MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
|
||||
MoreButton.IsLoading = false;
|
||||
|
||||
if (!sets.Any() && VisiblePages == 1)
|
||||
{
|
||||
|
@ -24,13 +24,11 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
|
||||
|
||||
protected override void ShowMore()
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += beatmaps => Schedule(() =>
|
||||
{
|
||||
ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
|
||||
ShowMoreLoading.Hide();
|
||||
MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
|
||||
MoreButton.IsLoading = false;
|
||||
|
||||
if (!beatmaps.Any() && VisiblePages == 1)
|
||||
{
|
||||
|
@ -7,20 +7,17 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Overlays.Profile.Sections
|
||||
{
|
||||
public class PaginatedContainer : FillFlowContainer
|
||||
public abstract class PaginatedContainer : FillFlowContainer
|
||||
{
|
||||
protected readonly FillFlowContainer ItemsContainer;
|
||||
protected readonly OsuHoverContainer ShowMoreButton;
|
||||
protected readonly LoadingAnimation ShowMoreLoading;
|
||||
protected readonly ShowMoreButton MoreButton;
|
||||
protected readonly OsuSpriteText MissingText;
|
||||
|
||||
protected int VisiblePages;
|
||||
@ -32,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Sections
|
||||
protected APIRequest RetrievalRequest;
|
||||
protected RulesetStore Rulesets;
|
||||
|
||||
public PaginatedContainer(Bindable<User> user, string header, string missing)
|
||||
protected PaginatedContainer(Bindable<User> user, string header, string missing)
|
||||
{
|
||||
User.BindTo(user);
|
||||
|
||||
@ -45,38 +42,26 @@ namespace osu.Game.Overlays.Profile.Sections
|
||||
new OsuSpriteText
|
||||
{
|
||||
Text = header,
|
||||
Font = OsuFont.GetFont(size: 15, weight: FontWeight.Regular, italics: true),
|
||||
Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold),
|
||||
Margin = new MarginPadding { Top = 10, Bottom = 10 },
|
||||
},
|
||||
ItemsContainer = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Margin = new MarginPadding { Bottom = 10 }
|
||||
Spacing = new Vector2(0, 2),
|
||||
},
|
||||
ShowMoreButton = new OsuHoverContainer
|
||||
MoreButton = new ShowMoreButton
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Alpha = 0,
|
||||
Margin = new MarginPadding { Top = 10 },
|
||||
Action = ShowMore,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Child = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 14),
|
||||
Text = "show more",
|
||||
Padding = new MarginPadding { Vertical = 10, Horizontal = 15 },
|
||||
}
|
||||
},
|
||||
ShowMoreLoading = new LoadingAnimation
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Size = new Vector2(14),
|
||||
},
|
||||
MissingText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 14),
|
||||
Font = OsuFont.GetFont(size: 15),
|
||||
Text = missing,
|
||||
Alpha = 0,
|
||||
},
|
||||
@ -97,16 +82,11 @@ namespace osu.Game.Overlays.Profile.Sections
|
||||
{
|
||||
VisiblePages = 0;
|
||||
ItemsContainer.Clear();
|
||||
ShowMoreButton.Hide();
|
||||
|
||||
if (e.NewValue != null)
|
||||
ShowMore();
|
||||
}
|
||||
|
||||
protected virtual void ShowMore()
|
||||
{
|
||||
ShowMoreLoading.Show();
|
||||
ShowMoreButton.Hide();
|
||||
}
|
||||
protected abstract void ShowMore();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Users;
|
||||
@ -9,6 +8,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
{
|
||||
@ -31,8 +31,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
|
||||
protected override void ShowMore()
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += scores => Schedule(() =>
|
||||
{
|
||||
@ -41,8 +39,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
|
||||
if (!scores.Any() && VisiblePages == 1)
|
||||
{
|
||||
ShowMoreButton.Hide();
|
||||
ShowMoreLoading.Hide();
|
||||
MoreButton.Hide();
|
||||
MoreButton.IsLoading = false;
|
||||
MissingText.Show();
|
||||
return;
|
||||
}
|
||||
@ -63,8 +61,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||
LoadComponentsAsync(drawableScores, s =>
|
||||
{
|
||||
MissingText.Hide();
|
||||
ShowMoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0);
|
||||
ShowMoreLoading.Hide();
|
||||
MoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0);
|
||||
MoreButton.IsLoading = false;
|
||||
|
||||
ItemsContainer.AddRange(s);
|
||||
});
|
||||
|
@ -22,13 +22,11 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
|
||||
|
||||
protected override void ShowMore()
|
||||
{
|
||||
base.ShowMore();
|
||||
|
||||
request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
|
||||
request.Success += activities => Schedule(() =>
|
||||
{
|
||||
ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
|
||||
ShowMoreLoading.Hide();
|
||||
MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
|
||||
MoreButton.IsLoading = false;
|
||||
|
||||
if (!activities.Any() && VisiblePages == 1)
|
||||
{
|
||||
|
146
osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs
Normal file
146
osu.Game/Overlays/Profile/Sections/ShowMoreButton.cs
Normal file
@ -0,0 +1,146 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osuTK;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Overlays.Profile.Sections
|
||||
{
|
||||
public class ShowMoreButton : OsuHoverContainer
|
||||
{
|
||||
private const float fade_duration = 200;
|
||||
|
||||
private readonly Box background;
|
||||
private readonly LoadingAnimation loading;
|
||||
private readonly FillFlowContainer content;
|
||||
|
||||
protected override IEnumerable<Drawable> EffectTargets => new[] { background };
|
||||
|
||||
private bool isLoading;
|
||||
|
||||
public bool IsLoading
|
||||
{
|
||||
get => isLoading;
|
||||
set
|
||||
{
|
||||
if (isLoading == value)
|
||||
return;
|
||||
|
||||
isLoading = value;
|
||||
|
||||
Enabled.Value = !isLoading;
|
||||
|
||||
if (value)
|
||||
{
|
||||
loading.FadeIn(fade_duration, Easing.OutQuint);
|
||||
content.FadeOut(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
else
|
||||
{
|
||||
loading.FadeOut(fade_duration, Easing.OutQuint);
|
||||
content.FadeIn(fade_duration, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ShowMoreButton()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new CircularContainer
|
||||
{
|
||||
Masking = true,
|
||||
Size = new Vector2(140, 30),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
content = new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(7),
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ChevronIcon(),
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold),
|
||||
Text = "show more".ToUpper(),
|
||||
},
|
||||
new ChevronIcon(),
|
||||
}
|
||||
},
|
||||
loading = new LoadingAnimation
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(12)
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colors)
|
||||
{
|
||||
IdleColour = colors.GreySeafoamDark;
|
||||
HoverColour = colors.GreySeafoam;
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (!Enabled.Value)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
return base.OnClick(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// run afterwards as this will disable this button.
|
||||
IsLoading = true;
|
||||
}
|
||||
}
|
||||
|
||||
private class ChevronIcon : SpriteIcon
|
||||
{
|
||||
private const int bottom_margin = 2;
|
||||
private const int icon_size = 8;
|
||||
|
||||
public ChevronIcon()
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
Margin = new MarginPadding { Bottom = bottom_margin };
|
||||
Size = new Vector2(icon_size);
|
||||
Icon = FontAwesome.Solid.ChevronDown;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colors)
|
||||
{
|
||||
Colour = colors.Yellow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,11 @@ namespace osu.Game.Overlays.Settings.Sections.Debug
|
||||
LabelText = "Bypass caching (slow)",
|
||||
Bindable = config.GetBindable<bool>(DebugSetting.BypassCaching)
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Bypass front-to-back render pass",
|
||||
Bindable = config.GetBindable<bool>(DebugSetting.BypassFrontToBackPass)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
|
||||
private Bindable<ScalingMode> scalingMode;
|
||||
private Bindable<Size> sizeFullscreen;
|
||||
private readonly BindableList<WindowMode> windowModes = new BindableList<WindowMode>();
|
||||
private readonly IBindableList<WindowMode> windowModes = new BindableList<WindowMode>();
|
||||
|
||||
private OsuGameBase game;
|
||||
private SettingsDropdown<Size> resolutionDropdown;
|
||||
|
@ -31,6 +31,7 @@ namespace osu.Game.Overlays.Toolbar
|
||||
public ToolbarRulesetSelector()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
AutoSizeAxes = Axes.X;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
@ -111,12 +112,6 @@ namespace osu.Game.Overlays.Toolbar
|
||||
|
||||
private void disabledChanged(bool isDisabled) => this.FadeColour(isDisabled ? Color4.Gray : Color4.White, 300);
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
Size = new Vector2(modeButtons.DrawSize.X, 1);
|
||||
}
|
||||
|
||||
private void rulesetChanged(ValueChangedEvent<RulesetInfo> e)
|
||||
{
|
||||
foreach (ToolbarRulesetButton m in modeButtons.Children.Cast<ToolbarRulesetButton>())
|
||||
|
@ -179,7 +179,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
shader.GetUniform<Vector2>("flashlightSize").UpdateValue(ref flashlightSize);
|
||||
shader.GetUniform<float>("flashlightDim").UpdateValue(ref flashlightDim);
|
||||
|
||||
Texture.WhitePixel.DrawQuad(screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction);
|
||||
DrawQuad(Texture.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction);
|
||||
|
||||
shader.Unbind();
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.UI
|
||||
/// <summary>
|
||||
/// The playfield.
|
||||
/// </summary>
|
||||
public Playfield Playfield => playfield.Value;
|
||||
public override Playfield Playfield => playfield.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Place to put drawables above hit objects but below UI.
|
||||
@ -342,6 +342,11 @@ namespace osu.Game.Rulesets.UI
|
||||
/// </summary>
|
||||
public readonly BindableBool IsPaused = new BindableBool();
|
||||
|
||||
/// <summary>
|
||||
/// The playfield.
|
||||
/// </summary>
|
||||
public abstract Playfield Playfield { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The frame-stable clock which is being used for playfield display.
|
||||
/// </summary>
|
||||
|
@ -7,10 +7,7 @@ namespace osu.Game.Scoring
|
||||
{
|
||||
public enum ScoreRank
|
||||
{
|
||||
[Description(@"F")]
|
||||
F,
|
||||
|
||||
[Description(@"F")]
|
||||
[Description(@"D")]
|
||||
D,
|
||||
|
||||
[Description(@"C")]
|
||||
|
@ -182,9 +182,9 @@ namespace osu.Game.Screens.Menu
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio)
|
||||
{
|
||||
sampleHover = audio.Sample.Get(@"Menu/button-hover");
|
||||
sampleHover = audio.Samples.Get(@"Menu/button-hover");
|
||||
if (!string.IsNullOrEmpty(sampleName))
|
||||
sampleClick = audio.Sample.Get($@"Menu/{sampleName}");
|
||||
sampleClick = audio.Samples.Get($@"Menu/{sampleName}");
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
|
@ -150,7 +150,7 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle);
|
||||
|
||||
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
||||
sampleBack = audio.Samples.Get(@"Menu/button-back-select");
|
||||
}
|
||||
|
||||
private void onMulti()
|
||||
|
@ -76,8 +76,8 @@ namespace osu.Game.Screens.Menu
|
||||
introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
||||
track = introBeatmap.Track;
|
||||
|
||||
welcome = audio.Sample.Get(@"welcome");
|
||||
seeya = audio.Sample.Get(@"seeya");
|
||||
welcome = audio.Samples.Get(@"welcome");
|
||||
seeya = audio.Samples.Get(@"seeya");
|
||||
}
|
||||
|
||||
private const double delay_step_one = 2300;
|
||||
|
@ -189,7 +189,6 @@ namespace osu.Game.Screens.Menu
|
||||
base.Draw(vertexAction);
|
||||
|
||||
shader.Bind();
|
||||
texture.TextureGL.Bind();
|
||||
|
||||
Vector2 inflation = DrawInfo.MatrixInverse.ExtractScale().Xy;
|
||||
|
||||
@ -224,7 +223,8 @@ namespace osu.Game.Screens.Menu
|
||||
Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix)
|
||||
);
|
||||
|
||||
texture.DrawQuad(
|
||||
DrawQuad(
|
||||
texture,
|
||||
rectangle,
|
||||
colourInfo,
|
||||
null,
|
||||
|
@ -255,8 +255,8 @@ namespace osu.Game.Screens.Menu
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(TextureStore textures, AudioManager audio)
|
||||
{
|
||||
sampleClick = audio.Sample.Get(@"Menu/osu-logo-select");
|
||||
sampleBeat = audio.Sample.Get(@"Menu/osu-logo-heartbeat");
|
||||
sampleClick = audio.Samples.Get(@"Menu/osu-logo-select");
|
||||
sampleBeat = audio.Samples.Get(@"Menu/osu-logo-heartbeat");
|
||||
|
||||
logo.Texture = textures.Get(@"Menu/logo");
|
||||
ripple.Texture = textures.Get(@"Menu/logo");
|
||||
|
@ -137,7 +137,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
|
||||
private class BackgroundSprite : UpdateableBeatmapBackgroundSprite
|
||||
{
|
||||
protected override double FadeDuration => 200;
|
||||
protected override double TransformDuration => 200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ namespace osu.Game.Screens.Multi
|
||||
|
||||
if (!track.IsRunning)
|
||||
{
|
||||
game.Audio.AddItemToList(track);
|
||||
game.Audio.AddItem(track);
|
||||
track.Seek(Beatmap.Value.Metadata.PreviewTime);
|
||||
track.Start();
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ namespace osu.Game.Screens
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuGame osu, AudioManager audio)
|
||||
{
|
||||
sampleExit = audio.Sample.Get(@"UI/screen-back");
|
||||
sampleExit = audio.Samples.Get(@"UI/screen-back");
|
||||
}
|
||||
|
||||
public virtual bool OnPressed(GlobalAction action)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user