diff --git a/osu.Android.props b/osu.Android.props
index b9451fc744..b24493665e 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -63,6 +63,6 @@
-
+
diff --git a/osu.Desktop/Program.cs b/osu.Desktop/Program.cs
index cb488fea52..141b2cdbbc 100644
--- a/osu.Desktop/Program.cs
+++ b/osu.Desktop/Program.cs
@@ -29,29 +29,36 @@ namespace osu.Desktop
if (!host.IsPrimaryInstance)
{
- var importer = new ArchiveImportIPCChannel(host);
- // Restore the cwd so relative paths given at the command line work correctly
- Directory.SetCurrentDirectory(cwd);
-
- foreach (var file in args)
+ if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args
{
- Console.WriteLine(@"Importing {0}", file);
- if (!importer.ImportAsync(Path.GetFullPath(file)).Wait(3000))
- throw new TimeoutException(@"IPC took too long to send");
+ var importer = new ArchiveImportIPCChannel(host);
+ // Restore the cwd so relative paths given at the command line work correctly
+ Directory.SetCurrentDirectory(cwd);
+
+ foreach (var file in args)
+ {
+ Console.WriteLine(@"Importing {0}", file);
+ if (!importer.ImportAsync(Path.GetFullPath(file)).Wait(3000))
+ throw new TimeoutException(@"IPC took too long to send");
+ }
+
+ return 0;
}
+
+ // we want to allow multiple instances to be started when in debug.
+ if (!DebugUtils.IsDebugBuild)
+ return 0;
}
- else
- {
- switch (args.FirstOrDefault() ?? string.Empty)
- {
- default:
- host.Run(new OsuGameDesktop(args));
- break;
- case "--tournament":
- host.Run(new TournamentGame());
- break;
- }
+ switch (args.FirstOrDefault() ?? string.Empty)
+ {
+ default:
+ host.Run(new OsuGameDesktop(args));
+ break;
+
+ case "--tournament":
+ host.Run(new TournamentGame());
+ break;
}
return 0;
diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs
index 5785d9a9ca..a1279e8443 100644
--- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs
+++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs
@@ -3,12 +3,10 @@
using System;
using osuTK;
-using osuTK.Graphics;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
-using osu.Game.Skinning;
namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
@@ -60,16 +58,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss);
}
- protected override void SkinChanged(ISkinSource skin, bool allowFallback)
- {
- base.SkinChanged(skin, allowFallback);
-
- if (HitObject is IHasComboInformation combo)
- AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
- }
+ protected override bool UseTransformStateManagement => false;
protected override void UpdateState(ArmedState state)
{
+ // TODO: update to use new state management.
using (BeginAbsoluteSequence(HitObject.StartTime - HitObject.TimePreempt))
this.FadeIn(200);
diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs
index 9cabdc3dd9..059310d671 100644
--- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs
+++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs
@@ -5,7 +5,6 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
using osuTK;
-using osuTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
@@ -27,16 +26,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
private void load()
{
AddInternal(pulp = new Pulp { Size = Size });
- }
- public override Color4 AccentColour
- {
- get => base.AccentColour;
- set
- {
- base.AccentColour = value;
- pulp.AccentColour = AccentColour;
- }
+ AccentColour.BindValueChanged(colour => { pulp.AccentColour = colour.NewValue; }, true);
}
}
}
diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs
index 77407def54..ce2daebbf1 100644
--- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs
+++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableFruit.cs
@@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
private void load()
{
// todo: this should come from the skin.
- AccentColour = colourForRepresentation(HitObject.VisualRepresentation);
+ AccentColour.Value = colourForRepresentation(HitObject.VisualRepresentation);
AddRangeInternal(new[]
{
@@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
Hollow = !HitObject.HyperDash,
Type = EdgeEffectType.Glow,
Radius = 4 * radius_adjust,
- Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Darken(1).Opacity(0.6f)
+ Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Value.Darken(1).Opacity(0.6f)
},
Size = new Vector2(Height),
Anchor = Anchor.Centre,
@@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
new Box
{
AlwaysPresent = true,
- Colour = AccentColour,
+ Colour = AccentColour.Value,
Alpha = 0,
RelativeSizeAxes = Axes.Both
}
@@ -115,32 +115,32 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(small_pulp),
Y = -0.34f,
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_4),
Position = positionAt(0, distance_from_centre_4),
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_4),
Position = positionAt(90, distance_from_centre_4),
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_4),
Position = positionAt(180, distance_from_centre_4),
},
new Pulp
{
Size = new Vector2(large_pulp_4),
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Position = positionAt(270, distance_from_centre_4),
},
}
@@ -154,32 +154,32 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(small_pulp),
Y = -0.3f,
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_4),
Position = positionAt(45, distance_from_centre_4),
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_4),
Position = positionAt(135, distance_from_centre_4),
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_4),
Position = positionAt(225, distance_from_centre_4),
},
new Pulp
{
Size = new Vector2(large_pulp_4),
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Position = positionAt(315, distance_from_centre_4),
},
}
@@ -193,26 +193,26 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(small_pulp),
Y = -0.33f,
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_3),
Position = positionAt(60, distance_from_centre_3),
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_3),
Position = positionAt(180, distance_from_centre_3),
},
new Pulp
{
Size = new Vector2(large_pulp_3),
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Position = positionAt(300, distance_from_centre_3),
},
}
@@ -226,26 +226,26 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(small_pulp),
Y = -0.25f,
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_3),
Position = positionAt(0, distance_from_centre_3),
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_3),
Position = positionAt(120, distance_from_centre_3),
},
new Pulp
{
Size = new Vector2(large_pulp_3),
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Position = positionAt(240, distance_from_centre_3),
},
}
@@ -259,13 +259,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(small_pulp),
Y = -0.3f
},
new Pulp
{
- AccentColour = AccentColour,
+ AccentColour = AccentColour.Value,
Size = new Vector2(large_pulp_4 * 0.8f, large_pulp_4 * 2.5f),
Y = 0.05f,
},
diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs
index 04c5724f93..622d840a0c 100644
--- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs
+++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteSelectionBlueprint.cs
@@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Mania.Tests
Child = drawableObject = new DrawableHoldNote(holdNote)
{
Height = 300,
- AccentColour = OsuColour.Gray(0.3f)
+ AccentColour = { Value = OsuColour.Gray(0.3f) }
}
};
}
diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs
index b2613a59d5..031abb08e2 100644
--- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs
+++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs
@@ -70,7 +70,7 @@ namespace osu.Game.Rulesets.Mania.Tests
AutoSizeAxes = Axes.Both,
Child = new NoteContainer(direction, $"note {identifier}, scrolling {direction.ToString().ToLowerInvariant()}")
{
- Child = hitObject = new DrawableNote(note) { AccentColour = Color4.OrangeRed }
+ Child = hitObject = new DrawableNote(note) { AccentColour = { Value = Color4.OrangeRed } }
}
};
}
@@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Mania.Tests
Child = hitObject = new DrawableHoldNote(note)
{
RelativeSizeAxes = Axes.Both,
- AccentColour = Color4.OrangeRed,
+ AccentColour = { Value = Color4.OrangeRed },
}
}
};
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
index 9368af987d..952c6e128e 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
@@ -6,7 +6,6 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
-using osuTK.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Scoring;
@@ -36,11 +35,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
///
private bool hasBroken;
- private readonly Container tickContainer;
-
public DrawableHoldNote(HoldNote hitObject)
: base(hitObject)
{
+ Container tickContainer;
RelativeSizeAxes = Axes.X;
AddRangeInternal(new Drawable[]
@@ -74,6 +72,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
AddNested(Head);
AddNested(Tail);
+
+ AccentColour.BindValueChanged(colour =>
+ {
+ bodyPiece.AccentColour = colour.NewValue;
+ Head.AccentColour.Value = colour.NewValue;
+ Tail.AccentColour.Value = colour.NewValue;
+ tickContainer.ForEach(t => t.AccentColour.Value = colour.NewValue);
+ }, true);
}
protected override void OnDirectionChanged(ValueChangedEvent e)
@@ -83,20 +89,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
bodyPiece.Anchor = bodyPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
}
- public override Color4 AccentColour
- {
- get => base.AccentColour;
- set
- {
- base.AccentColour = value;
-
- bodyPiece.AccentColour = value;
- Head.AccentColour = value;
- Tail.AccentColour = value;
- tickContainer.ForEach(t => t.AccentColour = value);
- }
- }
-
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
if (Tail.AllJudged)
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs
index 9a29273282..9b0322a6cd 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs
@@ -3,7 +3,6 @@
using System;
using osuTK;
-using osuTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -23,11 +22,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
///
public Func HoldStartTime;
- private readonly Container glowContainer;
-
public DrawableHoldNoteTick(HoldNoteTick hitObject)
: base(hitObject)
{
+ Container glowContainer;
+
Anchor = Anchor.TopCentre;
Origin = Anchor.TopCentre;
@@ -53,23 +52,17 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
}
}
});
- }
- public override Color4 AccentColour
- {
- get => base.AccentColour;
- set
+ AccentColour.BindValueChanged(colour =>
{
- base.AccentColour = value;
-
glowContainer.EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Glow,
Radius = 2f,
Roundness = 15f,
- Colour = value.Opacity(0.3f)
+ Colour = colour.NewValue.Opacity(0.3f)
};
- }
+ }, true);
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs
index 0873f753be..db6b53e76d 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs
@@ -58,8 +58,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
HitObject = hitObject;
}
+ protected override bool UseTransformStateManagement => false;
+
protected override void UpdateState(ArmedState state)
{
+ // TODO: update to use new state management.
switch (state)
{
case ArmedState.Miss:
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs
index afd7777861..dccff7f6ac 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs
@@ -3,7 +3,6 @@
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions;
-using osuTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Effects;
using osu.Framework.Input.Bindings;
@@ -30,6 +29,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Masking = true;
AddInternal(headPiece = new NotePiece());
+
+ AccentColour.BindValueChanged(colour =>
+ {
+ headPiece.AccentColour = colour.NewValue;
+
+ EdgeEffect = new EdgeEffectParameters
+ {
+ Type = EdgeEffectType.Glow,
+ Colour = colour.NewValue.Lighten(1f).Opacity(0.6f),
+ Radius = 10,
+ };
+ }, true);
}
protected override void OnDirectionChanged(ValueChangedEvent e)
@@ -39,23 +50,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
headPiece.Anchor = headPiece.Origin = e.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
}
- public override Color4 AccentColour
- {
- get => base.AccentColour;
- set
- {
- base.AccentColour = value;
- headPiece.AccentColour = AccentColour;
-
- EdgeEffect = new EdgeEffectParameters
- {
- Type = EdgeEffectType.Glow,
- Colour = AccentColour.Lighten(1f).Opacity(0.6f),
- Radius = 10,
- };
- }
- }
-
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
if (!userTriggered)
diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs
index c59bed4ea7..91dd236ab1 100644
--- a/osu.Game.Rulesets.Mania/UI/Column.cs
+++ b/osu.Game.Rulesets.Mania/UI/Column.cs
@@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Mania.UI
/// The DrawableHitObject to add.
public override void Add(DrawableHitObject hitObject)
{
- hitObject.AccentColour = AccentColour;
+ hitObject.AccentColour.Value = AccentColour;
hitObject.OnNewResult += OnNewResult;
HitObjectContainer.Add(hitObject);
diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs
index 0ec1fc38d2..48470add8b 100644
--- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs
+++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs
@@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Mania.UI
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Glow,
- Colour = Interpolation.ValueAt(0.1f, judgedObject.AccentColour, Color4.White, 0, 1),
+ Colour = Interpolation.ValueAt(0.1f, judgedObject.AccentColour.Value, Color4.White, 0, 1),
Radius = 100,
},
Child = new Box
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
index 7f6a60c400..fe11ead94d 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
@@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components
this.hitCircle = hitCircle;
Origin = Anchor.Centre;
- Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Scale = new Vector2(hitCircle.Scale);
CornerRadius = Size.X / 2;
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
index 957550a051..f1f55731b6 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
@@ -24,7 +24,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
InternalChild = body = new ManualSliderBody
{
AccentColour = Color4.Transparent,
- PathRadius = slider.Scale * 64
};
}
@@ -34,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
body.BorderColour = colours.Yellow;
PositionBindable.BindValueChanged(_ => updatePosition(), true);
- ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * 64, true);
+ ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * OsuHitObject.OBJECT_RADIUS, true);
}
private void updatePosition() => Position = slider.StackedPosition;
diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs
index 571756d056..f0db548e74 100644
--- a/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs
+++ b/osu.Game.Rulesets.Osu/Mods/OsuModTouchDevice.cs
@@ -11,6 +11,8 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Acronym => "TD";
public override double ScoreMultiplier => 1;
+ public override ModType Type => ModType.System;
+
public override bool Ranked => true;
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
index fef0bfdc2c..d3d763daf3 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
@@ -10,7 +10,6 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using osuTK;
using osu.Game.Rulesets.Scoring;
-using osuTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -98,19 +97,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
positionBindable.BindTo(HitObject.PositionBindable);
stackHeightBindable.BindTo(HitObject.StackHeightBindable);
scaleBindable.BindTo(HitObject.ScaleBindable);
- }
- public override Color4 AccentColour
- {
- get => base.AccentColour;
- set
+ AccentColour.BindValueChanged(colour =>
{
- base.AccentColour = value;
- explode.Colour = AccentColour;
- glow.Colour = AccentColour;
- circle.Colour = AccentColour;
- ApproachCircle.Colour = AccentColour;
- }
+ explode.Colour = colour.NewValue;
+ glow.Colour = colour.NewValue;
+ circle.Colour = colour.NewValue;
+ ApproachCircle.Colour = colour.NewValue;
+ }, true);
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
@@ -134,16 +128,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ApplyResult(r => r.Type = result);
}
- protected override void UpdatePreemptState()
+ protected override void UpdateInitialTransforms()
{
- base.UpdatePreemptState();
+ base.UpdateInitialTransforms();
ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt));
ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt);
ApproachCircle.Expire(true);
}
- protected override void UpdateCurrentState(ArmedState state)
+ protected override void UpdateStateTransforms(ArmedState state)
{
glow.FadeOut(400);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
index 4533e08a2b..579f16e0d4 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
@@ -1,15 +1,10 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements;
-using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Judgements;
-using osu.Game.Rulesets.Scoring;
-using osu.Game.Skinning;
-using osuTK.Graphics;
using osu.Game.Graphics.Containers;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
@@ -41,47 +36,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
- protected sealed override void UpdateState(ArmedState state)
- {
- double transformTime = HitObject.StartTime - HitObject.TimePreempt;
-
- base.ApplyTransformsAt(transformTime, true);
- base.ClearTransformsAfter(transformTime, true);
-
- using (BeginAbsoluteSequence(transformTime, true))
- {
- UpdatePreemptState();
-
- var judgementOffset = Math.Min(HitObject.HitWindows.HalfWindowFor(HitResult.Miss), Result?.TimeOffset ?? 0);
-
- using (BeginDelayedSequence(HitObject.TimePreempt + judgementOffset, true))
- UpdateCurrentState(state);
- }
- }
-
- protected override void SkinChanged(ISkinSource skin, bool allowFallback)
- {
- base.SkinChanged(skin, allowFallback);
-
- if (HitObject is IHasComboInformation combo)
- AccentColour = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
- }
-
- protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadeIn);
-
- protected virtual void UpdateCurrentState(ArmedState state)
- {
- }
-
- // Todo: At some point we need to move these to DrawableHitObject after ensuring that all other Rulesets apply
- // transforms in the same way and don't rely on them not being cleared
- public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null)
- {
- }
-
- public override void ApplyTransformsAt(double time, bool propagateChildren = false)
- {
- }
+ protected override void UpdateInitialTransforms() => this.FadeIn(HitObject.TimeFadeIn);
private OsuInputManager osuActionInputManager;
internal OsuInputManager OsuActionInputManager => osuActionInputManager ?? (osuActionInputManager = GetContainingInputManager() as OsuInputManager);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs
index cce6dfe106..1e2c0ae59f 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs
@@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ApplyResult(r => r.Type = drawableSlider.Tracking.Value ? HitResult.Great : HitResult.Miss);
}
- protected override void UpdatePreemptState()
+ protected override void UpdateInitialTransforms()
{
animDuration = Math.Min(150, repeatPoint.SpanDuration / 2);
@@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
);
}
- protected override void UpdateCurrentState(ArmedState state)
+ protected override void UpdateStateTransforms(ArmedState state)
{
switch (state)
{
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 4d67c9ae34..4a6bd45007 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
Body = new SnakingSliderBody(s)
{
- PathRadius = s.Scale * 64,
+ PathRadius = s.Scale * OsuHitObject.OBJECT_RADIUS,
},
ticks = new Container { RelativeSizeAxes = Axes.Both },
repeatPoints = new Container { RelativeSizeAxes = Axes.Both },
@@ -114,20 +114,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
pathBindable.BindTo(slider.PathBindable);
pathBindable.BindValueChanged(_ => Body.Refresh());
- }
- public override Color4 AccentColour
- {
- get => base.AccentColour;
- set
+ AccentColour.BindValueChanged(colour =>
{
- base.AccentColour = value;
- Body.AccentColour = AccentColour;
- Ball.AccentColour = AccentColour;
+ Body.AccentColour = colour.NewValue;
+ Ball.AccentColour = colour.NewValue;
foreach (var drawableHitObject in NestedHitObjects)
- drawableHitObject.AccentColour = AccentColour;
- }
+ drawableHitObject.AccentColour.Value = colour.NewValue;
+ }, true);
}
public readonly Bindable Tracking = new Bindable();
@@ -167,9 +162,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
base.SkinChanged(skin, allowFallback);
Body.BorderSize = skin.GetValue(s => s.SliderBorderSize) ?? SliderBody.DEFAULT_BORDER_SIZE;
- Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour;
+ Body.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderTrackOverride") ? s.CustomColours["SliderTrackOverride"] : (Color4?)null) ?? AccentColour.Value;
Body.BorderColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBorder") ? s.CustomColours["SliderBorder"] : (Color4?)null) ?? Color4.White;
- Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour;
+ Ball.AccentColour = skin.GetValue(s => s.CustomColours.ContainsKey("SliderBall") ? s.CustomColours["SliderBall"] : (Color4?)null) ?? AccentColour.Value;
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
@@ -195,7 +190,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
});
}
- protected override void UpdateCurrentState(ArmedState state)
+ protected override void UpdateStateTransforms(ArmedState state)
{
Ball.FadeIn();
Ball.ScaleTo(HitObject.Scale);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
index 72b648bfd0..f5f92dd05d 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
@@ -34,14 +34,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
RelativeSizeAxes = Axes.Both,
Origin = Anchor.Centre,
CornerRadius = Size.X / 2,
-
BorderThickness = 2,
BorderColour = Color4.White,
-
Child = new Box
{
RelativeSizeAxes = Axes.Both,
- Colour = AccentColour,
+ Colour = AccentColour.Value,
Alpha = 0.3f,
}
}, restrictSize: false)
@@ -54,13 +52,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ApplyResult(r => r.Type = Tracking ? HitResult.Great : HitResult.Miss);
}
- protected override void UpdatePreemptState()
+ protected override void UpdateInitialTransforms()
{
this.FadeOut().FadeIn(ANIM_DURATION);
this.ScaleTo(0.5f).ScaleTo(1f, ANIM_DURATION * 4, Easing.OutElasticHalf);
}
- protected override void UpdateCurrentState(ArmedState state)
+ protected override void UpdateStateTransforms(ArmedState state)
{
switch (state)
{
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
index 1794da54b7..a0bd301fdb 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -196,9 +196,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
symbol.RotateTo(Disc.Rotation / 2, 500, Easing.OutQuint);
}
- protected override void UpdatePreemptState()
+ protected override void UpdateInitialTransforms()
{
- base.UpdatePreemptState();
+ base.UpdateInitialTransforms();
circleContainer.ScaleTo(Spinner.Scale * 0.3f);
circleContainer.ScaleTo(Spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint);
@@ -213,7 +213,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
.ScaleTo(1, 500, Easing.OutQuint);
}
- protected override void UpdateCurrentState(ArmedState state)
+ protected override void UpdateStateTransforms(ArmedState state)
{
var sequence = this.Delay(Spinner.Duration).FadeOut(160);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs
index 786cac7198..dc0b149140 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs
@@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
public CirclePiece()
{
- Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Masking = true;
CornerRadius = Size.X / 2;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs
index b960f40578..8ff16f8b84 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public ExplodePiece()
{
- Size = new Vector2(128);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs
index 8e5eb886aa..c22073f56c 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs
@@ -1,4 +1,4 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public FlashPiece()
{
- Size = new Vector2(128);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs
index 28180a7f71..575f2c92c5 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs
@@ -1,4 +1,4 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public RingPiece()
{
- Size = new Vector2(128);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs
index 7d1d77ae96..9ba8ad3474 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs
@@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition
{
- private const float width = 128;
-
private Color4 accentColour = Color4.Black;
public Func GetInitialHitAction;
@@ -57,8 +55,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
- Width = width,
- Height = width,
+ Width = OsuHitObject.OBJECT_RADIUS * 2,
+ Height = OsuHitObject.OBJECT_RADIUS * 2,
Alpha = 0,
Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new CircularContainer
{
@@ -84,8 +82,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Alpha = 1,
Child = new Container
{
- Width = width,
- Height = width,
+ Width = OsuHitObject.OBJECT_RADIUS * 2,
+ Height = OsuHitObject.OBJECT_RADIUS * 2,
// TODO: support skin filename animation (sliderb0, sliderb1...)
Child = new SkinnableDrawable("Play/osu/sliderb", _ => new CircularContainer
{
diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
index 364c182dd4..d1221fd2d3 100644
--- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects
{
public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition
{
- public const double OBJECT_RADIUS = 64;
+ public const float OBJECT_RADIUS = 64;
public double TimePreempt = 600;
public double TimeFadeIn = 400;
diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs
index baa4aff413..8df0f77629 100644
--- a/osu.Game.Rulesets.Osu/OsuRuleset.cs
+++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs
@@ -138,6 +138,12 @@ namespace osu.Game.Rulesets.Osu
new MultiMod(new ModWindUp(), new ModWindDown()),
};
+ case ModType.System:
+ return new Mod[]
+ {
+ new OsuModTouchDevice(),
+ };
+
default:
return new Mod[] { };
}
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
index 4c8d5d5204..34ae7db984 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
@@ -94,6 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
protected override void UpdateState(ArmedState state)
{
+ // TODO: update to use new state management.
var circlePiece = MainPiece as CirclePiece;
circlePiece?.FlashBox.FinishTransforms();
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs
index bd45b52d7b..b46738c69a 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs
@@ -121,6 +121,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
}
}
+ protected override bool UseTransformStateManagement => false;
+
// Normal and clap samples are handled by the drum
protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != HitSampleInfo.HIT_NORMAL && s.Name != HitSampleInfo.HIT_CLAP);
diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs
index 883f0c5e3f..838347800f 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Online
{
typeof(HistoricalSection),
typeof(PaginatedMostPlayedBeatmapContainer),
- typeof(DrawableMostPlayedRow),
+ typeof(DrawableMostPlayedBeatmap),
typeof(DrawableProfileRow)
};
diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
index ea3f0b61b9..df3a45d1cc 100644
--- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
+++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
@@ -66,6 +66,11 @@ namespace osu.Game.Beatmaps
///
public int FavouriteCount { get; set; }
+ ///
+ /// Whether this beatmap set has been favourited by the current user.
+ ///
+ public bool HasFavourited { get; set; }
+
///
/// The availability of this beatmap set.
///
diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs
index 37aa0024da..949a2aab6f 100644
--- a/osu.Game/Beatmaps/WorkingBeatmap.cs
+++ b/osu.Game/Beatmaps/WorkingBeatmap.cs
@@ -247,7 +247,7 @@ namespace osu.Game.Beatmaps
// cancelling the beatmap load is safe for now since the retrieval is a synchronous
// operation. if we add an async retrieval method this may need to be reconsidered.
- beatmapCancellation.Cancel();
+ beatmapCancellation?.Cancel();
total_count.Value--;
}
diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs
index a2d8f42fac..2b68e8530d 100644
--- a/osu.Game/Graphics/Backgrounds/Triangles.cs
+++ b/osu.Game/Graphics/Backgrounds/Triangles.cs
@@ -214,7 +214,7 @@ namespace osu.Game.Graphics.Backgrounds
{
base.Draw(vertexAction);
- if (vertexBatch == null || vertexBatch.Size != Source.AimCount)
+ if (Source.AimCount > 0 && (vertexBatch == null || vertexBatch.Size != Source.AimCount))
{
vertexBatch?.Dispose();
vertexBatch = new TriangleBatch(Source.AimCount, 1);
diff --git a/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs
new file mode 100644
index 0000000000..8714138322
--- /dev/null
+++ b/osu.Game/Graphics/OpenGL/Vertices/PositionAndColourVertex.cs
@@ -0,0 +1,26 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using System.Runtime.InteropServices;
+using osu.Framework.Graphics.OpenGL.Vertices;
+using osuTK;
+using osuTK.Graphics;
+using osuTK.Graphics.ES30;
+
+namespace osu.Game.Graphics.OpenGL.Vertices
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PositionAndColourVertex : IEquatable, IVertex
+ {
+ [VertexMember(2, VertexAttribPointerType.Float)]
+ public Vector2 Position;
+
+ [VertexMember(4, VertexAttribPointerType.Float)]
+ public Color4 Colour;
+
+ public bool Equals(PositionAndColourVertex other)
+ => Position.Equals(other.Position)
+ && Colour.Equals(other.Colour);
+ }
+}
diff --git a/osu.Game/Graphics/Sprites/GlowingSpriteText.cs b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs
new file mode 100644
index 0000000000..74e387d60e
--- /dev/null
+++ b/osu.Game/Graphics/Sprites/GlowingSpriteText.cs
@@ -0,0 +1,80 @@
+// Copyright (c) ppy Pty Ltd . 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.Colour;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Sprites;
+using osuTK;
+
+namespace osu.Game.Graphics.Sprites
+{
+ public class GlowingSpriteText : Container, IHasText
+ {
+ private readonly OsuSpriteText spriteText, blurredText;
+
+ public string Text
+ {
+ get => spriteText.Text;
+ set => blurredText.Text = spriteText.Text = value;
+ }
+
+ public FontUsage Font
+ {
+ get => spriteText.Font;
+ set => blurredText.Font = spriteText.Font = value.With(fixedWidth: true);
+ }
+
+ public Vector2 TextSize
+ {
+ get => spriteText.Size;
+ set => blurredText.Size = spriteText.Size = value;
+ }
+
+ public ColourInfo TextColour
+ {
+ get => spriteText.Colour;
+ set => spriteText.Colour = value;
+ }
+
+ public ColourInfo GlowColour
+ {
+ get => blurredText.Colour;
+ set => blurredText.Colour = value;
+ }
+
+ public GlowingSpriteText()
+ {
+ AutoSizeAxes = Axes.Both;
+
+ Children = new Drawable[]
+ {
+ new BufferedContainer
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ BlurSigma = new Vector2(4),
+ CacheDrawnFrameBuffer = true,
+ RelativeSizeAxes = Axes.Both,
+ Blending = BlendingMode.Additive,
+ Size = new Vector2(3f),
+ Children = new[]
+ {
+ blurredText = new OsuSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Shadow = false,
+ },
+ },
+ },
+ spriteText = new OsuSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Shadow = false,
+ },
+ };
+ }
+ }
+}
diff --git a/osu.Game/Graphics/UserInterface/SearchTextBox.cs b/osu.Game/Graphics/UserInterface/SearchTextBox.cs
index 7023711aaa..c3efe2ed45 100644
--- a/osu.Game/Graphics/UserInterface/SearchTextBox.cs
+++ b/osu.Game/Graphics/UserInterface/SearchTextBox.cs
@@ -3,6 +3,7 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
+using osu.Framework.Input;
using osu.Framework.Input.Events;
using osuTK;
using osuTK.Input;
@@ -33,6 +34,17 @@ namespace osu.Game.Graphics.UserInterface
PlaceholderText = "type to search";
}
+ public override bool OnPressed(PlatformAction action)
+ {
+ // Shift+delete is handled via PlatformAction on macOS. this is not so useful in the context of a SearchTextBox
+ // as we do not allow arrow key navigation in the first place (ie. the care should always be at the end of text)
+ // Avoid handling it here to allow other components to potentially consume the shortcut.
+ if (action.ActionType == PlatformActionType.CharNext && action.ActionMethod == PlatformActionMethod.Delete)
+ return false;
+
+ return base.OnPressed(action);
+ }
+
protected override bool OnKeyDown(KeyDownEvent e)
{
if (!e.ControlPressed && !e.ShiftPressed)
diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs
index 200a705500..e5bfde8f8f 100644
--- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs
@@ -30,6 +30,9 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"preview_url")]
private string preview { get; set; }
+ [JsonProperty(@"has_favourited")]
+ private bool hasFavourited { get; set; }
+
[JsonProperty(@"play_count")]
private int playCount { get; set; }
@@ -91,6 +94,7 @@ namespace osu.Game.Online.API.Requests.Responses
Ranked = ranked,
LastUpdated = lastUpdated,
Availability = availability,
+ HasFavourited = hasFavourited,
},
Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(),
};
diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs
index 9840b59805..008f8208eb 100644
--- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs
+++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs
@@ -187,7 +187,13 @@ namespace osu.Game.Online.Leaderboards
Spacing = new Vector2(5f, 0f),
Children = new Drawable[]
{
- scoreLabel = new GlowingSpriteText(score.TotalScore.ToString(@"N0"), OsuFont.Numeric.With(size: 23), Color4.White, OsuColour.FromHex(@"83ccfa")),
+ scoreLabel = new GlowingSpriteText
+ {
+ TextColour = Color4.White,
+ GlowColour = OsuColour.FromHex(@"83ccfa"),
+ Text = score.TotalScore.ToString(@"N0"),
+ Font = OsuFont.Numeric.With(size: 23),
+ },
RankContainer = new Container
{
Size = new Vector2(40f, 20f),
@@ -275,49 +281,6 @@ namespace osu.Game.Online.Leaderboards
base.OnHoverLost(e);
}
- private class GlowingSpriteText : Container
- {
- public GlowingSpriteText(string text, FontUsage font, Color4 textColour, Color4 glowColour)
- {
- AutoSizeAxes = Axes.Both;
-
- Children = new Drawable[]
- {
- new BufferedContainer
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- BlurSigma = new Vector2(4),
- CacheDrawnFrameBuffer = true,
- RelativeSizeAxes = Axes.Both,
- Blending = BlendingMode.Additive,
- Size = new Vector2(3f),
- Children = new[]
- {
- new OsuSpriteText
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- Font = font.With(fixedWidth: true),
- Text = text,
- Colour = glowColour,
- Shadow = false,
- },
- },
- },
- new OsuSpriteText
- {
- Anchor = Anchor.Centre,
- Origin = Anchor.Centre,
- Font = font.With(fixedWidth: true),
- Text = text,
- Colour = textColour,
- Shadow = false,
- },
- };
- }
- }
-
private class ScoreComponentLabel : Container, IHasTooltip
{
private const float icon_size = 20;
@@ -367,10 +330,14 @@ namespace osu.Game.Online.Leaderboards
},
},
},
- new GlowingSpriteText(statistic.Value, OsuFont.GetFont(size: 17, weight: FontWeight.Bold), Color4.White, OsuColour.FromHex(@"83ccfa"))
+ new GlowingSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
+ TextColour = Color4.White,
+ GlowColour = OsuColour.FromHex(@"83ccfa"),
+ Text = statistic.Value,
+ Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold),
},
},
};
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 4c7fc688ab..6fb76c640f 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -20,6 +20,7 @@ using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Audio;
using osu.Framework.Bindables;
+using osu.Framework.Development;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input;
@@ -153,7 +154,7 @@ namespace osu.Game
{
this.frameworkConfig = frameworkConfig;
- if (!Host.IsPrimaryInstance)
+ if (!Host.IsPrimaryInstance && !DebugUtils.IsDebugBuild)
{
Logger.Log(@"osu! does not support multiple running instances.", LoggingTarget.Runtime, LogLevel.Error);
Environment.Exit(0);
diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs
index 7207739646..11f56bc163 100644
--- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs
+++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs
@@ -7,6 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
+using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osuTK;
@@ -15,7 +16,9 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
{
public class FavouriteButton : HeaderButton
{
- public readonly Bindable Favourited = new Bindable();
+ public readonly Bindable BeatmapSet = new Bindable();
+
+ private readonly Bindable favourited = new Bindable();
[BackgroundDependencyLoader]
private void load()
@@ -54,7 +57,15 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
},
});
- Favourited.ValueChanged += favourited =>
+ BeatmapSet.BindValueChanged(setInfo =>
+ {
+ if (setInfo.NewValue?.OnlineInfo?.HasFavourited == null)
+ return;
+
+ favourited.Value = setInfo.NewValue.OnlineInfo.HasFavourited;
+ });
+
+ favourited.ValueChanged += favourited =>
{
if (favourited.NewValue)
{
@@ -67,8 +78,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
icon.Icon = FontAwesome.Regular.Heart;
}
};
-
- Action = () => Favourited.Value = !Favourited.Value;
}
protected override void UpdateAfterChildren()
diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs
index b50eac2c1a..260a989628 100644
--- a/osu.Game/Overlays/BeatmapSet/Header.cs
+++ b/osu.Game/Overlays/BeatmapSet/Header.cs
@@ -161,7 +161,10 @@ namespace osu.Game.Overlays.BeatmapSet
Margin = new MarginPadding { Top = 10 },
Children = new Drawable[]
{
- favouriteButton = new FavouriteButton(),
+ favouriteButton = new FavouriteButton
+ {
+ BeatmapSet = { BindTarget = BeatmapSet }
+ },
downloadButtonsContainer = new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs
index e29216dffd..2576b38ec8 100644
--- a/osu.Game/Overlays/Chat/ChatLine.cs
+++ b/osu.Game/Overlays/Chat/ChatLine.cs
@@ -85,6 +85,7 @@ namespace osu.Game.Overlays.Chat
Drawable effectedUsername = username = new OsuSpriteText
{
+ Shadow = false,
Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length],
Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true)
};
@@ -133,6 +134,7 @@ namespace osu.Game.Overlays.Chat
{
timestamp = new OsuSpriteText
{
+ Shadow = false,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: TextSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true)
@@ -155,6 +157,8 @@ namespace osu.Game.Overlays.Chat
{
contentFlow = new LinkFlowContainer(t =>
{
+ t.Shadow = false;
+
if (Message.IsAction)
{
t.Font = OsuFont.GetFont(italics: true);
diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs
index 16326900f1..13b547eed3 100644
--- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs
@@ -4,26 +4,23 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Framework.Localisation;
using osu.Game.Beatmaps;
-using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
-using osu.Game.Graphics.Sprites;
namespace osu.Game.Overlays.Profile.Sections
{
///
/// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see ).
///
- public class BeatmapMetadataContainer : OsuHoverContainer
+ public abstract class BeatmapMetadataContainer : OsuHoverContainer
{
private readonly BeatmapInfo beatmap;
- public BeatmapMetadataContainer(BeatmapInfo beatmap)
+ protected BeatmapMetadataContainer(BeatmapInfo beatmap)
{
this.beatmap = beatmap;
+
AutoSizeAxes = Axes.Both;
- TooltipText = $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}";
}
[BackgroundDependencyLoader(true)]
@@ -40,23 +37,10 @@ namespace osu.Game.Overlays.Profile.Sections
Child = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
- Children = new Drawable[]
- {
- new OsuSpriteText
- {
- Text = new LocalisedString((
- $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ",
- $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")),
- Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold, italics: true)
- },
- new OsuSpriteText
- {
- Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)),
- Padding = new MarginPadding { Top = 3 },
- Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true)
- },
- },
+ Children = CreateText(beatmap),
};
}
+
+ protected abstract Drawable[] CreateText(BeatmapInfo beatmap);
}
}
diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs
new file mode 100644
index 0000000000..0206c4e13b
--- /dev/null
+++ b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedBeatmap.cs
@@ -0,0 +1,182 @@
+// Copyright (c) ppy Pty Ltd . 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.Localisation;
+using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.Drawables;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
+using osu.Game.Graphics.Sprites;
+using osuTK;
+using System.Collections.Generic;
+using osu.Framework.Graphics.Cursor;
+
+namespace osu.Game.Overlays.Profile.Sections.Historical
+{
+ public class DrawableMostPlayedBeatmap : OsuHoverContainer
+ {
+ private const int cover_width = 100;
+ private const int corner_radius = 6;
+ private const int height = 50;
+
+ private readonly BeatmapInfo beatmap;
+ private readonly int playCount;
+
+ private Box background;
+
+ protected override IEnumerable EffectTargets => new[] { background };
+
+ public DrawableMostPlayedBeatmap(BeatmapInfo beatmap, int playCount)
+ {
+ this.beatmap = beatmap;
+ this.playCount = playCount;
+ Enabled.Value = true; //manually enabled, because we have no action
+
+ RelativeSizeAxes = Axes.X;
+ Height = height;
+
+ Masking = true;
+ CornerRadius = corner_radius;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours)
+ {
+ IdleColour = colours.GreySeafoam;
+ HoverColour = colours.GreySeafoamLight;
+
+ Children = new Drawable[]
+ {
+ new UpdateableBeatmapSetCover
+ {
+ RelativeSizeAxes = Axes.Y,
+ Width = cover_width,
+ BeatmapSet = beatmap.BeatmapSet,
+ CoverType = BeatmapSetCoverType.List,
+ },
+ new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ Padding = new MarginPadding { Left = cover_width - corner_radius },
+ Children = new Drawable[]
+ {
+ new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ Masking = true,
+ CornerRadius = corner_radius,
+ Children = new Drawable[]
+ {
+ background = new Box { RelativeSizeAxes = Axes.Both },
+ new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ Padding = new MarginPadding(10),
+ Children = new Drawable[]
+ {
+ new FillFlowContainer
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ AutoSizeAxes = Axes.Both,
+ Direction = FillDirection.Vertical,
+ Children = new Drawable[]
+ {
+ new MostPlayedBeatmapMetadataContainer(beatmap),
+ new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular))
+ {
+ AutoSizeAxes = Axes.Both,
+ Direction = FillDirection.Horizontal,
+ Colour = colours.GreySeafoamLighter
+ }.With(d =>
+ {
+ d.AddText("mapped by ");
+ d.AddUserLink(beatmap.Metadata.Author);
+ }),
+ }
+ },
+ new PlayCountText(playCount)
+ {
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.CentreRight
+ },
+ }
+ },
+ }
+ }
+ }
+ }
+ };
+ }
+
+ private class MostPlayedBeatmapMetadataContainer : BeatmapMetadataContainer
+ {
+ public MostPlayedBeatmapMetadataContainer(BeatmapInfo beatmap)
+ : base(beatmap)
+ {
+ }
+
+ protected override Drawable[] CreateText(BeatmapInfo beatmap) => new Drawable[]
+ {
+ new OsuSpriteText
+ {
+ Text = new LocalisedString((
+ $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ",
+ $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")),
+ Font = OsuFont.GetFont(weight: FontWeight.Bold)
+ },
+ new OsuSpriteText
+ {
+ Text = "by " + new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)),
+ Font = OsuFont.GetFont(weight: FontWeight.Regular)
+ },
+ };
+ }
+
+ private class PlayCountText : CompositeDrawable, IHasTooltip
+ {
+ public string TooltipText => "times played";
+
+ public PlayCountText(int playCount)
+ {
+ AutoSizeAxes = Axes.Both;
+
+ InternalChild = new FillFlowContainer
+ {
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.CentreRight,
+ AutoSizeAxes = Axes.Both,
+ Spacing = new Vector2(5, 0),
+ Children = new Drawable[]
+ {
+ new SpriteIcon
+ {
+ Origin = Anchor.Centre,
+ Anchor = Anchor.Centre,
+ Size = new Vector2(12),
+ Icon = FontAwesome.Solid.Play,
+ },
+ new OsuSpriteText
+ {
+ Origin = Anchor.Centre,
+ Anchor = Anchor.Centre,
+ Text = playCount.ToString(),
+ Font = OsuFont.GetFont(size: 20, weight: FontWeight.Regular),
+ },
+ }
+ };
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(OsuColour colours)
+ {
+ Colour = colours.Yellow;
+ }
+ }
+ }
+}
diff --git a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs b/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs
deleted file mode 100644
index 1b286f92d3..0000000000
--- a/osu.Game/Overlays/Profile/Sections/Historical/DrawableMostPlayedRow.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) ppy Pty Ltd . 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.Game.Beatmaps;
-using osu.Game.Beatmaps.Drawables;
-using osu.Game.Graphics;
-using osu.Game.Graphics.Containers;
-using osu.Game.Graphics.Sprites;
-using osuTK;
-
-namespace osu.Game.Overlays.Profile.Sections.Historical
-{
- public class DrawableMostPlayedRow : DrawableProfileRow
- {
- private readonly BeatmapInfo beatmap;
- private readonly int playCount;
-
- public DrawableMostPlayedRow(BeatmapInfo beatmap, int playCount)
- {
- this.beatmap = beatmap;
- this.playCount = playCount;
- }
-
- protected override Drawable CreateLeftVisual() => new UpdateableBeatmapSetCover
- {
- Anchor = Anchor.CentreLeft,
- Origin = Anchor.CentreLeft,
- Size = new Vector2(80, 50),
- BeatmapSet = beatmap.BeatmapSet,
- CoverType = BeatmapSetCoverType.List,
- };
-
- [BackgroundDependencyLoader]
- private void load()
- {
- LeftFlowContainer.Add(new BeatmapMetadataContainer(beatmap));
- LeftFlowContainer.Add(new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: 12))
- {
- RelativeSizeAxes = Axes.X,
- AutoSizeAxes = Axes.Y,
- Direction = FillDirection.Horizontal,
- }.With(d =>
- {
- d.AddText("mapped by ");
- d.AddUserLink(beatmap.Metadata.Author);
- }));
-
- RightFlowContainer.Add(new FillFlowContainer
- {
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- AutoSizeAxes = Axes.Both,
- Direction = FillDirection.Horizontal,
- Children = new[]
- {
- new OsuSpriteText
- {
- Anchor = Anchor.BottomRight,
- Origin = Anchor.BottomRight,
- Text = playCount.ToString(),
- Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold, italics: true)
- },
- new OsuSpriteText
- {
- Anchor = Anchor.BottomRight,
- Origin = Anchor.BottomRight,
- Text = @"times played ",
- Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true)
- },
- }
- });
- }
- }
-}
diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
index 9409cd9aeb..23072f8d90 100644
--- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
@@ -40,7 +40,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
foreach (var beatmap in beatmaps)
{
- ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount));
+ ItemsContainer.Add(new DrawableMostPlayedBeatmap(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount));
}
});
diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs
index b77357edd8..e54ce44ca2 100644
--- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs
+++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs
@@ -10,6 +10,8 @@ using osu.Game.Online.Leaderboards;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
+using osu.Game.Beatmaps;
+using osu.Framework.Localisation;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
@@ -51,7 +53,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
RightFlowContainer.Insert(1, text);
- LeftFlowContainer.Add(new BeatmapMetadataContainer(Score.Beatmap));
+ LeftFlowContainer.Add(new ProfileScoreBeatmapMetadataContainer(Score.Beatmap));
LeftFlowContainer.Add(new DrawableDate(Score.Date));
foreach (Mod mod in Score.Mods)
@@ -64,5 +66,30 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
Width = 60,
FillMode = FillMode.Fit,
};
+
+ private class ProfileScoreBeatmapMetadataContainer : BeatmapMetadataContainer
+ {
+ public ProfileScoreBeatmapMetadataContainer(BeatmapInfo beatmap)
+ : base(beatmap)
+ {
+ }
+
+ protected override Drawable[] CreateText(BeatmapInfo beatmap) => new Drawable[]
+ {
+ new OsuSpriteText
+ {
+ Text = new LocalisedString((
+ $"{beatmap.Metadata.TitleUnicode ?? beatmap.Metadata.Title} [{beatmap.Version}] ",
+ $"{beatmap.Metadata.Title ?? beatmap.Metadata.TitleUnicode} [{beatmap.Version}] ")),
+ Font = OsuFont.GetFont(size: 15, weight: FontWeight.SemiBold, italics: true)
+ },
+ new OsuSpriteText
+ {
+ Text = new LocalisedString((beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist)),
+ Padding = new MarginPadding { Top = 3 },
+ Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true)
+ },
+ };
+ }
}
}
diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
index bf0cd91321..2c79f5bc0e 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
@@ -71,16 +71,11 @@ namespace osu.Game.Overlays.Toolbar
// Scheduled to allow the flow layout to be computed before the line position is updated
private void moveLineToCurrent() => ScheduleAfterChildren(() =>
{
- foreach (var tabItem in TabContainer)
+ if (SelectedTab != null)
{
- if (tabItem.Value.Equals(Current.Value))
- {
- ModeButtonLine.MoveToX(tabItem.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint);
- break;
- }
+ ModeButtonLine.MoveToX(SelectedTab.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint);
+ hasInitialPosition = true;
}
-
- hasInitialPosition = true;
});
public override bool HandleNonPositionalInput => !Current.Disabled && base.HandleNonPositionalInput;
diff --git a/osu.Game/Rulesets/Mods/ModFlashlight.cs b/osu.Game/Rulesets/Mods/ModFlashlight.cs
index 405d21c711..cb0c2fafe5 100644
--- a/osu.Game/Rulesets/Mods/ModFlashlight.cs
+++ b/osu.Game/Rulesets/Mods/ModFlashlight.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
+using osu.Framework.Graphics.Batches;
using osu.Framework.Graphics.OpenGL.Vertices;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shaders;
@@ -13,6 +14,7 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps.Timing;
using osu.Game.Graphics;
+using osu.Game.Graphics.OpenGL.Vertices;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
@@ -153,9 +155,17 @@ namespace osu.Game.Rulesets.Mods
private Vector2 flashlightSize;
private float flashlightDim;
+ private readonly VertexBatch quadBatch = new QuadBatch(1, 1);
+ private readonly Action addAction;
+
public FlashlightDrawNode(Flashlight source)
: base(source)
{
+ addAction = v => quadBatch.Add(new PositionAndColourVertex
+ {
+ Position = v.Position,
+ Colour = v.Colour
+ });
}
public override void ApplyState()
@@ -179,7 +189,7 @@ namespace osu.Game.Rulesets.Mods
shader.GetUniform("flashlightSize").UpdateValue(ref flashlightSize);
shader.GetUniform("flashlightDim").UpdateValue(ref flashlightDim);
- DrawQuad(Texture.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction);
+ DrawQuad(Texture.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: addAction);
shader.Unbind();
}
diff --git a/osu.Game/Rulesets/Mods/ModType.cs b/osu.Game/Rulesets/Mods/ModType.cs
index cd649728cf..e3c82e42f5 100644
--- a/osu.Game/Rulesets/Mods/ModType.cs
+++ b/osu.Game/Rulesets/Mods/ModType.cs
@@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Mods
DifficultyIncrease,
Conversion,
Automation,
- Fun
+ Fun,
+ System
}
}
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index e61fac679e..1d9d885527 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -9,7 +9,6 @@ using osu.Framework.Bindables;
using osu.Framework.Extensions.TypeExtensions;
using osu.Framework.Graphics.Primitives;
using osu.Game.Audio;
-using osu.Game.Graphics;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
@@ -18,14 +17,14 @@ using osuTK.Graphics;
namespace osu.Game.Rulesets.Objects.Drawables
{
- public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColour
+ public abstract class DrawableHitObject : SkinReloadableDrawable
{
public readonly HitObject HitObject;
///
/// The colour used for various elements of this DrawableHitObject.
///
- public virtual Color4 AccentColour { get; set; } = Color4.Gray;
+ public readonly Bindable AccentColour = new Bindable(Color4.Gray);
// Todo: Rulesets should be overriding the resources instead, but we need to figure out where/when to apply overrides first
protected virtual string SampleNamespace => null;
@@ -82,7 +81,9 @@ namespace osu.Game.Rulesets.Objects.Drawables
public override bool IsPresent => base.IsPresent || (State.Value == ArmedState.Idle && Clock?.CurrentTime >= LifetimeStart);
- public readonly Bindable State = new Bindable();
+ private readonly Bindable state = new Bindable();
+
+ public IBindable State => state;
protected DrawableHitObject(HitObject hitObject)
{
@@ -117,33 +118,120 @@ namespace osu.Game.Rulesets.Objects.Drawables
}
}
- protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}");
-
protected override void LoadComplete()
{
base.LoadComplete();
-
- State.ValueChanged += armed =>
- {
- UpdateState(armed.NewValue);
-
- // apply any custom state overrides
- ApplyCustomUpdateState?.Invoke(this, armed.NewValue);
-
- if (armed.NewValue == ArmedState.Hit)
- PlaySamples();
- };
-
- State.TriggerChange();
+ updateState(ArmedState.Idle, true);
}
- protected abstract void UpdateState(ArmedState state);
+ #region State / Transform Management
///
/// Bind to apply a custom state which can override the default implementation.
///
public event Action ApplyCustomUpdateState;
+ ///
+ /// Enables automatic transform management of this hitobject. Implementation of transforms should be done in and only. Rewinding and removing previous states is done automatically.
+ ///
+ ///
+ /// Going forward, this is the preferred way of implementing s. Previous functionality
+ /// is offered as a compatibility layer until all rulesets have been migrated across.
+ ///
+ protected virtual bool UseTransformStateManagement => true;
+
+ protected override void ClearInternal(bool disposeChildren = true) => throw new InvalidOperationException($"Should never clear a {nameof(DrawableHitObject)}");
+
+ private void updateState(ArmedState newState, bool force = false)
+ {
+ if (State.Value == newState && !force)
+ return;
+
+ // apply any custom state overrides
+ ApplyCustomUpdateState?.Invoke(this, newState);
+
+ if (newState == ArmedState.Hit)
+ PlaySamples();
+
+ if (UseTransformStateManagement)
+ {
+ double transformTime = HitObject.StartTime - InitialLifetimeOffset;
+
+ base.ApplyTransformsAt(transformTime, true);
+ base.ClearTransformsAfter(transformTime, true);
+
+ using (BeginAbsoluteSequence(transformTime, true))
+ {
+ UpdateInitialTransforms();
+
+ var judgementOffset = Math.Min(HitObject.HitWindows?.HalfWindowFor(HitResult.Miss) ?? double.MaxValue, Result?.TimeOffset ?? 0);
+
+ using (BeginDelayedSequence(InitialLifetimeOffset + judgementOffset, true))
+ {
+ UpdateStateTransforms(newState);
+ state.Value = newState;
+ }
+ }
+ }
+ else
+ state.Value = newState;
+
+ UpdateState(newState);
+ }
+
+ ///
+ /// Apply (generally fade-in) transforms leading into the start time.
+ /// The local drawable hierarchy is recursively delayed to for convenience.
+ ///
+ ///
+ /// This is called once before every . This is to ensure a good state in the case
+ /// the was negative and potentially altered the pre-hit transforms.
+ ///
+ protected virtual void UpdateInitialTransforms()
+ {
+ }
+
+ ///
+ /// Apply transforms based on the current . Previous states are automatically cleared.
+ ///
+ /// The new armed state.
+ protected virtual void UpdateStateTransforms(ArmedState state)
+ {
+ }
+
+ public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null)
+ {
+ // When we are using automatic state management, parent calls to this should be blocked for safety.
+ if (!UseTransformStateManagement)
+ base.ClearTransformsAfter(time, propagateChildren, targetMember);
+ }
+
+ public override void ApplyTransformsAt(double time, bool propagateChildren = false)
+ {
+ // When we are using automatic state management, parent calls to this should be blocked for safety.
+ if (!UseTransformStateManagement)
+ base.ApplyTransformsAt(time, propagateChildren);
+ }
+
+ ///
+ /// Legacy method to handle state changes.
+ /// Should generally not be used when is true; use instead.
+ ///
+ /// The new armed state.
+ protected virtual void UpdateState(ArmedState state)
+ {
+ }
+
+ #endregion
+
+ protected override void SkinChanged(ISkinSource skin, bool allowFallback)
+ {
+ base.SkinChanged(skin, allowFallback);
+
+ if (HitObject is IHasComboInformation combo)
+ AccentColour.Value = skin.GetValue(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
+ }
+
///
/// Plays all the hit sounds for this .
/// This is invoked automatically when this is hit.
@@ -164,7 +252,8 @@ namespace osu.Game.Rulesets.Objects.Drawables
Result.TimeOffset = 0;
Result.Type = HitResult.None;
- State.Value = ArmedState.Idle;
+
+ updateState(ArmedState.Idle);
}
}
}
@@ -196,6 +285,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
///
///
/// This is only used as an optimisation to delay the initial update of this and may be tuned more aggressively if required.
+ /// It is indirectly used to decide the automatic transform offset provided to .
/// A more accurate should be set inside for an state.
///
protected virtual double InitialLifetimeOffset => 10000;
@@ -244,11 +334,11 @@ namespace osu.Game.Rulesets.Objects.Drawables
break;
case HitResult.Miss:
- State.Value = ArmedState.Miss;
+ updateState(ArmedState.Miss);
break;
default:
- State.Value = ArmedState.Hit;
+ updateState(ArmedState.Hit);
break;
}
diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs
index bd0b0dd5cd..57fe15fd99 100644
--- a/osu.Game/Screens/Select/FilterControl.cs
+++ b/osu.Game/Screens/Select/FilterControl.cs
@@ -120,7 +120,8 @@ namespace osu.Game.Screens.Select
RelativeSizeAxes = Axes.X,
Height = 24,
Width = 0.5f,
- AutoSort = true
+ AutoSort = true,
+ Current = { Value = GroupMode.Title }
},
//spriteText = new OsuSpriteText
//{
@@ -139,6 +140,7 @@ namespace osu.Game.Screens.Select
Width = 0.5f,
Height = 24,
AutoSort = true,
+ Current = { Value = SortMode.Title }
}
}
},
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index d90b1d36e1..c05cc6f9dd 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index fa2521a19e..3b18039600 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -105,8 +105,8 @@
-
-
+
+