mirror of
https://github.com/osukey/osukey.git
synced 2025-08-06 16:13:57 +09:00
Merge remote-tracking branch 'origin/master' into timingchange-improvements
This commit is contained in:
Submodule osu-framework updated: c687b8b102...107c551767
@ -1,118 +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.Linq;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
|
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Desktop.Tests.Visual
|
|
||||||
{
|
|
||||||
internal class TestCaseTaikoHitObjects : OsuTestCase
|
|
||||||
{
|
|
||||||
public override string Description => "Taiko hit objects";
|
|
||||||
|
|
||||||
private bool kiai;
|
|
||||||
|
|
||||||
public TestCaseTaikoHitObjects()
|
|
||||||
{
|
|
||||||
AddToggleStep("Kiai", b =>
|
|
||||||
{
|
|
||||||
kiai = !kiai;
|
|
||||||
updateKiaiState();
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new CirclePiece
|
|
||||||
{
|
|
||||||
Position = new Vector2(100, 100),
|
|
||||||
AccentColour = Color4.DarkRed,
|
|
||||||
KiaiMode = kiai,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new CentreHitSymbolPiece()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new CirclePiece(true)
|
|
||||||
{
|
|
||||||
Position = new Vector2(350, 100),
|
|
||||||
AccentColour = Color4.DarkRed,
|
|
||||||
KiaiMode = kiai,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new CentreHitSymbolPiece()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new CirclePiece
|
|
||||||
{
|
|
||||||
Position = new Vector2(100, 300),
|
|
||||||
AccentColour = Color4.DarkBlue,
|
|
||||||
KiaiMode = kiai,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new RimHitSymbolPiece()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new CirclePiece(true)
|
|
||||||
{
|
|
||||||
Position = new Vector2(350, 300),
|
|
||||||
AccentColour = Color4.DarkBlue,
|
|
||||||
KiaiMode = kiai,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new RimHitSymbolPiece()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new CirclePiece
|
|
||||||
{
|
|
||||||
Position = new Vector2(100, 500),
|
|
||||||
AccentColour = Color4.Orange,
|
|
||||||
KiaiMode = kiai,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new SwellSymbolPiece()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new ElongatedCirclePiece
|
|
||||||
{
|
|
||||||
Position = new Vector2(575, 100),
|
|
||||||
AccentColour = Color4.Orange,
|
|
||||||
KiaiMode = kiai,
|
|
||||||
Length = 0.10f,
|
|
||||||
PlayfieldLengthReference = () => DrawSize.X
|
|
||||||
});
|
|
||||||
|
|
||||||
Add(new ElongatedCirclePiece(true)
|
|
||||||
{
|
|
||||||
Position = new Vector2(575, 300),
|
|
||||||
AccentColour = Color4.Orange,
|
|
||||||
KiaiMode = kiai,
|
|
||||||
Length = 0.10f,
|
|
||||||
PlayfieldLengthReference = () => DrawSize.X
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateKiaiState()
|
|
||||||
{
|
|
||||||
foreach (var c in Children.OfType<CirclePiece>())
|
|
||||||
c.KiaiMode = kiai;
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class BaseCircle : Container
|
|
||||||
{
|
|
||||||
protected readonly CirclePiece Piece;
|
|
||||||
|
|
||||||
protected BaseCircle(CirclePiece piece)
|
|
||||||
{
|
|
||||||
Piece = piece;
|
|
||||||
|
|
||||||
Add(Piece);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,12 +12,14 @@ using osu.Game.Rulesets.Taiko.Objects;
|
|||||||
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Taiko.UI;
|
using osu.Game.Rulesets.Taiko.UI;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
namespace osu.Desktop.Tests.Visual
|
namespace osu.Desktop.Tests.Visual
|
||||||
{
|
{
|
||||||
internal class TestCaseTaikoPlayfield : OsuTestCase
|
internal class TestCaseTaikoPlayfield : OsuTestCase
|
||||||
{
|
{
|
||||||
private const double default_duration = 300;
|
private const double default_duration = 1000;
|
||||||
private const float scroll_time = 1000;
|
private const float scroll_time = 1000;
|
||||||
|
|
||||||
public override string Description => "Taiko playfield";
|
public override string Description => "Taiko playfield";
|
||||||
@ -30,7 +32,8 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
|
|
||||||
public TestCaseTaikoPlayfield()
|
public TestCaseTaikoPlayfield()
|
||||||
{
|
{
|
||||||
AddStep("Hit!", addHitJudgement);
|
AddStep("Hit!", () => addHitJudgement(false));
|
||||||
|
AddStep("Kiai hit", () => addHitJudgement(true));
|
||||||
AddStep("Miss :(", addMissJudgement);
|
AddStep("Miss :(", addMissJudgement);
|
||||||
AddStep("DrumRoll", () => addDrumRoll(false));
|
AddStep("DrumRoll", () => addDrumRoll(false));
|
||||||
AddStep("Strong DrumRoll", () => addDrumRoll(true));
|
AddStep("Strong DrumRoll", () => addDrumRoll(true));
|
||||||
@ -55,7 +58,7 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT,
|
Height = TaikoPlayfield.DEFAULT_HEIGHT,
|
||||||
Clock = new FramedClock(rateAdjustClock),
|
Clock = new FramedClock(rateAdjustClock),
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
@ -84,7 +87,7 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
addDrumRoll(true);
|
addDrumRoll(true);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
addSwell(1000);
|
addSwell();
|
||||||
delay = scroll_time - 100;
|
delay = scroll_time - 100;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -96,16 +99,25 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, rng.Next(25, 400)), 500);
|
playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, rng.Next(25, 400)), 500);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT), 500);
|
playfieldContainer.Delay(delay).ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_HEIGHT), 500);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addHitJudgement()
|
private void addHitJudgement(bool kiai)
|
||||||
{
|
{
|
||||||
TaikoHitResult hitResult = RNG.Next(2) == 0 ? TaikoHitResult.Good : TaikoHitResult.Great;
|
TaikoHitResult hitResult = RNG.Next(2) == 0 ? TaikoHitResult.Good : TaikoHitResult.Great;
|
||||||
|
|
||||||
var h = new DrawableTestHit(new Hit())
|
var cpi = new ControlPointInfo();
|
||||||
|
cpi.EffectPoints.Add(new EffectControlPoint
|
||||||
|
{
|
||||||
|
KiaiMode = kiai
|
||||||
|
});
|
||||||
|
|
||||||
|
Hit hit = new Hit();
|
||||||
|
hit.ApplyDefaults(cpi, new BeatmapDifficulty());
|
||||||
|
|
||||||
|
var h = new DrawableTestHit(hit)
|
||||||
{
|
{
|
||||||
X = RNG.NextSingle(hitResult == TaikoHitResult.Good ? -0.1f : -0.05f, hitResult == TaikoHitResult.Good ? 0.1f : 0.05f),
|
X = RNG.NextSingle(hitResult == TaikoHitResult.Good ? -0.1f : -0.05f, hitResult == TaikoHitResult.Good ? 0.1f : 0.05f),
|
||||||
Judgement = new TaikoJudgement
|
Judgement = new TaikoJudgement
|
||||||
@ -179,7 +191,8 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
Hit h = new Hit
|
Hit h = new Hit
|
||||||
{
|
{
|
||||||
StartTime = playfield.Time.Current + scroll_time,
|
StartTime = playfield.Time.Current + scroll_time,
|
||||||
ScrollTime = scroll_time
|
ScrollTime = scroll_time,
|
||||||
|
IsStrong = strong
|
||||||
};
|
};
|
||||||
|
|
||||||
if (strong)
|
if (strong)
|
||||||
@ -193,7 +206,8 @@ namespace osu.Desktop.Tests.Visual
|
|||||||
Hit h = new Hit
|
Hit h = new Hit
|
||||||
{
|
{
|
||||||
StartTime = playfield.Time.Current + scroll_time,
|
StartTime = playfield.Time.Current + scroll_time,
|
||||||
ScrollTime = scroll_time
|
ScrollTime = scroll_time,
|
||||||
|
IsStrong = strong
|
||||||
};
|
};
|
||||||
|
|
||||||
if (strong)
|
if (strong)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -104,7 +104,6 @@
|
|||||||
<Compile Include="Visual\TestCaseSocial.cs" />
|
<Compile Include="Visual\TestCaseSocial.cs" />
|
||||||
<Compile Include="Visual\TestCaseSongProgress.cs" />
|
<Compile Include="Visual\TestCaseSongProgress.cs" />
|
||||||
<Compile Include="Visual\TestCaseTabControl.cs" />
|
<Compile Include="Visual\TestCaseTabControl.cs" />
|
||||||
<Compile Include="Visual\TestCaseTaikoHitObjects.cs" />
|
|
||||||
<Compile Include="Visual\TestCaseTaikoPlayfield.cs" />
|
<Compile Include="Visual\TestCaseTaikoPlayfield.cs" />
|
||||||
<Compile Include="Visual\TestCaseTextAwesome.cs" />
|
<Compile Include="Visual\TestCaseTextAwesome.cs" />
|
||||||
<Compile Include="Visual\TestCaseTwoLayerButton.cs" />
|
<Compile Include="Visual\TestCaseTwoLayerButton.cs" />
|
||||||
@ -170,4 +169,4 @@
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
</Project>
|
</Project>
|
@ -155,10 +155,6 @@
|
|||||||
<Project>{007b2356-ab6f-4bd9-96d5-116fc2dce69a}</Project>
|
<Project>{007b2356-ab6f-4bd9-96d5-116fc2dce69a}</Project>
|
||||||
<Name>osu.Framework.Testing</Name>
|
<Name>osu.Framework.Testing</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\osu-framework\osu.Framework.VisualTestBrowser\osu.Framework.VisualTestBrowser.csproj">
|
|
||||||
<Project>{1f02f11c-2c66-4d25-bbb5-5c752aad3e62}</Project>
|
|
||||||
<Name>osu.Framework.VisualTestBrowser</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
|
||||||
<Project>{c76bf5b3-985e-4d39-95fe-97c9c879b83a}</Project>
|
<Project>{c76bf5b3-985e-4d39-95fe-97c9c879b83a}</Project>
|
||||||
<Name>osu.Framework</Name>
|
<Name>osu.Framework</Name>
|
||||||
|
@ -10,6 +10,7 @@ using osu.Game.Rulesets.Taiko.Judgements;
|
|||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
|
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||||
{
|
{
|
||||||
@ -30,6 +31,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
public DrawableDrumRoll(DrumRoll drumRoll)
|
public DrawableDrumRoll(DrumRoll drumRoll)
|
||||||
: base(drumRoll)
|
: base(drumRoll)
|
||||||
{
|
{
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
AutoSizeAxes = Axes.X;
|
||||||
|
|
||||||
foreach (var tick in drumRoll.Ticks)
|
foreach (var tick in drumRoll.Ticks)
|
||||||
{
|
{
|
||||||
var newTick = new DrawableDrumRollTick(tick)
|
var newTick = new DrawableDrumRollTick(tick)
|
||||||
@ -46,7 +50,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
|
|
||||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong };
|
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong };
|
||||||
|
|
||||||
protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece(HitObject.IsStrong)
|
protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece
|
||||||
{
|
{
|
||||||
Length = (float)(HitObject.Duration / HitObject.ScrollTime),
|
Length = (float)(HitObject.Duration / HitObject.ScrollTime),
|
||||||
PlayfieldLengthReference = () => Parent.DrawSize.X
|
PlayfieldLengthReference = () => Parent.DrawSize.X
|
||||||
|
@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
public DrawableDrumRollTick(DrumRollTick tick)
|
public DrawableDrumRollTick(DrumRollTick tick)
|
||||||
: base(tick)
|
: base(tick)
|
||||||
{
|
{
|
||||||
|
FillMode = FillMode.Fit;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TaikoPiece CreateMainPiece() => new TickPiece
|
protected override TaikoPiece CreateMainPiece() => new TickPiece
|
||||||
|
@ -26,6 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
protected DrawableHit(Hit hit)
|
protected DrawableHit(Hit hit)
|
||||||
: base(hit)
|
: base(hit)
|
||||||
{
|
{
|
||||||
|
FillMode = FillMode.Fit;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void CheckJudgement(bool userTriggered)
|
protected override void CheckJudgement(bool userTriggered)
|
||||||
@ -92,12 +93,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
|
|
||||||
Content.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad);
|
Content.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad);
|
||||||
|
|
||||||
this.FadeOut(800)
|
this.MoveToY(-gravity_travel_height, gravity_time, Easing.Out)
|
||||||
.MoveToY(-gravity_travel_height, gravity_time, Easing.Out)
|
|
||||||
.Then()
|
.Then()
|
||||||
.MoveToY(gravity_travel_height * 2, gravity_time * 2, Easing.In);
|
.MoveToY(gravity_travel_height * 2, gravity_time * 2, Easing.In);
|
||||||
|
|
||||||
Expire();
|
this.FadeOut(800)
|
||||||
|
.Expire();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ using osu.Framework.Input;
|
|||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
using osu.Game.Rulesets.Taiko.Judgements;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||||
{
|
{
|
||||||
@ -28,8 +27,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TaikoPiece CreateMainPiece() => new CirclePiece(true);
|
|
||||||
|
|
||||||
protected override TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement();
|
protected override TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement();
|
||||||
|
|
||||||
protected override void CheckJudgement(bool userTriggered)
|
protected override void CheckJudgement(bool userTriggered)
|
||||||
|
@ -35,8 +35,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
private readonly CircularContainer targetRing;
|
private readonly CircularContainer targetRing;
|
||||||
private readonly CircularContainer expandingRing;
|
private readonly CircularContainer expandingRing;
|
||||||
|
|
||||||
private readonly CirclePiece circlePiece;
|
|
||||||
|
|
||||||
private readonly Key[] rimKeys = { Key.D, Key.K };
|
private readonly Key[] rimKeys = { Key.D, Key.K };
|
||||||
private readonly Key[] centreKeys = { Key.F, Key.J };
|
private readonly Key[] centreKeys = { Key.F, Key.J };
|
||||||
private Key[] lastKeySet;
|
private Key[] lastKeySet;
|
||||||
@ -52,89 +50,81 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
public DrawableSwell(Swell swell)
|
public DrawableSwell(Swell swell)
|
||||||
: base(swell)
|
: base(swell)
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
FillMode = FillMode.Fit;
|
||||||
|
|
||||||
|
Add(bodyContainer = new Container
|
||||||
{
|
{
|
||||||
bodyContainer = new Container
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Depth = 1,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
expandingRing = new CircularContainer
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
expandingRing = new CircularContainer
|
Name = "Expanding ring",
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Alpha = 0,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
BlendingMode = BlendingMode.Additive,
|
||||||
|
Masking = true,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
Name = "Expanding ring",
|
new Box
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Alpha = 0,
|
|
||||||
Size = new Vector2(TaikoHitObject.DEFAULT_CIRCLE_DIAMETER),
|
|
||||||
BlendingMode = BlendingMode.Additive,
|
|
||||||
Masking = true,
|
|
||||||
Children = new[]
|
|
||||||
{
|
{
|
||||||
new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
{
|
Alpha = inner_ring_alpha,
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = inner_ring_alpha,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
targetRing = new CircularContainer
|
},
|
||||||
|
targetRing = new CircularContainer
|
||||||
|
{
|
||||||
|
Name = "Target ring (thick border)",
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
BorderThickness = target_ring_thick_border,
|
||||||
|
BlendingMode = BlendingMode.Additive,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Name = "Target ring (thick border)",
|
new Box
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Size = new Vector2(TaikoHitObject.DEFAULT_CIRCLE_DIAMETER),
|
|
||||||
Masking = true,
|
|
||||||
BorderThickness = target_ring_thick_border,
|
|
||||||
BlendingMode = BlendingMode.Additive,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
},
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
Name = "Target ring (thin border)",
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
BorderThickness = target_ring_thin_border,
|
||||||
|
BorderColour = Color4.White,
|
||||||
|
Children = new[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
new Box
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true
|
|
||||||
},
|
|
||||||
new CircularContainer
|
|
||||||
{
|
|
||||||
Name = "Target ring (thin border)",
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
BorderThickness = target_ring_thin_border,
|
|
||||||
BorderColour = Color4.White,
|
|
||||||
Children = new[]
|
|
||||||
{
|
{
|
||||||
new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
{
|
Alpha = 0,
|
||||||
RelativeSizeAxes = Axes.Both,
|
AlwaysPresent = true
|
||||||
Alpha = 0,
|
|
||||||
AlwaysPresent = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
circlePiece = new CirclePiece
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
symbol = new SwellSymbolPiece()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
|
MainPiece.Add(symbol = new SwellSymbolPiece());
|
||||||
|
|
||||||
circlePiece.KiaiMode = HitObject.Kiai;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
circlePiece.AccentColour = colours.YellowDark;
|
MainPiece.AccentColour = colours.YellowDark;
|
||||||
expandingRing.Colour = colours.YellowLight;
|
expandingRing.Colour = colours.YellowLight;
|
||||||
targetRing.BorderColour = colours.YellowDark.Opacity(0.25f);
|
targetRing.BorderColour = colours.YellowDark.Opacity(0.25f);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.Taiko.Judgements;
|
using osu.Game.Rulesets.Taiko.Judgements;
|
||||||
@ -24,12 +23,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
|
|
||||||
public override Vector2 OriginPosition => new Vector2(DrawHeight / 2);
|
public override Vector2 OriginPosition => new Vector2(DrawHeight / 2);
|
||||||
|
|
||||||
protected override Container<Drawable> Content => bodyContainer;
|
|
||||||
|
|
||||||
protected readonly TaikoPiece MainPiece;
|
protected readonly TaikoPiece MainPiece;
|
||||||
|
|
||||||
private readonly Container bodyContainer;
|
|
||||||
|
|
||||||
public new TaikoHitType HitObject;
|
public new TaikoHitType HitObject;
|
||||||
|
|
||||||
protected DrawableTaikoHitObject(TaikoHitType hitObject)
|
protected DrawableTaikoHitObject(TaikoHitType hitObject)
|
||||||
@ -40,19 +35,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
Anchor = Anchor.CentreLeft;
|
Anchor = Anchor.CentreLeft;
|
||||||
Origin = Anchor.Custom;
|
Origin = Anchor.Custom;
|
||||||
|
|
||||||
AutoSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Size = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE);
|
||||||
|
|
||||||
RelativePositionAxes = Axes.X;
|
RelativePositionAxes = Axes.X;
|
||||||
|
|
||||||
AddInternal(bodyContainer = new Container
|
Add(MainPiece = CreateMainPiece());
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
MainPiece = CreateMainPiece()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
MainPiece.KiaiMode = HitObject.Kiai;
|
MainPiece.KiaiMode = HitObject.Kiai;
|
||||||
|
|
||||||
LifetimeStart = HitObject.StartTime - HitObject.ScrollTime * 2;
|
LifetimeStart = HitObject.StartTime - HitObject.ScrollTime * 2;
|
||||||
@ -60,7 +48,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
|||||||
|
|
||||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
||||||
|
|
||||||
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(HitObject.IsStrong);
|
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the scroll position of the DrawableHitObject relative to the offset between
|
/// Sets the scroll position of the DrawableHitObject relative to the offset between
|
||||||
|
@ -11,19 +11,24 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The symbol used for centre hit pieces.
|
/// The symbol used for centre hit pieces.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CentreHitSymbolPiece : CircularContainer
|
public class CentreHitSymbolPiece : Container
|
||||||
{
|
{
|
||||||
public CentreHitSymbolPiece()
|
public CentreHitSymbolPiece()
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
Size = new Vector2(CirclePiece.SYMBOL_INNER_SIZE);
|
|
||||||
Masking = true;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Size = new Vector2(CirclePiece.SYMBOL_SIZE);
|
||||||
|
Padding = new MarginPadding(CirclePiece.SYMBOL_BORDER);
|
||||||
|
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
new Box
|
new CircularContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
Children = new[] { new Box { RelativeSizeAxes = Axes.Both } }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CirclePiece : TaikoPiece
|
public class CirclePiece : TaikoPiece
|
||||||
{
|
{
|
||||||
public const float SYMBOL_SIZE = TaikoHitObject.DEFAULT_CIRCLE_DIAMETER * 0.45f;
|
public const float SYMBOL_SIZE = 0.45f;
|
||||||
public const float SYMBOL_BORDER = 8;
|
public const float SYMBOL_BORDER = 8;
|
||||||
public const float SYMBOL_INNER_SIZE = SYMBOL_SIZE - 2 * SYMBOL_BORDER;
|
|
||||||
private const double pre_beat_transition_time = 80;
|
private const double pre_beat_transition_time = 80;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -64,7 +63,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
public Box FlashBox;
|
public Box FlashBox;
|
||||||
|
|
||||||
public CirclePiece(bool isStrong = false)
|
public CirclePiece()
|
||||||
{
|
{
|
||||||
EarlyActivationMilliseconds = pre_beat_transition_time;
|
EarlyActivationMilliseconds = pre_beat_transition_time;
|
||||||
|
|
||||||
@ -120,28 +119,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
},
|
},
|
||||||
content = new Container
|
content = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Name = "Content",
|
Name = "Content",
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isStrong)
|
|
||||||
{
|
|
||||||
Size *= TaikoHitObject.STRONG_CIRCLE_DIAMETER_SCALE;
|
|
||||||
|
|
||||||
//default for symbols etc.
|
|
||||||
Content.Scale *= TaikoHitObject.STRONG_CIRCLE_DIAMETER_SCALE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
//we want to allow for width of content to remain mapped to the area inside us, regardless of the scale applied above.
|
|
||||||
Content.Width = 1 / Content.Scale.X;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private const float edge_alpha_kiai = 0.5f;
|
private const float edge_alpha_kiai = 0.5f;
|
||||||
|
@ -18,8 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public float Length;
|
public float Length;
|
||||||
|
|
||||||
public ElongatedCirclePiece(bool isStrong = false) : base(isStrong)
|
public ElongatedCirclePiece()
|
||||||
{
|
{
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
|
@ -18,7 +18,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
Size = new Vector2(CirclePiece.SYMBOL_SIZE);
|
Size = new Vector2(CirclePiece.SYMBOL_SIZE);
|
||||||
|
|
||||||
BorderThickness = CirclePiece.SYMBOL_BORDER;
|
BorderThickness = CirclePiece.SYMBOL_BORDER;
|
||||||
BorderColour = Color4.White;
|
BorderColour = Color4.White;
|
||||||
Masking = true;
|
Masking = true;
|
||||||
|
@ -1,24 +1,36 @@
|
|||||||
// 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 osu.Framework.Graphics;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The symbol used for swell pieces.
|
/// The symbol used for swell pieces.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SwellSymbolPiece : SpriteIcon
|
public class SwellSymbolPiece : Container
|
||||||
{
|
{
|
||||||
public SwellSymbolPiece()
|
public SwellSymbolPiece()
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
Size = new Vector2(CirclePiece.SYMBOL_INNER_SIZE);
|
|
||||||
Icon = FontAwesome.fa_asterisk;
|
RelativeSizeAxes = Axes.Both;
|
||||||
Shadow = false;
|
Size = new Vector2(CirclePiece.SYMBOL_SIZE);
|
||||||
|
Padding = new MarginPadding(CirclePiece.SYMBOL_BORDER);
|
||||||
|
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new SpriteIcon
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Icon = FontAwesome.fa_asterisk,
|
||||||
|
Shadow = false
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
// 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 osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using OpenTK;
|
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
@ -35,8 +35,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
public TaikoPiece()
|
public TaikoPiece()
|
||||||
{
|
{
|
||||||
//just a default
|
RelativeSizeAxes = Axes.Both;
|
||||||
Size = new Vector2(TaikoHitObject.DEFAULT_CIRCLE_DIAMETER);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
/// Any tick that is not the first for a drumroll is not filled, but is instead displayed
|
/// Any tick that is not the first for a drumroll is not filled, but is instead displayed
|
||||||
/// as a hollow circle. This is what controls the border width of that circle.
|
/// as a hollow circle. This is what controls the border width of that circle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float tick_border_width = TaikoHitObject.DEFAULT_CIRCLE_DIAMETER / 16;
|
private const float tick_border_width = 5;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The size of a tick.
|
/// The size of a tick.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float tick_size = TaikoHitObject.DEFAULT_CIRCLE_DIAMETER / 6;
|
private const float tick_size = 0.35f;
|
||||||
|
|
||||||
private bool filled;
|
private bool filled;
|
||||||
public bool Filled
|
public bool Filled
|
||||||
@ -37,6 +37,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
public TickPiece()
|
public TickPiece()
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.Centre;
|
||||||
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
FillMode = FillMode.Fit;
|
||||||
Size = new Vector2(tick_size);
|
Size = new Vector2(tick_size);
|
||||||
|
|
||||||
Add(new CircularContainer
|
Add(new CircularContainer
|
||||||
|
@ -4,31 +4,25 @@
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Taiko.UI;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Objects
|
namespace osu.Game.Rulesets.Taiko.Objects
|
||||||
{
|
{
|
||||||
public abstract class TaikoHitObject : HitObject
|
public abstract class TaikoHitObject : HitObject
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Diameter of a circle relative to the size of the <see cref="TaikoPlayfield"/>.
|
/// Default size of a drawable taiko hit object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float PLAYFIELD_RELATIVE_DIAMETER = 0.45f;
|
public const float DEFAULT_SIZE = 0.45f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scale multiplier for a strong circle.
|
/// Scale multiplier for a strong drawable taiko hit object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float STRONG_CIRCLE_DIAMETER_SCALE = 1.4f;
|
public const float STRONG_SCALE = 1.4f;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default circle diameter.
|
/// Default size of a strong drawable taiko hit object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float DEFAULT_CIRCLE_DIAMETER = TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT * PLAYFIELD_RELATIVE_DIAMETER;
|
public const float DEFAULT_STRONG_SIZE = DEFAULT_SIZE * STRONG_SCALE;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default strong circle diameter.
|
|
||||||
/// </summary>
|
|
||||||
public const float DEFAULT_STRONG_CIRCLE_DIAMETER = DEFAULT_CIRCLE_DIAMETER * STRONG_CIRCLE_DIAMETER_SCALE;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time taken from the initial (off-screen) spawn position to the centre of the hit target for a <see cref="TimingControlPoint.BeatLength"/> of 1000ms.
|
/// The time taken from the initial (off-screen) spawn position to the centre of the hit target for a <see cref="TimingControlPoint.BeatLength"/> of 1000ms.
|
||||||
|
@ -30,10 +30,11 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
Judgement = judgement;
|
Judgement = judgement;
|
||||||
|
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.CentreLeft;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
Size = new Vector2(TaikoPlayfield.HIT_TARGET_OFFSET + TaikoHitObject.DEFAULT_CIRCLE_DIAMETER);
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
Size = new Vector2(TaikoHitObject.DEFAULT_SIZE);
|
||||||
|
|
||||||
RelativePositionAxes = Axes.Both;
|
RelativePositionAxes = Axes.Both;
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void VisualiseSecondHit()
|
public void VisualiseSecondHit()
|
||||||
{
|
{
|
||||||
this.ResizeTo(new Vector2(TaikoPlayfield.HIT_TARGET_OFFSET + TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER), 50);
|
this.ResizeTo(new Vector2(TaikoHitObject.DEFAULT_STRONG_SIZE), 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class HitTarget : Container
|
internal class HitTarget : Container
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The 1px inner border of the taiko playfield.
|
|
||||||
/// </summary>
|
|
||||||
private const float border_offset = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Thickness of all drawn line pieces.
|
/// Thickness of all drawn line pieces.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -27,8 +22,6 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
public HitTarget()
|
public HitTarget()
|
||||||
{
|
{
|
||||||
Size = new Vector2(TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT);
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
@ -36,8 +29,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Name = "Bar Upper",
|
Name = "Bar Upper",
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
Y = border_offset,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Size = new Vector2(border_thickness, (TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT - TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER) / 2f - border_offset),
|
Size = new Vector2(border_thickness, (1 - TaikoHitObject.DEFAULT_STRONG_SIZE) / 2f),
|
||||||
Alpha = 0.1f
|
Alpha = 0.1f
|
||||||
},
|
},
|
||||||
new CircularContainer
|
new CircularContainer
|
||||||
@ -45,7 +38,9 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Name = "Strong Hit Ring",
|
Name = "Strong Hit Ring",
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER),
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
Scale = new Vector2(TaikoHitObject.DEFAULT_STRONG_SIZE),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
BorderThickness = border_thickness,
|
BorderThickness = border_thickness,
|
||||||
@ -65,7 +60,9 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Name = "Normal Hit Ring",
|
Name = "Normal Hit Ring",
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Size = new Vector2(TaikoHitObject.DEFAULT_CIRCLE_DIAMETER),
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
Scale = new Vector2(TaikoHitObject.DEFAULT_SIZE),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
BorderThickness = border_thickness,
|
BorderThickness = border_thickness,
|
||||||
@ -85,8 +82,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Name = "Bar Lower",
|
Name = "Bar Lower",
|
||||||
Anchor = Anchor.BottomCentre,
|
Anchor = Anchor.BottomCentre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
Y = -border_offset,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Size = new Vector2(border_thickness, (TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT - TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER) / 2f - border_offset),
|
Size = new Vector2(border_thickness, (1 - TaikoHitObject.DEFAULT_STRONG_SIZE) / 2f),
|
||||||
Alpha = 0.1f
|
Alpha = 0.1f
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -21,9 +21,10 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
{
|
{
|
||||||
public InputDrum()
|
public InputDrum()
|
||||||
{
|
{
|
||||||
Size = new Vector2(TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT);
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
FillMode = FillMode.Fit;
|
||||||
|
|
||||||
const float middle_split = 10;
|
const float middle_split = 0.025f;
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -33,6 +34,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.CentreRight,
|
Origin = Anchor.CentreRight,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
RelativePositionAxes = Axes.X,
|
||||||
X = -middle_split / 2,
|
X = -middle_split / 2,
|
||||||
RimKey = Key.D,
|
RimKey = Key.D,
|
||||||
CentreKey = Key.F
|
CentreKey = Key.F
|
||||||
@ -43,8 +45,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
RelativePositionAxes = Axes.X,
|
||||||
X = middle_split / 2,
|
X = middle_split / 2,
|
||||||
Position = new Vector2(-1f, 0),
|
|
||||||
RimKey = Key.K,
|
RimKey = Key.K,
|
||||||
CentreKey = Key.J
|
CentreKey = Key.J
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,11 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
Judgement = judgement;
|
Judgement = judgement;
|
||||||
|
|
||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.CentreLeft;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Both;
|
||||||
Size = new Vector2(TaikoHitObject.DEFAULT_CIRCLE_DIAMETER, 1);
|
Size = new Vector2(TaikoHitObject.DEFAULT_SIZE, 1);
|
||||||
|
|
||||||
Masking = true;
|
Masking = true;
|
||||||
Alpha = 0.25f;
|
Alpha = 0.25f;
|
||||||
|
@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
|
|
||||||
protected override Vector2 GetPlayfieldAspectAdjust()
|
protected override Vector2 GetPlayfieldAspectAdjust()
|
||||||
{
|
{
|
||||||
const float default_relative_height = TaikoPlayfield.DEFAULT_PLAYFIELD_HEIGHT / 768;
|
const float default_relative_height = TaikoPlayfield.DEFAULT_HEIGHT / 768;
|
||||||
const float default_aspect = 16f / 9f;
|
const float default_aspect = 16f / 9f;
|
||||||
|
|
||||||
float aspectAdjust = MathHelper.Clamp(DrawWidth / DrawHeight, 0.4f, 4) / default_aspect;
|
float aspectAdjust = MathHelper.Clamp(DrawWidth / DrawHeight, 0.4f, 4) / default_aspect;
|
||||||
|
@ -15,21 +15,20 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
using osu.Game.Rulesets.Taiko.Objects.Drawables;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.UI
|
namespace osu.Game.Rulesets.Taiko.UI
|
||||||
{
|
{
|
||||||
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement>
|
public class TaikoPlayfield : Playfield<TaikoHitObject, TaikoJudgement>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default play field height.
|
/// Default height of a <see cref="TaikoPlayfield"/> when inside a <see cref="TaikoHitRenderer"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float DEFAULT_PLAYFIELD_HEIGHT = 178f;
|
public const float DEFAULT_HEIGHT = 178;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
|
/// The offset from <see cref="left_area_size"/> which the center of the hit target lies at.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const float HIT_TARGET_OFFSET = TaikoHitObject.DEFAULT_STRONG_CIRCLE_DIAMETER / 2f + 40;
|
public const float HIT_TARGET_OFFSET = 100;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The size of the left area of the playfield. This area contains the input drum.
|
/// The size of the left area of the playfield. This area contains the input drum.
|
||||||
@ -56,112 +55,124 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
{
|
{
|
||||||
AddRangeInternal(new Drawable[]
|
AddRangeInternal(new Drawable[]
|
||||||
{
|
{
|
||||||
new ScaleFixContainer
|
backgroundContainer = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
Name = "Transparent playfield background",
|
||||||
Height = DEFAULT_PLAYFIELD_HEIGHT,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Children = new[]
|
Masking = true,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
{
|
{
|
||||||
backgroundContainer = new Container
|
Type = EdgeEffectType.Shadow,
|
||||||
|
Colour = Color4.Black.Opacity(0.2f),
|
||||||
|
Radius = 5,
|
||||||
|
},
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
background = new Box
|
||||||
{
|
{
|
||||||
Name = "Transparent playfield background",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
BorderThickness = 2,
|
Alpha = 0.6f
|
||||||
Masking = true,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
|
||||||
Radius = 5,
|
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
background = new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Alpha = 0.6f
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Name = "Right area",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Left = left_area_size },
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
Name = "Right area",
|
Name = "Masked elements",
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Margin = new MarginPadding { Left = left_area_size },
|
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
||||||
|
Masking = true,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
hitExplosionContainer = new Container<HitExplosion>
|
||||||
{
|
{
|
||||||
Name = "Masked elements",
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Padding = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
FillMode = FillMode.Fit,
|
||||||
Masking = true,
|
BlendingMode = BlendingMode.Additive,
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
hitExplosionContainer = new Container<HitExplosion>
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
BlendingMode = BlendingMode.Additive,
|
|
||||||
},
|
|
||||||
barLineContainer = new Container<DrawableBarLine>
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
new HitTarget
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
},
|
|
||||||
hitObjectContainer = new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
kiaiExplosionContainer = new Container<KiaiHitExplosion>
|
barLineContainer = new Container<DrawableBarLine>
|
||||||
{
|
|
||||||
Name = "Kiai hit explosions",
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
|
||||||
BlendingMode = BlendingMode.Additive
|
|
||||||
},
|
|
||||||
judgementContainer = new Container<DrawableTaikoJudgement>
|
|
||||||
{
|
|
||||||
Name = "Judgements",
|
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
|
||||||
BlendingMode = BlendingMode.Additive
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
overlayBackgroundContainer = new Container
|
|
||||||
{
|
|
||||||
Name = "Left overlay",
|
|
||||||
Size = new Vector2(left_area_size, DEFAULT_PLAYFIELD_HEIGHT),
|
|
||||||
BorderThickness = 1,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
overlayBackground = new Box
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
new InputDrum
|
new HitTarget
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativePositionAxes = Axes.X,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Position = new Vector2(0.10f, 0),
|
FillMode = FillMode.Fit
|
||||||
Scale = new Vector2(0.9f)
|
|
||||||
},
|
},
|
||||||
new Box
|
hitObjectContainer = new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopRight,
|
RelativeSizeAxes = Axes.Both,
|
||||||
RelativeSizeAxes = Axes.Y,
|
|
||||||
Width = 10,
|
|
||||||
Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
kiaiExplosionContainer = new Container<KiaiHitExplosion>
|
||||||
|
{
|
||||||
|
Name = "Kiai hit explosions",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
||||||
|
BlendingMode = BlendingMode.Additive
|
||||||
|
},
|
||||||
|
judgementContainer = new Container<DrawableTaikoJudgement>
|
||||||
|
{
|
||||||
|
Name = "Judgements",
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Margin = new MarginPadding { Left = HIT_TARGET_OFFSET },
|
||||||
|
BlendingMode = BlendingMode.Additive
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
overlayBackgroundContainer = new Container
|
||||||
|
{
|
||||||
|
Name = "Left overlay",
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Size = new Vector2(left_area_size, 1),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
overlayBackground = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new InputDrum
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Scale = new Vector2(0.9f),
|
||||||
|
Margin = new MarginPadding { Right = 20 }
|
||||||
|
},
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
RelativeSizeAxes = Axes.Y,
|
||||||
|
Width = 10,
|
||||||
|
Colour = Framework.Graphics.Colour.ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.6f), Color4.Black.Opacity(0)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Name = "Border",
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
MaskingSmoothness = 0,
|
||||||
|
BorderThickness = 2,
|
||||||
|
AlwaysPresent = true,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
topLevelHitContainer = new Container
|
topLevelHitContainer = new Container
|
||||||
@ -233,56 +244,5 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
else
|
else
|
||||||
hitExplosionContainer.Children.FirstOrDefault(e => e.Judgement == judgedObject.Judgement)?.VisualiseSecondHit();
|
hitExplosionContainer.Children.FirstOrDefault(e => e.Judgement == judgedObject.Judgement)?.VisualiseSecondHit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is a very special type of container. It serves a similar purpose to <see cref="FillMode.Fit"/>, however unlike <see cref="FillMode.Fit"/>,
|
|
||||||
/// this will only adjust the scale relative to the height of its parent and will maintain the original width relative to its parent.
|
|
||||||
///
|
|
||||||
/// <para>
|
|
||||||
/// By adjusting the scale relative to the height of its parent, the aspect ratio of this container's children is maintained, however this is undesirable
|
|
||||||
/// in the case where the hit object container should not have its width adjusted by scale. To counteract this, another container is nested inside this
|
|
||||||
/// container which takes care of reversing the width adjustment while appearing transparent to the user.
|
|
||||||
/// </para>
|
|
||||||
/// </summary>
|
|
||||||
private class ScaleFixContainer : Container
|
|
||||||
{
|
|
||||||
protected override Container<Drawable> Content => widthAdjustmentContainer;
|
|
||||||
private readonly WidthAdjustmentContainer widthAdjustmentContainer;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// We only want to apply DrawScale in the Y-axis to preserve aspect ratio and <see cref="TaikoPlayfield"/> doesn't care about having its width adjusted.
|
|
||||||
/// </summary>
|
|
||||||
protected override Vector2 DrawScale => Scale * RelativeToAbsoluteFactor.Y / DrawHeight;
|
|
||||||
|
|
||||||
public ScaleFixContainer()
|
|
||||||
{
|
|
||||||
AddInternal(widthAdjustmentContainer = new WidthAdjustmentContainer { ParentDrawScaleReference = () => DrawScale.X });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The container type that reverses the <see cref="Drawable.DrawScale"/> width adjustment.
|
|
||||||
/// </summary>
|
|
||||||
private class WidthAdjustmentContainer : Container
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This container needs to know its parent's <see cref="Drawable.DrawScale"/> so it can reverse the width adjustment caused by <see cref="Drawable.DrawScale"/>.
|
|
||||||
/// </summary>
|
|
||||||
public Func<float> ParentDrawScaleReference;
|
|
||||||
|
|
||||||
public WidthAdjustmentContainer()
|
|
||||||
{
|
|
||||||
// This container doesn't care about height, it should always fill its parent
|
|
||||||
RelativeSizeAxes = Axes.Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
// Reverse the DrawScale adjustment
|
|
||||||
Width = Parent.DrawSize.X / ParentDrawScaleReference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ using osu.Game.Rulesets.Objects;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.IO.Serialization;
|
||||||
|
|
||||||
namespace osu.Game.Beatmaps
|
namespace osu.Game.Beatmaps
|
||||||
{
|
{
|
||||||
@ -45,7 +46,7 @@ namespace osu.Game.Beatmaps
|
|||||||
/// <param name="original">The original beatmap to use the parameters of.</param>
|
/// <param name="original">The original beatmap to use the parameters of.</param>
|
||||||
public Beatmap(Beatmap original = null)
|
public Beatmap(Beatmap original = null)
|
||||||
{
|
{
|
||||||
BeatmapInfo = original?.BeatmapInfo ?? BeatmapInfo;
|
BeatmapInfo = original?.BeatmapInfo.DeepClone() ?? BeatmapInfo;
|
||||||
ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo;
|
ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo;
|
||||||
Breaks = original?.Breaks ?? Breaks;
|
Breaks = original?.Breaks ?? Breaks;
|
||||||
ComboColors = original?.ComboColors ?? ComboColors;
|
ComboColors = original?.ComboColors ?? ComboColors;
|
||||||
|
@ -69,7 +69,7 @@ namespace osu.Game.Beatmaps
|
|||||||
|
|
||||||
// Editor
|
// Editor
|
||||||
// This bookmarks stuff is necessary because DB doesn't know how to store int[]
|
// This bookmarks stuff is necessary because DB doesn't know how to store int[]
|
||||||
public string StoredBookmarks { get; internal set; }
|
public string StoredBookmarks { get; set; }
|
||||||
|
|
||||||
[Ignore]
|
[Ignore]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
@ -52,7 +52,14 @@ namespace osu.Game.Beatmaps
|
|||||||
{
|
{
|
||||||
lock (beatmapLock)
|
lock (beatmapLock)
|
||||||
{
|
{
|
||||||
return beatmap ?? (beatmap = GetBeatmap());
|
if (beatmap != null) return beatmap;
|
||||||
|
|
||||||
|
beatmap = GetBeatmap();
|
||||||
|
|
||||||
|
// use the database-backed info.
|
||||||
|
beatmap.BeatmapInfo = BeatmapInfo;
|
||||||
|
|
||||||
|
return beatmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,13 +128,11 @@ namespace osu.Game.Graphics.Containers
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
ScrollbarVisible = false,
|
ScrollbarVisible = false,
|
||||||
Children = new Drawable[] { scrollContentContainer = CreateScrollContentContainer() },
|
Children = new Drawable[] { scrollContentContainer = CreateScrollContentContainer() }
|
||||||
Depth = float.MaxValue
|
|
||||||
});
|
});
|
||||||
AddInternal(headerBackgroundContainer = new Container
|
AddInternal(headerBackgroundContainer = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X
|
||||||
Depth = float.MaxValue / 2
|
|
||||||
});
|
});
|
||||||
originalSectionsMargin = scrollContentContainer.Margin;
|
originalSectionsMargin = scrollContentContainer.Margin;
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,19 @@ namespace osu.Game.Graphics
|
|||||||
public static class AccentedColourExtensions
|
public static class AccentedColourExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tweens the accent colour of a drawable to another colour.
|
/// Smoothly adjusts <see cref="IHasAccentColour.AccentColour"/> over time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="accentedDrawable">The drawable to apply the accent colour to.</param>
|
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
|
||||||
/// <param name="newColour">The new accent colour.</param>
|
|
||||||
/// <param name="duration">The tween duration.</param>
|
|
||||||
/// <param name="easing">The tween easing.</param>
|
|
||||||
public static TransformSequence<T> FadeAccent<T>(this T accentedDrawable, Color4 newColour, double duration = 0, Easing easing = Easing.None)
|
public static TransformSequence<T> FadeAccent<T>(this T accentedDrawable, Color4 newColour, double duration = 0, Easing easing = Easing.None)
|
||||||
where T : IHasAccentColour
|
where T : IHasAccentColour
|
||||||
=> accentedDrawable.TransformTo(nameof(accentedDrawable.AccentColour), newColour, duration, easing);
|
=> accentedDrawable.TransformTo(nameof(accentedDrawable.AccentColour), newColour, duration, easing);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Smoothly adjusts <see cref="IHasAccentColour.AccentColour"/> over time.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="TransformSequence{T}"/> to which further transforms can be added.</returns>
|
||||||
|
public static TransformSequence<T> FadeAccent<T>(this TransformSequence<T> t, Color4 newColour, double duration = 0, Easing easing = Easing.None)
|
||||||
|
where T : Drawable, IHasAccentColour
|
||||||
|
=> t.Append(o => o.FadeAccent(newColour, duration, easing));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
@ -8,6 +9,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
using osu.Framework.Caching;
|
||||||
|
|
||||||
namespace osu.Game.Graphics
|
namespace osu.Game.Graphics
|
||||||
{
|
{
|
||||||
@ -16,19 +18,28 @@ namespace osu.Game.Graphics
|
|||||||
private readonly Sprite spriteShadow;
|
private readonly Sprite spriteShadow;
|
||||||
private readonly Sprite spriteMain;
|
private readonly Sprite spriteMain;
|
||||||
|
|
||||||
|
private Cached layout = new Cached();
|
||||||
|
private readonly Container shadowVisibility;
|
||||||
|
|
||||||
public SpriteIcon()
|
public SpriteIcon()
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
spriteShadow = new Sprite
|
shadowVisibility = new Container
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
FillMode = FillMode.Fit,
|
Child = spriteShadow = new Sprite
|
||||||
Position = new Vector2(0, 0.06f),
|
{
|
||||||
Colour = new Color4(0f, 0f, 0f, 0.2f),
|
Anchor = Anchor.Centre,
|
||||||
Alpha = 0
|
Origin = Anchor.Centre,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
FillMode = FillMode.Fit,
|
||||||
|
Y = 2,
|
||||||
|
Colour = new Color4(0f, 0f, 0f, 0.2f),
|
||||||
|
},
|
||||||
|
Alpha = 0,
|
||||||
},
|
},
|
||||||
spriteMain = new Sprite
|
spriteMain = new Sprite
|
||||||
{
|
{
|
||||||
@ -60,10 +71,34 @@ namespace osu.Game.Graphics
|
|||||||
Size = new Vector2(texture?.DisplayWidth ?? 0, texture?.DisplayHeight ?? 0);
|
Size = new Vector2(texture?.DisplayWidth ?? 0, texture?.DisplayHeight ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||||
|
{
|
||||||
|
if ((invalidation & Invalidation.Colour) > 0 && Shadow)
|
||||||
|
layout.Invalidate();
|
||||||
|
return base.Invalidate(invalidation, source, shallPropagate);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
if (!layout.IsValid)
|
||||||
|
{
|
||||||
|
//adjust shadow alpha based on highest component intensity to avoid muddy display of darker text.
|
||||||
|
//squared result for quadratic fall-off seems to give the best result.
|
||||||
|
var avgColour = (Color4)DrawInfo.Colour.AverageColour;
|
||||||
|
|
||||||
|
spriteShadow.Alpha = (float)Math.Pow(Math.Max(Math.Max(avgColour.R, avgColour.G), avgColour.B), 2);
|
||||||
|
|
||||||
|
layout.Validate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool Shadow
|
public bool Shadow
|
||||||
{
|
{
|
||||||
get { return spriteShadow.IsPresent; }
|
get { return spriteShadow.IsPresent; }
|
||||||
set { spriteShadow.Alpha = value ? 1 : 0; }
|
set
|
||||||
|
{
|
||||||
|
shadowVisibility.Alpha = value ? 1 : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FontAwesome icon;
|
private FontAwesome icon;
|
||||||
|
@ -13,7 +13,7 @@ namespace osu.Game.IO.Serialization
|
|||||||
{
|
{
|
||||||
public static string Serialize(this IJsonSerializable obj)
|
public static string Serialize(this IJsonSerializable obj)
|
||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject(obj);
|
return JsonConvert.SerializeObject(obj, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Deserialize<T>(this string objString)
|
public static T Deserialize<T>(this string objString)
|
||||||
|
@ -169,13 +169,11 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
header.User = user;
|
header.User = user;
|
||||||
|
|
||||||
for (int i = 0; i < user.ProfileOrder.Length; i++)
|
foreach (string id in user.ProfileOrder)
|
||||||
{
|
{
|
||||||
string id = user.ProfileOrder[i];
|
|
||||||
var sec = sections.FirstOrDefault(s => s.Identifier == id);
|
var sec = sections.FirstOrDefault(s => s.Identifier == id);
|
||||||
if (sec != null)
|
if (sec != null)
|
||||||
{
|
{
|
||||||
sec.Depth = -i;
|
|
||||||
sectionsContainer.Add(sec);
|
sectionsContainer.Add(sec);
|
||||||
tabs.AddItem(sec);
|
tabs.AddItem(sec);
|
||||||
}
|
}
|
||||||
|
15
osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs
Normal file
15
osu.Game/Rulesets/Mods/IApplicableToDifficulty.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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.Game.Beatmaps;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mods
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interface for mods that make general adjustments to difficulty.
|
||||||
|
/// </summary>
|
||||||
|
public interface IApplicableToDifficulty
|
||||||
|
{
|
||||||
|
void ApplyToDifficulty(BeatmapDifficulty difficulty);
|
||||||
|
}
|
||||||
|
}
|
@ -45,5 +45,10 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
/// The mods this mod cannot be enabled with.
|
/// The mods this mod cannot be enabled with.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual Type[] IncompatibleMods => new Type[] { };
|
public virtual Type[] IncompatibleMods => new Type[] { };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether we should allow failing at the current point in time.
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool AllowFail => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
// 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;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mods
|
namespace osu.Game.Rulesets.Mods
|
||||||
{
|
{
|
||||||
public abstract class ModEasy : Mod
|
public abstract class ModEasy : Mod, IApplicableToDifficulty
|
||||||
{
|
{
|
||||||
public override string Name => "Easy";
|
public override string Name => "Easy";
|
||||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy;
|
public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy;
|
||||||
@ -15,5 +16,14 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
public override double ScoreMultiplier => 0.5;
|
public override double ScoreMultiplier => 0.5;
|
||||||
public override bool Ranked => true;
|
public override bool Ranked => true;
|
||||||
public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) };
|
public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) };
|
||||||
|
|
||||||
|
public void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
const float ratio = 0.5f;
|
||||||
|
difficulty.CircleSize *= ratio;
|
||||||
|
difficulty.ApproachRate *= ratio;
|
||||||
|
difficulty.DrainRate *= ratio;
|
||||||
|
difficulty.OverallDifficulty *= ratio;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,16 +2,26 @@
|
|||||||
// 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;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Mods
|
namespace osu.Game.Rulesets.Mods
|
||||||
{
|
{
|
||||||
public abstract class ModHardRock : Mod
|
public abstract class ModHardRock : Mod, IApplicableToDifficulty
|
||||||
{
|
{
|
||||||
public override string Name => "Hard Rock";
|
public override string Name => "Hard Rock";
|
||||||
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock;
|
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock;
|
||||||
public override ModType Type => ModType.DifficultyIncrease;
|
public override ModType Type => ModType.DifficultyIncrease;
|
||||||
public override string Description => "Everything just got a bit harder...";
|
public override string Description => "Everything just got a bit harder...";
|
||||||
public override Type[] IncompatibleMods => new[] { typeof(ModEasy) };
|
public override Type[] IncompatibleMods => new[] { typeof(ModEasy) };
|
||||||
|
|
||||||
|
public void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||||
|
{
|
||||||
|
const float ratio = 1.4f;
|
||||||
|
difficulty.CircleSize *= 1.3f; // CS uses a custom 1.3 ratio.
|
||||||
|
difficulty.ApproachRate *= ratio;
|
||||||
|
difficulty.DrainRate *= ratio;
|
||||||
|
difficulty.OverallDifficulty *= ratio;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,5 +15,10 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
public override double ScoreMultiplier => 0.5;
|
public override double ScoreMultiplier => 0.5;
|
||||||
public override bool Ranked => true;
|
public override bool Ranked => true;
|
||||||
public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModAutoplay) };
|
public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModAutoplay) };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// We never fail, 'yo.
|
||||||
|
/// </summary>
|
||||||
|
public override bool AllowFail => false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,8 +16,9 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when the ScoreProcessor is in a failed state.
|
/// Invoked when the ScoreProcessor is in a failed state.
|
||||||
|
/// Return true if the fail was permitted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action Failed;
|
public event Func<bool> Failed;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the <see cref="ScoreProcessor"/>.
|
/// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the <see cref="ScoreProcessor"/>.
|
||||||
@ -106,8 +107,8 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
if (alreadyFailed || !HasFailed)
|
if (alreadyFailed || !HasFailed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
alreadyFailed = true;
|
if (Failed?.Invoke() != false)
|
||||||
Failed?.Invoke();
|
alreadyFailed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -153,6 +153,10 @@ namespace osu.Game.Rulesets.UI
|
|||||||
// Convert the beatmap
|
// Convert the beatmap
|
||||||
Beatmap = converter.Convert(beatmap.Beatmap, isForCurrentRuleset);
|
Beatmap = converter.Convert(beatmap.Beatmap, isForCurrentRuleset);
|
||||||
|
|
||||||
|
// Apply difficulty adjustments from mods before using Difficulty.
|
||||||
|
foreach (var mod in Mods.OfType<IApplicableToDifficulty>())
|
||||||
|
mod.ApplyToDifficulty(Beatmap.BeatmapInfo.Difficulty);
|
||||||
|
|
||||||
// Apply defaults
|
// Apply defaults
|
||||||
foreach (var h in Beatmap.HitObjects)
|
foreach (var h in Beatmap.HitObjects)
|
||||||
h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.Difficulty);
|
h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.Difficulty);
|
||||||
@ -163,7 +167,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
ApplyBeatmap();
|
ApplyBeatmap();
|
||||||
|
|
||||||
// Add mods, should always be the last thing applied to give full control to mods
|
// Add mods, should always be the last thing applied to give full control to mods
|
||||||
applyMods(beatmap.Mods.Value);
|
applyMods(Mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -45,10 +45,11 @@ namespace osu.Game.Rulesets.UI
|
|||||||
},
|
},
|
||||||
modIcon = new SpriteIcon
|
modIcon = new SpriteIcon
|
||||||
{
|
{
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.TopCentre,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.TopCentre,
|
||||||
Colour = OsuColour.Gray(84),
|
Colour = OsuColour.Gray(84),
|
||||||
Size = new Vector2(icon_size - 35),
|
Size = new Vector2(icon_size - 35),
|
||||||
|
Y = 25,
|
||||||
Icon = mod.Icon
|
Icon = mod.Icon
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,7 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
namespace osu.Game.Screens.Play
|
||||||
{
|
{
|
||||||
@ -77,23 +78,28 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
Ruleset rulesetInstance;
|
Ruleset rulesetInstance;
|
||||||
|
|
||||||
|
WorkingBeatmap working = Beatmap.Value;
|
||||||
|
Beatmap beatmap;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Beatmap.Value.Beatmap == null)
|
beatmap = working.Beatmap;
|
||||||
|
|
||||||
|
if (beatmap == null)
|
||||||
throw new InvalidOperationException("Beatmap was not loaded");
|
throw new InvalidOperationException("Beatmap was not loaded");
|
||||||
|
|
||||||
ruleset = osu?.Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset;
|
ruleset = osu?.Ruleset.Value ?? beatmap.BeatmapInfo.Ruleset;
|
||||||
rulesetInstance = ruleset.CreateInstance();
|
rulesetInstance = ruleset.CreateInstance();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap, ruleset.ID == Beatmap.Value.BeatmapInfo.Ruleset.ID);
|
HitRenderer = rulesetInstance.CreateHitRendererWith(working, ruleset.ID == beatmap.BeatmapInfo.Ruleset.ID);
|
||||||
}
|
}
|
||||||
catch (BeatmapInvalidForRulesetException)
|
catch (BeatmapInvalidForRulesetException)
|
||||||
{
|
{
|
||||||
// we may fail to create a HitRenderer if the beatmap cannot be loaded with the user's preferred ruleset
|
// we may fail to create a HitRenderer if the beatmap cannot be loaded with the user's preferred ruleset
|
||||||
// let's try again forcing the beatmap's ruleset.
|
// let's try again forcing the beatmap's ruleset.
|
||||||
ruleset = Beatmap.Value.BeatmapInfo.Ruleset;
|
ruleset = beatmap.BeatmapInfo.Ruleset;
|
||||||
rulesetInstance = ruleset.CreateInstance();
|
rulesetInstance = ruleset.CreateInstance();
|
||||||
HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap, true);
|
HitRenderer = rulesetInstance.CreateHitRendererWith(Beatmap, true);
|
||||||
}
|
}
|
||||||
@ -110,11 +116,11 @@ namespace osu.Game.Screens.Play
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustableSourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
|
adjustableSourceClock = (IAdjustableClock)working.Track ?? new StopwatchClock();
|
||||||
decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = false };
|
||||||
|
|
||||||
var firstObjectTime = HitRenderer.Objects.First().StartTime;
|
var firstObjectTime = HitRenderer.Objects.First().StartTime;
|
||||||
decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(Beatmap.Value.Beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, Beatmap.Value.BeatmapInfo.AudioLeadIn)));
|
decoupledClock.Seek(Math.Min(0, firstObjectTime - Math.Max(beatmap.ControlPointInfo.TimingPointAt(firstObjectTime).BeatLength * 4, beatmap.BeatmapInfo.AudioLeadIn)));
|
||||||
decoupledClock.ProcessFrame();
|
decoupledClock.ProcessFrame();
|
||||||
|
|
||||||
offsetClock = new FramedOffsetClock(decoupledClock);
|
offsetClock = new FramedOffsetClock(decoupledClock);
|
||||||
@ -127,7 +133,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
adjustableSourceClock.Reset();
|
adjustableSourceClock.Reset();
|
||||||
|
|
||||||
foreach (var mod in Beatmap.Value.Mods.Value.OfType<IApplicableToClock>())
|
foreach (var mod in working.Mods.Value.OfType<IApplicableToClock>())
|
||||||
mod.ApplyToClock(adjustableSourceClock);
|
mod.ApplyToClock(adjustableSourceClock);
|
||||||
|
|
||||||
decoupledClock.ChangeSource(adjustableSourceClock);
|
decoupledClock.ChangeSource(adjustableSourceClock);
|
||||||
@ -195,7 +201,7 @@ namespace osu.Game.Screens.Play
|
|||||||
hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded;
|
hudOverlay.Progress.AllowSeeking = HitRenderer.HasReplayLoaded;
|
||||||
hudOverlay.Progress.OnSeek = pos => decoupledClock.Seek(pos);
|
hudOverlay.Progress.OnSeek = pos => decoupledClock.Seek(pos);
|
||||||
|
|
||||||
hudOverlay.ModDisplay.Current.BindTo(Beatmap.Value.Mods);
|
hudOverlay.ModDisplay.Current.BindTo(working.Mods);
|
||||||
|
|
||||||
//bind HitRenderer to ScoreProcessor and ourselves (for a pass situation)
|
//bind HitRenderer to ScoreProcessor and ourselves (for a pass situation)
|
||||||
HitRenderer.OnAllJudged += onCompletion;
|
HitRenderer.OnAllJudged += onCompletion;
|
||||||
@ -238,13 +244,17 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFail()
|
private bool onFail()
|
||||||
{
|
{
|
||||||
|
if (Beatmap.Value.Mods.Value.Any(m => !m.AllowFail))
|
||||||
|
return false;
|
||||||
|
|
||||||
decoupledClock.Stop();
|
decoupledClock.Stop();
|
||||||
|
|
||||||
HasFailed = true;
|
HasFailed = true;
|
||||||
failOverlay.Retries = RestartCount;
|
failOverlay.Retries = RestartCount;
|
||||||
failOverlay.Show();
|
failOverlay.Show();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEntering(Screen last)
|
protected override void OnEntering(Screen last)
|
||||||
|
@ -117,6 +117,7 @@
|
|||||||
<Compile Include="Overlays\Profile\Sections\RanksSection.cs" />
|
<Compile Include="Overlays\Profile\Sections\RanksSection.cs" />
|
||||||
<Compile Include="Overlays\Profile\Sections\RecentSection.cs" />
|
<Compile Include="Overlays\Profile\Sections\RecentSection.cs" />
|
||||||
<Compile Include="Graphics\Containers\ConstrainedIconContainer.cs" />
|
<Compile Include="Graphics\Containers\ConstrainedIconContainer.cs" />
|
||||||
|
<Compile Include="Rulesets\Mods\IApplicableToDifficulty.cs" />
|
||||||
<Compile Include="Users\UserCoverBackground.cs" />
|
<Compile Include="Users\UserCoverBackground.cs" />
|
||||||
<Compile Include="Overlays\UserProfileOverlay.cs" />
|
<Compile Include="Overlays\UserProfileOverlay.cs" />
|
||||||
<Compile Include="Overlays\Profile\ProfileHeader.cs" />
|
<Compile Include="Overlays\Profile\ProfileHeader.cs" />
|
||||||
|
Reference in New Issue
Block a user