Merge remote-tracking branch 'origin/master' into netstandard

This commit is contained in:
smoogipoo
2018-03-24 14:49:46 +09:00
465 changed files with 12513 additions and 4969 deletions

View File

@ -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);
@ -163,7 +168,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private class TrailDrawNodeSharedData
{
public VertexBuffer<TexturedVertex2D> VertexBuffer;
public VertexBuffer<TexturedTrailVertex> VertexBuffer;
}
private class TrailDrawNode : DrawNode
@ -189,7 +194,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;
@ -206,17 +211,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;
}
@ -241,5 +248,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);
}
}
}
}

View File

@ -11,6 +11,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Bindings;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Skinning;
using OpenTK;
using OpenTK.Graphics;
@ -20,118 +21,24 @@ 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 class OsuCursor : Container
{
private Container cursorContainer;
private Bindable<double> cursorScale;
private Bindable<bool> autoCursorScale;
private Bindable<WorkingBeatmap> beatmap;
public OsuCursor()
{
Origin = Anchor.Centre;
Size = new Vector2(42);
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config, OsuGameBase game)
{
Children = new Drawable[]
{
cursorContainer = new CircularContainer
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderThickness = Size.X / 6,
BorderColour = Color4.White,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Pink.Opacity(0.5f),
Radius = 5,
},
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true,
},
new CircularContainer
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderThickness = Size.X / 3,
BorderColour = Color4.White.Opacity(0.5f),
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true,
},
},
},
new CircularContainer
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.1f),
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.White,
},
},
},
}
},
};
beatmap = game.Beatmap.GetBoundCopy();
beatmap.ValueChanged += v => calculateScale();
cursorScale = config.GetBindable<double>(OsuSetting.GameplayCursorSize);
cursorScale.ValueChanged += v => calculateScale();
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
autoCursorScale.ValueChanged += v => calculateScale();
calculateScale();
}
private void calculateScale()
{
float scale = (float)cursorScale.Value;
if (autoCursorScale && beatmap.Value != null)
{
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY);
}
cursorContainer.Scale = new Vector2(scale);
}
}
public bool OnPressed(OsuAction action)
{
switch (action)
@ -160,16 +67,123 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
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()
{
ActiveCursor.FadeTo(1, 250, Easing.OutQuint);
fadeContainer.FadeTo(1, 300, 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);
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint);
}
public class OsuCursor : Container
{
private Drawable cursorContainer;
private Bindable<double> cursorScale;
private Bindable<bool> autoCursorScale;
private Bindable<WorkingBeatmap> beatmap;
public OsuCursor()
{
Origin = Anchor.Centre;
Size = new Vector2(42);
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config, OsuGameBase game)
{
Child = cursorContainer = new SkinnableDrawable("cursor", _ => new CircularContainer
{
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderThickness = Size.X / 6,
BorderColour = Color4.White,
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = Color4.Pink.Opacity(0.5f),
Radius = 5,
},
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true,
},
new CircularContainer
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Masking = true,
BorderThickness = Size.X / 3,
BorderColour = Color4.White.Opacity(0.5f),
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Alpha = 0,
AlwaysPresent = true,
},
},
},
new CircularContainer
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
Scale = new Vector2(0.1f),
Masking = true,
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.White,
},
},
},
}
}, restrictSize: false)
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
};
beatmap = game.Beatmap.GetBoundCopy();
beatmap.ValueChanged += v => calculateScale();
cursorScale = config.GetBindable<double>(OsuSetting.GameplayCursorSize);
cursorScale.ValueChanged += v => calculateScale();
autoCursorScale = config.GetBindable<bool>(OsuSetting.AutoCursorSize);
autoCursorScale.ValueChanged += v => calculateScale();
calculateScale();
}
private void calculateScale()
{
float scale = (float)cursorScale.Value;
if (autoCursorScale && beatmap.Value != null)
{
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
scale *= (float)(1 - 0.7 * (1 + beatmap.Value.BeatmapInfo.BaseDifficulty.CircleSize - BeatmapDifficulty.DEFAULT_DIFFICULTY) / BeatmapDifficulty.DEFAULT_DIFFICULTY);
}
cursorContainer.Scale = new Vector2(scale);
}
}
}
}