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",
|
||||
"configurations": [{
|
||||
"name": "osu! (VisualTests)",
|
||||
"name": "osu! VisualTests (Debug)",
|
||||
"windows": {
|
||||
"type": "clr"
|
||||
},
|
||||
@ -18,7 +18,24 @@
|
||||
"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": {
|
||||
"type": "clr"
|
||||
},
|
||||
@ -32,7 +49,7 @@
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "osu! (release)",
|
||||
"name": "osu! (Release)",
|
||||
"windows": {
|
||||
"type": "clr"
|
||||
},
|
||||
|
1
.vscode/tasks.json
vendored
1
.vscode/tasks.json
vendored
@ -23,6 +23,7 @@
|
||||
},
|
||||
{
|
||||
"taskName": "Build (Release)",
|
||||
"group": "build",
|
||||
"args": [
|
||||
"/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 System.Collections.Generic;
|
||||
using System;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
|
||||
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)
|
||||
{
|
||||
if (!(obj is IHasXPosition))
|
||||
var curveData = obj as IHasCurve;
|
||||
var positionData = obj as IHasPosition;
|
||||
var comboData = obj as IHasCombo;
|
||||
|
||||
if (positionData == null)
|
||||
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
|
||||
{
|
||||
StartTime = obj.StartTime,
|
||||
NewCombo = (obj as IHasCombo)?.NewCombo ?? false,
|
||||
X = ((IHasXPosition)obj).X / OsuPlayfield.BASE_SIZE.X
|
||||
Samples = obj.Samples,
|
||||
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>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.MathUtils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
{
|
||||
public class DrawableFruit : DrawableScrollingHitObject<CatchBaseHit>
|
||||
public class DrawableFruit : DrawableCatchHitObject<Fruit>
|
||||
{
|
||||
private const float pulp_size = 20;
|
||||
|
||||
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)
|
||||
public DrawableFruit(Fruit h)
|
||||
: base(h)
|
||||
{
|
||||
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;
|
||||
|
||||
Masking = false;
|
||||
|
||||
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
|
||||
}
|
||||
|
||||
public Func<CatchBaseHit, bool> CheckPosition;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (fruit != null)
|
||||
|
@ -2,8 +2,6 @@
|
||||
// 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
|
||||
{
|
||||
@ -13,15 +11,5 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
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 static readonly float BASE_WIDTH = 512;
|
||||
|
||||
protected override Container<Drawable> Content => content;
|
||||
private readonly Container<Drawable> content;
|
||||
|
||||
@ -28,8 +30,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
Reversed.Value = true;
|
||||
|
||||
Size = new Vector2(1);
|
||||
|
||||
Anchor = Anchor.TopCentre;
|
||||
Origin = Anchor.TopCentre;
|
||||
|
||||
@ -74,7 +74,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
base.Add(h);
|
||||
|
||||
var fruit = (DrawableFruit)h;
|
||||
var fruit = (DrawableCatchHitObject)h;
|
||||
fruit.CheckPosition = CheckIfWeCanCatch;
|
||||
}
|
||||
|
||||
@ -83,7 +83,11 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
if (judgement.IsHit)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,13 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
protected override DrawableHitObject<CatchBaseHit> GetVisualRepresentation(CatchBaseHit h)
|
||||
{
|
||||
if (h is Fruit)
|
||||
return new DrawableFruit(h);
|
||||
var fruit = h as Fruit;
|
||||
if (fruit != null)
|
||||
return new DrawableFruit(fruit);
|
||||
|
||||
var stream = h as JuiceStream;
|
||||
if (stream != null)
|
||||
return new DrawableJuiceStream(stream);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -50,14 +50,21 @@
|
||||
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
|
||||
<Compile Include="CatchDifficultyCalculator.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="Judgements\CatchJudgement.cs" />
|
||||
<Compile Include="Objects\CatchBaseHit.cs" />
|
||||
<Compile Include="Objects\Drawable\DrawableFruit.cs" />
|
||||
<Compile Include="Objects\Droplet.cs" />
|
||||
<Compile Include="Objects\Fruit.cs" />
|
||||
<Compile Include="Objects\TinyDroplet.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Tests\TestCaseCatcher.cs" />
|
||||
<Compile Include="Tests\TestCaseCatchStacker.cs" />
|
||||
<Compile Include="Tests\TestCaseCatchPlayer.cs" />
|
||||
<Compile Include="UI\Catcher.cs" />
|
||||
<Compile Include="UI\CatchRulesetContainer.cs" />
|
||||
@ -79,11 +86,6 @@
|
||||
<Name>osu.Framework</Name>
|
||||
<Private>False</Private>
|
||||
</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">
|
||||
<Project>{2a66dd92-adb1-4994-89e2-c94e04acda0d}</Project>
|
||||
<Name>osu.Game</Name>
|
||||
|
@ -10,7 +10,7 @@ using osu.Game.Tests.Visual;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Testing
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
internal class TestCaseManiaHitObjects : OsuTestCase
|
@ -17,7 +17,7 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Timing;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Testing
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
internal class TestCaseManiaPlayfield : OsuTestCase
|
@ -80,8 +80,8 @@
|
||||
<Compile Include="Objects\Note.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ManiaInputManager.cs" />
|
||||
<Compile Include="Testing\TestCaseManiaHitObjects.cs" />
|
||||
<Compile Include="Testing\TestCaseManiaPlayfield.cs" />
|
||||
<Compile Include="Tests\TestCaseManiaHitObjects.cs" />
|
||||
<Compile Include="Tests\TestCaseManiaPlayfield.cs" />
|
||||
<Compile Include="Timing\GravityScrollingContainer.cs" />
|
||||
<Compile Include="Timing\ScrollingAlgorithm.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 DisplayJudgement => false;
|
||||
|
||||
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
|
||||
{
|
||||
this.sliderTick = sliderTick;
|
||||
|
@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
private readonly SpinnerDisc disc;
|
||||
private readonly SpinnerTicks ticks;
|
||||
private readonly SpinnerSpmCounter spmCounter;
|
||||
|
||||
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()
|
||||
{
|
||||
disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton);
|
||||
if (!spmCounter.IsPresent && disc.Tracking)
|
||||
spmCounter.FadeIn(TIME_FADEIN);
|
||||
|
||||
base.Update();
|
||||
}
|
||||
@ -167,6 +177,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
circle.Rotation = disc.Rotation;
|
||||
ticks.Rotation = disc.Rotation;
|
||||
spmCounter.SetRotation(disc.RotationAbsolute);
|
||||
|
||||
float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
|
||||
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 currentRotation;
|
||||
public float RotationAbsolute;
|
||||
|
||||
private int completeTick;
|
||||
|
||||
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 osuObject = (OsuHitObject)judgedObject.HitObject;
|
||||
|
||||
if (!judgedObject.DisplayJudgement)
|
||||
return;
|
||||
|
||||
DrawableOsuJudgement explosion = new DrawableOsuJudgement(osuJudgement)
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
|
@ -68,6 +68,7 @@
|
||||
<Compile Include="Objects\Drawables\Pieces\RingPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\SliderBouncer.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\TrianglesPiece.cs" />
|
||||
<Compile Include="Objects\Drawables\Pieces\SliderBall.cs" />
|
||||
|
@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
FillMode = FillMode.Fit;
|
||||
}
|
||||
|
||||
public override bool DisplayJudgement => false;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -117,18 +117,27 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
//ensure we were stored to beatmap database backing...
|
||||
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.
|
||||
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);
|
||||
|
||||
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(),
|
||||
$@"Incorrect database beatmap count post-import ({resultBeatmaps.Count()} but should be {set.Beatmaps.Count}).");
|
||||
int countBeatmapSetBeatmaps = 0;
|
||||
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.Count > 0);
|
||||
|
@ -550,7 +550,7 @@ namespace osu.Game.Beatmaps
|
||||
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()
|
||||
{
|
||||
@ -573,6 +573,8 @@ namespace osu.Game.Beatmaps
|
||||
}
|
||||
catch { return new TrackVirtual(); }
|
||||
}
|
||||
|
||||
protected override Waveform GetWaveform() => new Waveform(store.GetStream(getPathForFile(Metadata.AudioFile)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -613,7 +613,7 @@ namespace osu.Game.Beatmaps.Formats
|
||||
string line;
|
||||
while ((line = stream.ReadLine()) != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
continue;
|
||||
|
||||
if (line.StartsWith("//"))
|
||||
@ -679,10 +679,12 @@ namespace osu.Game.Beatmaps.Formats
|
||||
|
||||
private KeyValuePair<string, string> splitKeyVal(string line, char separator)
|
||||
{
|
||||
var split = line.Trim().Split(new[] { separator }, 2);
|
||||
|
||||
return new KeyValuePair<string, string>
|
||||
(
|
||||
line.Remove(line.IndexOf(separator)).Trim(),
|
||||
line.Substring(line.IndexOf(separator) + 1).Trim()
|
||||
split[0].Trim(),
|
||||
split.Length > 1 ? split[1].Trim() : string.Empty
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ namespace osu.Game.Beatmaps
|
||||
protected abstract Beatmap GetBeatmap();
|
||||
protected abstract Texture GetBackground();
|
||||
protected abstract Track GetTrack();
|
||||
protected virtual Waveform GetWaveform() => new Waveform();
|
||||
|
||||
private Beatmap beatmap;
|
||||
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 void TransferTo(WorkingBeatmap other)
|
||||
@ -114,6 +126,8 @@ namespace osu.Game.Beatmaps
|
||||
{
|
||||
background?.Dispose();
|
||||
background = null;
|
||||
|
||||
waveform?.Dispose();
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
private readonly SpriteIcon icon;
|
||||
private readonly Box hover;
|
||||
private readonly Container content;
|
||||
private const float button_size = 30;
|
||||
|
||||
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
|
||||
{
|
||||
get { return icon.Icon; }
|
||||
set { icon.Icon = value; }
|
||||
}
|
||||
|
||||
private const float button_size = 30;
|
||||
private Color4 flashColour;
|
||||
|
||||
/// <summary>
|
||||
/// The icon scale. This does not affect <see cref="IconButton.Scale"/>.
|
||||
/// </summary>
|
||||
public Vector2 IconScale
|
||||
{
|
||||
get { return icon.Scale; }
|
||||
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()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
Origin = Anchor.Centre;
|
||||
Anchor = Anchor.Centre;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
content = new Container
|
||||
@ -48,7 +107,6 @@ namespace osu.Game.Graphics.UserInterface
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Size = new Vector2(button_size),
|
||||
|
||||
CornerRadius = 5,
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
@ -78,8 +136,11 @@ namespace osu.Game.Graphics.UserInterface
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
hover.Colour = colours.Yellow.Opacity(0.6f);
|
||||
flashColour = colours.Yellow;
|
||||
if (hoverColour == null)
|
||||
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);
|
||||
}
|
||||
@ -87,18 +148,20 @@ namespace osu.Game.Graphics.UserInterface
|
||||
protected override bool OnHover(InputState state)
|
||||
{
|
||||
hover.FadeIn(500, Easing.OutQuint);
|
||||
icon.FadeColour(IconHoverColour, 500, Easing.OutQuint);
|
||||
return base.OnHover(state);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(InputState state)
|
||||
{
|
||||
hover.FadeOut(500, Easing.OutQuint);
|
||||
icon.FadeColour(IconColour, 500, Easing.OutQuint);
|
||||
base.OnHoverLost(state);
|
||||
}
|
||||
|
||||
protected override bool OnClick(InputState state)
|
||||
{
|
||||
hover.FlashColour(flashColour, 800, Easing.OutQuint);
|
||||
hover.FlashColour(FlashColour, 800, Easing.OutQuint);
|
||||
return base.OnClick(state);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ namespace osu.Game.Online.API.Requests
|
||||
private int onlineId { get; set; }
|
||||
|
||||
[JsonProperty(@"creator")]
|
||||
private string creatorUsername;
|
||||
private string creatorUsername { get; set; }
|
||||
|
||||
[JsonProperty(@"user_id")]
|
||||
private long creatorId = 1;
|
||||
|
@ -15,7 +15,6 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Graphics.Processing;
|
||||
using osu.Game.Online.API;
|
||||
using SQLite.Net;
|
||||
using osu.Framework.Graphics.Performance;
|
||||
@ -186,7 +185,7 @@ namespace osu.Game
|
||||
|
||||
GlobalKeyBindingInputManager globalBinding;
|
||||
|
||||
base.Content.Add(new RatioAdjust
|
||||
base.Content.Add(new DrawSizePreservingFillContainer
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
|
@ -159,7 +159,7 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,7 @@ namespace osu.Game.Overlays.MedalSplash
|
||||
},
|
||||
description = new TextFlowContainer
|
||||
{
|
||||
TextAnchor = Anchor.TopCentre,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
@ -115,15 +116,16 @@ namespace osu.Game.Overlays.MedalSplash
|
||||
medalSprite.Texture = textures.Get(medal.ImageUrl);
|
||||
medalGlow.Texture = textures.Get(@"MedalSplash/medal-glow");
|
||||
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()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
updateState();
|
||||
|
||||
unlocked.Position = new Vector2(0f, medalContainer.DrawSize.Y / 2 + 10);
|
||||
infoFlow.Position = new Vector2(0f, unlocked.Position.Y + 90);
|
||||
}
|
||||
|
||||
public DisplayState State
|
||||
@ -172,6 +174,7 @@ namespace osu.Game.Overlays.MedalSplash
|
||||
|
||||
this.ScaleTo(scale_when_full, duration, Easing.OutExpo);
|
||||
this.MoveToY(MedalOverlay.DISC_SIZE / 2 - 60, duration, Easing.OutExpo);
|
||||
unlocked.Show();
|
||||
name.FadeInFromZero(duration + 100);
|
||||
description.FadeInFromZero(duration * 2);
|
||||
break;
|
||||
|
@ -161,11 +161,15 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
prevButton = new IconButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Action = prev,
|
||||
Icon = FontAwesome.fa_step_backward,
|
||||
},
|
||||
playButton = new IconButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Scale = new Vector2(1.4f),
|
||||
IconScale = new Vector2(1.4f),
|
||||
Action = play,
|
||||
@ -173,6 +177,8 @@ namespace osu.Game.Overlays
|
||||
},
|
||||
nextButton = new IconButton
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Action = next,
|
||||
Icon = FontAwesome.fa_step_forward,
|
||||
},
|
||||
|
@ -25,6 +25,11 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
/// </summary>
|
||||
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)
|
||||
{
|
||||
HitObject = hitObject;
|
||||
|
@ -200,4 +200,4 @@ namespace osu.Game.Rulesets.Objects
|
||||
return interpolateVertices(indexOfDistance(d), d) + Offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Screens.Edit.Screens.Compose.Timeline;
|
||||
|
||||
namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
{
|
||||
@ -13,6 +14,7 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
{
|
||||
public Compose()
|
||||
{
|
||||
ScrollableTimeline timeline;
|
||||
Children = new[]
|
||||
{
|
||||
new Container
|
||||
@ -31,11 +33,22 @@ namespace osu.Game.Screens.Edit.Screens.Compose
|
||||
{
|
||||
Name = "Content",
|
||||
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>.
|
||||
// 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.MedalSplash;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
@ -10,6 +13,12 @@ namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public override string Description => @"medal get!";
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(MedalOverlay),
|
||||
typeof(DrawableMedal),
|
||||
};
|
||||
|
||||
public TestCaseMedalOverlay()
|
||||
{
|
||||
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>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
@ -77,7 +76,6 @@
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
@ -103,7 +101,6 @@
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<LangVersion>6</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<StartArguments>--tests</StartArguments>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
@ -266,6 +263,7 @@
|
||||
<Compile Include="Beatmaps\Drawables\BeatmapPanel.cs" />
|
||||
<Compile Include="Beatmaps\Drawables\BeatmapSetCover.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\DifficultyIcon.cs" />
|
||||
<Compile Include="Beatmaps\Drawables\Panel.cs" />
|
||||
@ -274,6 +272,7 @@
|
||||
<Compile Include="Beatmaps\Formats\OsuLegacyDecoder.cs" />
|
||||
<Compile Include="Beatmaps\IO\ArchiveReader.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\BlurredIcon.cs" />
|
||||
<Compile Include="Screens\Play\BreaksOverlay\BreakOverlay.cs" />
|
||||
@ -312,7 +311,6 @@
|
||||
<Compile Include="Graphics\Cursor\OsuTooltipContainer.cs" />
|
||||
<Compile Include="Graphics\IHasAccentColour.cs" />
|
||||
<Compile Include="Graphics\OsuColour.cs" />
|
||||
<Compile Include="Graphics\Processing\RatioAdjust.cs" />
|
||||
<Compile Include="Graphics\SpriteIcon.cs" />
|
||||
<Compile Include="Graphics\Sprites\OsuSpriteText.cs" />
|
||||
<Compile Include="Graphics\UserInterface\BackButton.cs" />
|
||||
@ -630,6 +628,8 @@
|
||||
<Compile Include="Screens\Edit\Screens\Design\Design.cs" />
|
||||
<Compile Include="Screens\Edit\Screens\EditorScreen.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\Menu\Button.cs" />
|
||||
<Compile Include="Screens\Menu\ButtonSystem.cs" />
|
||||
@ -756,10 +756,12 @@
|
||||
<Compile Include="Tests\Visual\TestCaseDrawableRoom.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseDrawings.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseEditor.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseEditorComposeTimeline.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseEditorMenuBar.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseEditorSummaryTimeline.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseGamefield.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseGraph.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseIconButton.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseKeyConfiguration.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseKeyCounter.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseLeaderboard.cs" />
|
||||
@ -788,6 +790,7 @@
|
||||
<Compile Include="Tests\Visual\TestCaseTwoLayerButton.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseUserPanel.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseUserProfile.cs" />
|
||||
<Compile Include="Tests\Visual\TestCaseWaveform.cs" />
|
||||
<Compile Include="Users\Avatar.cs" />
|
||||
<Compile Include="Users\Country.cs" />
|
||||
<Compile Include="Users\Medal.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user