mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 20:13:21 +08:00
Merge remote-tracking branch 'origin/master' into taiko_legacy_rep
This commit is contained in:
commit
bea9bf9dd4
@ -1 +1 @@
|
||||
Subproject commit f6fa5b80ed06f84c8fd25a2576eea8d51565785c
|
||||
Subproject commit 16a4bef775a49166f38faa6e952d83d8823fe3e0
|
@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override Vector2 GetAspectAdjustedSize() => new Vector2(1, 0.8f);
|
||||
protected override Vector2 PlayfieldArea => new Vector2(1, 0.8f);
|
||||
|
||||
protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay, this);
|
||||
|
||||
|
@ -5,6 +5,7 @@ using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
@ -17,6 +18,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
|
||||
protected override Playfield CreatePlayfield() => new OsuEditPlayfield();
|
||||
|
||||
protected override Vector2 PlayfieldArea => Vector2.One;
|
||||
|
||||
protected override CursorContainer CreateCursor() => null;
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,12 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
@ -25,5 +27,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
new HitObjectCompositionTool<Slider>(),
|
||||
new HitObjectCompositionTool<Spinner>()
|
||||
};
|
||||
|
||||
protected override ScalableContainer CreateLayerContainer() => new ScalableContainer(OsuPlayfield.BASE_SIZE.X) { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
bool isRepeatAtEnd = repeatPoint.RepeatIndex % 2 == 0;
|
||||
List<Vector2> curve = drawableSlider.Body.CurrentCurve;
|
||||
|
||||
Position = isRepeatAtEnd ? end : start;
|
||||
var positionOnCurve = isRepeatAtEnd ? end : start;
|
||||
Position = positionOnCurve + drawableSlider.HitObject.StackOffset;
|
||||
|
||||
if (curve.Count < 2)
|
||||
return;
|
||||
@ -89,10 +90,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
// find the next vector2 in the curve which is not equal to our current position to infer a rotation.
|
||||
for (int i = searchStart; i >= 0 && i < curve.Count; i += direction)
|
||||
{
|
||||
if (curve[i] == Position)
|
||||
if (curve[i] == positionOnCurve)
|
||||
continue;
|
||||
|
||||
Rotation = MathHelper.RadiansToDegrees((float)Math.Atan2(curve[i].Y - Position.Y, curve[i].X - Position.X));
|
||||
Rotation = MathHelper.RadiansToDegrees((float)Math.Atan2(curve[i].Y - positionOnCurve.Y, curve[i].X - positionOnCurve.X));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,11 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
@ -66,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
var drawableTick = new DrawableSliderTick(tick)
|
||||
{
|
||||
Position = tick.Position
|
||||
Position = tick.StackedPosition
|
||||
};
|
||||
|
||||
ticks.Add(drawableTick);
|
||||
@ -78,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
var drawableRepeatPoint = new DrawableRepeatPoint(repeatPoint, this)
|
||||
{
|
||||
Position = repeatPoint.Position
|
||||
Position = repeatPoint.StackedPosition
|
||||
};
|
||||
|
||||
repeatPoints.Add(drawableRepeatPoint);
|
||||
@ -87,7 +88,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
private int currentSpan;
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
{
|
||||
config.BindWith(OsuSetting.SnakingInSliders, Body.SnakingIn);
|
||||
config.BindWith(OsuSetting.SnakingOutSliders, Body.SnakingOut);
|
||||
}
|
||||
|
||||
public bool Tracking;
|
||||
|
||||
protected override void Update()
|
||||
@ -96,19 +103,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
Tracking = Ball.Tracking;
|
||||
|
||||
double progress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
||||
|
||||
int span = slider.SpanAt(progress);
|
||||
progress = slider.ProgressAt(progress);
|
||||
|
||||
if (span > currentSpan)
|
||||
currentSpan = span;
|
||||
double completionProgress = MathHelper.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
||||
|
||||
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
|
||||
if (!HeadCircle.IsHit)
|
||||
HeadCircle.Position = slider.Curve.PositionAt(progress);
|
||||
HeadCircle.Position = slider.StackedPositionAt(completionProgress);
|
||||
|
||||
foreach (var c in components.OfType<ISliderProgress>()) c.UpdateProgress(progress, span);
|
||||
foreach (var c in components.OfType<ISliderProgress>()) c.UpdateProgress(completionProgress);
|
||||
foreach (var c in components.OfType<ITrackSnaking>()) c.UpdateSnakingPosition(slider.Curve.PositionAt(Body.SnakedStart ?? 0), slider.Curve.PositionAt(Body.SnakedEnd ?? 0));
|
||||
foreach (var t in components.OfType<IRequireTracking>()) t.Tracking = Ball.Tracking;
|
||||
}
|
||||
|
@ -139,9 +139,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateProgress(double progress, int span)
|
||||
public void UpdateProgress(double completionProgress)
|
||||
{
|
||||
Position = slider.Curve.PositionAt(progress);
|
||||
Position = slider.StackedPositionAt(completionProgress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Configuration;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.ES30;
|
||||
using OpenTK.Graphics;
|
||||
@ -30,6 +29,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
set { path.PathWidth = value; }
|
||||
}
|
||||
|
||||
public readonly Bindable<bool> SnakingIn = new Bindable<bool>();
|
||||
public readonly Bindable<bool> SnakingOut = new Bindable<bool>();
|
||||
|
||||
public double? SnakedStart { get; private set; }
|
||||
public double? SnakedEnd { get; private set; }
|
||||
|
||||
@ -46,8 +48,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return;
|
||||
accentColour = value;
|
||||
|
||||
if (LoadState == LoadState.Ready)
|
||||
Schedule(reloadTexture);
|
||||
if (LoadState >= LoadState.Ready)
|
||||
reloadTexture();
|
||||
}
|
||||
}
|
||||
|
||||
private Color4 borderColour = Color4.White;
|
||||
/// <summary>
|
||||
/// Used to colour the path border.
|
||||
/// </summary>
|
||||
public new Color4 BorderColour
|
||||
{
|
||||
get { return borderColour; }
|
||||
set
|
||||
{
|
||||
if (borderColour == value)
|
||||
return;
|
||||
borderColour = value;
|
||||
|
||||
if (LoadState >= LoadState.Ready)
|
||||
reloadTexture();
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,15 +117,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
}
|
||||
}
|
||||
|
||||
private Bindable<bool> snakingIn;
|
||||
private Bindable<bool> snakingOut;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
private void load()
|
||||
{
|
||||
snakingIn = config.GetBindable<bool>(OsuSetting.SnakingInSliders);
|
||||
snakingOut = config.GetBindable<bool>(OsuSetting.SnakingOutSliders);
|
||||
|
||||
reloadTexture();
|
||||
}
|
||||
|
||||
@ -130,10 +144,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
|
||||
if (progress <= border_portion)
|
||||
{
|
||||
bytes[i * 4] = 255;
|
||||
bytes[i * 4 + 1] = 255;
|
||||
bytes[i * 4 + 2] = 255;
|
||||
bytes[i * 4 + 3] = (byte)(Math.Min(progress / aa_portion, 1) * 255);
|
||||
bytes[i * 4] = (byte)(BorderColour.R * 255);
|
||||
bytes[i * 4 + 1] = (byte)(BorderColour.G * 255);
|
||||
bytes[i * 4 + 2] = (byte)(BorderColour.B * 255);
|
||||
bytes[i * 4 + 3] = (byte)(Math.Min(progress / aa_portion, 1) * (BorderColour.A * 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -167,21 +181,24 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UpdateProgress(double progress, int span)
|
||||
public void UpdateProgress(double completionProgress)
|
||||
{
|
||||
var span = slider.SpanAt(completionProgress);
|
||||
var spanProgress = slider.ProgressAt(completionProgress);
|
||||
|
||||
double start = 0;
|
||||
double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadein, 0, 1) : 1;
|
||||
double end = SnakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadein, 0, 1) : 1;
|
||||
|
||||
if (span >= slider.SpanCount() - 1)
|
||||
{
|
||||
if (Math.Min(span, slider.SpanCount() - 1) % 2 == 1)
|
||||
{
|
||||
start = 0;
|
||||
end = snakingOut ? progress : 1;
|
||||
end = SnakingOut ? spanProgress : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = snakingOut ? progress : 0;
|
||||
start = SnakingOut ? spanProgress : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,10 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
public interface ISliderProgress
|
||||
{
|
||||
void UpdateProgress(double progress, int span);
|
||||
/// <summary>
|
||||
/// Updates the progress of this <see cref="ISliderProgress"/> element along the slider.
|
||||
/// </summary>
|
||||
/// <param name="completionProgress">Amount of the slider completed.</param>
|
||||
void UpdateProgress(double completionProgress);
|
||||
}
|
||||
}
|
||||
|
@ -66,18 +66,6 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
/// </summary>
|
||||
public double SpanDuration => Duration / this.SpanCount();
|
||||
|
||||
private int stackHeight;
|
||||
|
||||
public override int StackHeight
|
||||
{
|
||||
get { return stackHeight; }
|
||||
set
|
||||
{
|
||||
stackHeight = value;
|
||||
Curve.Offset = StackOffset;
|
||||
}
|
||||
}
|
||||
|
||||
public double Velocity;
|
||||
public double TickDistance;
|
||||
|
||||
|
@ -315,11 +315,11 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
|
||||
for (double j = FrameDelay; j < s.Duration; j += FrameDelay)
|
||||
{
|
||||
Vector2 pos = s.PositionAt(j / s.Duration);
|
||||
Vector2 pos = s.StackedPositionAt(j / s.Duration);
|
||||
AddFrameToReplay(new ReplayFrame(h.StartTime + j, pos.X, pos.Y, button));
|
||||
}
|
||||
|
||||
AddFrameToReplay(new ReplayFrame(s.EndTime, s.EndPosition.X, s.EndPosition.Y, button));
|
||||
AddFrameToReplay(new ReplayFrame(s.EndTime, s.StackedEndPosition.X, s.StackedEndPosition.Y, button));
|
||||
}
|
||||
|
||||
// We only want to let go of our button if we are at the end of the current replay. Otherwise something is still going on after us so we need to keep the button pressed!
|
||||
|
@ -88,10 +88,15 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
AddStep("Catmull Slider", () => testCatmull());
|
||||
AddStep("Catmull Slider 1 Repeat", () => testCatmull(1));
|
||||
AddStep("Catmull Slider 2 Repeats", () => testCatmull(2));
|
||||
|
||||
AddStep("Big Single, Large StackOffset", () => testSimpleBigLargeStackOffset());
|
||||
AddStep("Big 1 Repeat, Large StackOffset", () => testSimpleBigLargeStackOffset(1));
|
||||
}
|
||||
|
||||
private void testSimpleBig(int repeats = 0) => createSlider(2, repeats: repeats);
|
||||
|
||||
private void testSimpleBigLargeStackOffset(int repeats = 0) => createSlider(2, repeats: repeats, stackHeight: 10);
|
||||
|
||||
private void testSimpleMedium(int repeats = 0) => createSlider(5, repeats: repeats);
|
||||
|
||||
private void testSimpleSmall(int repeats = 0) => createSlider(7, repeats: repeats);
|
||||
@ -104,7 +109,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
private void testShortHighSpeed(int repeats = 0) => createSlider(distance: 100, repeats: repeats, speedMultiplier: 15);
|
||||
|
||||
private void createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2)
|
||||
private void createSlider(float circleSize = 2, float distance = 400, int repeats = 0, double speedMultiplier = 2, int stackHeight = 0)
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
@ -118,7 +123,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
},
|
||||
Distance = distance,
|
||||
RepeatCount = repeats,
|
||||
RepeatSamples = createEmptySamples(repeats)
|
||||
RepeatSamples = createEmptySamples(repeats),
|
||||
StackHeight = stackHeight
|
||||
};
|
||||
|
||||
addSlider(slider, circleSize, speedMultiplier);
|
||||
|
@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
protected override Vector2 GetAspectAdjustedSize()
|
||||
{
|
||||
var aspectSize = DrawSize.X * 0.75f < DrawSize.Y ? new Vector2(DrawSize.X, DrawSize.X * 0.75f) : new Vector2(DrawSize.Y * 4f / 3f, DrawSize.Y);
|
||||
return new Vector2(aspectSize.X / DrawSize.X, aspectSize.Y / DrawSize.Y) * 0.75f;
|
||||
return new Vector2(aspectSize.X / DrawSize.X, aspectSize.Y / DrawSize.Y);
|
||||
}
|
||||
|
||||
protected override CursorContainer CreateCursor() => new GameplayCursor();
|
||||
|
@ -88,6 +88,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
return new Vector2(1, default_relative_height * aspectAdjust);
|
||||
}
|
||||
|
||||
protected override Vector2 PlayfieldArea => Vector2.One;
|
||||
|
||||
public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this);
|
||||
|
||||
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter(IsForCurrentRuleset);
|
||||
|
@ -5,15 +5,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using OpenTK;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Edit.Layers.Selection;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Osu.Edit;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
@ -27,44 +25,31 @@ namespace osu.Game.Tests.Visual
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(OsuGameBase osuGame)
|
||||
{
|
||||
var playfield = new OsuEditPlayfield();
|
||||
|
||||
Children = new Drawable[]
|
||||
osuGame.Beatmap.Value = new TestWorkingBeatmap(new Beatmap
|
||||
{
|
||||
new Container
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = new FramedClock(new StopwatchClock()),
|
||||
Child = playfield
|
||||
new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f },
|
||||
new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f },
|
||||
new Slider
|
||||
{
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
new Vector2(128, 256),
|
||||
new Vector2(344, 256),
|
||||
},
|
||||
Distance = 400,
|
||||
Position = new Vector2(128, 256),
|
||||
Velocity = 1,
|
||||
TickDistance = 100,
|
||||
Scale = 0.5f,
|
||||
}
|
||||
},
|
||||
new SelectionLayer(playfield)
|
||||
};
|
||||
});
|
||||
|
||||
var hitCircle1 = new HitCircle { Position = new Vector2(256, 192), Scale = 0.5f };
|
||||
var hitCircle2 = new HitCircle { Position = new Vector2(344, 148), Scale = 0.5f };
|
||||
var slider = new Slider
|
||||
{
|
||||
ControlPoints = new List<Vector2>
|
||||
{
|
||||
new Vector2(128, 256),
|
||||
new Vector2(344, 256),
|
||||
},
|
||||
Distance = 400,
|
||||
Position = new Vector2(128, 256),
|
||||
Velocity = 1,
|
||||
TickDistance = 100,
|
||||
Scale = 0.5f,
|
||||
};
|
||||
|
||||
hitCircle1.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
hitCircle2.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
slider.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
playfield.Add(new DrawableHitCircle(hitCircle1));
|
||||
playfield.Add(new DrawableHitCircle(hitCircle2));
|
||||
playfield.Add(new DrawableSlider(slider));
|
||||
Child = new OsuHitObjectComposer(new OsuRuleset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ namespace osu.Game.Configuration
|
||||
{
|
||||
// UI/selection defaults
|
||||
Set(OsuSetting.Ruleset, 0, 0, int.MaxValue);
|
||||
Set(OsuSetting.Skin, 0, 0, int.MaxValue);
|
||||
|
||||
Set(OsuSetting.BeatmapDetailTab, BeatmapDetailTab.Details);
|
||||
|
||||
Set(OsuSetting.ShowConvertedBeatmaps, true);
|
||||
@ -122,6 +124,7 @@ namespace osu.Game.Configuration
|
||||
ChatDisplayHeight,
|
||||
Version,
|
||||
ShowConvertedBeatmaps,
|
||||
SpeedChangeVisualisation
|
||||
SpeedChangeVisualisation,
|
||||
Skin
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ using osu.Game.IO;
|
||||
using osu.Game.Rulesets;
|
||||
using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding;
|
||||
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Database
|
||||
{
|
||||
@ -26,6 +27,7 @@ namespace osu.Game.Database
|
||||
public DbSet<DatabasedSetting> DatabasedSetting { get; set; }
|
||||
public DbSet<FileInfo> FileInfo { get; set; }
|
||||
public DbSet<RulesetInfo> RulesetInfo { get; set; }
|
||||
public DbSet<SkinInfo> SkinInfo { get; set; }
|
||||
|
||||
private readonly string connectionString;
|
||||
|
||||
|
379
osu.Game/Migrations/20180219060912_AddSkins.Designer.cs
generated
Normal file
379
osu.Game/Migrations/20180219060912_AddSkins.Designer.cs
generated
Normal file
@ -0,0 +1,379 @@
|
||||
// <auto-generated />
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using osu.Game.Database;
|
||||
using System;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
[DbContext(typeof(OsuDbContext))]
|
||||
[Migration("20180219060912_AddSkins")]
|
||||
partial class AddSkins
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.0.0-rtm-26452");
|
||||
|
||||
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<float>("SliderMultiplier");
|
||||
|
||||
b.Property<float>("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<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")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MD5Hash")
|
||||
.IsUnique();
|
||||
|
||||
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.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeletePending");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("MetadataID");
|
||||
|
||||
b.HasIndex("OnlineBeatmapSetID")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("BeatmapSetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntKey")
|
||||
.HasColumnName("Key");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<string>("StringValue")
|
||||
.HasColumnName("Value");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("Settings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("IntAction")
|
||||
.HasColumnName("Action");
|
||||
|
||||
b.Property<string>("KeysString")
|
||||
.HasColumnName("Keys");
|
||||
|
||||
b.Property<int?>("RulesetID");
|
||||
|
||||
b.Property<int?>("Variant");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("IntAction");
|
||||
|
||||
b.HasIndex("RulesetID", "Variant");
|
||||
|
||||
b.ToTable("KeyBinding");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Hash");
|
||||
|
||||
b.Property<int>("ReferenceCount");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Hash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ReferenceCount");
|
||||
|
||||
b.ToTable("FileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
|
||||
{
|
||||
b.Property<int?>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<bool>("Available");
|
||||
|
||||
b.Property<string>("InstantiationInfo");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("ShortName");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("Available");
|
||||
|
||||
b.HasIndex("ShortName")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("RulesetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SkinInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.ToTable("SkinFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Creator");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("SkinInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||
.WithMany()
|
||||
.HasForeignKey("BaseDifficultyID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("Beatmaps")
|
||||
.HasForeignKey("MetadataID");
|
||||
|
||||
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
|
||||
.WithMany()
|
||||
.HasForeignKey("RulesetID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("BeatmapSetInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
|
||||
.WithMany("BeatmapSets")
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("SkinInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
73
osu.Game/Migrations/20180219060912_AddSkins.cs
Normal file
73
osu.Game/Migrations/20180219060912_AddSkins.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Migrations
|
||||
{
|
||||
public partial class AddSkins : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SkinInfo",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Creator = table.Column<string>(type: "TEXT", nullable: true),
|
||||
DeletePending = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SkinInfo", x => x.ID);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SkinFileInfo",
|
||||
columns: table => new
|
||||
{
|
||||
ID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
FileInfoID = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Filename = table.Column<string>(type: "TEXT", nullable: false),
|
||||
SkinInfoID = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_SkinFileInfo", x => x.ID);
|
||||
table.ForeignKey(
|
||||
name: "FK_SkinFileInfo_FileInfo_FileInfoID",
|
||||
column: x => x.FileInfoID,
|
||||
principalTable: "FileInfo",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_SkinFileInfo_SkinInfo_SkinInfoID",
|
||||
column: x => x.SkinInfoID,
|
||||
principalTable: "SkinInfo",
|
||||
principalColumn: "ID",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SkinFileInfo_FileInfoID",
|
||||
table: "SkinFileInfo",
|
||||
column: "FileInfoID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SkinFileInfo_SkinInfoID",
|
||||
table: "SkinFileInfo",
|
||||
column: "SkinInfoID");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "SkinFileInfo");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SkinInfo");
|
||||
}
|
||||
}
|
||||
}
|
@ -281,6 +281,43 @@ namespace osu.Game.Migrations
|
||||
b.ToTable("RulesetInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("FileInfoID");
|
||||
|
||||
b.Property<string>("Filename")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int>("SkinInfoID");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("FileInfoID");
|
||||
|
||||
b.HasIndex("SkinInfoID");
|
||||
|
||||
b.ToTable("SkinFileInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
|
||||
{
|
||||
b.Property<int>("ID")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Creator");
|
||||
|
||||
b.Property<bool>("DeletePending");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("SkinInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
|
||||
@ -322,6 +359,19 @@ namespace osu.Game.Migrations
|
||||
.WithMany("BeatmapSets")
|
||||
.HasForeignKey("MetadataID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
|
||||
{
|
||||
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
|
||||
.WithMany()
|
||||
.HasForeignKey("FileInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("osu.Game.Skinning.SkinInfo")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("SkinInfoID")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game
|
||||
@ -79,6 +80,8 @@ namespace osu.Game
|
||||
private Bindable<int> configRuleset;
|
||||
public Bindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
|
||||
|
||||
private Bindable<int> configSkin;
|
||||
|
||||
private readonly string[] args;
|
||||
|
||||
private SettingsOverlay settings;
|
||||
@ -122,10 +125,18 @@ namespace osu.Game
|
||||
|
||||
dependencies.CacheAs(this);
|
||||
|
||||
// bind config int to database RulesetInfo
|
||||
configRuleset = LocalConfig.GetBindable<int>(OsuSetting.Ruleset);
|
||||
Ruleset.Value = RulesetStore.GetRuleset(configRuleset.Value) ?? RulesetStore.AvailableRulesets.First();
|
||||
Ruleset.ValueChanged += r => configRuleset.Value = r.ID ?? 0;
|
||||
|
||||
// bind config int to database SkinInfo
|
||||
configSkin = LocalConfig.GetBindable<int>(OsuSetting.Skin);
|
||||
|
||||
SkinManager.CurrentSkinInfo.ValueChanged += s => configSkin.Value = s.ID;
|
||||
configSkin.ValueChanged += id => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == id) ?? SkinInfo.Default;
|
||||
configSkin.TriggerChange();
|
||||
|
||||
LocalConfig.BindWith(OsuSetting.VolumeInactive, inactiveVolumeAdjust);
|
||||
}
|
||||
|
||||
@ -187,7 +198,9 @@ namespace osu.Game
|
||||
CursorOverrideContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;
|
||||
|
||||
// hook up notifications to components.
|
||||
SkinManager.PostNotification = n => notifications?.Post(n);
|
||||
BeatmapManager.PostNotification = n => notifications?.Post(n);
|
||||
|
||||
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
||||
|
||||
AddRange(new Drawable[]
|
||||
|
@ -30,6 +30,7 @@ using osu.Game.Input.Bindings;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game
|
||||
{
|
||||
@ -39,6 +40,8 @@ namespace osu.Game
|
||||
|
||||
protected BeatmapManager BeatmapManager;
|
||||
|
||||
protected SkinManager SkinManager;
|
||||
|
||||
protected RulesetStore RulesetStore;
|
||||
|
||||
protected FileStore FileStore;
|
||||
@ -103,6 +106,8 @@ namespace osu.Game
|
||||
|
||||
runMigrations();
|
||||
|
||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host));
|
||||
|
||||
dependencies.Cache(API = new APIAccess
|
||||
{
|
||||
Username = LocalConfig.Get<string>(OsuSetting.Username),
|
||||
@ -120,6 +125,7 @@ namespace osu.Game
|
||||
|
||||
fileImporters.Add(BeatmapManager);
|
||||
fileImporters.Add(ScoreStore);
|
||||
fileImporters.Add(SkinManager);
|
||||
|
||||
//this completely overrides the framework default. will need to change once we make a proper FontStore.
|
||||
dependencies.Cache(Fonts = new FontStore { ScaleAdjust = 100 });
|
||||
|
@ -477,7 +477,7 @@ namespace osu.Game.Overlays
|
||||
|
||||
if (!api.IsLoggedIn)
|
||||
{
|
||||
target.AddNewMessages(new ErrorMessage("Please login to participate in chat!"));
|
||||
target.AddNewMessages(new ErrorMessage("Please sign in to participate in chat!"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ namespace osu.Game.Overlays.Direct
|
||||
public Track Preview { get; private set; }
|
||||
|
||||
private BeatmapSetInfo beatmapSet;
|
||||
|
||||
public BeatmapSetInfo BeatmapSet
|
||||
{
|
||||
get { return beatmapSet; }
|
||||
@ -199,8 +200,7 @@ namespace osu.Game.Overlays.Direct
|
||||
// add back the user's music volume setting (since we are no longer in the global TrackManager's hierarchy).
|
||||
config.BindWith(FrameworkSetting.VolumeMusic, trackManager.Volume);
|
||||
|
||||
if (!string.IsNullOrEmpty(preview))
|
||||
Preview = trackManager.Get(preview);
|
||||
Preview = trackManager.Get(preview);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
|
@ -208,7 +208,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
{
|
||||
username = new OsuTextBox
|
||||
{
|
||||
PlaceholderText = "Username",
|
||||
PlaceholderText = "Email address",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = api?.Username ?? string.Empty,
|
||||
TabbableContentContainer = this
|
||||
@ -222,12 +222,12 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Remember username",
|
||||
LabelText = "Remember email address",
|
||||
Bindable = config.GetBindable<bool>(OsuSetting.SaveUsername),
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
LabelText = "Stay logged in",
|
||||
LabelText = "Stay signed in",
|
||||
Bindable = config.GetBindable<bool>(OsuSetting.SavePassword),
|
||||
},
|
||||
new SettingsButton
|
||||
@ -237,7 +237,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
},
|
||||
new SettingsButton
|
||||
{
|
||||
Text = "Register new account",
|
||||
Text = "Register",
|
||||
//Action = registerLink
|
||||
}
|
||||
};
|
||||
|
@ -1,26 +1,33 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
public class SkinSection : SettingsSection
|
||||
{
|
||||
private SettingsDropdown<int> skinDropdown;
|
||||
|
||||
public override string Header => "Skin";
|
||||
|
||||
public override FontAwesome Icon => FontAwesome.fa_paint_brush;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
private void load(OsuConfigManager config, SkinManager skins)
|
||||
{
|
||||
FlowContent.Spacing = new Vector2(0, 5);
|
||||
Children = new Drawable[]
|
||||
{
|
||||
skinDropdown = new SettingsDropdown<int>(),
|
||||
new SettingsSlider<double, SizeSlider>
|
||||
{
|
||||
LabelText = "Menu cursor size",
|
||||
@ -39,6 +46,14 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
Bindable = config.GetBindable<bool>(OsuSetting.AutoCursorSize)
|
||||
},
|
||||
};
|
||||
|
||||
void reloadSkins() => skinDropdown.Items = skins.GetAllUsableSkins().Select(s => new KeyValuePair<string, int>(s.Name, s.ID));
|
||||
skins.ItemAdded += _ => reloadSkins();
|
||||
skins.ItemRemoved += _ => reloadSkins();
|
||||
|
||||
reloadSkins();
|
||||
|
||||
skinDropdown.Bindable = config.GetBindable<int>(OsuSetting.Skin);
|
||||
}
|
||||
|
||||
private class SizeSlider : OsuSliderBar<double>
|
||||
|
@ -25,20 +25,24 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
protected ICompositionTool CurrentTool { get; private set; }
|
||||
|
||||
private RulesetContainer rulesetContainer;
|
||||
private readonly List<Container> layerContainers = new List<Container>();
|
||||
|
||||
protected HitObjectComposer(Ruleset ruleset)
|
||||
{
|
||||
this.ruleset = ruleset;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuGameBase osuGame)
|
||||
{
|
||||
RulesetContainer rulesetContainer;
|
||||
try
|
||||
{
|
||||
rulesetContainer = CreateRulesetContainer(ruleset, osuGame.Beatmap.Value);
|
||||
|
||||
// TODO: should probably be done at a RulesetContainer level to share logic with Player.
|
||||
rulesetContainer.Clock = new InterpolatingFramedClock((IAdjustableClock)osuGame.Beatmap.Value.Track ?? new StopwatchClock());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -46,6 +50,14 @@ namespace osu.Game.Rulesets.Edit
|
||||
return;
|
||||
}
|
||||
|
||||
ScalableContainer createLayerContainerWithContent(Drawable content)
|
||||
{
|
||||
var container = CreateLayerContainer();
|
||||
container.Child = content;
|
||||
layerContainers.Add(container);
|
||||
return container;
|
||||
}
|
||||
|
||||
RadioButtonCollection toolboxCollection;
|
||||
InternalChild = new GridContainer
|
||||
{
|
||||
@ -66,20 +78,21 @@ namespace osu.Game.Rulesets.Edit
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Name = "Content",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
BorderColour = Color4.White,
|
||||
BorderThickness = 2,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
createLayerContainerWithContent(new Container
|
||||
{
|
||||
Name = "Border",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true,
|
||||
},
|
||||
Masking = true,
|
||||
BorderColour = Color4.White,
|
||||
BorderThickness = 2,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both, Alpha = 0, AlwaysPresent = true }
|
||||
}),
|
||||
rulesetContainer,
|
||||
new SelectionLayer(rulesetContainer.Playfield)
|
||||
createLayerContainerWithContent(new SelectionLayer(rulesetContainer.Playfield))
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -90,8 +103,6 @@ namespace osu.Game.Rulesets.Edit
|
||||
}
|
||||
};
|
||||
|
||||
rulesetContainer.Clock = new InterpolatingFramedClock((IAdjustableClock)osuGame.Beatmap.Value.Track ?? new StopwatchClock());
|
||||
|
||||
toolboxCollection.Items =
|
||||
new[] { new RadioButton("Select", () => setCompositionTool(null)) }
|
||||
.Concat(
|
||||
@ -102,10 +113,28 @@ namespace osu.Game.Rulesets.Edit
|
||||
toolboxCollection.Items[0].Select();
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
|
||||
layerContainers.ForEach(l =>
|
||||
{
|
||||
l.Anchor = rulesetContainer.Playfield.Anchor;
|
||||
l.Origin = rulesetContainer.Playfield.Origin;
|
||||
l.Position = rulesetContainer.Playfield.Position;
|
||||
l.Size = rulesetContainer.Playfield.Size;
|
||||
});
|
||||
}
|
||||
|
||||
private void setCompositionTool(ICompositionTool tool) => CurrentTool = tool;
|
||||
|
||||
protected virtual RulesetContainer CreateRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap) => ruleset.CreateRulesetContainerWith(beatmap, true);
|
||||
|
||||
protected abstract IReadOnlyList<ICompositionTool> CompositionTools { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ScalableContainer"/> which provides a layer above or below the <see cref="Playfield"/>.
|
||||
/// </summary>
|
||||
protected virtual ScalableContainer CreateLayerContainer() => new ScalableContainer { RelativeSizeAxes = Axes.Both };
|
||||
}
|
||||
}
|
||||
|
@ -30,21 +30,19 @@ namespace osu.Game.Rulesets.Objects.Types
|
||||
public static class HasCurveExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Computes the position on the curve at a given progress, accounting for repeat logic.
|
||||
/// <para>
|
||||
/// Ranges from [0, 1] where 0 is the beginning of the curve and 1 is the end of the curve.
|
||||
/// </para>
|
||||
/// Computes the position on the curve relative to how much of the <see cref="HitObject"/> has been completed.
|
||||
/// </summary>
|
||||
/// <param name="obj">The curve.</param>
|
||||
/// <param name="progress">[0, 1] where 0 is the beginning of the curve and 1 is the end of the curve.</param>
|
||||
/// <param name="progress">[0, 1] where 0 is the start time of the <see cref="HitObject"/> and 1 is the end time of the <see cref="HitObject"/>.</param>
|
||||
/// <returns>The position on the curve.</returns>
|
||||
public static Vector2 PositionAt(this IHasCurve obj, double progress)
|
||||
=> obj.Curve.PositionAt(obj.ProgressAt(progress));
|
||||
|
||||
/// <summary>
|
||||
/// Finds the progress along the curve, accounting for repeat logic.
|
||||
/// Computes the progress along the curve relative to how much of the <see cref="HitObject"/> has been completed.
|
||||
/// </summary>
|
||||
/// <param name="obj">The curve.</param>
|
||||
/// <param name="progress">[0, 1] where 0 is the beginning of the curve and 1 is the end of the curve.</param>
|
||||
/// <param name="progress">[0, 1] where 0 is the start time of the <see cref="HitObject"/> and 1 is the end time of the <see cref="HitObject"/>.</param>
|
||||
/// <returns>[0, 1] where 0 is the beginning of the curve and 1 is the end of the curve.</returns>
|
||||
public static double ProgressAt(this IHasCurve obj, double progress)
|
||||
{
|
||||
|
@ -3,52 +3,37 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using OpenTK;
|
||||
using osu.Framework.Allocation;
|
||||
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
public abstract class Playfield : Container
|
||||
public abstract class Playfield : ScalableContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// The HitObjects contained in this Playfield.
|
||||
/// </summary>
|
||||
public HitObjectContainer HitObjects { get; private set; }
|
||||
|
||||
public Container<Drawable> ScaledContent;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container<Drawable> content;
|
||||
|
||||
private List<Playfield> nestedPlayfields;
|
||||
|
||||
/// <summary>
|
||||
/// All the <see cref="Playfield"/>s nested inside this playfield.
|
||||
/// </summary>
|
||||
public IReadOnlyList<Playfield> NestedPlayfields => nestedPlayfields;
|
||||
private List<Playfield> nestedPlayfields;
|
||||
|
||||
/// <summary>
|
||||
/// A container for keeping track of DrawableHitObjects.
|
||||
/// </summary>
|
||||
/// <param name="customWidth">Whether we want our internal coordinate system to be scaled to a specified width.</param>
|
||||
protected Playfield(float? customWidth = null)
|
||||
/// <param name="customWidth">The width to scale the internal coordinate space to.
|
||||
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
|
||||
/// </param>
|
||||
/// <param name="customHeight">The height to scale the internal coordinate space to.
|
||||
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
|
||||
/// </param>
|
||||
protected Playfield(float? customWidth = null, float? customHeight = null)
|
||||
: base(customWidth, customHeight)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
AddInternal(ScaledContent = new ScaledContainer
|
||||
{
|
||||
CustomWidth = customWidth,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -94,22 +79,5 @@ namespace osu.Game.Rulesets.UI
|
||||
/// Creates the container that will be used to contain the <see cref="DrawableHitObject"/>s.
|
||||
/// </summary>
|
||||
protected virtual HitObjectContainer CreateHitObjectContainer() => new HitObjectContainer();
|
||||
|
||||
private class ScaledContainer : Container
|
||||
{
|
||||
/// <summary>
|
||||
/// A value (in game pixels that we should scale our content to match).
|
||||
/// </summary>
|
||||
public float? CustomWidth;
|
||||
|
||||
//dividing by the customwidth will effectively scale our content to the required container size.
|
||||
protected override Vector2 DrawScale => CustomWidth.HasValue ? new Vector2(DrawSize.X / CustomWidth.Value) : base.DrawScale;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
RelativeChildSize = new Vector2(DrawScale.X, RelativeChildSize.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
base.Update();
|
||||
|
||||
Playfield.Size = GetAspectAdjustedSize();
|
||||
Playfield.Size = GetAspectAdjustedSize() * PlayfieldArea;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -330,11 +330,17 @@ namespace osu.Game.Rulesets.UI
|
||||
protected virtual BeatmapProcessor<TObject> CreateBeatmapProcessor() => new BeatmapProcessor<TObject>();
|
||||
|
||||
/// <summary>
|
||||
/// Computes the final size of the <see cref="Playfield"/> in relative coordinate space after all
|
||||
/// aspect and scale adjustments.
|
||||
/// Computes the size of the <see cref="Playfield"/> in relative coordinate space after aspect adjustments.
|
||||
/// </summary>
|
||||
/// <returns>The aspect-adjusted size.</returns>
|
||||
protected virtual Vector2 GetAspectAdjustedSize() => new Vector2(0.75f); // A sane default
|
||||
protected virtual Vector2 GetAspectAdjustedSize() => Vector2.One;
|
||||
|
||||
/// <summary>
|
||||
/// The area of this <see cref="RulesetContainer"/> that is available for the <see cref="Playfield"/> to use.
|
||||
/// Must be specified in relative coordinate space to this <see cref="RulesetContainer"/>.
|
||||
/// This affects the final size of the <see cref="Playfield"/> but does not affect the <see cref="Playfield"/>'s scale.
|
||||
/// </summary>
|
||||
protected virtual Vector2 PlayfieldArea => new Vector2(0.75f); // A sane default
|
||||
|
||||
/// <summary>
|
||||
/// Creates a converter to convert Beatmap to a specific mode.
|
||||
|
86
osu.Game/Rulesets/UI/ScalableContainer.cs
Normal file
86
osu.Game/Rulesets/UI/ScalableContainer.cs
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="Container"/> which can have its internal coordinate system scaled to a specific size.
|
||||
/// </summary>
|
||||
public class ScalableContainer : Container
|
||||
{
|
||||
/// <summary>
|
||||
/// The scaled content.
|
||||
/// </summary>
|
||||
public readonly Container ScaledContent;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container content;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Container"/> which can have its internal coordinate system scaled to a specific size.
|
||||
/// </summary>
|
||||
/// <param name="customWidth">The width to scale the internal coordinate space to.
|
||||
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
|
||||
/// </param>
|
||||
/// <param name="customHeight">The height to scale the internal coordinate space to.
|
||||
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
|
||||
/// </param>
|
||||
public ScalableContainer(float? customWidth = null, float? customHeight = null)
|
||||
{
|
||||
AddInternal(ScaledContent = new ScaledContainer
|
||||
{
|
||||
CustomWidth = customWidth,
|
||||
CustomHeight = customHeight,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = content = new Container { RelativeSizeAxes = Axes.Both }
|
||||
});
|
||||
}
|
||||
|
||||
public class ScaledContainer : Container
|
||||
{
|
||||
/// <summary>
|
||||
/// The value to scale the width of the content to match.
|
||||
/// If null, <see cref="CustomHeight"/> is used.
|
||||
/// </summary>
|
||||
public float? CustomWidth;
|
||||
|
||||
/// <summary>
|
||||
/// The value to scale the height of the content to match.
|
||||
/// if null, <see cref="CustomWidth"/> is used.
|
||||
/// </summary>
|
||||
public float? CustomHeight;
|
||||
|
||||
/// <summary>
|
||||
/// The scale that is required for the size of the content to match <see cref="CustomWidth"/> and <see cref="CustomHeight"/>.
|
||||
/// </summary>
|
||||
private Vector2 sizeScale
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CustomWidth.HasValue && CustomHeight.HasValue)
|
||||
return Vector2.Divide(DrawSize, new Vector2(CustomWidth.Value, CustomHeight.Value));
|
||||
if (CustomWidth.HasValue)
|
||||
return new Vector2(DrawSize.X / CustomWidth.Value);
|
||||
if (CustomHeight.HasValue)
|
||||
return new Vector2(DrawSize.Y / CustomHeight.Value);
|
||||
return Vector2.One;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale the content to the required container size by multiplying by <see cref="sizeScale"/>.
|
||||
/// </summary>
|
||||
protected override Vector2 DrawScale => sizeScale * base.DrawScale;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
RelativeChildSize = new Vector2(CustomWidth.HasValue ? sizeScale.X : RelativeChildSize.X, CustomHeight.HasValue ? sizeScale.Y : RelativeChildSize.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -62,9 +62,14 @@ namespace osu.Game.Rulesets.UI.Scrolling
|
||||
/// Creates a new <see cref="ScrollingPlayfield"/>.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction in which <see cref="DrawableHitObject"/>s in this container should scroll.</param>
|
||||
/// <param name="customWidth">Whether we want our internal coordinate system to be scaled to a specified width</param>
|
||||
protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null)
|
||||
: base(customWidth)
|
||||
/// <param name="customWidth">The width to scale the internal coordinate space to.
|
||||
/// May be null if scaling based on <paramref name="customHeight"/> is desired. If <paramref name="customHeight"/> is also null, no scaling will occur.
|
||||
/// </param>
|
||||
/// <param name="customHeight">The height to scale the internal coordinate space to.
|
||||
/// May be null if scaling based on <paramref name="customWidth"/> is desired. If <paramref name="customWidth"/> is also null, no scaling will occur.
|
||||
/// </param>
|
||||
protected ScrollingPlayfield(ScrollingDirection direction, float? customWidth = null, float? customHeight = null)
|
||||
: base(customWidth, customHeight)
|
||||
{
|
||||
this.direction = direction;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
replacePlaceholder(new MessagePlaceholder(@"No records yet!"));
|
||||
break;
|
||||
case PlaceholderState.NotLoggedIn:
|
||||
replacePlaceholder(new MessagePlaceholder(@"Please login to view online leaderboards!"));
|
||||
replacePlaceholder(new MessagePlaceholder(@"Please sign in to view online leaderboards!"));
|
||||
break;
|
||||
case PlaceholderState.NotSupporter:
|
||||
replacePlaceholder(new MessagePlaceholder(@"Please invest in a supporter tag to view this leaderboard!"));
|
||||
|
25
osu.Game/Skinning/SkinFileInfo.cs
Normal file
25
osu.Game/Skinning/SkinFileInfo.cs
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinFileInfo : INamedFileInfo
|
||||
{
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int ID { get; set; }
|
||||
|
||||
public int SkinInfoID { get; set; }
|
||||
|
||||
public int FileInfoID { get; set; }
|
||||
|
||||
public FileInfo FileInfo { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Filename { get; set; }
|
||||
}
|
||||
}
|
28
osu.Game/Skinning/SkinInfo.cs
Normal file
28
osu.Game/Skinning/SkinInfo.cs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinInfo : IHasFiles<SkinFileInfo>, IEquatable<SkinInfo>, IHasPrimaryKey, ISoftDelete
|
||||
{
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int ID { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Creator { get; set; }
|
||||
|
||||
public List<SkinFileInfo> Files { get; set; }
|
||||
|
||||
public bool DeletePending { get; set; }
|
||||
|
||||
public static SkinInfo Default { get; } = new SkinInfo { Name = "osu!lazer", Creator = "team osu!" };
|
||||
|
||||
public bool Equals(SkinInfo other) => other != null && ID == other.ID;
|
||||
}
|
||||
}
|
49
osu.Game/Skinning/SkinManager.cs
Normal file
49
osu.Game/Skinning/SkinManager.cs
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.IO.Archives;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinManager : ArchiveModelManager<SkinInfo, SkinFileInfo>
|
||||
{
|
||||
public readonly Bindable<SkinInfo> CurrentSkinInfo = new Bindable<SkinInfo>(SkinInfo.Default) { Default = SkinInfo.Default };
|
||||
|
||||
public override string[] HandledExtensions => new[] { ".osk" };
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all usable <see cref="SkinInfo"/>s.
|
||||
/// </summary>
|
||||
/// <returns>A list of available <see cref="SkinInfo"/>.</returns>
|
||||
public List<SkinInfo> GetAllUsableSkins()
|
||||
{
|
||||
var userSkins = ModelStore.ConsumableItems.Where(s => !s.DeletePending).ToList();
|
||||
userSkins.Insert(0, SkinInfo.Default);
|
||||
return userSkins;
|
||||
}
|
||||
|
||||
protected override SkinInfo CreateModel(ArchiveReader archive) => new SkinInfo { Name = archive.Name };
|
||||
|
||||
private SkinStore store;
|
||||
|
||||
public SkinManager(Storage storage, DatabaseContextFactory contextFactory, IIpcHost importHost)
|
||||
: base(storage, contextFactory, new SkinStore(contextFactory, storage), importHost)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a lookup query on available <see cref="SkinInfo"/>s.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
||||
public SkinInfo Query(Expression<Func<SkinInfo, bool>> query) => ModelStore.ConsumableItems.AsNoTracking().FirstOrDefault(query);
|
||||
}
|
||||
}
|
22
osu.Game/Skinning/SkinStore.cs
Normal file
22
osu.Game/Skinning/SkinStore.cs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
public class SkinStore : MutableDatabaseBackedStore<SkinInfo>
|
||||
{
|
||||
public SkinStore(DatabaseContextFactory contextFactory, Storage storage = null)
|
||||
: base(contextFactory, storage)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IQueryable<SkinInfo> AddIncludesForConsumption(IQueryable<SkinInfo> query) =>
|
||||
base.AddIncludesForConsumption(query)
|
||||
.Include(s => s.Files).ThenInclude(f => f.FileInfo);
|
||||
}
|
||||
}
|
@ -230,7 +230,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Text = "Please login to see online scores",
|
||||
Text = "Please sign in to see online scores",
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -322,6 +322,10 @@
|
||||
<Compile Include="Migrations\20171209034410_AddRulesetInfoShortName.Designer.cs">
|
||||
<DependentUpon>20171209034410_AddRulesetInfoShortName.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\20180219060912_AddSkins.cs" />
|
||||
<Compile Include="Migrations\20180219060912_AddSkins.designer.cs">
|
||||
<DependentUpon>20180219060912_AddSkins.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Migrations\OsuDbContextModelSnapshot.cs" />
|
||||
<Compile Include="Online\API\Requests\GetBeatmapSetRequest.cs" />
|
||||
<Compile Include="Online\Chat\DrawableLinkCompiler.cs" />
|
||||
@ -357,6 +361,7 @@
|
||||
<Compile Include="Overlays\Social\SocialPanel.cs" />
|
||||
<Compile Include="Rulesets\Mods\IApplicableToDrawableHitObject.cs" />
|
||||
<Compile Include="Rulesets\Objects\HitWindows.cs" />
|
||||
<Compile Include="Rulesets\UI\ScalableContainer.cs" />
|
||||
<Compile Include="Screens\Play\PlayerSettings\VisualSettings.cs" />
|
||||
<Compile Include="Rulesets\Objects\CatmullApproximator.cs" />
|
||||
<Compile Include="Rulesets\UI\HitObjectContainer.cs" />
|
||||
@ -849,6 +854,10 @@
|
||||
<Compile Include="Screens\Tournament\Teams\DrawingsTeam.cs" />
|
||||
<Compile Include="Screens\Tournament\Teams\ITeamList.cs" />
|
||||
<Compile Include="Screens\Tournament\Teams\StorageBackedTeamList.cs" />
|
||||
<Compile Include="Skinning\SkinFileInfo.cs" />
|
||||
<Compile Include="Skinning\SkinInfo.cs" />
|
||||
<Compile Include="Skinning\SkinManager.cs" />
|
||||
<Compile Include="Skinning\SkinStore.cs" />
|
||||
<Compile Include="Storyboards\CommandLoop.cs" />
|
||||
<Compile Include="Storyboards\CommandTimeline.cs" />
|
||||
<Compile Include="Storyboards\CommandTimelineGroup.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user