mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 06:52:55 +08:00
Merge branch 'master' into drawable-composite-hit-object
This commit is contained in:
commit
23ffee3d38
@ -1 +1 @@
|
||||
Subproject commit d29c8365ba3cf7924b57cf22341f4af55658764c
|
||||
Subproject commit 41e2a0a4304544fb67779c21cad1435c105982d5
|
@ -1 +1 @@
|
||||
Subproject commit 92ec3d10b12c5e9bfc1d3b05d3db174a506efd6d
|
||||
Subproject commit 7bb0782200abadf73b79ed1a3bc1d5b926c6a81e
|
@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
{
|
||||
public override void PostProcess(Beatmap<CatchHitObject> beatmap)
|
||||
{
|
||||
if (beatmap.ComboColors.Count == 0)
|
||||
if (beatmap.ComboColours.Count == 0)
|
||||
return;
|
||||
|
||||
int index = 0;
|
||||
@ -31,11 +31,11 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||
if (obj.NewCombo)
|
||||
{
|
||||
if (lastObj != null) lastObj.LastInCombo = true;
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count;
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
|
||||
}
|
||||
|
||||
obj.IndexInBeatmap = index++;
|
||||
obj.ComboColour = beatmap.ComboColors[colourIndex];
|
||||
obj.ComboColour = beatmap.ComboColours[colourIndex];
|
||||
|
||||
lastObj = obj;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
{
|
||||
applyStacking(beatmap);
|
||||
|
||||
if (beatmap.ComboColors.Count == 0)
|
||||
if (beatmap.ComboColours.Count == 0)
|
||||
return;
|
||||
|
||||
int comboIndex = 0;
|
||||
@ -25,11 +25,11 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
if (obj.NewCombo)
|
||||
{
|
||||
comboIndex = 0;
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count;
|
||||
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
|
||||
}
|
||||
|
||||
obj.IndexInCurrentCombo = comboIndex++;
|
||||
obj.ComboColour = beatmap.ComboColors[colourIndex];
|
||||
obj.ComboColour = beatmap.ComboColours[colourIndex];
|
||||
}
|
||||
}
|
||||
|
||||
|
33
osu.Game.Rulesets.Osu/Tests/TestCaseGameplayCursor.cs
Normal file
33
osu.Game.Rulesets.Osu/Tests/TestCaseGameplayCursor.cs
Normal file
@ -0,0 +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;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseGameplayCursor : OsuTestCase, IProvideCursor
|
||||
{
|
||||
private GameplayCursor cursor;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new [] { typeof(CursorTrail) };
|
||||
|
||||
public CursorContainer Cursor => cursor;
|
||||
|
||||
public bool ProvidingUserCursor => true;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Add(cursor = new GameplayCursor { RelativeSizeAxes = Axes.Both });
|
||||
}
|
||||
}
|
||||
}
|
@ -3,9 +3,9 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.OpenGL.Buffers;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
@ -14,11 +14,12 @@ using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Timing;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.ES30;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
internal class CursorTrail : Drawable
|
||||
internal class CursorTrail : Drawable, IRequireHighFrequencyMousePosition
|
||||
{
|
||||
private int currentIndex;
|
||||
|
||||
@ -31,6 +32,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
private float time;
|
||||
|
||||
public override bool IsPresent => true;
|
||||
|
||||
private readonly TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData();
|
||||
private const int max_sprites = 2048;
|
||||
|
||||
@ -96,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
const int fade_clock_reset_threshold = 1000000;
|
||||
|
||||
time = (float)(Time.Current - timeOffset) / 500f;
|
||||
time = (float)(Time.Current - timeOffset) / 300f;
|
||||
if (time > fade_clock_reset_threshold)
|
||||
resetTime();
|
||||
}
|
||||
@ -115,14 +118,16 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
protected override bool OnMouseMove(InputState state)
|
||||
{
|
||||
Vector2 pos = state.Mouse.NativeState.Position;
|
||||
|
||||
if (lastPosition == null)
|
||||
{
|
||||
lastPosition = state.Mouse.NativeState.Position;
|
||||
lastPosition = pos;
|
||||
resampler.AddPosition(lastPosition.Value);
|
||||
return base.OnMouseMove(state);
|
||||
}
|
||||
|
||||
foreach (Vector2 pos2 in resampler.AddPosition(state.Mouse.NativeState.Position))
|
||||
foreach (Vector2 pos2 in resampler.AddPosition(pos))
|
||||
{
|
||||
Trace.Assert(lastPosition.HasValue);
|
||||
|
||||
@ -162,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
|
||||
private class TrailDrawNodeSharedData
|
||||
{
|
||||
public VertexBuffer<TexturedVertex2D> VertexBuffer;
|
||||
public VertexBuffer<TexturedTrailVertex> VertexBuffer;
|
||||
}
|
||||
|
||||
private class TrailDrawNode : DrawNode
|
||||
@ -188,7 +193,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
||||
{
|
||||
if (Shared.VertexBuffer == null)
|
||||
Shared.VertexBuffer = new QuadVertexBuffer<TexturedVertex2D>(max_sprites, BufferUsageHint.DynamicDraw);
|
||||
Shared.VertexBuffer = new QuadVertexBuffer<TexturedTrailVertex>(max_sprites, BufferUsageHint.DynamicDraw);
|
||||
|
||||
Shader.GetUniform<float>("g_FadeClock").Value = Time;
|
||||
|
||||
@ -205,17 +210,19 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
int end = start;
|
||||
|
||||
Vector2 pos = Parts[i].Position;
|
||||
ColourInfo colour = DrawInfo.Colour;
|
||||
colour.TopLeft.Linear.A = Parts[i].Time + colour.TopLeft.Linear.A;
|
||||
colour.TopRight.Linear.A = Parts[i].Time + colour.TopRight.Linear.A;
|
||||
colour.BottomLeft.Linear.A = Parts[i].Time + colour.BottomLeft.Linear.A;
|
||||
colour.BottomRight.Linear.A = Parts[i].Time + colour.BottomRight.Linear.A;
|
||||
float time = Parts[i].Time;
|
||||
|
||||
Texture.DrawQuad(
|
||||
new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y),
|
||||
colour,
|
||||
DrawInfo.Colour,
|
||||
null,
|
||||
v => Shared.VertexBuffer.Vertices[end++] = v);
|
||||
v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex
|
||||
{
|
||||
Position = v.Position,
|
||||
TexturePosition = v.TexturePosition,
|
||||
Time = time + 1,
|
||||
Colour = v.Colour,
|
||||
});
|
||||
|
||||
Parts[i].WasUpdated = false;
|
||||
}
|
||||
@ -240,5 +247,26 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
Shader.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct TexturedTrailVertex : IEquatable<TexturedTrailVertex>, IVertex
|
||||
{
|
||||
[VertexMember(2, VertexAttribPointerType.Float)]
|
||||
public Vector2 Position;
|
||||
[VertexMember(4, VertexAttribPointerType.Float)]
|
||||
public Color4 Colour;
|
||||
[VertexMember(2, VertexAttribPointerType.Float)]
|
||||
public Vector2 TexturePosition;
|
||||
[VertexMember(1, VertexAttribPointerType.Float)]
|
||||
public float Time;
|
||||
|
||||
public bool Equals(TexturedTrailVertex other)
|
||||
{
|
||||
return Position.Equals(other.Position)
|
||||
&& TexturePosition.Equals(other.TexturePosition)
|
||||
&& Colour.Equals(other.Colour)
|
||||
&& Time.Equals(other.Time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,13 +20,66 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
{
|
||||
protected override Drawable CreateCursor() => new OsuCursor();
|
||||
|
||||
protected override Container<Drawable> Content => fadeContainer;
|
||||
|
||||
private readonly Container<Drawable> fadeContainer;
|
||||
|
||||
public GameplayCursor()
|
||||
{
|
||||
Add(new CursorTrail { Depth = 1 });
|
||||
InternalChild = fadeContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new CursorTrail { Depth = 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private int downCount;
|
||||
|
||||
public bool OnPressed(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
downCount++;
|
||||
ActiveCursor.ScaleTo(1).ScaleTo(1.2f, 100, Easing.OutQuad);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
if (--downCount == 0)
|
||||
ActiveCursor.ScaleTo(1, 200, Easing.OutQuad);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool HandleMouseInput => true; // OverlayContainer will set this false when we go hidden, but we always want to receive input.
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint);
|
||||
}
|
||||
|
||||
public class OsuCursor : Container
|
||||
{
|
||||
private Container cursorContainer;
|
||||
@ -131,45 +184,5 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
cursorContainer.Scale = new Vector2(scale);
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
downCount++;
|
||||
ActiveCursor.ScaleTo(1).ScaleTo(1.2f, 100, Easing.OutQuad);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool OnReleased(OsuAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
if (--downCount == 0)
|
||||
ActiveCursor.ScaleTo(1, 200, Easing.OutQuad);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
ActiveCursor.FadeTo(1, 250, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
ActiveCursor.FadeTo(0, 250, Easing.OutQuint);
|
||||
ActiveCursor.ScaleTo(0.6f, 250, Easing.In);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,7 @@
|
||||
<Compile Include="Replays\OsuReplayInputHandler.cs" />
|
||||
<Compile Include="Tests\OsuBeatmapConversionTest.cs" />
|
||||
<Compile Include="Tests\TestCaseEditor.cs" />
|
||||
<Compile Include="Tests\TestCaseGameplayCursor.cs" />
|
||||
<Compile Include="Tests\TestCaseHitCircle.cs" />
|
||||
<Compile Include="Tests\TestCaseHitCircleHidden.cs" />
|
||||
<Compile Include="Tests\TestCasePerformancePoints.cs" />
|
||||
|
@ -167,7 +167,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
|
||||
using (var stream = new StreamReader(resStream))
|
||||
{
|
||||
var comboColors = decoder.Decode(stream).ComboColors;
|
||||
var comboColors = decoder.Decode(stream).ComboColours;
|
||||
|
||||
Color4[] expectedColors =
|
||||
{
|
||||
|
@ -102,9 +102,9 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
new Color4(255, 187, 255, 255),
|
||||
new Color4(255, 177, 140, 255),
|
||||
};
|
||||
Assert.AreEqual(expected.Length, beatmap.ComboColors.Count);
|
||||
Assert.AreEqual(expected.Length, beatmap.ComboColours.Count);
|
||||
for (int i = 0; i < expected.Length; i++)
|
||||
Assert.AreEqual(expected[i], beatmap.ComboColors[i]);
|
||||
Assert.AreEqual(expected[i], beatmap.ComboColours[i]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Add(new SkipButton(Clock.CurrentTime + 5000));
|
||||
Add(new SkipOverlay(Clock.CurrentTime + 5000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ using System.Linq;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.IO.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
using osu.Game.IO.Serialization.Converters;
|
||||
|
||||
namespace osu.Game.Beatmaps
|
||||
@ -16,14 +17,14 @@ namespace osu.Game.Beatmaps
|
||||
/// <summary>
|
||||
/// A Beatmap containing converted HitObjects.
|
||||
/// </summary>
|
||||
public class Beatmap<T> : IJsonSerializable
|
||||
public class Beatmap<T> : IJsonSerializable, IHasComboColours
|
||||
where T : HitObject
|
||||
{
|
||||
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
|
||||
public ControlPointInfo ControlPointInfo = new ControlPointInfo();
|
||||
public List<BreakPeriod> Breaks = new List<BreakPeriod>();
|
||||
|
||||
public List<Color4> ComboColors = new List<Color4>
|
||||
public List<Color4> ComboColours { get; set; } = new List<Color4>
|
||||
{
|
||||
new Color4(17, 136, 170, 255),
|
||||
new Color4(102, 136, 0, 255),
|
||||
@ -55,7 +56,7 @@ namespace osu.Game.Beatmaps
|
||||
BeatmapInfo = original?.BeatmapInfo.DeepClone() ?? BeatmapInfo;
|
||||
ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo;
|
||||
Breaks = original?.Breaks ?? Breaks;
|
||||
ComboColors = original?.ComboColors ?? ComboColors;
|
||||
ComboColours = original?.ComboColours ?? ComboColours;
|
||||
HitObjects = original?.HitObjects ?? HitObjects;
|
||||
|
||||
if (original == null && Metadata == null)
|
||||
|
@ -50,9 +50,14 @@ namespace osu.Game.Beatmaps
|
||||
protected virtual Beatmap<T> ConvertBeatmap(Beatmap original)
|
||||
{
|
||||
var beatmap = CreateBeatmap();
|
||||
|
||||
// todo: this *must* share logic (or directly use) Beatmap<T>'s constructor.
|
||||
// right now this isn't easily possible due to generic entanglement.
|
||||
beatmap.BeatmapInfo = original.BeatmapInfo;
|
||||
beatmap.ControlPointInfo = original.ControlPointInfo;
|
||||
beatmap.HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList();
|
||||
beatmap.Breaks = original.Breaks;
|
||||
beatmap.ComboColours = original.ComboColours;
|
||||
|
||||
return beatmap;
|
||||
}
|
||||
|
13
osu.Game/Beatmaps/Formats/IHasComboColours.cs
Normal file
13
osu.Game/Beatmaps/Formats/IHasComboColours.cs
Normal file
@ -0,0 +1,13 @@
|
||||
// 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 OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
public interface IHasComboColours
|
||||
{
|
||||
List<Color4> ComboColours { get; set; }
|
||||
}
|
||||
}
|
13
osu.Game/Beatmaps/Formats/IHasCustomColours.cs
Normal file
13
osu.Game/Beatmaps/Formats/IHasCustomColours.cs
Normal file
@ -0,0 +1,13 @@
|
||||
// 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 OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
public interface IHasCustomColours
|
||||
{
|
||||
Dictionary<string, Color4> CustomColours { get; set; }
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Rulesets.Objects.Legacy;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
@ -19,7 +18,6 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
private Beatmap beatmap;
|
||||
|
||||
private bool hasCustomColours;
|
||||
private ConvertHitObjectParser parser;
|
||||
|
||||
private LegacySampleBank defaultSampleBank;
|
||||
@ -72,29 +70,28 @@ namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
case Section.General:
|
||||
handleGeneral(line);
|
||||
break;
|
||||
return;
|
||||
case Section.Editor:
|
||||
handleEditor(line);
|
||||
break;
|
||||
return;
|
||||
case Section.Metadata:
|
||||
handleMetadata(line);
|
||||
break;
|
||||
return;
|
||||
case Section.Difficulty:
|
||||
handleDifficulty(line);
|
||||
break;
|
||||
return;
|
||||
case Section.Events:
|
||||
handleEvents(line);
|
||||
break;
|
||||
return;
|
||||
case Section.TimingPoints:
|
||||
handleTimingPoints(line);
|
||||
break;
|
||||
case Section.Colours:
|
||||
handleColours(line);
|
||||
break;
|
||||
return;
|
||||
case Section.HitObjects:
|
||||
handleHitObjects(line);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
base.ParseLine(beatmap, section, line);
|
||||
}
|
||||
|
||||
private void handleGeneral(string line)
|
||||
@ -364,38 +361,6 @@ namespace osu.Game.Beatmaps.Formats
|
||||
}
|
||||
}
|
||||
|
||||
private void handleColours(string line)
|
||||
{
|
||||
var pair = SplitKeyVal(line, ':');
|
||||
|
||||
string[] split = pair.Value.Split(',');
|
||||
|
||||
if (split.Length != 3)
|
||||
throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {pair.Value}");
|
||||
|
||||
byte r, g, b;
|
||||
if (!byte.TryParse(split[0], out r) || !byte.TryParse(split[1], out g) || !byte.TryParse(split[2], out b))
|
||||
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
|
||||
|
||||
if (!hasCustomColours)
|
||||
{
|
||||
beatmap.ComboColors.Clear();
|
||||
hasCustomColours = true;
|
||||
}
|
||||
|
||||
// Note: the combo index specified in the beatmap is discarded
|
||||
if (pair.Key.StartsWith(@"Combo"))
|
||||
{
|
||||
beatmap.ComboColors.Add(new Color4
|
||||
{
|
||||
R = r / 255f,
|
||||
G = g / 255f,
|
||||
B = b / 255f,
|
||||
A = 1f,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHitObjects(string line)
|
||||
{
|
||||
// If the ruleset wasn't specified, assume the osu!standard ruleset.
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
@ -40,7 +41,53 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//");
|
||||
|
||||
protected abstract void ParseLine(T output, Section section, string line);
|
||||
protected virtual void ParseLine(T output, Section section, string line)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case Section.Colours:
|
||||
handleColours(output, line);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private bool hasComboColours;
|
||||
|
||||
private void handleColours(T output, string line)
|
||||
{
|
||||
var pair = SplitKeyVal(line, ':');
|
||||
|
||||
bool isCombo = pair.Key.StartsWith(@"Combo");
|
||||
|
||||
string[] split = pair.Value.Split(',');
|
||||
|
||||
if (split.Length != 3)
|
||||
throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {pair.Value}");
|
||||
|
||||
if (!byte.TryParse(split[0], out var r) || !byte.TryParse(split[1], out var g) || !byte.TryParse(split[2], out var b))
|
||||
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
|
||||
|
||||
Color4 colour = new Color4(r, g, b, 255);
|
||||
|
||||
if (isCombo)
|
||||
{
|
||||
if (!(output is IHasComboColours tHasComboColours)) return;
|
||||
|
||||
if (!hasComboColours)
|
||||
{
|
||||
// remove default colours.
|
||||
tHasComboColours.ComboColours.Clear();
|
||||
hasComboColours = true;
|
||||
}
|
||||
|
||||
tHasComboColours.ComboColours.Add(colour);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(output is IHasCustomColours tHasCustomColours)) return;
|
||||
tHasCustomColours.CustomColours[pair.Key] = colour;
|
||||
}
|
||||
}
|
||||
|
||||
protected KeyValuePair<string, string> SplitKeyVal(string line, char separator)
|
||||
{
|
||||
@ -65,6 +112,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
Colours,
|
||||
HitObjects,
|
||||
Variables,
|
||||
Fonts
|
||||
}
|
||||
|
||||
internal enum LegacySampleBank
|
||||
|
@ -46,11 +46,13 @@ namespace osu.Game.Beatmaps.Formats
|
||||
{
|
||||
case Section.Events:
|
||||
handleEvents(line);
|
||||
break;
|
||||
return;
|
||||
case Section.Variables:
|
||||
handleVariables(line);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
base.ParseLine(storyboard, section, line);
|
||||
}
|
||||
|
||||
private void handleEvents(string line)
|
||||
|
@ -8,15 +8,17 @@ using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Online.API
|
||||
{
|
||||
public class APIAccess : IAPIProvider
|
||||
public class APIAccess : Component, IAPIProvider
|
||||
{
|
||||
private readonly OsuConfigManager config;
|
||||
private readonly OAuth authentication;
|
||||
|
||||
public string Endpoint = @"https://osu.ppy.sh";
|
||||
@ -25,13 +27,12 @@ namespace osu.Game.Online.API
|
||||
|
||||
private ConcurrentQueue<APIRequest> queue = new ConcurrentQueue<APIRequest>();
|
||||
|
||||
public Scheduler Scheduler = new Scheduler();
|
||||
/// <summary>
|
||||
/// The username/email provided by the user when initiating a login.
|
||||
/// </summary>
|
||||
public string ProvidedUsername { get; private set; }
|
||||
|
||||
public string Username;
|
||||
|
||||
//private SecurePassword password;
|
||||
|
||||
public string Password;
|
||||
private string password;
|
||||
|
||||
public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser());
|
||||
|
||||
@ -41,24 +42,31 @@ namespace osu.Game.Online.API
|
||||
set { authentication.Token = string.IsNullOrEmpty(value) ? null : OAuthToken.Parse(value); }
|
||||
}
|
||||
|
||||
protected bool HasLogin => Token != null || !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
|
||||
protected bool HasLogin => Token != null || !string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password);
|
||||
|
||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (should dispose of this or at very least keep a reference).
|
||||
private readonly Thread thread;
|
||||
|
||||
private readonly Logger log;
|
||||
|
||||
public APIAccess()
|
||||
public APIAccess(OsuConfigManager config)
|
||||
{
|
||||
this.config = config;
|
||||
|
||||
authentication = new OAuth(client_id, client_secret, Endpoint);
|
||||
log = Logger.GetLogger(LoggingTarget.Network);
|
||||
|
||||
ProvidedUsername = config.Get<string>(OsuSetting.Username);
|
||||
Token = config.Get<string>(OsuSetting.Token);
|
||||
|
||||
thread = new Thread(run) { IsBackground = true };
|
||||
thread.Start();
|
||||
}
|
||||
|
||||
private readonly List<IOnlineComponent> components = new List<IOnlineComponent>();
|
||||
|
||||
internal void Schedule(Action action) => base.Schedule(action);
|
||||
|
||||
public void Register(IOnlineComponent component)
|
||||
{
|
||||
Scheduler.Add(delegate
|
||||
@ -111,12 +119,15 @@ namespace osu.Game.Online.API
|
||||
|
||||
State = APIState.Connecting;
|
||||
|
||||
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password))
|
||||
// save the username at this point, if the user requested for it to be.
|
||||
config.Set(OsuSetting.Username, config.Get<bool>(OsuSetting.SaveUsername) ? ProvidedUsername : string.Empty);
|
||||
|
||||
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(ProvidedUsername, password))
|
||||
{
|
||||
//todo: this fails even on network-related issues. we should probably handle those differently.
|
||||
//NotificationOverlay.ShowMessage("Login failed!");
|
||||
log.Add(@"Login failed!");
|
||||
Password = null;
|
||||
password = null;
|
||||
authentication.Clear();
|
||||
continue;
|
||||
}
|
||||
@ -173,8 +184,8 @@ namespace osu.Game.Online.API
|
||||
{
|
||||
Debug.Assert(State == APIState.Offline);
|
||||
|
||||
Username = username;
|
||||
Password = password;
|
||||
ProvidedUsername = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -283,8 +294,8 @@ namespace osu.Game.Online.API
|
||||
public void Logout(bool clearUsername = true)
|
||||
{
|
||||
flushQueue();
|
||||
if (clearUsername) Username = null;
|
||||
Password = null;
|
||||
if (clearUsername) ProvidedUsername = null;
|
||||
password = null;
|
||||
authentication.Clear();
|
||||
LocalUser.Value = createGuestUser();
|
||||
}
|
||||
@ -295,9 +306,12 @@ namespace osu.Game.Online.API
|
||||
Id = 1,
|
||||
};
|
||||
|
||||
public void Update()
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
Scheduler.Update();
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
config.Set(OsuSetting.Token, config.Get<bool>(OsuSetting.SavePassword) ? Token : string.Empty);
|
||||
config.Save();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Online.API
|
||||
return request;
|
||||
}
|
||||
|
||||
private void request_Progress(long current, long total) => API.Scheduler.Add(delegate { Progress?.Invoke(current, total); });
|
||||
private void request_Progress(long current, long total) => API.Schedule(() => Progress?.Invoke(current, total));
|
||||
|
||||
protected APIDownloadRequest()
|
||||
{
|
||||
|
@ -85,7 +85,7 @@ namespace osu.Game.Online.API
|
||||
if (checkAndProcessFailure())
|
||||
return;
|
||||
|
||||
api.Scheduler.Add(delegate { Success?.Invoke(); });
|
||||
api.Schedule(delegate { Success?.Invoke(); });
|
||||
}
|
||||
|
||||
public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled"));
|
||||
@ -108,7 +108,7 @@ namespace osu.Game.Online.API
|
||||
{
|
||||
if (API == null || pendingFailure == null) return cancelled;
|
||||
|
||||
API.Scheduler.Add(pendingFailure);
|
||||
API.Schedule(pendingFailure);
|
||||
pendingFailure = null;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Online.API
|
||||
{
|
||||
public interface IAPIProvider : IUpdateable
|
||||
public interface IAPIProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The local user.
|
||||
|
@ -34,7 +34,7 @@ using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game
|
||||
{
|
||||
public class OsuGameBase : Framework.Game, IOnlineComponent, ICanAcceptFiles
|
||||
public class OsuGameBase : Framework.Game, ICanAcceptFiles
|
||||
{
|
||||
protected OsuConfigManager LocalConfig;
|
||||
|
||||
@ -56,8 +56,6 @@ namespace osu.Game
|
||||
|
||||
protected override string MainResourceFile => @"osu.Game.Resources.dll";
|
||||
|
||||
public APIAccess API;
|
||||
|
||||
private Container content;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
@ -108,16 +106,14 @@ namespace osu.Game
|
||||
|
||||
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
|
||||
|
||||
dependencies.Cache(API = new APIAccess
|
||||
{
|
||||
Username = LocalConfig.Get<string>(OsuSetting.Username),
|
||||
Token = LocalConfig.Get<string>(OsuSetting.Token)
|
||||
});
|
||||
dependencies.CacheAs<IAPIProvider>(API);
|
||||
var api = new APIAccess(LocalConfig);
|
||||
|
||||
dependencies.Cache(api);
|
||||
dependencies.CacheAs<IAPIProvider>(api);
|
||||
|
||||
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory));
|
||||
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
|
||||
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Host));
|
||||
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Host));
|
||||
dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore));
|
||||
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
|
||||
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
|
||||
@ -183,9 +179,9 @@ namespace osu.Game
|
||||
lastBeatmap = b;
|
||||
};
|
||||
|
||||
API.Register(this);
|
||||
|
||||
FileStore.Cleanup();
|
||||
|
||||
AddInternal(api);
|
||||
}
|
||||
|
||||
private void runMigrations()
|
||||
@ -211,16 +207,6 @@ namespace osu.Game
|
||||
|
||||
private WorkingBeatmap lastBeatmap;
|
||||
|
||||
public void APIStateChanged(APIAccess api, APIState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case APIState.Online:
|
||||
LocalConfig.Set(OsuSetting.Username, LocalConfig.Get<bool>(OsuSetting.SaveUsername) ? API.Username : string.Empty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -253,24 +239,6 @@ namespace osu.Game
|
||||
base.SetHost(host);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
API.Update();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
//refresh token may have changed.
|
||||
if (LocalConfig != null && API != null)
|
||||
{
|
||||
LocalConfig.Set(OsuSetting.Token, LocalConfig.Get<bool>(OsuSetting.SavePassword) ? API.Token : string.Empty);
|
||||
LocalConfig.Save();
|
||||
}
|
||||
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
|
||||
private readonly List<ICanAcceptFiles> fileImporters = new List<ICanAcceptFiles>();
|
||||
|
||||
public void Import(params string[] paths)
|
||||
|
@ -186,7 +186,7 @@ namespace osu.Game.Overlays.Direct
|
||||
progressBar.FadeOut(500);
|
||||
};
|
||||
|
||||
request.DownloadProgressed += progress => progressBar.Current.Value = progress;
|
||||
request.DownloadProgressed += progress => Schedule(() => progressBar.Current.Value = progress);
|
||||
|
||||
request.Success += data =>
|
||||
{
|
||||
|
@ -210,7 +210,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
||||
{
|
||||
PlaceholderText = "Email address",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Text = api?.Username ?? string.Empty,
|
||||
Text = api?.ProvidedUsername ?? string.Empty,
|
||||
TabbableContentContainer = this
|
||||
},
|
||||
password = new OsuPasswordTextBox
|
||||
|
@ -18,7 +18,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public abstract class GameplayMenuOverlay : OverlayContainer, IRequireHighFrequencyMousePosition
|
||||
public abstract class GameplayMenuOverlay : OverlayContainer
|
||||
{
|
||||
private const int transition_duration = 200;
|
||||
private const int button_height = 70;
|
||||
|
@ -164,7 +164,7 @@ namespace osu.Game.Screens.Play
|
||||
Alpha = 0,
|
||||
},
|
||||
RulesetContainer,
|
||||
new SkipButton(firstObjectTime)
|
||||
new SkipOverlay(firstObjectTime)
|
||||
{
|
||||
Clock = Clock, // skip button doesn't want to use the audio clock directly
|
||||
ProcessCustomClock = false,
|
||||
|
@ -5,12 +5,14 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using OpenTK;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
|
||||
@ -21,7 +23,6 @@ namespace osu.Game.Screens.Play
|
||||
private Player player;
|
||||
|
||||
private BeatmapMetadataDisplay info;
|
||||
private VisualSettings visualSettings;
|
||||
|
||||
private bool showOverlays = true;
|
||||
public override bool ShowOverlaysOnEnter => showOverlays;
|
||||
@ -46,7 +47,8 @@ namespace osu.Game.Screens.Play
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
Add(visualSettings = new VisualSettings
|
||||
|
||||
Add(new VisualSettings
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
@ -93,7 +95,7 @@ namespace osu.Game.Screens.Play
|
||||
contentIn();
|
||||
|
||||
info.Delay(750).FadeIn(500);
|
||||
this.Delay(2150).Schedule(pushWhenLoaded);
|
||||
this.Delay(1800).Schedule(pushWhenLoaded);
|
||||
}
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
@ -109,29 +111,65 @@ namespace osu.Game.Screens.Play
|
||||
logo.Delay(resuming ? 0 : 500).MoveToOffset(new Vector2(0, -0.24f), 500, Easing.InOutExpo);
|
||||
}
|
||||
|
||||
private bool weHandledMouseDown;
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
{
|
||||
weHandledMouseDown = true;
|
||||
return base.OnMouseDown(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
weHandledMouseDown = false;
|
||||
return base.OnMouseUp(state, args);
|
||||
}
|
||||
|
||||
private ScheduledDelegate pushDebounce;
|
||||
|
||||
private bool readyForPush => player.LoadState == LoadState.Ready && IsHovered && (!GetContainingInputManager().CurrentState.Mouse.HasAnyButtonPressed || weHandledMouseDown);
|
||||
|
||||
private void pushWhenLoaded()
|
||||
{
|
||||
if (player.LoadState != LoadState.Ready || visualSettings.IsHovered)
|
||||
if (!IsCurrentScreen) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (!readyForPush)
|
||||
{
|
||||
// as the pushDebounce below has a delay, we need to keep checking and cancel a future debounce
|
||||
// if we become unready for push during the delay.
|
||||
pushDebounce?.Cancel();
|
||||
pushDebounce = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pushDebounce != null)
|
||||
return;
|
||||
|
||||
pushDebounce = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
contentOut();
|
||||
|
||||
this.Delay(250).Schedule(() =>
|
||||
{
|
||||
if (!IsCurrentScreen) return;
|
||||
|
||||
if (!Push(player))
|
||||
Exit();
|
||||
else
|
||||
{
|
||||
//By default, we want to load the player and never be returned to.
|
||||
//Note that this may change if the player we load requested a re-run.
|
||||
ValidForResume = false;
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Schedule(pushWhenLoaded);
|
||||
return;
|
||||
}
|
||||
|
||||
contentOut();
|
||||
|
||||
this.Delay(250).Schedule(() =>
|
||||
{
|
||||
if (!IsCurrentScreen) return;
|
||||
|
||||
if (!Push(player))
|
||||
Exit();
|
||||
else
|
||||
{
|
||||
//By default, we want to load the player and never be returned to.
|
||||
//Note that this may change if the player we load requested a re-run.
|
||||
ValidForResume = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override bool OnExiting(Screen next)
|
||||
|
@ -5,6 +5,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -133,5 +134,8 @@ namespace osu.Game.Screens.Play.PlayerSettings
|
||||
}
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
protected override bool OnHover(InputState state) => true;
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ using osu.Game.Input.Bindings;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class SkipButton : OverlayContainer, IKeyBindingHandler<GlobalAction>
|
||||
public class SkipOverlay : OverlayContainer, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
private readonly double startTime;
|
||||
|
||||
@ -35,8 +35,9 @@ namespace osu.Game.Screens.Play
|
||||
private double displayTime;
|
||||
|
||||
public override bool ReceiveMouseInputAt(Vector2 screenSpacePos) => true;
|
||||
protected override bool BlockPassThroughMouse => false;
|
||||
|
||||
public SkipButton(double startTime)
|
||||
public SkipOverlay(double startTime)
|
||||
{
|
||||
this.startTime = startTime;
|
||||
|
||||
@ -51,12 +52,6 @@ namespace osu.Game.Screens.Play
|
||||
Origin = Anchor.Centre;
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(InputState state)
|
||||
{
|
||||
fadeContainer.State = Visibility.Visible;
|
||||
return base.OnMouseMove(state);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
@ -121,15 +116,9 @@ namespace osu.Game.Screens.Play
|
||||
Expire();
|
||||
}
|
||||
|
||||
protected override void PopIn()
|
||||
{
|
||||
this.FadeIn();
|
||||
}
|
||||
protected override void PopIn() => this.FadeIn();
|
||||
|
||||
protected override void PopOut()
|
||||
{
|
||||
this.FadeOut();
|
||||
}
|
||||
protected override void PopOut() => this.FadeOut();
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
@ -137,6 +126,13 @@ namespace osu.Game.Screens.Play
|
||||
remainingTimeBox.ResizeWidthTo((float)Math.Max(0, 1 - (Time.Current - displayTime) / (beginFadeTime - displayTime)), 120, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(InputState state)
|
||||
{
|
||||
if (!state.Mouse.HasAnyButtonPressed)
|
||||
fadeContainer.State = Visibility.Visible;
|
||||
return base.OnMouseMove(state);
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
{
|
||||
switch (action)
|
||||
@ -176,7 +172,7 @@ namespace osu.Game.Screens.Play
|
||||
if (stateChanged)
|
||||
this.FadeIn(500, Easing.OutExpo);
|
||||
|
||||
if (!IsHovered)
|
||||
if (!IsHovered && !IsDragged)
|
||||
using (BeginDelayedSequence(1000))
|
||||
scheduledHide = Schedule(() => State = Visibility.Hidden);
|
||||
break;
|
||||
@ -194,6 +190,18 @@ namespace osu.Game.Screens.Play
|
||||
base.LoadComplete();
|
||||
State = Visibility.Visible;
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(InputState state, MouseDownEventArgs args)
|
||||
{
|
||||
scheduledHide?.Cancel();
|
||||
return base.OnMouseDown(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnMouseUp(InputState state, MouseUpEventArgs args)
|
||||
{
|
||||
State = Visibility.Visible;
|
||||
return base.OnMouseUp(state, args);
|
||||
}
|
||||
}
|
||||
|
||||
private class Button : OsuClickableContainer
|
||||
@ -274,7 +282,7 @@ namespace osu.Game.Screens.Play
|
||||
flow.TransformSpacingTo(new Vector2(5), 500, Easing.OutQuint);
|
||||
box.FadeColour(colourHover, 500, Easing.OutQuint);
|
||||
background.FadeTo(0.4f, 500, Easing.OutQuint);
|
||||
return base.OnHover(state);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
@ -267,6 +267,8 @@
|
||||
<Compile Include="Beatmaps\DifficultyCalculator.cs" />
|
||||
<Compile Include="Beatmaps\Drawables\BeatmapBackgroundSprite.cs" />
|
||||
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.cs" />
|
||||
<Compile Include="Beatmaps\Formats\IHasComboColours.cs" />
|
||||
<Compile Include="Beatmaps\Formats\IHasCustomColours.cs" />
|
||||
<Compile Include="Beatmaps\Formats\JsonBeatmapDecoder.cs" />
|
||||
<Compile Include="Beatmaps\Formats\LegacyDecoder.cs" />
|
||||
<Compile Include="Beatmaps\Formats\LegacyStoryboardDecoder.cs" />
|
||||
@ -809,7 +811,7 @@
|
||||
<Compile Include="Screens\Play\PlayerSettings\PlayerCheckbox.cs" />
|
||||
<Compile Include="Screens\Play\PlayerSettings\PlayerSettingsGroup.cs" />
|
||||
<Compile Include="Screens\Play\PlayerSettings\PlayerSliderBar.cs" />
|
||||
<Compile Include="Screens\Play\SkipButton.cs" />
|
||||
<Compile Include="Screens\Play\SkipOverlay.cs" />
|
||||
<Compile Include="Screens\Play\SongProgress.cs" />
|
||||
<Compile Include="Screens\Play\SongProgressBar.cs" />
|
||||
<Compile Include="Screens\Play\SongProgressGraph.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user