mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 01:02:55 +08:00
Merge remote-tracking branch 'upstream/master' into direct-previews
This commit is contained in:
commit
f9a1240325
23
.vscode/launch.json
vendored
23
.vscode/launch.json
vendored
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [{
|
"configurations": [{
|
||||||
"name": "osu! (VisualTests)",
|
"name": "osu! VisualTests (Debug)",
|
||||||
"windows": {
|
"windows": {
|
||||||
"type": "clr"
|
"type": "clr"
|
||||||
},
|
},
|
||||||
@ -18,7 +18,24 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "osu! (debug)",
|
"name": "osu! VisualTests (Release)",
|
||||||
|
"windows": {
|
||||||
|
"type": "clr"
|
||||||
|
},
|
||||||
|
"type": "mono",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/osu.Game/bin/Release/osu!.exe",
|
||||||
|
"args": [
|
||||||
|
"--tests"
|
||||||
|
],
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"preLaunchTask": "Build (Release)",
|
||||||
|
"runtimeExecutable": null,
|
||||||
|
"env": {},
|
||||||
|
"console": "internalConsole"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "osu! (Debug)",
|
||||||
"windows": {
|
"windows": {
|
||||||
"type": "clr"
|
"type": "clr"
|
||||||
},
|
},
|
||||||
@ -32,7 +49,7 @@
|
|||||||
"console": "internalConsole"
|
"console": "internalConsole"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "osu! (release)",
|
"name": "osu! (Release)",
|
||||||
"windows": {
|
"windows": {
|
||||||
"type": "clr"
|
"type": "clr"
|
||||||
},
|
},
|
||||||
|
1
.vscode/tasks.json
vendored
1
.vscode/tasks.json
vendored
@ -23,6 +23,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"taskName": "Build (Release)",
|
"taskName": "Build (Release)",
|
||||||
|
"group": "build",
|
||||||
"args": [
|
"args": [
|
||||||
"/property:Configuration=Release"
|
"/property:Configuration=Release"
|
||||||
],
|
],
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit ef889b4ec7e6175d52d64411c15f4f195fd16209
|
Subproject commit 255b94f5dde0188db1a5b37daf9649659e2b8366
|
@ -5,9 +5,9 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Catch.Objects;
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System;
|
using System;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Beatmaps
|
namespace osu.Game.Rulesets.Catch.Beatmaps
|
||||||
{
|
{
|
||||||
@ -17,14 +17,37 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
|
|||||||
|
|
||||||
protected override IEnumerable<CatchBaseHit> ConvertHitObject(HitObject obj, Beatmap beatmap)
|
protected override IEnumerable<CatchBaseHit> ConvertHitObject(HitObject obj, Beatmap beatmap)
|
||||||
{
|
{
|
||||||
if (!(obj is IHasXPosition))
|
var curveData = obj as IHasCurve;
|
||||||
|
var positionData = obj as IHasPosition;
|
||||||
|
var comboData = obj as IHasCombo;
|
||||||
|
|
||||||
|
if (positionData == null)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
|
if (curveData != null)
|
||||||
|
{
|
||||||
|
yield return new JuiceStream
|
||||||
|
{
|
||||||
|
StartTime = obj.StartTime,
|
||||||
|
Samples = obj.Samples,
|
||||||
|
ControlPoints = curveData.ControlPoints,
|
||||||
|
CurveType = curveData.CurveType,
|
||||||
|
Distance = curveData.Distance,
|
||||||
|
RepeatSamples = curveData.RepeatSamples,
|
||||||
|
RepeatCount = curveData.RepeatCount,
|
||||||
|
X = positionData.X / CatchPlayfield.BASE_WIDTH,
|
||||||
|
NewCombo = comboData?.NewCombo ?? false
|
||||||
|
};
|
||||||
|
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
yield return new Fruit
|
yield return new Fruit
|
||||||
{
|
{
|
||||||
StartTime = obj.StartTime,
|
StartTime = obj.StartTime,
|
||||||
NewCombo = (obj as IHasCombo)?.NewCombo ?? false,
|
Samples = obj.Samples,
|
||||||
X = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X
|
NewCombo = comboData?.NewCombo ?? false,
|
||||||
|
X = positionData.X / CatchPlayfield.BASE_WIDTH
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
|
{
|
||||||
|
public abstract class DrawableCatchHitObject<TObject> : DrawableCatchHitObject
|
||||||
|
where TObject : CatchBaseHit
|
||||||
|
{
|
||||||
|
public new TObject HitObject;
|
||||||
|
|
||||||
|
protected DrawableCatchHitObject(TObject hitObject)
|
||||||
|
: base(hitObject)
|
||||||
|
{
|
||||||
|
HitObject = hitObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class DrawableCatchHitObject : DrawableScrollingHitObject<CatchBaseHit>
|
||||||
|
{
|
||||||
|
protected DrawableCatchHitObject(CatchBaseHit hitObject)
|
||||||
|
: base(hitObject)
|
||||||
|
{
|
||||||
|
RelativePositionAxes = Axes.Both;
|
||||||
|
X = hitObject.X;
|
||||||
|
Y = (float)HitObject.StartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Func<CatchBaseHit, bool> CheckPosition;
|
||||||
|
|
||||||
|
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
||||||
|
{
|
||||||
|
if (timeOffset > 0)
|
||||||
|
AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss });
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float preempt = 1000;
|
||||||
|
|
||||||
|
protected override void UpdateState(ArmedState state)
|
||||||
|
{
|
||||||
|
using (BeginAbsoluteSequence(HitObject.StartTime - preempt))
|
||||||
|
{
|
||||||
|
// animation
|
||||||
|
this.FadeIn(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case ArmedState.Miss:
|
||||||
|
using (BeginAbsoluteSequence(HitObject.StartTime, true))
|
||||||
|
this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs
Normal file
34
osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
|
{
|
||||||
|
public class DrawableDroplet : DrawableCatchHitObject<Droplet>
|
||||||
|
{
|
||||||
|
public DrawableDroplet(Droplet h)
|
||||||
|
: base(h)
|
||||||
|
{
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
Size = new Vector2(Pulp.PULP_SIZE);
|
||||||
|
|
||||||
|
AccentColour = h.ComboColour;
|
||||||
|
Masking = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Child = new Pulp
|
||||||
|
{
|
||||||
|
AccentColour = AccentColour,
|
||||||
|
Scale = new Vector2(0.8f),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,72 +1,29 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
{
|
{
|
||||||
public class DrawableFruit : DrawableScrollingHitObject<CatchBaseHit>
|
public class DrawableFruit : DrawableCatchHitObject<Fruit>
|
||||||
{
|
{
|
||||||
private const float pulp_size = 20;
|
public DrawableFruit(Fruit h)
|
||||||
|
|
||||||
private class Pulp : Circle, IHasAccentColour
|
|
||||||
{
|
|
||||||
public Pulp()
|
|
||||||
{
|
|
||||||
Size = new Vector2(pulp_size);
|
|
||||||
|
|
||||||
Blending = BlendingMode.Additive;
|
|
||||||
Colour = Color4.White.Opacity(0.9f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color4 accentColour;
|
|
||||||
public Color4 AccentColour
|
|
||||||
{
|
|
||||||
get { return accentColour; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
accentColour = value;
|
|
||||||
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Radius = 5,
|
|
||||||
Colour = accentColour.Lighten(100),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public DrawableFruit(CatchBaseHit h)
|
|
||||||
: base(h)
|
: base(h)
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
Size = new Vector2(pulp_size * 2.2f, pulp_size * 2.8f);
|
|
||||||
|
|
||||||
RelativePositionAxes = Axes.Both;
|
|
||||||
X = h.X;
|
|
||||||
|
|
||||||
|
Size = new Vector2(Pulp.PULP_SIZE * 2.2f, Pulp.PULP_SIZE * 2.8f);
|
||||||
AccentColour = HitObject.ComboColour;
|
AccentColour = HitObject.ComboColour;
|
||||||
|
|
||||||
Masking = false;
|
Masking = false;
|
||||||
|
|
||||||
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<CatchBaseHit, bool> CheckPosition;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
@ -114,30 +71,5 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private const float preempt = 1000;
|
|
||||||
|
|
||||||
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
|
|
||||||
{
|
|
||||||
if (timeOffset > 0)
|
|
||||||
AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss });
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateState(ArmedState state)
|
|
||||||
{
|
|
||||||
using (BeginAbsoluteSequence(HitObject.StartTime - preempt))
|
|
||||||
{
|
|
||||||
// animation
|
|
||||||
this.FadeIn(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case ArmedState.Miss:
|
|
||||||
using (BeginAbsoluteSequence(HitObject.StartTime, true))
|
|
||||||
this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||||
|
{
|
||||||
|
public class DrawableJuiceStream : DrawableCatchHitObject<JuiceStream>
|
||||||
|
{
|
||||||
|
private readonly Container dropletContainer;
|
||||||
|
|
||||||
|
public DrawableJuiceStream(JuiceStream s) : base(s)
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Height = (float)HitObject.Duration;
|
||||||
|
X = 0;
|
||||||
|
|
||||||
|
Child = dropletContainer = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime),
|
||||||
|
RelativeChildSize = new Vector2(1, (float)HitObject.Duration)
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (CatchBaseHit tick in s.Ticks)
|
||||||
|
{
|
||||||
|
TinyDroplet tiny = tick as TinyDroplet;
|
||||||
|
if (tiny != null)
|
||||||
|
{
|
||||||
|
AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Droplet droplet = tick as Droplet;
|
||||||
|
if (droplet != null)
|
||||||
|
AddNested(new DrawableDroplet(droplet));
|
||||||
|
|
||||||
|
Fruit fruit = tick as Fruit;
|
||||||
|
if (fruit != null)
|
||||||
|
AddNested(new DrawableFruit(fruit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddNested(DrawableHitObject<CatchBaseHit> h)
|
||||||
|
{
|
||||||
|
((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
|
||||||
|
dropletContainer.Add(h);
|
||||||
|
base.AddNested(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs
Normal file
43
osu.Game.Rulesets.Catch/Objects/Drawable/Pieces/Pulp.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
|
||||||
|
{
|
||||||
|
public class Pulp : Circle, IHasAccentColour
|
||||||
|
{
|
||||||
|
public const float PULP_SIZE = 20;
|
||||||
|
|
||||||
|
public Pulp()
|
||||||
|
{
|
||||||
|
Size = new Vector2(PULP_SIZE);
|
||||||
|
|
||||||
|
Blending = BlendingMode.Additive;
|
||||||
|
Colour = Color4.White.Opacity(0.9f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4 accentColour;
|
||||||
|
public Color4 AccentColour
|
||||||
|
{
|
||||||
|
get { return accentColour; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
accentColour = value;
|
||||||
|
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Radius = 5,
|
||||||
|
Colour = accentColour.Lighten(100),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
169
osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
Normal file
169
osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Rulesets.Catch.UI;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Lists;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects
|
||||||
|
{
|
||||||
|
public class JuiceStream : CatchBaseHit, IHasCurve
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Positional distance that results in a duration of one second, before any speed adjustments.
|
||||||
|
/// </summary>
|
||||||
|
private const float base_scoring_distance = 100;
|
||||||
|
|
||||||
|
public readonly SliderCurve Curve = new SliderCurve();
|
||||||
|
|
||||||
|
public int RepeatCount { get; set; } = 1;
|
||||||
|
|
||||||
|
public double Velocity;
|
||||||
|
public double TickDistance;
|
||||||
|
|
||||||
|
public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
base.ApplyDefaults(controlPointInfo, difficulty);
|
||||||
|
|
||||||
|
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||||
|
DifficultyControlPoint difficultyPoint = controlPointInfo.DifficultyPointAt(StartTime);
|
||||||
|
|
||||||
|
double scoringDistance = base_scoring_distance * difficulty.SliderMultiplier * difficultyPoint.SpeedMultiplier;
|
||||||
|
|
||||||
|
Velocity = scoringDistance / timingPoint.BeatLength;
|
||||||
|
TickDistance = scoringDistance / difficulty.SliderTickRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CatchBaseHit> Ticks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
SortedList<CatchBaseHit> ticks = new SortedList<CatchBaseHit>((a, b) => a.StartTime.CompareTo(b.StartTime));
|
||||||
|
|
||||||
|
if (TickDistance == 0)
|
||||||
|
return ticks;
|
||||||
|
|
||||||
|
var length = Curve.Distance;
|
||||||
|
var tickDistance = Math.Min(TickDistance, length);
|
||||||
|
var repeatDuration = length / Velocity;
|
||||||
|
|
||||||
|
var minDistanceFromEnd = Velocity * 0.01;
|
||||||
|
|
||||||
|
ticks.Add(new Fruit
|
||||||
|
{
|
||||||
|
Samples = Samples,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
StartTime = StartTime,
|
||||||
|
X = X
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var repeat = 0; repeat < RepeatCount; repeat++)
|
||||||
|
{
|
||||||
|
var repeatStartTime = StartTime + repeat * repeatDuration;
|
||||||
|
var reversed = repeat % 2 == 1;
|
||||||
|
|
||||||
|
for (var d = tickDistance; d <= length; d += tickDistance)
|
||||||
|
{
|
||||||
|
if (d > length - minDistanceFromEnd)
|
||||||
|
break;
|
||||||
|
|
||||||
|
var timeProgress = d / length;
|
||||||
|
var distanceProgress = reversed ? 1 - timeProgress : timeProgress;
|
||||||
|
|
||||||
|
var lastTickTime = repeatStartTime + timeProgress * repeatDuration;
|
||||||
|
ticks.Add(new Droplet
|
||||||
|
{
|
||||||
|
StartTime = lastTickTime,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
X = Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
|
||||||
|
Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
|
||||||
|
{
|
||||||
|
Bank = s.Bank,
|
||||||
|
Name = @"slidertick",
|
||||||
|
Volume = s.Volume
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
double tinyTickInterval = tickDistance / length * repeatDuration;
|
||||||
|
while (tinyTickInterval > 100)
|
||||||
|
tinyTickInterval /= 2;
|
||||||
|
|
||||||
|
for (double t = 0; t < repeatDuration; t += tinyTickInterval)
|
||||||
|
{
|
||||||
|
double progress = reversed ? 1 - t / repeatDuration : t / repeatDuration;
|
||||||
|
|
||||||
|
ticks.Add(new TinyDroplet
|
||||||
|
{
|
||||||
|
StartTime = repeatStartTime + t,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
X = Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
|
||||||
|
Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
|
||||||
|
{
|
||||||
|
Bank = s.Bank,
|
||||||
|
Name = @"slidertick",
|
||||||
|
Volume = s.Volume
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ticks.Add(new Fruit
|
||||||
|
{
|
||||||
|
Samples = Samples,
|
||||||
|
ComboColour = ComboColour,
|
||||||
|
StartTime = repeatStartTime + repeatDuration,
|
||||||
|
X = Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity;
|
||||||
|
|
||||||
|
public float EndX => Curve.PositionAt(ProgressAt(1)).X / CatchPlayfield.BASE_WIDTH;
|
||||||
|
|
||||||
|
public double Duration => EndTime - StartTime;
|
||||||
|
|
||||||
|
public double Distance
|
||||||
|
{
|
||||||
|
get { return Curve.Distance; }
|
||||||
|
set { Curve.Distance = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Vector2> ControlPoints
|
||||||
|
{
|
||||||
|
get { return Curve.ControlPoints; }
|
||||||
|
set { Curve.ControlPoints = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SampleInfoList> RepeatSamples { get; set; } = new List<SampleInfoList>();
|
||||||
|
|
||||||
|
public CurveType CurveType
|
||||||
|
{
|
||||||
|
get { return Curve.CurveType; }
|
||||||
|
set { Curve.CurveType = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 PositionAt(double progress) => Curve.PositionAt(ProgressAt(progress));
|
||||||
|
|
||||||
|
public double ProgressAt(double progress)
|
||||||
|
{
|
||||||
|
double p = progress * RepeatCount % 1;
|
||||||
|
if (RepeatAt(progress) % 2 == 1)
|
||||||
|
p = 1 - p;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RepeatAt(double progress) => (int)(progress * RepeatCount);
|
||||||
|
}
|
||||||
|
}
|
9
osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs
Normal file
9
osu.Game.Rulesets.Catch/Objects/TinyDroplet.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Objects
|
||||||
|
{
|
||||||
|
public class TinyDroplet : Droplet
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,19 @@ namespace osu.Game.Rulesets.Catch.Scoring
|
|||||||
{
|
{
|
||||||
foreach (var obj in beatmap.HitObjects)
|
foreach (var obj in beatmap.HitObjects)
|
||||||
{
|
{
|
||||||
|
var stream = obj as JuiceStream;
|
||||||
|
|
||||||
|
if (stream != null)
|
||||||
|
{
|
||||||
|
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
|
||||||
|
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
|
||||||
|
|
||||||
|
foreach (var unused in stream.Ticks)
|
||||||
|
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var fruit = obj as Fruit;
|
var fruit = obj as Fruit;
|
||||||
|
|
||||||
if (fruit != null)
|
if (fruit != null)
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Catch.Objects;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Tests
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
{
|
{
|
||||||
@ -13,15 +11,5 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
public TestCaseCatchPlayer() : base(typeof(CatchRuleset))
|
public TestCaseCatchPlayer() : base(typeof(CatchRuleset))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Beatmap CreateBeatmap()
|
|
||||||
{
|
|
||||||
var beatmap = new Beatmap();
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
beatmap.HitObjects.Add(new Fruit { X = 0.5f, StartTime = i * 100, NewCombo = i % 8 == 0 });
|
|
||||||
|
|
||||||
return beatmap;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs
Normal file
27
osu.Game.Rulesets.Catch/Tests/TestCaseCatchStacker.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Catch.Objects;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestCaseCatchStacker : Game.Tests.Visual.TestCasePlayer
|
||||||
|
{
|
||||||
|
public TestCaseCatchStacker() : base(typeof(CatchRuleset))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Beatmap CreateBeatmap()
|
||||||
|
{
|
||||||
|
var beatmap = new Beatmap();
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
beatmap.HitObjects.Add(new Fruit { X = 0.5f, StartTime = i * 100, NewCombo = i % 8 == 0 });
|
||||||
|
|
||||||
|
return beatmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
{
|
{
|
||||||
public class CatchPlayfield : ScrollingPlayfield
|
public class CatchPlayfield : ScrollingPlayfield
|
||||||
{
|
{
|
||||||
|
public static readonly float BASE_WIDTH = 512;
|
||||||
|
|
||||||
protected override Container<Drawable> Content => content;
|
protected override Container<Drawable> Content => content;
|
||||||
private readonly Container<Drawable> content;
|
private readonly Container<Drawable> content;
|
||||||
|
|
||||||
@ -28,8 +30,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
Reversed.Value = true;
|
Reversed.Value = true;
|
||||||
|
|
||||||
Size = new Vector2(1);
|
|
||||||
|
|
||||||
Anchor = Anchor.TopCentre;
|
Anchor = Anchor.TopCentre;
|
||||||
Origin = Anchor.TopCentre;
|
Origin = Anchor.TopCentre;
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
base.Add(h);
|
base.Add(h);
|
||||||
|
|
||||||
var fruit = (DrawableFruit)h;
|
var fruit = (DrawableCatchHitObject)h;
|
||||||
fruit.CheckPosition = CheckIfWeCanCatch;
|
fruit.CheckPosition = CheckIfWeCanCatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
if (judgement.IsHit)
|
if (judgement.IsHit)
|
||||||
{
|
{
|
||||||
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
|
||||||
Remove(judgedObject);
|
|
||||||
|
// todo: don't do this
|
||||||
|
(judgedObject.Parent as Container<DrawableHitObject>)?.Remove(judgedObject);
|
||||||
|
(judgedObject.Parent as Container)?.Remove(judgedObject);
|
||||||
|
|
||||||
catcher.Add(judgedObject, screenPosition);
|
catcher.Add(judgedObject, screenPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,13 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
|
|
||||||
protected override DrawableHitObject<CatchBaseHit> GetVisualRepresentation(CatchBaseHit h)
|
protected override DrawableHitObject<CatchBaseHit> GetVisualRepresentation(CatchBaseHit h)
|
||||||
{
|
{
|
||||||
if (h is Fruit)
|
var fruit = h as Fruit;
|
||||||
return new DrawableFruit(h);
|
if (fruit != null)
|
||||||
|
return new DrawableFruit(fruit);
|
||||||
|
|
||||||
|
var stream = h as JuiceStream;
|
||||||
|
if (stream != null)
|
||||||
|
return new DrawableJuiceStream(stream);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -50,14 +50,21 @@
|
|||||||
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
|
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
|
||||||
<Compile Include="CatchDifficultyCalculator.cs" />
|
<Compile Include="CatchDifficultyCalculator.cs" />
|
||||||
<Compile Include="CatchInputManager.cs" />
|
<Compile Include="CatchInputManager.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\DrawableCatchHitObject.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\DrawableDroplet.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\DrawableJuiceStream.cs" />
|
||||||
|
<Compile Include="Objects\Drawable\Pieces\Pulp.cs" />
|
||||||
|
<Compile Include="Objects\JuiceStream.cs" />
|
||||||
<Compile Include="Scoring\CatchScoreProcessor.cs" />
|
<Compile Include="Scoring\CatchScoreProcessor.cs" />
|
||||||
<Compile Include="Judgements\CatchJudgement.cs" />
|
<Compile Include="Judgements\CatchJudgement.cs" />
|
||||||
<Compile Include="Objects\CatchBaseHit.cs" />
|
<Compile Include="Objects\CatchBaseHit.cs" />
|
||||||
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
|
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
|
||||||
<Compile Include="Objects\Droplet.cs" />
|
<Compile Include="Objects\Droplet.cs" />
|
||||||
<Compile Include="Objects\Fruit.cs" />
|
<Compile Include="Objects\Fruit.cs" />
|
||||||
|
<Compile Include="Objects\TinyDroplet.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Tests\TestCaseCatcher.cs" />
|
<Compile Include="Tests\TestCaseCatcher.cs" />
|
||||||
|
<Compile Include="Tests\TestCaseCatchStacker.cs" />
|
||||||
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
||||||
<Compile Include="UI\Catcher.cs" />
|
<Compile Include="UI\Catcher.cs" />
|
||||||
<Compile Include="UI\CatchRulesetContainer.cs" />
|
<Compile Include="UI\CatchRulesetContainer.cs" />
|
||||||
@ -79,11 +86,6 @@
|
|||||||
<Name>osu.Framework</Name>
|
<Name>osu.Framework</Name>
|
||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\osu.Game.Rulesets.Osu\osu.Game.Rulesets.Osu.csproj">
|
|
||||||
<Project>{C92A607B-1FDD-4954-9F92-03FF547D9080}</Project>
|
|
||||||
<Name>osu.Game.Rulesets.Osu</Name>
|
|
||||||
<Private>False</Private>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
|
||||||
<Project>{2a66dd92-adb1-4994-89e2-c94e04acda0d}</Project>
|
<Project>{2a66dd92-adb1-4994-89e2-c94e04acda0d}</Project>
|
||||||
<Name>osu.Game</Name>
|
<Name>osu.Game</Name>
|
||||||
|
@ -10,7 +10,7 @@ using osu.Game.Tests.Visual;
|
|||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Testing
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
internal class TestCaseManiaHitObjects : OsuTestCase
|
internal class TestCaseManiaHitObjects : OsuTestCase
|
@ -17,7 +17,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
|||||||
using osu.Game.Rulesets.Timing;
|
using osu.Game.Rulesets.Timing;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Testing
|
namespace osu.Game.Rulesets.Mania.Tests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
internal class TestCaseManiaPlayfield : OsuTestCase
|
internal class TestCaseManiaPlayfield : OsuTestCase
|
@ -80,8 +80,8 @@
|
|||||||
<Compile Include="Objects\Note.cs" />
|
<Compile Include="Objects\Note.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ManiaInputManager.cs" />
|
<Compile Include="ManiaInputManager.cs" />
|
||||||
<Compile Include="Testing\TestCaseManiaHitObjects.cs" />
|
<Compile Include="Tests\TestCaseManiaHitObjects.cs" />
|
||||||
<Compile Include="Testing\TestCaseManiaPlayfield.cs" />
|
<Compile Include="Tests\TestCaseManiaPlayfield.cs" />
|
||||||
<Compile Include="Timing\GravityScrollingContainer.cs" />
|
<Compile Include="Timing\GravityScrollingContainer.cs" />
|
||||||
<Compile Include="Timing\ScrollingAlgorithm.cs" />
|
<Compile Include="Timing\ScrollingAlgorithm.cs" />
|
||||||
<Compile Include="UI\Column.cs" />
|
<Compile Include="UI\Column.cs" />
|
||||||
|
@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
public override bool RemoveWhenNotAlive => false;
|
public override bool RemoveWhenNotAlive => false;
|
||||||
|
|
||||||
|
public override bool DisplayJudgement => false;
|
||||||
|
|
||||||
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
|
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
|
||||||
{
|
{
|
||||||
this.sliderTick = sliderTick;
|
this.sliderTick = sliderTick;
|
||||||
|
@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
private readonly SpinnerDisc disc;
|
private readonly SpinnerDisc disc;
|
||||||
private readonly SpinnerTicks ticks;
|
private readonly SpinnerTicks ticks;
|
||||||
|
private readonly SpinnerSpmCounter spmCounter;
|
||||||
|
|
||||||
private readonly Container mainContainer;
|
private readonly Container mainContainer;
|
||||||
|
|
||||||
@ -103,6 +104,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
spmCounter = new SpinnerSpmCounter
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Y = 120,
|
||||||
|
Alpha = 0
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +165,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton);
|
disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton);
|
||||||
|
if (!spmCounter.IsPresent && disc.Tracking)
|
||||||
|
spmCounter.FadeIn(TIME_FADEIN);
|
||||||
|
|
||||||
base.Update();
|
base.Update();
|
||||||
}
|
}
|
||||||
@ -167,6 +177,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
circle.Rotation = disc.Rotation;
|
circle.Rotation = disc.Rotation;
|
||||||
ticks.Rotation = disc.Rotation;
|
ticks.Rotation = disc.Rotation;
|
||||||
|
spmCounter.SetRotation(disc.RotationAbsolute);
|
||||||
|
|
||||||
float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
|
float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
|
||||||
disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint);
|
disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint);
|
||||||
|
@ -77,7 +77,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
private float lastAngle;
|
private float lastAngle;
|
||||||
private float currentRotation;
|
private float currentRotation;
|
||||||
public float RotationAbsolute;
|
public float RotationAbsolute;
|
||||||
|
|
||||||
private int completeTick;
|
private int completeTick;
|
||||||
|
|
||||||
private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360));
|
private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360));
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
// Copyright (c) 2007-2017 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 osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||||
|
{
|
||||||
|
public class SpinnerSpmCounter : Container
|
||||||
|
{
|
||||||
|
private readonly OsuSpriteText spmText;
|
||||||
|
|
||||||
|
public SpinnerSpmCounter()
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
spmText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = @"0",
|
||||||
|
Font = @"Venera",
|
||||||
|
TextSize = 24
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = @"SPINS PER MINUTE",
|
||||||
|
Font = @"Venera",
|
||||||
|
TextSize = 12,
|
||||||
|
Y = 30
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private double spm;
|
||||||
|
|
||||||
|
public double SpinsPerMinute
|
||||||
|
{
|
||||||
|
get { return spm; }
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (value == spm) return;
|
||||||
|
spm = value;
|
||||||
|
spmText.Text = Math.Truncate(value).ToString(@"#0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct RotationRecord
|
||||||
|
{
|
||||||
|
public float Rotation;
|
||||||
|
public double Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Queue<RotationRecord> records = new Queue<RotationRecord>();
|
||||||
|
private const double spm_count_duration = 595; // not using hundreds to avoid frame rounding issues
|
||||||
|
|
||||||
|
public void SetRotation(float currentRotation)
|
||||||
|
{
|
||||||
|
if (records.Count > 0)
|
||||||
|
{
|
||||||
|
var record = records.Peek();
|
||||||
|
while (records.Count > 0 && Time.Current - records.Peek().Time > spm_count_duration)
|
||||||
|
record = records.Dequeue();
|
||||||
|
SpinsPerMinute = (currentRotation - record.Rotation) / (Time.Current - record.Time) * 1000 * 60 / 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
records.Enqueue(new RotationRecord { Rotation = currentRotation, Time = Time.Current });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -91,6 +91,9 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
var osuJudgement = (OsuJudgement)judgement;
|
var osuJudgement = (OsuJudgement)judgement;
|
||||||
var osuObject = (OsuHitObject)judgedObject.HitObject;
|
var osuObject = (OsuHitObject)judgedObject.HitObject;
|
||||||
|
|
||||||
|
if (!judgedObject.DisplayJudgement)
|
||||||
|
return;
|
||||||
|
|
||||||
DrawableOsuJudgement explosion = new DrawableOsuJudgement(osuJudgement)
|
DrawableOsuJudgement explosion = new DrawableOsuJudgement(osuJudgement)
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
<Compile Include="Objects\Drawables\Pieces\RingPiece.cs" />
|
<Compile Include="Objects\Drawables\Pieces\RingPiece.cs" />
|
||||||
<Compile Include="Objects\Drawables\Pieces\SliderBouncer.cs" />
|
<Compile Include="Objects\Drawables\Pieces\SliderBouncer.cs" />
|
||||||
<Compile Include="Objects\Drawables\Pieces\SpinnerDisc.cs" />
|
<Compile Include="Objects\Drawables\Pieces\SpinnerDisc.cs" />
|
||||||
|
<Compile Include="Objects\Drawables\Pieces\SpinnerSpmCounter.cs" />
|
||||||
<Compile Include="Objects\Drawables\Pieces\SpinnerTicks.cs" />
|
<Compile Include="Objects\Drawables\Pieces\SpinnerTicks.cs" />
|
||||||
<Compile Include="Objects\Drawables\Pieces\TrianglesPiece.cs" />
|
<Compile Include="Objects\Drawables\Pieces\TrianglesPiece.cs" />
|
||||||
<Compile Include="Objects\Drawables\Pieces\SliderBall.cs" />
|
<Compile Include="Objects\Drawables\Pieces\SliderBall.cs" />
|
||||||
|
@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
FillMode = FillMode.Fit;
|
FillMode = FillMode.Fit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool DisplayJudgement => false;
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
|
||||||
{
|
{
|
||||||
if (judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null)
|
if (judgedObject.DisplayJudgement && judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null)
|
||||||
{
|
{
|
||||||
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject, judgement)
|
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject, judgement)
|
||||||
{
|
{
|
||||||
|
@ -117,18 +117,27 @@ namespace osu.Game.Tests.Beatmaps.IO
|
|||||||
//ensure we were stored to beatmap database backing...
|
//ensure we were stored to beatmap database backing...
|
||||||
Assert.IsTrue(resultSets.Count() == 1, $@"Incorrect result count found ({resultSets.Count()} but should be 1).");
|
Assert.IsTrue(resultSets.Count() == 1, $@"Incorrect result count found ({resultSets.Count()} but should be 1).");
|
||||||
|
|
||||||
IEnumerable<BeatmapInfo> resultBeatmaps = null;
|
Func<IEnumerable<BeatmapInfo>> queryBeatmaps = () => store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0);
|
||||||
|
Func<IEnumerable<BeatmapSetInfo>> queryBeatmapSets = () => store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526);
|
||||||
|
|
||||||
//if we don't re-check here, the set will be inserted but the beatmaps won't be present yet.
|
//if we don't re-check here, the set will be inserted but the beatmaps won't be present yet.
|
||||||
waitForOrAssert(() => (resultBeatmaps = store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() == 12,
|
waitForOrAssert(() => queryBeatmaps().Count() == 12,
|
||||||
@"Beatmaps did not import to the database in allocated time", timeout);
|
@"Beatmaps did not import to the database in allocated time", timeout);
|
||||||
|
|
||||||
var set = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526).First();
|
waitForOrAssert(() => queryBeatmapSets().Count() == 1,
|
||||||
|
@"BeatmapSet did not import to the database in allocated time", timeout);
|
||||||
|
|
||||||
Assert.IsTrue(set.Beatmaps.Count == resultBeatmaps.Count(),
|
int countBeatmapSetBeatmaps = 0;
|
||||||
$@"Incorrect database beatmap count post-import ({resultBeatmaps.Count()} but should be {set.Beatmaps.Count}).");
|
int countBeatmaps = 0;
|
||||||
|
|
||||||
foreach (BeatmapInfo b in resultBeatmaps)
|
waitForOrAssert(() =>
|
||||||
|
(countBeatmapSetBeatmaps = queryBeatmapSets().First().Beatmaps.Count) ==
|
||||||
|
(countBeatmaps = queryBeatmaps().Count()),
|
||||||
|
$@"Incorrect database beatmap count post-import ({countBeatmaps} but should be {countBeatmapSetBeatmaps}).", timeout);
|
||||||
|
|
||||||
|
var set = queryBeatmapSets().First();
|
||||||
|
|
||||||
|
foreach (BeatmapInfo b in set.Beatmaps)
|
||||||
Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID));
|
Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID));
|
||||||
|
|
||||||
Assert.IsTrue(set.Beatmaps.Count > 0);
|
Assert.IsTrue(set.Beatmaps.Count > 0);
|
||||||
|
@ -550,7 +550,7 @@ namespace osu.Game.Beatmaps
|
|||||||
catch { return null; }
|
catch { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => f.Filename == filename).FileInfo.StoragePath;
|
private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath;
|
||||||
|
|
||||||
protected override Texture GetBackground()
|
protected override Texture GetBackground()
|
||||||
{
|
{
|
||||||
@ -573,6 +573,8 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
catch { return new TrackVirtual(); }
|
catch { return new TrackVirtual(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override Waveform GetWaveform() => new Waveform(store.GetStream(getPathForFile(Metadata.AudioFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -613,7 +613,7 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
string line;
|
string line;
|
||||||
while ((line = stream.ReadLine()) != null)
|
while ((line = stream.ReadLine()) != null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(line))
|
if (string.IsNullOrWhiteSpace(line))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (line.StartsWith("//"))
|
if (line.StartsWith("//"))
|
||||||
@ -679,10 +679,12 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
|
|
||||||
private KeyValuePair<string, string> splitKeyVal(string line, char separator)
|
private KeyValuePair<string, string> splitKeyVal(string line, char separator)
|
||||||
{
|
{
|
||||||
|
var split = line.Trim().Split(new[] { separator }, 2);
|
||||||
|
|
||||||
return new KeyValuePair<string, string>
|
return new KeyValuePair<string, string>
|
||||||
(
|
(
|
||||||
line.Remove(line.IndexOf(separator)).Trim(),
|
split[0].Trim(),
|
||||||
line.Substring(line.IndexOf(separator) + 1).Trim()
|
split.Length > 1 ? split[1].Trim() : string.Empty
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ namespace osu.Game.Beatmaps
|
|||||||
protected abstract Beatmap GetBeatmap();
|
protected abstract Beatmap GetBeatmap();
|
||||||
protected abstract Texture GetBackground();
|
protected abstract Texture GetBackground();
|
||||||
protected abstract Track GetTrack();
|
protected abstract Track GetTrack();
|
||||||
|
protected virtual Waveform GetWaveform() => new Waveform();
|
||||||
|
|
||||||
private Beatmap beatmap;
|
private Beatmap beatmap;
|
||||||
private readonly object beatmapLock = new object();
|
private readonly object beatmapLock = new object();
|
||||||
@ -96,6 +97,17 @@ namespace osu.Game.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Waveform waveform;
|
||||||
|
private readonly object waveformLock = new object();
|
||||||
|
public Waveform Waveform
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (waveformLock)
|
||||||
|
return waveform ?? (waveform = GetWaveform());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool TrackLoaded => track != null;
|
public bool TrackLoaded => track != null;
|
||||||
|
|
||||||
public void TransferTo(WorkingBeatmap other)
|
public void TransferTo(WorkingBeatmap other)
|
||||||
@ -114,6 +126,8 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
background?.Dispose();
|
background?.Dispose();
|
||||||
background = null;
|
background = null;
|
||||||
|
|
||||||
|
waveform?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeTrack()
|
public void DisposeTrack()
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using OpenTK;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Processing
|
|
||||||
{
|
|
||||||
internal class RatioAdjust : Container
|
|
||||||
{
|
|
||||||
public RatioAdjust()
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
Vector2 parent = Parent.DrawSize;
|
|
||||||
|
|
||||||
Scale = new Vector2(Math.Min(parent.Y / 768f, parent.X / 1024f));
|
|
||||||
Size = new Vector2(1 / Scale.X);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,32 +15,91 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
{
|
{
|
||||||
public class IconButton : OsuClickableContainer
|
public class IconButton : OsuClickableContainer
|
||||||
{
|
{
|
||||||
private readonly SpriteIcon icon;
|
private const float button_size = 30;
|
||||||
private readonly Box hover;
|
|
||||||
private readonly Container content;
|
|
||||||
|
|
||||||
|
private Color4? flashColour;
|
||||||
|
/// <summary>
|
||||||
|
/// The colour that should be flashed when the <see cref="IconButton"/> is clicked.
|
||||||
|
/// </summary>
|
||||||
|
public Color4 FlashColour
|
||||||
|
{
|
||||||
|
get { return flashColour ?? Color4.White; }
|
||||||
|
set { flashColour = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4? iconColour;
|
||||||
|
/// <summary>
|
||||||
|
/// The icon colour. This does not affect <see cref="IconButton.Colour"/>.
|
||||||
|
/// </summary>
|
||||||
|
public Color4 IconColour
|
||||||
|
{
|
||||||
|
get { return iconColour ?? Color4.White; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
iconColour = value;
|
||||||
|
icon.Colour = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4? iconHoverColour;
|
||||||
|
/// <summary>
|
||||||
|
/// The icon colour while the <see cref="IconButton"/> is hovered.
|
||||||
|
/// </summary>
|
||||||
|
public Color4 IconHoverColour
|
||||||
|
{
|
||||||
|
get { return iconHoverColour ?? IconColour; }
|
||||||
|
set { iconHoverColour = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color4? hoverColour;
|
||||||
|
/// <summary>
|
||||||
|
/// The background colour of the <see cref="IconButton"/> while it is hovered.
|
||||||
|
/// </summary>
|
||||||
|
public Color4 HoverColour
|
||||||
|
{
|
||||||
|
get { return hoverColour ?? Color4.White; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
hoverColour = value;
|
||||||
|
hover.Colour = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The icon.
|
||||||
|
/// </summary>
|
||||||
public FontAwesome Icon
|
public FontAwesome Icon
|
||||||
{
|
{
|
||||||
get { return icon.Icon; }
|
get { return icon.Icon; }
|
||||||
set { icon.Icon = value; }
|
set { icon.Icon = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private const float button_size = 30;
|
/// <summary>
|
||||||
private Color4 flashColour;
|
/// The icon scale. This does not affect <see cref="IconButton.Scale"/>.
|
||||||
|
/// </summary>
|
||||||
public Vector2 IconScale
|
public Vector2 IconScale
|
||||||
{
|
{
|
||||||
get { return icon.Scale; }
|
get { return icon.Scale; }
|
||||||
set { icon.Scale = value; }
|
set { icon.Scale = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of the <see cref="IconButton"/> while it is not being pressed.
|
||||||
|
/// </summary>
|
||||||
|
public Vector2 ButtonSize
|
||||||
|
{
|
||||||
|
get { return content.Size; }
|
||||||
|
set { content.Size = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Container content;
|
||||||
|
private readonly SpriteIcon icon;
|
||||||
|
private readonly Box hover;
|
||||||
|
|
||||||
public IconButton()
|
public IconButton()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
|
||||||
Origin = Anchor.Centre;
|
|
||||||
Anchor = Anchor.Centre;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
content = new Container
|
content = new Container
|
||||||
@ -48,7 +107,6 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Size = new Vector2(button_size),
|
Size = new Vector2(button_size),
|
||||||
|
|
||||||
CornerRadius = 5,
|
CornerRadius = 5,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
EdgeEffect = new EdgeEffectParameters
|
EdgeEffect = new EdgeEffectParameters
|
||||||
@ -78,8 +136,11 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
hover.Colour = colours.Yellow.Opacity(0.6f);
|
if (hoverColour == null)
|
||||||
flashColour = colours.Yellow;
|
HoverColour = colours.Yellow.Opacity(0.6f);
|
||||||
|
|
||||||
|
if (flashColour == null)
|
||||||
|
FlashColour = colours.Yellow;
|
||||||
|
|
||||||
Enabled.ValueChanged += enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint);
|
Enabled.ValueChanged += enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
@ -87,18 +148,20 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
protected override bool OnHover(InputState state)
|
protected override bool OnHover(InputState state)
|
||||||
{
|
{
|
||||||
hover.FadeIn(500, Easing.OutQuint);
|
hover.FadeIn(500, Easing.OutQuint);
|
||||||
|
icon.FadeColour(IconHoverColour, 500, Easing.OutQuint);
|
||||||
return base.OnHover(state);
|
return base.OnHover(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(InputState state)
|
protected override void OnHoverLost(InputState state)
|
||||||
{
|
{
|
||||||
hover.FadeOut(500, Easing.OutQuint);
|
hover.FadeOut(500, Easing.OutQuint);
|
||||||
|
icon.FadeColour(IconColour, 500, Easing.OutQuint);
|
||||||
base.OnHoverLost(state);
|
base.OnHoverLost(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(InputState state)
|
protected override bool OnClick(InputState state)
|
||||||
{
|
{
|
||||||
hover.FlashColour(flashColour, 800, Easing.OutQuint);
|
hover.FlashColour(FlashColour, 800, Easing.OutQuint);
|
||||||
return base.OnClick(state);
|
return base.OnClick(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
private int onlineId { get; set; }
|
private int onlineId { get; set; }
|
||||||
|
|
||||||
[JsonProperty(@"creator")]
|
[JsonProperty(@"creator")]
|
||||||
private string creatorUsername;
|
private string creatorUsername { get; set; }
|
||||||
|
|
||||||
[JsonProperty(@"user_id")]
|
[JsonProperty(@"user_id")]
|
||||||
private long creatorId = 1;
|
private long creatorId = 1;
|
||||||
|
@ -15,7 +15,6 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Cursor;
|
using osu.Game.Graphics.Cursor;
|
||||||
using osu.Game.Graphics.Processing;
|
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using SQLite.Net;
|
using SQLite.Net;
|
||||||
using osu.Framework.Graphics.Performance;
|
using osu.Framework.Graphics.Performance;
|
||||||
@ -186,7 +185,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
GlobalKeyBindingInputManager globalBinding;
|
GlobalKeyBindingInputManager globalBinding;
|
||||||
|
|
||||||
base.Content.Add(new RatioAdjust
|
base.Content.Add(new DrawSizePreservingFillContainer
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
@ -159,7 +159,7 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.Both,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ namespace osu.Game.Overlays.MedalSplash
|
|||||||
},
|
},
|
||||||
description = new TextFlowContainer
|
description = new TextFlowContainer
|
||||||
{
|
{
|
||||||
|
TextAnchor = Anchor.TopCentre,
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
@ -115,15 +116,16 @@ namespace osu.Game.Overlays.MedalSplash
|
|||||||
medalSprite.Texture = textures.Get(medal.ImageUrl);
|
medalSprite.Texture = textures.Get(medal.ImageUrl);
|
||||||
medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow");
|
medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow");
|
||||||
description.Colour = colours.BlueLight;
|
description.Colour = colours.BlueLight;
|
||||||
|
|
||||||
unlocked.Position = new Vector2(0f, medalContainer.Size.Y / 2 + 10);
|
|
||||||
infoFlow.Position = new Vector2(0f, unlocked.Position.Y + 90);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
updateState();
|
updateState();
|
||||||
|
|
||||||
|
unlocked.Position = new Vector2(0f, medalContainer.DrawSize.Y / 2 + 10);
|
||||||
|
infoFlow.Position = new Vector2(0f, unlocked.Position.Y + 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisplayState State
|
public DisplayState State
|
||||||
@ -172,6 +174,7 @@ namespace osu.Game.Overlays.MedalSplash
|
|||||||
|
|
||||||
this.ScaleTo(scale_when_full, duration, Easing.OutExpo);
|
this.ScaleTo(scale_when_full, duration, Easing.OutExpo);
|
||||||
this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 60, duration, Easing.OutExpo);
|
this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 60, duration, Easing.OutExpo);
|
||||||
|
unlocked.Show();
|
||||||
name.FadeInFromZero(duration + 100);
|
name.FadeInFromZero(duration + 100);
|
||||||
description.FadeInFromZero(duration * 2);
|
description.FadeInFromZero(duration * 2);
|
||||||
break;
|
break;
|
||||||
|
@ -161,11 +161,15 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
prevButton = new IconButton
|
prevButton = new IconButton
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
Action = prev,
|
Action = prev,
|
||||||
Icon = FontAwesome.fa_step_backward,
|
Icon = FontAwesome.fa_step_backward,
|
||||||
},
|
},
|
||||||
playButton = new IconButton
|
playButton = new IconButton
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
Scale = new Vector2(1.4f),
|
Scale = new Vector2(1.4f),
|
||||||
IconScale = new Vector2(1.4f),
|
IconScale = new Vector2(1.4f),
|
||||||
Action = play,
|
Action = play,
|
||||||
@ -173,6 +177,8 @@ namespace osu.Game.Overlays
|
|||||||
},
|
},
|
||||||
nextButton = new IconButton
|
nextButton = new IconButton
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
Action = next,
|
Action = next,
|
||||||
Icon = FontAwesome.fa_step_forward,
|
Icon = FontAwesome.fa_step_forward,
|
||||||
},
|
},
|
||||||
|
@ -25,6 +25,11 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual Color4 AccentColour { get; set; } = Color4.Gray;
|
public virtual Color4 AccentColour { get; set; } = Color4.Gray;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether a visible judgement should be displayed when this representation is hit.
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool DisplayJudgement => true;
|
||||||
|
|
||||||
protected DrawableHitObject(HitObject hitObject)
|
protected DrawableHitObject(HitObject hitObject)
|
||||||
{
|
{
|
||||||
HitObject = hitObject;
|
HitObject = hitObject;
|
||||||
|
@ -200,4 +200,4 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
return interpolateVertices(indexOfDistance(d), d) + Offset;
|
return interpolateVertices(indexOfDistance(d), d) + Offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using osu.Framework.Extensions.Color4Extensions;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Screens.Edit.Screens.Compose.Timeline;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Edit.Screens.Compose
|
namespace osu.Game.Screens.Edit.Screens.Compose
|
||||||
{
|
{
|
||||||
@ -13,6 +14,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
|||||||
{
|
{
|
||||||
public Compose()
|
public Compose()
|
||||||
{
|
{
|
||||||
|
ScrollableTimeline timeline;
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
new Container
|
new Container
|
||||||
@ -31,11 +33,22 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
|||||||
{
|
{
|
||||||
Name = "Content",
|
Name = "Content",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Horizontal = 17, Vertical = 10 }
|
Padding = new MarginPadding { Horizontal = 17, Vertical = 10 },
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Right = 115 },
|
||||||
|
Child = timeline = new ScrollableTimeline { RelativeSizeAxes = Axes.Both }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
timeline.Beatmap.BindTo(Beatmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Audio;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
|
||||||
|
{
|
||||||
|
public class BeatmapWaveformGraph : CompositeDrawable
|
||||||
|
{
|
||||||
|
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
private readonly WaveformGraph graph;
|
||||||
|
|
||||||
|
public BeatmapWaveformGraph()
|
||||||
|
{
|
||||||
|
InternalChild = graph = new WaveformGraph { RelativeSizeAxes = Axes.Both };
|
||||||
|
Beatmap.ValueChanged += b => graph.Waveform = b.Waveform;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="WaveformGraph.Resolution"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float Resolution
|
||||||
|
{
|
||||||
|
get { return graph.Resolution; }
|
||||||
|
set { graph.Resolution = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
|
||||||
|
{
|
||||||
|
public class ScrollableTimeline : CompositeDrawable
|
||||||
|
{
|
||||||
|
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
private readonly ScrollingTimelineContainer timelineContainer;
|
||||||
|
|
||||||
|
public ScrollableTimeline()
|
||||||
|
{
|
||||||
|
Masking = true;
|
||||||
|
CornerRadius = 5;
|
||||||
|
|
||||||
|
OsuCheckbox hitObjectsCheckbox;
|
||||||
|
OsuCheckbox hitSoundsCheckbox;
|
||||||
|
OsuCheckbox waveformCheckbox;
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = OsuColour.FromHex("111")
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.X,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = OsuColour.FromHex("222")
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Width = 160,
|
||||||
|
Padding = new MarginPadding { Horizontal = 15 },
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 4),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
hitObjectsCheckbox = new OsuCheckbox { LabelText = "Hitobjects" },
|
||||||
|
hitSoundsCheckbox = new OsuCheckbox { LabelText = "Hitsounds" },
|
||||||
|
waveformCheckbox = new OsuCheckbox { LabelText = "Waveform" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.X,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = OsuColour.FromHex("333")
|
||||||
|
},
|
||||||
|
new Container<TimelineButton>
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
AutoSizeAxes = Axes.X,
|
||||||
|
Masking = true,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new TimelineButton
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Height = 0.5f,
|
||||||
|
Icon = FontAwesome.fa_search_plus,
|
||||||
|
Action = () => timelineContainer.Zoom++
|
||||||
|
},
|
||||||
|
new TimelineButton
|
||||||
|
{
|
||||||
|
Anchor = Anchor.BottomLeft,
|
||||||
|
Origin = Anchor.BottomLeft,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Height = 0.5f,
|
||||||
|
Icon = FontAwesome.fa_search_minus,
|
||||||
|
Action = () => timelineContainer.Zoom--
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
timelineContainer = new ScrollingTimelineContainer { RelativeSizeAxes = Axes.Y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
hitObjectsCheckbox.Current.Value = true;
|
||||||
|
hitSoundsCheckbox.Current.Value = true;
|
||||||
|
waveformCheckbox.Current.Value = true;
|
||||||
|
|
||||||
|
timelineContainer.Beatmap.BindTo(Beatmap);
|
||||||
|
timelineContainer.WaveformVisible.BindTo(waveformCheckbox.Current);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
timelineContainer.Size = new Vector2(DrawSize.X - timelineContainer.DrawPosition.X, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using OpenTK;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
|
||||||
|
{
|
||||||
|
internal class ScrollingTimelineContainer : ScrollContainer
|
||||||
|
{
|
||||||
|
public readonly Bindable<bool> HitObjectsVisible = new Bindable<bool>();
|
||||||
|
public readonly Bindable<bool> HitSoundsVisible = new Bindable<bool>();
|
||||||
|
public readonly Bindable<bool> WaveformVisible = new Bindable<bool>();
|
||||||
|
public readonly Bindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
private readonly BeatmapWaveformGraph waveform;
|
||||||
|
|
||||||
|
public ScrollingTimelineContainer()
|
||||||
|
: base(Direction.Horizontal)
|
||||||
|
{
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
|
Add(waveform = new BeatmapWaveformGraph
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = OsuColour.FromHex("222"),
|
||||||
|
Depth = float.MaxValue
|
||||||
|
});
|
||||||
|
|
||||||
|
Content.AutoSizeAxes = Axes.None;
|
||||||
|
Content.RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
|
waveform.Beatmap.BindTo(Beatmap);
|
||||||
|
WaveformVisible.ValueChanged += waveformVisibilityChanged;
|
||||||
|
|
||||||
|
Zoom = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float minZoom = 1;
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum zoom level allowed.
|
||||||
|
/// </summary>
|
||||||
|
public float MinZoom
|
||||||
|
{
|
||||||
|
get { return minZoom; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value));
|
||||||
|
if (minZoom == value)
|
||||||
|
return;
|
||||||
|
minZoom = value;
|
||||||
|
|
||||||
|
// Update the zoom level
|
||||||
|
Zoom = Zoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float maxZoom = 30;
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum zoom level allowed.
|
||||||
|
/// </summary>
|
||||||
|
public float MaxZoom
|
||||||
|
{
|
||||||
|
get { return maxZoom; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(value));
|
||||||
|
if (maxZoom == value)
|
||||||
|
return;
|
||||||
|
maxZoom = value;
|
||||||
|
|
||||||
|
// Update the zoom level
|
||||||
|
Zoom = Zoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float zoom = 1;
|
||||||
|
/// <summary>
|
||||||
|
/// The current zoom level.
|
||||||
|
/// </summary>
|
||||||
|
public float Zoom
|
||||||
|
{
|
||||||
|
get { return zoom; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
value = MathHelper.Clamp(value, MinZoom, MaxZoom);
|
||||||
|
if (zoom == value)
|
||||||
|
return;
|
||||||
|
zoom = value;
|
||||||
|
|
||||||
|
// Make the zoom target default to the center of the graph if it hasn't been set
|
||||||
|
if (relativeContentZoomTarget == null)
|
||||||
|
relativeContentZoomTarget = ToSpaceOfOtherDrawable(DrawSize / 2, Content).X / Content.DrawSize.X;
|
||||||
|
if (localZoomTarget == null)
|
||||||
|
localZoomTarget = DrawSize.X / 2;
|
||||||
|
|
||||||
|
Content.ResizeWidthTo(Zoom);
|
||||||
|
|
||||||
|
// Update the scroll position to focus on the zoom target
|
||||||
|
float scrollPos = Content.DrawSize.X * relativeContentZoomTarget.Value - localZoomTarget.Value;
|
||||||
|
ScrollTo(scrollPos, false);
|
||||||
|
|
||||||
|
relativeContentZoomTarget = null;
|
||||||
|
localZoomTarget = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Zoom target as a relative position in the <see cref="Content"/> space.
|
||||||
|
/// </summary>
|
||||||
|
private float? relativeContentZoomTarget;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Zoom target as a position in our local space.
|
||||||
|
/// </summary>
|
||||||
|
private float? localZoomTarget;
|
||||||
|
|
||||||
|
protected override bool OnWheel(InputState state)
|
||||||
|
{
|
||||||
|
if (!state.Keyboard.ControlPressed)
|
||||||
|
return base.OnWheel(state);
|
||||||
|
|
||||||
|
relativeContentZoomTarget = Content.ToLocalSpace(state.Mouse.NativeState.Position).X / Content.DrawSize.X;
|
||||||
|
localZoomTarget = ToLocalSpace(state.Mouse.NativeState.Position).X;
|
||||||
|
|
||||||
|
Zoom += state.Mouse.WheelDelta;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waveformVisibilityChanged(bool visible) => waveform.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Edit.Screens.Compose.Timeline
|
||||||
|
{
|
||||||
|
public class TimelineButton : CompositeDrawable
|
||||||
|
{
|
||||||
|
public Action Action;
|
||||||
|
public readonly BindableBool Enabled = new BindableBool(true);
|
||||||
|
|
||||||
|
public FontAwesome Icon
|
||||||
|
{
|
||||||
|
get { return button.Icon; }
|
||||||
|
set { button.Icon = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IconButton button;
|
||||||
|
|
||||||
|
public TimelineButton()
|
||||||
|
{
|
||||||
|
InternalChild = button = new IconButton
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
IconColour = OsuColour.Gray(0.35f),
|
||||||
|
IconHoverColour = Color4.White,
|
||||||
|
HoverColour = OsuColour.Gray(0.25f),
|
||||||
|
FlashColour = OsuColour.Gray(0.5f),
|
||||||
|
Action = () => Action?.Invoke()
|
||||||
|
};
|
||||||
|
|
||||||
|
button.Enabled.BindTo(Enabled);
|
||||||
|
Width = button.ButtonSize.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
button.ButtonSize = new Vector2(button.ButtonSize.X, DrawHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
osu.Game/Tests/Visual/TestCaseEditorComposeTimeline.cs
Normal file
46
osu.Game/Tests/Visual/TestCaseEditorComposeTimeline.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2007-2017 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 OpenTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Screens.Edit.Screens.Compose.Timeline;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
public class TestCaseEditorComposeTimeline : OsuTestCase
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ScrollableTimeline), typeof(ScrollingTimelineContainer), typeof(BeatmapWaveformGraph), typeof(TimelineButton) };
|
||||||
|
|
||||||
|
private readonly ScrollableTimeline timeline;
|
||||||
|
|
||||||
|
public TestCaseEditorComposeTimeline()
|
||||||
|
{
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new MusicController
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
State = Visibility.Visible
|
||||||
|
},
|
||||||
|
timeline = new ScrollableTimeline
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Size = new Vector2(1000, 100)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuGameBase osuGame)
|
||||||
|
{
|
||||||
|
timeline.Beatmap.BindTo(osuGame.Beatmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
113
osu.Game/Tests/Visual/TestCaseIconButton.cs
Normal file
113
osu.Game/Tests/Visual/TestCaseIconButton.cs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
public class TestCaseIconButton : OsuTestCase
|
||||||
|
{
|
||||||
|
public override string Description => "Various display modes of icon buttons";
|
||||||
|
|
||||||
|
public TestCaseIconButton()
|
||||||
|
{
|
||||||
|
Child = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Spacing = new Vector2(10, 10),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new NamedIconButton("No change", new IconButton()),
|
||||||
|
new NamedIconButton("Background colours", new IconButton
|
||||||
|
{
|
||||||
|
FlashColour = Color4.DarkGreen,
|
||||||
|
HoverColour = Color4.Green,
|
||||||
|
}),
|
||||||
|
new NamedIconButton("Full-width", new IconButton { ButtonSize = new Vector2(200, 30) }),
|
||||||
|
new NamedIconButton("Unchanging size", new IconButton(), false),
|
||||||
|
new NamedIconButton("Icon colours", new IconButton
|
||||||
|
{
|
||||||
|
IconColour = Color4.Green,
|
||||||
|
IconHoverColour = Color4.Red
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NamedIconButton : Container
|
||||||
|
{
|
||||||
|
public NamedIconButton(string name, IconButton button, bool allowSizeChange = true)
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
Width = 200;
|
||||||
|
|
||||||
|
Container iconContainer;
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black,
|
||||||
|
Alpha = 0.5f,
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Text = name
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0.1f,
|
||||||
|
},
|
||||||
|
iconContainer = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Child = button
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (allowSizeChange)
|
||||||
|
iconContainer.AutoSizeAxes = Axes.Both;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iconContainer.RelativeSizeAxes = Axes.X;
|
||||||
|
iconContainer.Height = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.Anchor = Anchor.Centre;
|
||||||
|
button.Origin = Anchor.Centre;
|
||||||
|
button.Icon = FontAwesome.fa_osu_osu_o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,10 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.MedalSplash;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual
|
namespace osu.Game.Tests.Visual
|
||||||
@ -10,6 +13,12 @@ namespace osu.Game.Tests.Visual
|
|||||||
{
|
{
|
||||||
public override string Description => @"medal get!";
|
public override string Description => @"medal get!";
|
||||||
|
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(MedalOverlay),
|
||||||
|
typeof(DrawableMedal),
|
||||||
|
};
|
||||||
|
|
||||||
public TestCaseMedalOverlay()
|
public TestCaseMedalOverlay()
|
||||||
{
|
{
|
||||||
AddStep(@"display", () =>
|
AddStep(@"display", () =>
|
||||||
|
88
osu.Game/Tests/Visual/TestCaseWaveform.cs
Normal file
88
osu.Game/Tests/Visual/TestCaseWaveform.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||||
|
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||||
|
|
||||||
|
using OpenTK;
|
||||||
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Configuration;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Screens.Edit.Screens.Compose.Timeline;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual
|
||||||
|
{
|
||||||
|
internal class TestCaseWaveform : OsuTestCase
|
||||||
|
{
|
||||||
|
private readonly Bindable<WorkingBeatmap> beatmapBacking = new Bindable<WorkingBeatmap>();
|
||||||
|
|
||||||
|
public TestCaseWaveform()
|
||||||
|
{
|
||||||
|
FillFlowContainer flow;
|
||||||
|
Child = flow = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new MusicController
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Y = 100,
|
||||||
|
State = Visibility.Visible
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 1; i <= 16; i *= 2)
|
||||||
|
{
|
||||||
|
var newDisplay = new BeatmapWaveformGraph
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Resolution = 1f / i
|
||||||
|
};
|
||||||
|
|
||||||
|
newDisplay.Beatmap.BindTo(beatmapBacking);
|
||||||
|
|
||||||
|
flow.Add(new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 100,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
newDisplay,
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = Color4.Black,
|
||||||
|
Alpha = 0.75f
|
||||||
|
},
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Text = $"Resolution: {1f / i:0.00}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuGameBase osuGame) => beatmapBacking.BindTo(osuGame.Beatmap);
|
||||||
|
}
|
||||||
|
}
|
@ -57,7 +57,6 @@
|
|||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
@ -77,7 +76,6 @@
|
|||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -103,7 +101,6 @@
|
|||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||||
<LangVersion>6</LangVersion>
|
<LangVersion>6</LangVersion>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
<StartArguments>--tests</StartArguments>
|
<StartArguments>--tests</StartArguments>
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -266,6 +263,7 @@
|
|||||||
<Compile Include="Beatmaps\Drawables\BeatmapPanel.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapPanel.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\BeatmapSetHeader.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapSetHeader.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Screens\Compose\Timeline\BeatmapWaveformGraph.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\DifficultyColouredContainer.cs" />
|
<Compile Include="Beatmaps\Drawables\DifficultyColouredContainer.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />
|
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\Panel.cs" />
|
<Compile Include="Beatmaps\Drawables\Panel.cs" />
|
||||||
@ -274,6 +272,7 @@
|
|||||||
<Compile Include="Beatmaps\Formats\OsuLegacyDecoder.cs" />
|
<Compile Include="Beatmaps\Formats\OsuLegacyDecoder.cs" />
|
||||||
<Compile Include="Beatmaps\IO\ArchiveReader.cs" />
|
<Compile Include="Beatmaps\IO\ArchiveReader.cs" />
|
||||||
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
|
<Compile Include="Beatmaps\IO\LegacyFilesystemReader.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Screens\Compose\Timeline\TimelineButton.cs" />
|
||||||
<Compile Include="Screens\Play\BreaksOverlay\ArrowsOverlay.cs" />
|
<Compile Include="Screens\Play\BreaksOverlay\ArrowsOverlay.cs" />
|
||||||
<Compile Include="Screens\Play\BreaksOverlay\BlurredIcon.cs" />
|
<Compile Include="Screens\Play\BreaksOverlay\BlurredIcon.cs" />
|
||||||
<Compile Include="Screens\Play\BreaksOverlay\BreakOverlay.cs" />
|
<Compile Include="Screens\Play\BreaksOverlay\BreakOverlay.cs" />
|
||||||
@ -312,7 +311,6 @@
|
|||||||
<Compile Include="Graphics\Cursor\OsuTooltipContainer.cs" />
|
<Compile Include="Graphics\Cursor\OsuTooltipContainer.cs" />
|
||||||
<Compile Include="Graphics\IHasAccentColour.cs" />
|
<Compile Include="Graphics\IHasAccentColour.cs" />
|
||||||
<Compile Include="Graphics\OsuColour.cs" />
|
<Compile Include="Graphics\OsuColour.cs" />
|
||||||
<Compile Include="Graphics\Processing\RatioAdjust.cs" />
|
|
||||||
<Compile Include="Graphics\SpriteIcon.cs" />
|
<Compile Include="Graphics\SpriteIcon.cs" />
|
||||||
<Compile Include="Graphics\Sprites\OsuSpriteText.cs" />
|
<Compile Include="Graphics\Sprites\OsuSpriteText.cs" />
|
||||||
<Compile Include="Graphics\UserInterface\BackButton.cs" />
|
<Compile Include="Graphics\UserInterface\BackButton.cs" />
|
||||||
@ -630,6 +628,8 @@
|
|||||||
<Compile Include="Screens\Edit\Screens\Design\Design.cs" />
|
<Compile Include="Screens\Edit\Screens\Design\Design.cs" />
|
||||||
<Compile Include="Screens\Edit\Screens\EditorScreen.cs" />
|
<Compile Include="Screens\Edit\Screens\EditorScreen.cs" />
|
||||||
<Compile Include="Screens\Edit\Screens\Compose\Compose.cs" />
|
<Compile Include="Screens\Edit\Screens\Compose\Compose.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Screens\Compose\Timeline\ScrollableTimeline.cs" />
|
||||||
|
<Compile Include="Screens\Edit\Screens\Compose\Timeline\ScrollingTimelineContainer.cs" />
|
||||||
<Compile Include="Screens\Loader.cs" />
|
<Compile Include="Screens\Loader.cs" />
|
||||||
<Compile Include="Screens\Menu\Button.cs" />
|
<Compile Include="Screens\Menu\Button.cs" />
|
||||||
<Compile Include="Screens\Menu\ButtonSystem.cs" />
|
<Compile Include="Screens\Menu\ButtonSystem.cs" />
|
||||||
@ -756,10 +756,12 @@
|
|||||||
<Compile Include="Tests\Visual\TestCaseDrawableRoom.cs" />
|
<Compile Include="Tests\Visual\TestCaseDrawableRoom.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseDrawings.cs" />
|
<Compile Include="Tests\Visual\TestCaseDrawings.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseEditor.cs" />
|
<Compile Include="Tests\Visual\TestCaseEditor.cs" />
|
||||||
|
<Compile Include="Tests\Visual\TestCaseEditorComposeTimeline.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseEditorMenuBar.cs" />
|
<Compile Include="Tests\Visual\TestCaseEditorMenuBar.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseEditorSummaryTimeline.cs" />
|
<Compile Include="Tests\Visual\TestCaseEditorSummaryTimeline.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseGamefield.cs" />
|
<Compile Include="Tests\Visual\TestCaseGamefield.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseGraph.cs" />
|
<Compile Include="Tests\Visual\TestCaseGraph.cs" />
|
||||||
|
<Compile Include="Tests\Visual\TestCaseIconButton.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseKeyConfiguration.cs" />
|
<Compile Include="Tests\Visual\TestCaseKeyConfiguration.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseKeyCounter.cs" />
|
<Compile Include="Tests\Visual\TestCaseKeyCounter.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseLeaderboard.cs" />
|
<Compile Include="Tests\Visual\TestCaseLeaderboard.cs" />
|
||||||
@ -788,6 +790,7 @@
|
|||||||
<Compile Include="Tests\Visual\TestCaseTwoLayerButton.cs" />
|
<Compile Include="Tests\Visual\TestCaseTwoLayerButton.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseUserPanel.cs" />
|
<Compile Include="Tests\Visual\TestCaseUserPanel.cs" />
|
||||||
<Compile Include="Tests\Visual\TestCaseUserProfile.cs" />
|
<Compile Include="Tests\Visual\TestCaseUserProfile.cs" />
|
||||||
|
<Compile Include="Tests\Visual\TestCaseWaveform.cs" />
|
||||||
<Compile Include="Users\Avatar.cs" />
|
<Compile Include="Users\Avatar.cs" />
|
||||||
<Compile Include="Users\Country.cs" />
|
<Compile Include="Users\Country.cs" />
|
||||||
<Compile Include="Users\Medal.cs" />
|
<Compile Include="Users\Medal.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user