Compare commits
937 Commits
2020.317.0
...
2020.418.0
@@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.osu.Desktop/.idea/.idea.osu.Desktop.iml" filepath="$PROJECT_DIR$/.idea/.idea.osu.Desktop/.idea/.idea.osu.Desktop.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.osu.Desktop/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.osu.Desktop/riderModule.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="1" />
|
||||
<option name="vcsConfiguration" value="2" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -93,7 +93,7 @@ JetBrains ReSharper InspectCode is also used for wider rule sets. You can run it
|
||||
|
||||
We welcome all contributions, but keep in mind that we already have a lot of the UI designed. If you wish to work on something with the intention of having it included in the official distribution, please open an issue for discussion and we will give you what you need from a design perspective to proceed. If you want to make *changes* to the design, we recommend you open an issue with your intentions before spending too much time to ensure no effort is wasted.
|
||||
|
||||
If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu/issues) (especially those with the ["good first issue"](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) label).
|
||||
If you're unsure of what you can help with, check out the [list of open issues](https://github.com/ppy/osu/issues) (especially those with the ["good first issue"](https://github.com/ppy/osu/issues?q=is%3Aopen+label%3Agood-first-issue+sort%3Aupdated-desc) label).
|
||||
|
||||
Before starting, please make sure you are familiar with the [development and testing](https://github.com/ppy/osu-framework/wiki/Development-and-Testing) procedure we have set up. New component development, and where possible, bug fixing and debugging existing components **should always be done under VisualTests**.
|
||||
|
||||
|
||||
@@ -97,8 +97,10 @@ platform :ios do
|
||||
changelog.gsub!('$BUILD_ID', options[:build])
|
||||
|
||||
pilot(
|
||||
wait_processing_interval: 1800,
|
||||
wait_processing_interval: 900,
|
||||
changelog: changelog,
|
||||
groups: ['osu! supporters', 'public'],
|
||||
distribute_external: true,
|
||||
ipa: './osu.iOS/bin/iPhone/Release/osu.iOS.ipa'
|
||||
)
|
||||
end
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
"version": "3.1.100"
|
||||
},
|
||||
"msbuild-sdks": {
|
||||
"Microsoft.Build.Traversal": "2.0.24"
|
||||
"Microsoft.Build.Traversal": "2.0.34"
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@
|
||||
<Reference Include="Java.Interop" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.315.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.317.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.412.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.417.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.0" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
|
||||
<PackageReference Include="nunit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Catch.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public abstract class CatchSkinnableTestScene : SkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(CatchRuleset),
|
||||
typeof(CatchLegacySkinTransformer),
|
||||
};
|
||||
|
||||
protected override Ruleset CreateRulesetForSkinProvider() => new CatchRuleset();
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
@@ -4,21 +4,21 @@
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Tests.Visual;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneCatcher : SkinnableTestScene
|
||||
public class TestSceneCatcher : CatchSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||
{
|
||||
typeof(CatcherArea),
|
||||
typeof(CatcherSprite)
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
|
||||
@@ -17,12 +17,11 @@ using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneCatcherArea : SkinnableTestScene
|
||||
public class TestSceneCatcherArea : CatchSkinnableTestScene
|
||||
{
|
||||
private RulesetInfo catchRuleset;
|
||||
|
||||
|
||||
@@ -3,20 +3,20 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Catch.Objects.Drawables.Pieces;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneFruitObjects : SkinnableTestScene
|
||||
public class TestSceneFruitObjects : CatchSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||
{
|
||||
typeof(CatchHitObject),
|
||||
typeof(Fruit),
|
||||
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
typeof(DrawableBanana),
|
||||
typeof(DrawableBananaShower),
|
||||
typeof(Pulp),
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Catch
|
||||
new KeyBinding(InputKey.Shift, CatchAction.Dash),
|
||||
};
|
||||
|
||||
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||
public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods)
|
||||
{
|
||||
if (mods.HasFlag(LegacyMods.Nightcore))
|
||||
yield return new CatchModNightcore();
|
||||
@@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Catch
|
||||
|
||||
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new CatchDifficultyCalculator(this, beatmap);
|
||||
|
||||
public override ISkin CreateLegacySkinProvider(ISkinSource source) => new CatchLegacySkinTransformer(source);
|
||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new CatchLegacySkinTransformer(source);
|
||||
|
||||
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new CatchPerformanceCalculator(this, beatmap, score);
|
||||
|
||||
|
||||
@@ -72,10 +72,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
protected override Skill[] CreateSkills(IBeatmap beatmap)
|
||||
{
|
||||
using (var catcher = new Catcher(beatmap.BeatmapInfo.BaseDifficulty))
|
||||
{
|
||||
halfCatcherWidth = catcher.CatchWidth * 0.5f;
|
||||
halfCatcherWidth *= 0.8f; // We're only using 80% of the catcher's width to simulate imperfect gameplay.
|
||||
}
|
||||
|
||||
return new Skill[]
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
@@ -30,6 +31,22 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
Value = 5,
|
||||
};
|
||||
|
||||
public override string SettingDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
string circleSize = CircleSize.IsDefault ? string.Empty : $"CS {CircleSize.Value:N1}";
|
||||
string approachRate = ApproachRate.IsDefault ? string.Empty : $"AR {ApproachRate.Value:N1}";
|
||||
|
||||
return string.Join(", ", new[]
|
||||
{
|
||||
circleSize,
|
||||
base.SettingDescription,
|
||||
approachRate
|
||||
}.Where(s => !string.IsNullOrEmpty(s)));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void TransferSettings(BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.TransferSettings(difficulty);
|
||||
|
||||
@@ -70,6 +70,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
|
||||
|
||||
public float DisplayRadius => DrawSize.X / 2 * Scale.X * HitObject.Scale;
|
||||
|
||||
protected override float SamplePlaybackPosition => HitObject.X;
|
||||
|
||||
protected DrawableCatchHitObject(CatchHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
}
|
||||
}
|
||||
|
||||
public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null)
|
||||
public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null)
|
||||
{
|
||||
Position = currentFrame.Position.X / CatchPlayfield.BASE_WIDTH;
|
||||
Dashing = currentFrame.ButtonState == ReplayButtonState.Left1;
|
||||
@@ -56,5 +56,14 @@ namespace osu.Game.Rulesets.Catch.Replays
|
||||
Actions.Add(CatchAction.MoveLeft);
|
||||
}
|
||||
}
|
||||
|
||||
public LegacyReplayFrame ToLegacy(IBeatmap beatmap)
|
||||
{
|
||||
ReplayButtonState state = ReplayButtonState.None;
|
||||
|
||||
if (Actions.Contains(CatchAction.Dash)) state |= ReplayButtonState.Left1;
|
||||
|
||||
return new LegacyReplayFrame(Time, Position * CatchPlayfield.BASE_WIDTH, null, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets.Catch.Replays;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public class CatchReplayRecorder : ReplayRecorder<CatchAction>
|
||||
{
|
||||
private readonly CatchPlayfield playfield;
|
||||
|
||||
public CatchReplayRecorder(Replay target, CatchPlayfield playfield)
|
||||
: base(target)
|
||||
{
|
||||
this.playfield = playfield;
|
||||
}
|
||||
|
||||
protected override ReplayFrame HandleFrame(Vector2 mousePosition, List<CatchAction> actions, ReplayFrame previousFrame)
|
||||
=> new CatchReplayFrame(Time.Current, playfield.CatcherArea.MovableCatcher.X, actions.Contains(CatchAction.Dash), previousFrame as CatchReplayFrame);
|
||||
}
|
||||
}
|
||||
@@ -37,10 +37,15 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public CatcherAnimationState CurrentState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The width of the catcher which can receive fruit. Equivalent to "catchMargin" in osu-stable.
|
||||
/// </summary>
|
||||
private const float allowed_catch_range = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
/// Width of the area that can be used to attempt catches during gameplay.
|
||||
/// </summary>
|
||||
internal float CatchWidth => CatcherArea.CATCHER_SIZE * Math.Abs(Scale.X);
|
||||
internal float CatchWidth => CatcherArea.CATCHER_SIZE * Math.Abs(Scale.X) * allowed_catch_range;
|
||||
|
||||
protected bool Dashing
|
||||
{
|
||||
@@ -141,14 +146,14 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
var ourRadius = fruit.DisplayRadius;
|
||||
float theirRadius = 0;
|
||||
|
||||
const float allowance = 6;
|
||||
const float allowance = 10;
|
||||
|
||||
while (caughtFruit.Any(f =>
|
||||
f.LifetimeEnd == double.MaxValue &&
|
||||
Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = f.DrawSize.X / 2 * f.Scale.X)) / (allowance / 2)))
|
||||
{
|
||||
var diff = (ourRadius + theirRadius) / allowance;
|
||||
fruit.X += (RNG.NextSingle() - 0.5f) * 2 * diff;
|
||||
fruit.X += (RNG.NextSingle() - 0.5f) * diff * 2;
|
||||
fruit.Y -= RNG.NextSingle() * diff;
|
||||
}
|
||||
|
||||
@@ -379,7 +384,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
}
|
||||
|
||||
currentCatcher.Show();
|
||||
(currentCatcher.Drawable as IAnimation)?.GotoFrame(0);
|
||||
(currentCatcher.Drawable as IFramedAnimation)?.GotoFrame(0);
|
||||
}
|
||||
|
||||
private void beginTrail()
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
public CatcherSprite(CatcherAnimationState state)
|
||||
: base(new CatchSkinComponent(componentFromState(state)), _ =>
|
||||
new DefaultCatcherSprite(state), confineMode: ConfineMode.ScaleDownToFit)
|
||||
new DefaultCatcherSprite(state), confineMode: ConfineMode.ScaleToFit)
|
||||
{
|
||||
RelativeSizeAxes = Axes.None;
|
||||
Size = new Vector2(CatcherArea.CATCHER_SIZE);
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
|
||||
|
||||
protected override ReplayRecorder CreateReplayRecorder(Replay replay) => new CatchReplayRecorder(replay, (CatchPlayfield)Playfield);
|
||||
|
||||
protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, CreateDrawableRepresentation);
|
||||
|
||||
public override PlayfieldAdjustmentContainer CreatePlayfieldAdjustmentContainer() => new CatchPlayfieldAdjustmentContainer();
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ManiaColumnTypeTest
|
||||
{
|
||||
[TestCase(new[]
|
||||
{
|
||||
ColumnType.Special
|
||||
}, 1)]
|
||||
[TestCase(new[]
|
||||
{
|
||||
ColumnType.Odd,
|
||||
ColumnType.Even,
|
||||
ColumnType.Even,
|
||||
ColumnType.Odd
|
||||
}, 4)]
|
||||
[TestCase(new[]
|
||||
{
|
||||
ColumnType.Odd,
|
||||
ColumnType.Even,
|
||||
ColumnType.Odd,
|
||||
ColumnType.Special,
|
||||
ColumnType.Odd,
|
||||
ColumnType.Even,
|
||||
ColumnType.Odd
|
||||
}, 7)]
|
||||
public void Test(IEnumerable<ColumnType> expected, int columns)
|
||||
{
|
||||
var definition = new StageDefinition
|
||||
{
|
||||
Columns = columns
|
||||
};
|
||||
var results = getResults(definition);
|
||||
Assert.AreEqual(expected, results);
|
||||
}
|
||||
|
||||
private IEnumerable<ColumnType> getResults(StageDefinition definition)
|
||||
{
|
||||
for (var i = 0; i < definition.Columns; i++)
|
||||
yield return definition.GetTypeOfColumn(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
}
|
||||
|
||||
protected override RulesetKeyBindingContainer CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
|
||||
protected override KeyBindingContainer<ManiaAction> CreateKeyBindingContainer(RulesetInfo ruleset, int variant, SimultaneousBindingMode unique)
|
||||
=> new LocalKeyBindingContainer(ruleset, variant, unique);
|
||||
|
||||
private class LocalKeyBindingContainer : RulesetKeyBindingContainer
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Replays;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ManiaLegacyReplayTest
|
||||
{
|
||||
[TestCase(ManiaAction.Key1)]
|
||||
[TestCase(ManiaAction.Key1, ManiaAction.Key2)]
|
||||
[TestCase(ManiaAction.Special1)]
|
||||
[TestCase(ManiaAction.Key8)]
|
||||
public void TestEncodeDecodeSingleStage(params ManiaAction[] actions)
|
||||
{
|
||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 9 });
|
||||
|
||||
var frame = new ManiaReplayFrame(0, actions);
|
||||
var legacyFrame = frame.ToLegacy(beatmap);
|
||||
|
||||
var decodedFrame = new ManiaReplayFrame();
|
||||
decodedFrame.FromLegacy(legacyFrame, beatmap);
|
||||
|
||||
Assert.That(decodedFrame.Actions, Is.EquivalentTo(frame.Actions));
|
||||
}
|
||||
|
||||
[TestCase(ManiaAction.Key1)]
|
||||
[TestCase(ManiaAction.Key1, ManiaAction.Key2)]
|
||||
[TestCase(ManiaAction.Special1)]
|
||||
[TestCase(ManiaAction.Special2)]
|
||||
[TestCase(ManiaAction.Special1, ManiaAction.Special2)]
|
||||
[TestCase(ManiaAction.Special1, ManiaAction.Key5)]
|
||||
[TestCase(ManiaAction.Key8)]
|
||||
public void TestEncodeDecodeDualStage(params ManiaAction[] actions)
|
||||
{
|
||||
var beatmap = new ManiaBeatmap(new StageDefinition { Columns = 5 });
|
||||
beatmap.Stages.Add(new StageDefinition { Columns = 5 });
|
||||
|
||||
var frame = new ManiaReplayFrame(0, actions);
|
||||
var legacyFrame = frame.ToLegacy(beatmap);
|
||||
|
||||
var decodedFrame = new ManiaReplayFrame();
|
||||
decodedFrame.FromLegacy(legacyFrame, beatmap);
|
||||
|
||||
Assert.That(decodedFrame.Actions, Is.EquivalentTo(frame.Actions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// A container to be used in a <see cref="ManiaSkinnableTestScene"/> to provide a resolvable <see cref="Column"/> dependency.
|
||||
/// </summary>
|
||||
public class ColumnTestContainer : Container
|
||||
{
|
||||
protected override Container<Drawable> Content => content;
|
||||
|
||||
private readonly Container content;
|
||||
|
||||
[Cached]
|
||||
private readonly Column column;
|
||||
|
||||
public ColumnTestContainer(int column, ManiaAction action)
|
||||
{
|
||||
this.column = new Column(column)
|
||||
{
|
||||
Action = { Value = action },
|
||||
AccentColour = Color4.Orange,
|
||||
ColumnType = column % 2 == 0 ? ColumnType.Even : ColumnType.Odd
|
||||
};
|
||||
|
||||
InternalChild = content = new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// A test scene for a mania hitobject.
|
||||
/// </summary>
|
||||
public abstract class ManiaHitObjectTestScene : ManiaSkinnableTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.7f,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ColumnTestContainer(0, ManiaAction.Key1)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 80,
|
||||
Child = new ScrollingHitObjectContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}.With(c =>
|
||||
{
|
||||
c.Add(CreateHitObject().With(h =>
|
||||
{
|
||||
h.HitObject.StartTime = START_TIME;
|
||||
h.AccentColour.Value = Color4.Orange;
|
||||
}));
|
||||
})
|
||||
},
|
||||
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = 80,
|
||||
Child = new ScrollingHitObjectContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}.With(c =>
|
||||
{
|
||||
c.Add(CreateHitObject().With(h =>
|
||||
{
|
||||
h.HitObject.StartTime = START_TIME;
|
||||
h.AccentColour.Value = Color4.Orange;
|
||||
}));
|
||||
})
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract DrawableManiaHitObject CreateHitObject();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Rulesets.UI.Scrolling.Algorithms;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// A test scene for skinnable mania components.
|
||||
/// </summary>
|
||||
public abstract class ManiaSkinnableTestScene : SkinnableTestScene
|
||||
{
|
||||
protected const double START_TIME = 1000000000;
|
||||
|
||||
[Cached(Type = typeof(IScrollingInfo))]
|
||||
private readonly TestScrollingInfo scrollingInfo = new TestScrollingInfo();
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(ManiaRuleset),
|
||||
typeof(ManiaLegacySkinTransformer),
|
||||
typeof(ManiaSettingsSubsection)
|
||||
};
|
||||
|
||||
protected override Ruleset CreateRulesetForSkinProvider() => new ManiaRuleset();
|
||||
|
||||
protected ManiaSkinnableTestScene()
|
||||
{
|
||||
scrollingInfo.Direction.Value = ScrollingDirection.Down;
|
||||
|
||||
Add(new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.SlateGray.Opacity(0.2f),
|
||||
Depth = 1
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScrollingDown()
|
||||
{
|
||||
AddStep("change direction to down", () => scrollingInfo.Direction.Value = ScrollingDirection.Down);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScrollingUp()
|
||||
{
|
||||
AddStep("change direction to up", () => scrollingInfo.Direction.Value = ScrollingDirection.Up);
|
||||
}
|
||||
|
||||
private class TestScrollingInfo : IScrollingInfo
|
||||
{
|
||||
public readonly Bindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
IBindable<ScrollingDirection> IScrollingInfo.Direction => Direction;
|
||||
IBindable<double> IScrollingInfo.TimeRange { get; } = new Bindable<double>(1000);
|
||||
IScrollAlgorithm IScrollingInfo.Algorithm { get; } = new ZeroScrollAlgorithm();
|
||||
}
|
||||
|
||||
private class ZeroScrollAlgorithm : IScrollAlgorithm
|
||||
{
|
||||
public double GetDisplayStartTime(double originTime, float offset, double timeRange, float scrollLength)
|
||||
=> double.MinValue;
|
||||
|
||||
public float GetLength(double startTime, double endTime, double timeRange, float scrollLength)
|
||||
=> scrollLength;
|
||||
|
||||
public float PositionAt(double time, double currentTime, double timeRange, float scrollLength)
|
||||
=> (float)((time - START_TIME) / timeRange) * scrollLength;
|
||||
|
||||
public double TimeAt(float position, double currentTime, double timeRange, float scrollLength)
|
||||
=> 0;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.UI.Components;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneColumnBackground : ManiaSkinnableTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.8f),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ColumnTestContainer(0, ManiaAction.Key1)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, 0), _ => new DefaultColumnBackground())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, 0), _ => new DefaultColumnBackground())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.UI.Components;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneColumnHitObjectArea : ManiaSkinnableTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.8f),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ColumnTestContainer(0, ManiaAction.Key1)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new ColumnHitObjectArea(0, new HitObjectContainer())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
},
|
||||
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new ColumnHitObjectArea(1, new HitObjectContainer())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,15 +6,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneDrawableJudgement : SkinnableTestScene
|
||||
public class TestSceneDrawableJudgement : ManiaSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneHitExplosion : ManiaSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(DrawableNote),
|
||||
typeof(DrawableManiaHitObject),
|
||||
};
|
||||
|
||||
public TestSceneHitExplosion()
|
||||
{
|
||||
int runcount = 0;
|
||||
|
||||
AddRepeatStep("explode", () =>
|
||||
{
|
||||
runcount++;
|
||||
|
||||
if (runcount % 15 > 12)
|
||||
return;
|
||||
|
||||
CreatedDrawables.OfType<Container>().ForEach(c =>
|
||||
{
|
||||
c.Add(new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HitExplosion, 0),
|
||||
_ => new DefaultHitExplosion((runcount / 15) % 2 == 0 ? new Color4(94, 0, 57, 255) : new Color4(6, 84, 0, 255), runcount % 6 != 0)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}));
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new ColumnTestContainer(0, ManiaAction.Key1)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Y = -0.25f,
|
||||
Size = new Vector2(Column.COLUMN_WIDTH, DefaultNotePiece.NOTE_HEIGHT),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneHoldNote : ManiaHitObjectTestScene
|
||||
{
|
||||
public TestSceneHoldNote()
|
||||
{
|
||||
AddToggleStep("toggle hitting", v =>
|
||||
{
|
||||
foreach (var holdNote in CreatedDrawables.SelectMany(d => d.ChildrenOfType<DrawableHoldNote>()))
|
||||
{
|
||||
((Bindable<bool>)holdNote.IsHitting).Value = v;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override DrawableManiaHitObject CreateHitObject()
|
||||
{
|
||||
var note = new HoldNote { Duration = 1000 };
|
||||
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
return new DrawableHoldNote(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Rulesets.Mania.UI.Components;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneKeyArea : ManiaSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(DefaultKeyArea),
|
||||
typeof(LegacyKeyArea)
|
||||
};
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Size = new Vector2(0.8f),
|
||||
Direction = FillDirection.Horizontal,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ColumnTestContainer(0, ManiaAction.Key1)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, 0), _ => new DefaultKeyArea())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
new ColumnTestContainer(1, ManiaAction.Key2)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
Child = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, 1), _ => new DefaultKeyArea())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneNote : ManiaHitObjectTestScene
|
||||
{
|
||||
protected override DrawableManiaHitObject CreateHitObject()
|
||||
{
|
||||
var note = new Note();
|
||||
note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
return new DrawableNote(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestScenePlayfield : ManiaSkinnableTestScene
|
||||
{
|
||||
private List<StageDefinition> stageDefinitions = new List<StageDefinition>();
|
||||
|
||||
[Test]
|
||||
public void TestSingleStage()
|
||||
{
|
||||
AddStep("create stage", () =>
|
||||
{
|
||||
stageDefinitions = new List<StageDefinition>
|
||||
{
|
||||
new StageDefinition { Columns = 2 }
|
||||
};
|
||||
|
||||
SetContents(() => new ManiaPlayfield(stageDefinitions));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDualStages()
|
||||
{
|
||||
AddStep("create stage", () =>
|
||||
{
|
||||
stageDefinitions = new List<StageDefinition>
|
||||
{
|
||||
new StageDefinition { Columns = 2 },
|
||||
new StageDefinition { Columns = 2 }
|
||||
};
|
||||
|
||||
SetContents(() => new ManiaPlayfield(stageDefinitions));
|
||||
});
|
||||
}
|
||||
|
||||
protected override IBeatmap CreateBeatmapForSkinProvider()
|
||||
{
|
||||
var maniaBeatmap = (ManiaBeatmap)base.CreateBeatmapForSkinProvider();
|
||||
maniaBeatmap.Stages = stageDefinitions;
|
||||
return maniaBeatmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneStage : ManiaSkinnableTestScene
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() =>
|
||||
{
|
||||
ManiaAction normalAction = ManiaAction.Key1;
|
||||
ManiaAction specialAction = ManiaAction.Special1;
|
||||
|
||||
return new ManiaInputManager(new ManiaRuleset().RulesetInfo, 4)
|
||||
{
|
||||
Child = new Stage(0, new StageDefinition { Columns = 4 }, ref normalAction, ref specialAction)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Rulesets.Mania.UI.Components;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneStageBackground : ManiaSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||
{
|
||||
typeof(DefaultStageBackground),
|
||||
typeof(LegacyStageBackground),
|
||||
}).ToList();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground), _ => new DefaultStageBackground())
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Skinning
|
||||
{
|
||||
public class TestSceneStageForeground : ManiaSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||
{
|
||||
typeof(LegacyStageForeground),
|
||||
}).ToList();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
SetContents(() => new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground), _ => null)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Width = 0.5f,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
typeof(Column),
|
||||
typeof(ColumnBackground),
|
||||
typeof(ColumnKeyArea),
|
||||
typeof(ColumnHitObjectArea)
|
||||
typeof(ColumnHitObjectArea),
|
||||
typeof(DefaultKeyArea),
|
||||
typeof(DefaultHitTarget)
|
||||
};
|
||||
|
||||
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneHitExplosion : OsuTestScene
|
||||
{
|
||||
private ScrollingTestContainer scrolling;
|
||||
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(DrawableNote),
|
||||
typeof(DrawableManiaHitObject),
|
||||
};
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Child = scrolling = new ScrollingTestContainer(ScrollingDirection.Down)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativePositionAxes = Axes.Y,
|
||||
Y = -0.25f,
|
||||
Size = new Vector2(Column.COLUMN_WIDTH, NotePiece.NOTE_HEIGHT),
|
||||
};
|
||||
|
||||
int runcount = 0;
|
||||
|
||||
AddRepeatStep("explode", () =>
|
||||
{
|
||||
runcount++;
|
||||
|
||||
if (runcount % 15 > 12)
|
||||
return;
|
||||
|
||||
scrolling.AddRange(new Drawable[]
|
||||
{
|
||||
new HitExplosion((runcount / 15) % 2 == 0 ? new Color4(94, 0, 57, 255) : new Color4(6, 84, 0, 255), runcount % 6 != 0)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
[Cached(typeof(IReadOnlyList<Mod>))]
|
||||
private IReadOnlyList<Mod> mods { get; set; } = Array.Empty<Mod>();
|
||||
|
||||
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
||||
private readonly List<Stage> stages = new List<Stage>();
|
||||
|
||||
private FillFlowContainer<ScrollingTestContainer> fill;
|
||||
|
||||
@@ -81,9 +81,9 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
AddAssert("check bar anchors", () => barsInStageAreAnchored(stages[1], Anchor.TopCentre));
|
||||
}
|
||||
|
||||
private bool notesInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.Columns.SelectMany(c => c.AllHitObjects).All(o => o.Anchor == anchor);
|
||||
private bool notesInStageAreAnchored(Stage stage, Anchor anchor) => stage.Columns.SelectMany(c => c.AllHitObjects).All(o => o.Anchor == anchor);
|
||||
|
||||
private bool barsInStageAreAnchored(ManiaStage stage, Anchor anchor) => stage.AllHitObjects.Where(obj => obj is DrawableBarLine).All(o => o.Anchor == anchor);
|
||||
private bool barsInStageAreAnchored(Stage stage, Anchor anchor) => stage.AllHitObjects.Where(obj => obj is DrawableBarLine).All(o => o.Anchor == anchor);
|
||||
|
||||
private void createNote()
|
||||
{
|
||||
@@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
var specialAction = ManiaAction.Special1;
|
||||
|
||||
var stage = new ManiaStage(0, new StageDefinition { Columns = 2 }, ref action, ref specialAction);
|
||||
var stage = new Stage(0, new StageDefinition { Columns = 2 }, ref action, ref specialAction);
|
||||
stages.Add(stage);
|
||||
|
||||
return new ScrollingTestContainer(direction)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
{
|
||||
public enum ColumnType
|
||||
{
|
||||
Even,
|
||||
Odd,
|
||||
Special
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
@@ -21,5 +22,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
|
||||
/// <param name="column">The 0-based column index.</param>
|
||||
/// <returns>Whether the column is a special column.</returns>
|
||||
public bool IsSpecialColumn(int column) => Columns % 2 == 1 && column == Columns / 2;
|
||||
|
||||
/// <summary>
|
||||
/// Get the type of column given a column index.
|
||||
/// </summary>
|
||||
/// <param name="column">The 0-based column index.</param>
|
||||
/// <returns>The type of the column.</returns>
|
||||
public ColumnType GetTypeOfColumn(int column)
|
||||
{
|
||||
if (IsSpecialColumn(column))
|
||||
return ColumnType.Special;
|
||||
|
||||
int distanceToEdge = Math.Min(column, (Columns - 1) - column);
|
||||
return distanceToEdge % 2 == 0 ? ColumnType.Odd : ColumnType.Even;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Configuration.Tracking;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Configuration;
|
||||
@@ -19,13 +20,14 @@ namespace osu.Game.Rulesets.Mania.Configuration
|
||||
{
|
||||
base.InitialiseDefaults();
|
||||
|
||||
Set(ManiaRulesetSetting.ScrollTime, 1500.0, 50.0, 5000.0, 50.0);
|
||||
Set(ManiaRulesetSetting.ScrollTime, 1500.0, DrawableManiaRuleset.MIN_TIME_RANGE, DrawableManiaRuleset.MAX_TIME_RANGE, 1);
|
||||
Set(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down);
|
||||
}
|
||||
|
||||
public override TrackedSettings CreateTrackedSettings() => new TrackedSettings
|
||||
{
|
||||
new TrackedSetting<double>(ManiaRulesetSetting.ScrollTime, v => new SettingDescription(v, "Scroll Time", $"{v}ms"))
|
||||
new TrackedSetting<double>(ManiaRulesetSetting.ScrollTime,
|
||||
v => new SettingDescription(v, "Scroll Speed", $"{(int)Math.Round(DrawableManiaRuleset.MAX_TIME_RANGE / v)} ({v}ms)"))
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components
|
||||
{
|
||||
public class EditBodyPiece : BodyPiece
|
||||
public class EditBodyPiece : DefaultBodyPiece
|
||||
{
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
AccentColour = colours.Yellow;
|
||||
AccentColour.Value = colours.Yellow;
|
||||
|
||||
Background.Alpha = 0.5f;
|
||||
Foreground.Alpha = 0;
|
||||
|
||||
@@ -12,12 +12,12 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints.Components
|
||||
{
|
||||
public EditNotePiece()
|
||||
{
|
||||
Height = NotePiece.NOTE_HEIGHT;
|
||||
Height = DefaultNotePiece.NOTE_HEIGHT;
|
||||
|
||||
CornerRadius = 5;
|
||||
Masking = true;
|
||||
|
||||
InternalChild = new NotePiece();
|
||||
InternalChild = new DefaultNotePiece();
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
{
|
||||
@@ -42,11 +42,19 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
{
|
||||
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.Start),
|
||||
new HoldNoteNoteSelectionBlueprint(DrawableObject, HoldNotePosition.End),
|
||||
new BodyPiece
|
||||
new Container
|
||||
{
|
||||
AccentColour = Color4.Transparent,
|
||||
BorderColour = colours.Yellow
|
||||
},
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
BorderThickness = 1,
|
||||
BorderColour = colours.Yellow,
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -122,11 +122,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
switch (scrollingInfo.Direction.Value)
|
||||
{
|
||||
case ScrollingDirection.Up:
|
||||
mousePosition.Y -= NotePiece.NOTE_HEIGHT / 2;
|
||||
mousePosition.Y -= DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||
break;
|
||||
|
||||
case ScrollingDirection.Down:
|
||||
mousePosition.Y += NotePiece.NOTE_HEIGHT / 2;
|
||||
mousePosition.Y += DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -143,11 +143,11 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
switch (scrollingInfo.Direction.Value)
|
||||
{
|
||||
case ScrollingDirection.Up:
|
||||
hitObjectPosition.Y += NotePiece.NOTE_HEIGHT / 2;
|
||||
hitObjectPosition.Y += DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||
break;
|
||||
|
||||
case ScrollingDirection.Down:
|
||||
hitObjectPosition.Y -= NotePiece.NOTE_HEIGHT / 2;
|
||||
hitObjectPosition.Y -= DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ namespace osu.Game.Rulesets.Mania
|
||||
|
||||
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);
|
||||
|
||||
public override ISkin CreateLegacySkinProvider(ISkinSource source) => new ManiaLegacySkinTransformer(source);
|
||||
public override ISkin CreateLegacySkinProvider(ISkinSource source, IBeatmap beatmap) => new ManiaLegacySkinTransformer(source, beatmap);
|
||||
|
||||
public override IEnumerable<Mod> ConvertLegacyMods(LegacyMods mods)
|
||||
public override IEnumerable<Mod> ConvertFromLegacyMods(LegacyMods mods)
|
||||
{
|
||||
if (mods.HasFlag(LegacyMods.Nightcore))
|
||||
yield return new ManiaModNightcore();
|
||||
@@ -118,6 +118,59 @@ namespace osu.Game.Rulesets.Mania
|
||||
yield return new ManiaModRandom();
|
||||
}
|
||||
|
||||
public override LegacyMods ConvertToLegacyMods(Mod[] mods)
|
||||
{
|
||||
var value = base.ConvertToLegacyMods(mods);
|
||||
|
||||
foreach (var mod in mods)
|
||||
{
|
||||
switch (mod)
|
||||
{
|
||||
case ManiaModKey1 _:
|
||||
value |= LegacyMods.Key1;
|
||||
break;
|
||||
|
||||
case ManiaModKey2 _:
|
||||
value |= LegacyMods.Key2;
|
||||
break;
|
||||
|
||||
case ManiaModKey3 _:
|
||||
value |= LegacyMods.Key3;
|
||||
break;
|
||||
|
||||
case ManiaModKey4 _:
|
||||
value |= LegacyMods.Key4;
|
||||
break;
|
||||
|
||||
case ManiaModKey5 _:
|
||||
value |= LegacyMods.Key5;
|
||||
break;
|
||||
|
||||
case ManiaModKey6 _:
|
||||
value |= LegacyMods.Key6;
|
||||
break;
|
||||
|
||||
case ManiaModKey7 _:
|
||||
value |= LegacyMods.Key7;
|
||||
break;
|
||||
|
||||
case ManiaModKey8 _:
|
||||
value |= LegacyMods.Key8;
|
||||
break;
|
||||
|
||||
case ManiaModKey9 _:
|
||||
value |= LegacyMods.Key9;
|
||||
break;
|
||||
|
||||
case ManiaModFadeIn _:
|
||||
value |= LegacyMods.FadeIn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public override IEnumerable<Mod> GetModsFor(ModType type)
|
||||
{
|
||||
switch (type)
|
||||
|
||||
@@ -1,19 +1,46 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania
|
||||
{
|
||||
public class ManiaSkinComponent : GameplaySkinComponent<ManiaSkinComponents>
|
||||
{
|
||||
public ManiaSkinComponent(ManiaSkinComponents component)
|
||||
/// <summary>
|
||||
/// The intended <see cref="Column"/> index for this component.
|
||||
/// May be null if the component does not exist in a <see cref="Column"/>.
|
||||
/// </summary>
|
||||
public readonly int? TargetColumn;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ManiaSkinComponent"/>.
|
||||
/// </summary>
|
||||
/// <param name="component">The component.</param>
|
||||
/// <param name="targetColumn">The intended <see cref="Column"/> index for this component. May be null if the component does not exist in a <see cref="Column"/>.</param>
|
||||
public ManiaSkinComponent(ManiaSkinComponents component, int? targetColumn = null)
|
||||
: base(component)
|
||||
{
|
||||
TargetColumn = targetColumn;
|
||||
}
|
||||
|
||||
protected override string RulesetPrefix => ManiaRuleset.SHORT_NAME;
|
||||
|
||||
protected override string ComponentName => Component.ToString().ToLower();
|
||||
}
|
||||
|
||||
public enum ManiaSkinComponents
|
||||
{
|
||||
ColumnBackground,
|
||||
HitTarget,
|
||||
KeyArea,
|
||||
Note,
|
||||
HoldNoteHead,
|
||||
HoldNoteTail,
|
||||
HoldNoteBody,
|
||||
HitExplosion,
|
||||
StageBackground,
|
||||
StageForeground,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,24 +3,17 @@
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public class ManiaModRandom : Mod, IApplicableToBeatmap
|
||||
public class ManiaModRandom : ModRandom, IApplicableToBeatmap
|
||||
{
|
||||
public override string Name => "Random";
|
||||
public override string Acronym => "RD";
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override IconUsage? Icon => OsuIcon.Dice;
|
||||
public override string Description => @"Shuffle around the keys!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
@@ -20,6 +21,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
public override bool DisplayResult => false;
|
||||
|
||||
public IBindable<bool> IsHitting => isHitting;
|
||||
|
||||
private readonly Bindable<bool> isHitting = new Bindable<bool>();
|
||||
|
||||
public DrawableHoldNoteHead Head => headContainer.Child;
|
||||
public DrawableHoldNoteTail Tail => tailContainer.Child;
|
||||
|
||||
@@ -27,7 +32,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
private readonly Container<DrawableHoldNoteTail> tailContainer;
|
||||
private readonly Container<DrawableHoldNoteTick> tickContainer;
|
||||
|
||||
private readonly BodyPiece bodyPiece;
|
||||
private readonly Drawable bodyPiece;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which the user started holding this hold note. Null if the user is not holding this hold note.
|
||||
@@ -44,18 +49,16 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
|
||||
AddRangeInternal(new Drawable[]
|
||||
AddRangeInternal(new[]
|
||||
{
|
||||
bodyPiece = new BodyPiece { RelativeSizeAxes = Axes.X },
|
||||
bodyPiece = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HoldNoteBody, hitObject.Column), _ => new DefaultBodyPiece())
|
||||
{
|
||||
RelativeSizeAxes = Axes.X
|
||||
},
|
||||
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
|
||||
headContainer = new Container<DrawableHoldNoteHead> { RelativeSizeAxes = Axes.Both },
|
||||
tailContainer = new Container<DrawableHoldNoteTail> { RelativeSizeAxes = Axes.Both },
|
||||
});
|
||||
|
||||
AccentColour.BindValueChanged(colour =>
|
||||
{
|
||||
bodyPiece.AccentColour = colour.NewValue;
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
||||
@@ -168,7 +171,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
return;
|
||||
|
||||
HoldStartTime = Time.Current;
|
||||
bodyPiece.Hitting = true;
|
||||
isHitting.Value = true;
|
||||
}
|
||||
|
||||
public void OnReleased(ManiaAction action)
|
||||
@@ -194,7 +197,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
private void endHold()
|
||||
{
|
||||
HoldStartTime = null;
|
||||
bodyPiece.Hitting = false;
|
||||
isHitting.Value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
/// </summary>
|
||||
public class DrawableHoldNoteHead : DrawableNote
|
||||
{
|
||||
protected override ManiaSkinComponents Component => ManiaSkinComponents.HoldNoteHead;
|
||||
|
||||
public DrawableHoldNoteHead(DrawableHoldNote holdNote)
|
||||
: base(holdNote.HitObject.Head)
|
||||
{
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
/// </summary>
|
||||
private const double release_window_lenience = 1.5;
|
||||
|
||||
protected override ManiaSkinComponents Component => ManiaSkinComponents.HoldNoteTail;
|
||||
|
||||
private readonly DrawableHoldNote holdNote;
|
||||
|
||||
public DrawableHoldNoteTail(DrawableHoldNote holdNote)
|
||||
|
||||
@@ -7,6 +7,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
@@ -24,6 +25,20 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
|
||||
protected readonly IBindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
[Resolved(canBeNull: true)]
|
||||
private ManiaPlayfield playfield { get; set; }
|
||||
|
||||
protected override float SamplePlaybackPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
if (playfield == null)
|
||||
return base.SamplePlaybackPosition;
|
||||
|
||||
return (float)HitObject.Column / playfield.TotalColumns;
|
||||
}
|
||||
}
|
||||
|
||||
protected DrawableManiaHitObject(ManiaHitObject hitObject)
|
||||
: base(hitObject)
|
||||
{
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
{
|
||||
@@ -18,7 +17,9 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
/// </summary>
|
||||
public class DrawableNote : DrawableManiaHitObject<Note>, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly NotePiece headPiece;
|
||||
protected virtual ManiaSkinComponents Component => ManiaSkinComponents.Note;
|
||||
|
||||
private readonly Drawable headPiece;
|
||||
|
||||
public DrawableNote(Note hitObject)
|
||||
: base(hitObject)
|
||||
@@ -26,22 +27,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
CornerRadius = 5;
|
||||
Masking = true;
|
||||
|
||||
AddInternal(headPiece = new NotePiece());
|
||||
|
||||
AccentColour.BindValueChanged(colour =>
|
||||
AddInternal(headPiece = new SkinnableDrawable(new ManiaSkinComponent(Component, hitObject.Column), _ => new DefaultNotePiece())
|
||||
{
|
||||
headPiece.AccentColour = colour.NewValue;
|
||||
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = colour.NewValue.Lighten(1f).Opacity(0.2f),
|
||||
Radius = 10,
|
||||
};
|
||||
}, true);
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> e)
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
@@ -9,26 +12,38 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Layout;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents length-wise portion of a hold note.
|
||||
/// </summary>
|
||||
public class BodyPiece : Container, IHasAccentColour
|
||||
public class DefaultBodyPiece : CompositeDrawable
|
||||
{
|
||||
private readonly Container subtractionLayer;
|
||||
protected readonly Bindable<Color4> AccentColour = new Bindable<Color4>();
|
||||
|
||||
protected readonly Drawable Background;
|
||||
protected readonly BufferedContainer Foreground;
|
||||
private readonly BufferedContainer subtractionContainer;
|
||||
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
||||
private readonly IBindable<bool> isHitting = new Bindable<bool>();
|
||||
|
||||
public BodyPiece()
|
||||
protected Drawable Background { get; private set; }
|
||||
protected BufferedContainer Foreground { get; private set; }
|
||||
|
||||
private BufferedContainer subtractionContainer;
|
||||
private Container subtractionLayer;
|
||||
|
||||
public DefaultBodyPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
Blending = BlendingParameters.Additive;
|
||||
|
||||
Children = new[]
|
||||
AddLayout(subtractionCache);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load([CanBeNull] DrawableHitObject drawableObject)
|
||||
{
|
||||
InternalChildren = new[]
|
||||
{
|
||||
Background = new Box { RelativeSizeAxes = Axes.Both },
|
||||
Foreground = new BufferedContainer
|
||||
@@ -66,43 +81,37 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
}
|
||||
};
|
||||
|
||||
AddLayout(subtractionCache);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
updateAccentColour();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
if (drawableObject != null)
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
var holdNote = (DrawableHoldNote)drawableObject;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
updateAccentColour();
|
||||
AccentColour.BindTo(drawableObject.AccentColour);
|
||||
isHitting.BindTo(holdNote.IsHitting);
|
||||
}
|
||||
|
||||
AccentColour.BindValueChanged(onAccentChanged, true);
|
||||
isHitting.BindValueChanged(_ => onAccentChanged(new ValueChangedEvent<Color4>(AccentColour.Value, AccentColour.Value)), true);
|
||||
}
|
||||
|
||||
public bool Hitting
|
||||
private void onAccentChanged(ValueChangedEvent<Color4> accent)
|
||||
{
|
||||
get => hitting;
|
||||
set
|
||||
{
|
||||
hitting = value;
|
||||
updateAccentColour();
|
||||
}
|
||||
}
|
||||
Foreground.Colour = accent.NewValue.Opacity(0.5f);
|
||||
Background.Colour = accent.NewValue.Opacity(0.7f);
|
||||
|
||||
private readonly LayoutValue subtractionCache = new LayoutValue(Invalidation.DrawSize);
|
||||
const float animation_length = 50;
|
||||
|
||||
Foreground.ClearTransforms(false, nameof(Foreground.Colour));
|
||||
|
||||
if (isHitting.Value)
|
||||
{
|
||||
// wait for the next sync point
|
||||
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
||||
using (Foreground.BeginDelayedSequence(synchronisedOffset))
|
||||
Foreground.FadeColour(accent.NewValue.Lighten(0.2f), animation_length).Then().FadeColour(Foreground.Colour, animation_length).Loop();
|
||||
}
|
||||
|
||||
subtractionCache.Invalidate();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
@@ -125,30 +134,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
subtractionCache.Validate();
|
||||
}
|
||||
}
|
||||
|
||||
private bool hitting;
|
||||
|
||||
private void updateAccentColour()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
Foreground.Colour = AccentColour.Opacity(0.5f);
|
||||
Background.Colour = AccentColour.Opacity(0.7f);
|
||||
|
||||
const float animation_length = 50;
|
||||
|
||||
Foreground.ClearTransforms(false, nameof(Foreground.Colour));
|
||||
|
||||
if (hitting)
|
||||
{
|
||||
// wait for the next sync point
|
||||
double synchronisedOffset = animation_length * 2 - Time.Current % (animation_length * 2);
|
||||
using (Foreground.BeginDelayedSequence(synchronisedOffset))
|
||||
Foreground.FadeColour(AccentColour.Lighten(0.2f), animation_length).Then().FadeColour(Foreground.Colour, animation_length).Loop();
|
||||
}
|
||||
|
||||
subtractionCache.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the static hit markers of notes.
|
||||
/// </summary>
|
||||
internal class DefaultNotePiece : CompositeDrawable
|
||||
{
|
||||
public const float NOTE_HEIGHT = 12;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private readonly IBindable<Color4> accentColour = new Bindable<Color4>();
|
||||
|
||||
private readonly Box colouredBox;
|
||||
|
||||
public DefaultNotePiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = NOTE_HEIGHT;
|
||||
|
||||
CornerRadius = 5;
|
||||
Masking = true;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
colouredBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = NOTE_HEIGHT / 2,
|
||||
Alpha = 0.1f
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load([NotNull] IScrollingInfo scrollingInfo, [CanBeNull] DrawableHitObject drawableObject)
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
|
||||
if (drawableObject != null)
|
||||
{
|
||||
accentColour.BindTo(drawableObject.AccentColour);
|
||||
accentColour.BindValueChanged(onAccentChanged, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
colouredBox.Anchor = colouredBox.Origin = direction.NewValue == ScrollingDirection.Up
|
||||
? Anchor.TopCentre
|
||||
: Anchor.BottomCentre;
|
||||
}
|
||||
|
||||
private void onAccentChanged(ValueChangedEvent<Color4> accent)
|
||||
{
|
||||
colouredBox.Colour = accent.NewValue.Lighten(0.9f);
|
||||
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Colour = accent.NewValue.Lighten(1f).Opacity(0.2f),
|
||||
Radius = 10,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the static hit markers of notes.
|
||||
/// </summary>
|
||||
internal class NotePiece : Container, IHasAccentColour
|
||||
{
|
||||
public const float NOTE_HEIGHT = 12;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private readonly Box colouredBox;
|
||||
|
||||
public NotePiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = NOTE_HEIGHT;
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
colouredBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = NOTE_HEIGHT / 2,
|
||||
Alpha = 0.1f
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(dir =>
|
||||
{
|
||||
colouredBox.Anchor = colouredBox.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
||||
}, true);
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
colouredBox.Colour = AccentColour.Lighten(0.9f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Replays.Legacy;
|
||||
@@ -24,15 +25,9 @@ namespace osu.Game.Rulesets.Mania.Replays
|
||||
Actions.AddRange(actions);
|
||||
}
|
||||
|
||||
public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null)
|
||||
public void FromLegacy(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null)
|
||||
{
|
||||
// We don't need to fully convert, just create the converter
|
||||
var converter = new ManiaBeatmapConverter(beatmap, new ManiaRuleset());
|
||||
|
||||
// NB: Via co-op mod, osu-stable can have two stages with floor(col/2) and ceil(col/2) columns. This will need special handling
|
||||
// elsewhere in the game if we do choose to support the old co-op mod anyway. For now, assume that there is only one stage.
|
||||
|
||||
var stage = new StageDefinition { Columns = converter.TargetColumns };
|
||||
var maniaBeatmap = (ManiaBeatmap)beatmap;
|
||||
|
||||
var normalAction = ManiaAction.Key1;
|
||||
var specialAction = ManiaAction.Special1;
|
||||
@@ -42,7 +37,7 @@ namespace osu.Game.Rulesets.Mania.Replays
|
||||
|
||||
while (activeColumns > 0)
|
||||
{
|
||||
var isSpecial = stage.IsSpecialColumn(counter);
|
||||
bool isSpecial = isColumnAtIndexSpecial(maniaBeatmap, counter);
|
||||
|
||||
if ((activeColumns & 1) > 0)
|
||||
Actions.Add(isSpecial ? specialAction : normalAction);
|
||||
@@ -56,5 +51,94 @@ namespace osu.Game.Rulesets.Mania.Replays
|
||||
activeColumns >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
public LegacyReplayFrame ToLegacy(IBeatmap beatmap)
|
||||
{
|
||||
var maniaBeatmap = (ManiaBeatmap)beatmap;
|
||||
|
||||
int keys = 0;
|
||||
|
||||
foreach (var action in Actions)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ManiaAction.Special1:
|
||||
keys |= 1 << getSpecialColumnIndex(maniaBeatmap, 0);
|
||||
break;
|
||||
|
||||
case ManiaAction.Special2:
|
||||
keys |= 1 << getSpecialColumnIndex(maniaBeatmap, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
// the index in lazer, which doesn't include special keys.
|
||||
int nonSpecialKeyIndex = action - ManiaAction.Key1;
|
||||
|
||||
// the index inclusive of special keys.
|
||||
int overallIndex = 0;
|
||||
|
||||
// iterate to find the index including special keys.
|
||||
for (; overallIndex < maniaBeatmap.TotalColumns; overallIndex++)
|
||||
{
|
||||
// skip over special columns.
|
||||
if (isColumnAtIndexSpecial(maniaBeatmap, overallIndex))
|
||||
continue;
|
||||
// found a non-special column to use.
|
||||
if (nonSpecialKeyIndex == 0)
|
||||
break;
|
||||
// found a non-special column but not ours.
|
||||
nonSpecialKeyIndex--;
|
||||
}
|
||||
|
||||
keys |= 1 << overallIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new LegacyReplayFrame(Time, keys, null, ReplayButtonState.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the overall index (across all stages) for a specified special key.
|
||||
/// </summary>
|
||||
/// <param name="maniaBeatmap">The beatmap.</param>
|
||||
/// <param name="specialOffset">The special key offset (0 is S1).</param>
|
||||
/// <returns>The overall index for the special column.</returns>
|
||||
private int getSpecialColumnIndex(ManiaBeatmap maniaBeatmap, int specialOffset)
|
||||
{
|
||||
for (int i = 0; i < maniaBeatmap.TotalColumns; i++)
|
||||
{
|
||||
if (isColumnAtIndexSpecial(maniaBeatmap, i))
|
||||
{
|
||||
if (specialOffset == 0)
|
||||
return i;
|
||||
|
||||
specialOffset--;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException("Special key index is too high.", nameof(specialOffset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check whether the column at an overall index (across all stages) is a special column.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap.</param>
|
||||
/// <param name="index">The overall index to check.</param>
|
||||
private bool isColumnAtIndexSpecial(ManiaBeatmap beatmap, int index)
|
||||
{
|
||||
foreach (var stage in beatmap.Stages)
|
||||
{
|
||||
if (index >= stage.Columns)
|
||||
{
|
||||
index -= stage.Columns;
|
||||
continue;
|
||||
}
|
||||
|
||||
return stage.IsSpecialColumn(index);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Column index is too high.", nameof(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyBodyPiece : LegacyManiaColumnElement
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private readonly IBindable<bool> isHitting = new Bindable<bool>();
|
||||
|
||||
private Drawable sprite;
|
||||
|
||||
public LegacyBodyPiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo, DrawableHitObject drawableObject)
|
||||
{
|
||||
string imageName = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.HoldNoteBodyImage)?.Value
|
||||
?? $"mania-note{FallbackColumnIndex}L";
|
||||
|
||||
sprite = skin.GetAnimation(imageName, true, true).With(d =>
|
||||
{
|
||||
if (d == null)
|
||||
return;
|
||||
|
||||
if (d is TextureAnimation animation)
|
||||
animation.IsPlaying = false;
|
||||
|
||||
d.Anchor = Anchor.TopCentre;
|
||||
d.RelativeSizeAxes = Axes.Both;
|
||||
d.Size = Vector2.One;
|
||||
d.FillMode = FillMode.Stretch;
|
||||
// Todo: Wrap
|
||||
});
|
||||
|
||||
if (sprite != null)
|
||||
InternalChild = sprite;
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
|
||||
var holdNote = (DrawableHoldNote)drawableObject;
|
||||
isHitting.BindTo(holdNote.IsHitting);
|
||||
isHitting.BindValueChanged(onIsHittingChanged, true);
|
||||
}
|
||||
|
||||
private void onIsHittingChanged(ValueChangedEvent<bool> isHitting)
|
||||
{
|
||||
if (!(sprite is TextureAnimation animation))
|
||||
return;
|
||||
|
||||
animation.GotoFrame(0);
|
||||
animation.IsPlaying = isHitting.NewValue;
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (sprite == null)
|
||||
return;
|
||||
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
sprite.Origin = Anchor.BottomCentre;
|
||||
sprite.Scale = new Vector2(1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite.Origin = Anchor.TopCentre;
|
||||
sprite.Scale = Vector2.One;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyColumnBackground : LegacyManiaColumnElement, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
private readonly bool isLastColumn;
|
||||
|
||||
private Container lightContainer;
|
||||
private Sprite light;
|
||||
|
||||
public LegacyColumnBackground(bool isLastColumn)
|
||||
{
|
||||
this.isLastColumn = isLastColumn;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
string lightImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.LightImage, 0)?.Value
|
||||
?? "mania-stage-light";
|
||||
|
||||
float leftLineWidth = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.LeftLineWidth)
|
||||
?.Value ?? 1;
|
||||
float rightLineWidth = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.RightLineWidth)
|
||||
?.Value ?? 1;
|
||||
|
||||
bool hasLeftLine = leftLineWidth > 0;
|
||||
bool hasRightLine = rightLineWidth > 0 && skin.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version)?.Value >= 2.4m
|
||||
|| isLastColumn;
|
||||
|
||||
float lightPosition = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.LightPosition)?.Value
|
||||
?? 0;
|
||||
|
||||
Color4 lineColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.ColumnLineColour)?.Value
|
||||
?? Color4.White;
|
||||
|
||||
Color4 backgroundColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.ColumnBackgroundColour)?.Value
|
||||
?? Color4.Black;
|
||||
|
||||
Color4 lightColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.ColumnLightColour)?.Value
|
||||
?? Color4.White;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = backgroundColour
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = leftLineWidth,
|
||||
Colour = lineColour,
|
||||
Alpha = hasLeftLine ? 1 : 0
|
||||
},
|
||||
new Box
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Width = rightLineWidth,
|
||||
Colour = lineColour,
|
||||
Alpha = hasRightLine ? 1 : 0
|
||||
},
|
||||
lightContainer = new Container
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Bottom = lightPosition },
|
||||
Child = light = new Sprite
|
||||
{
|
||||
Anchor = Anchor.BottomCentre,
|
||||
Origin = Anchor.BottomCentre,
|
||||
Colour = lightColour,
|
||||
Texture = skin.GetTexture(lightImage),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 1,
|
||||
Alpha = 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
lightContainer.Anchor = Anchor.TopCentre;
|
||||
lightContainer.Scale = new Vector2(1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
lightContainer.Anchor = Anchor.BottomCentre;
|
||||
lightContainer.Scale = Vector2.One;
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (action == Column.Action.Value)
|
||||
{
|
||||
light.FadeIn();
|
||||
light.ScaleTo(Vector2.One);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
// Todo: Should be 400 * 100 / CurrentBPM
|
||||
const double animation_length = 250;
|
||||
|
||||
if (action == Column.Action.Value)
|
||||
{
|
||||
light.FadeTo(0, animation_length);
|
||||
light.ScaleTo(new Vector2(1, 0), animation_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyHitExplosion : LegacyManiaColumnElement
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Drawable explosion;
|
||||
|
||||
public LegacyHitExplosion()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
string imageName = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.ExplosionImage)?.Value
|
||||
?? "lightingN";
|
||||
|
||||
float explosionScale = GetManiaSkinConfig<float>(skin, LegacyManiaSkinConfigurationLookups.ExplosionScale)?.Value
|
||||
?? 1;
|
||||
|
||||
// Create a temporary animation to retrieve the number of frames, in an effort to calculate the intended frame length.
|
||||
// This animation is discarded and re-queried with the appropriate frame length afterwards.
|
||||
var tmp = skin.GetAnimation(imageName, true, false);
|
||||
double frameLength = 0;
|
||||
if (tmp is IFramedAnimation tmpAnimation && tmpAnimation.FrameCount > 0)
|
||||
frameLength = Math.Max(1000 / 60.0, 170.0 / tmpAnimation.FrameCount);
|
||||
|
||||
explosion = skin.GetAnimation(imageName, true, false, frameLength: frameLength).With(d =>
|
||||
{
|
||||
if (d == null)
|
||||
return;
|
||||
|
||||
d.Origin = Anchor.Centre;
|
||||
d.Blending = BlendingParameters.Additive;
|
||||
d.Scale = new Vector2(explosionScale);
|
||||
});
|
||||
|
||||
if (explosion != null)
|
||||
InternalChild = explosion;
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (explosion != null)
|
||||
explosion.Anchor = direction.NewValue == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
explosion?.FadeInFromZero(80)
|
||||
.Then().FadeOut(120);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyHitTarget : LegacyManiaElement
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container directionContainer;
|
||||
|
||||
public LegacyHitTarget()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
string targetImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.HitTargetImage)?.Value
|
||||
?? "mania-stage-hint";
|
||||
|
||||
bool showJudgementLine = GetManiaSkinConfig<bool>(skin, LegacyManiaSkinConfigurationLookups.ShowJudgementLine)?.Value
|
||||
?? true;
|
||||
|
||||
Color4 lineColour = GetManiaSkinConfig<Color4>(skin, LegacyManiaSkinConfigurationLookups.JudgementLineColour)?.Value
|
||||
?? Color4.White;
|
||||
|
||||
InternalChild = directionContainer = new Container
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Sprite
|
||||
{
|
||||
Texture = skin.GetTexture(targetImage),
|
||||
Scale = new Vector2(1, 0.9f * 1.6025f),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 1
|
||||
},
|
||||
new Box
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
Colour = lineColour,
|
||||
Alpha = showJudgementLine ? 0.9f : 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
directionContainer.Anchor = Anchor.TopLeft;
|
||||
directionContainer.Scale = new Vector2(1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
directionContainer.Anchor = Anchor.BottomLeft;
|
||||
directionContainer.Scale = Vector2.One;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyHoldNoteHeadPiece : LegacyNotePiece
|
||||
{
|
||||
protected override Texture GetTexture(ISkinSource skin)
|
||||
{
|
||||
// TODO: Should fallback to the head from default legacy skin instead of note.
|
||||
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyHoldNoteTailPiece : LegacyNotePiece
|
||||
{
|
||||
protected override void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
// Invert the direction
|
||||
base.OnDirectionChanged(direction.NewValue == ScrollingDirection.Up
|
||||
? new ValueChangedEvent<ScrollingDirection>(ScrollingDirection.Down, ScrollingDirection.Down)
|
||||
: new ValueChangedEvent<ScrollingDirection>(ScrollingDirection.Up, ScrollingDirection.Up));
|
||||
}
|
||||
|
||||
protected override Texture GetTexture(ISkinSource skin)
|
||||
{
|
||||
// TODO: Should fallback to the head from default legacy skin instead of note.
|
||||
return GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteTailImage)
|
||||
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage)
|
||||
?? GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyKeyArea : LegacyManiaColumnElement, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container directionContainer;
|
||||
private Sprite upSprite;
|
||||
private Sprite downSprite;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; }
|
||||
|
||||
public LegacyKeyArea()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
string upImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.KeyImage)?.Value
|
||||
?? $"mania-key{FallbackColumnIndex}";
|
||||
|
||||
string downImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.KeyImageDown)?.Value
|
||||
?? $"mania-key{FallbackColumnIndex}D";
|
||||
|
||||
InternalChild = directionContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
upSprite = new Sprite
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
Texture = skin.GetTexture(upImage),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 1
|
||||
},
|
||||
downSprite = new Sprite
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
Texture = skin.GetTexture(downImage),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 1,
|
||||
Alpha = 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
directionContainer.Anchor = directionContainer.Origin = Anchor.TopCentre;
|
||||
upSprite.Anchor = downSprite.Anchor = Anchor.TopCentre;
|
||||
upSprite.Scale = downSprite.Scale = new Vector2(1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
directionContainer.Anchor = directionContainer.Origin = Anchor.BottomCentre;
|
||||
upSprite.Anchor = downSprite.Anchor = Anchor.BottomCentre;
|
||||
upSprite.Scale = downSprite.Scale = Vector2.One;
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (action == column.Action.Value)
|
||||
{
|
||||
upSprite.FadeTo(0);
|
||||
downSprite.FadeTo(1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
if (action == column.Action.Value)
|
||||
{
|
||||
upSprite.FadeTo(1);
|
||||
downSprite.FadeTo(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="CompositeDrawable"/> which is placed somewhere within a <see cref="Column"/>.
|
||||
/// </summary>
|
||||
public class LegacyManiaColumnElement : LegacyManiaElement
|
||||
{
|
||||
[Resolved]
|
||||
protected Column Column { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The column type identifier to use for texture lookups, in the case of no user-provided configuration.
|
||||
/// </summary>
|
||||
protected string FallbackColumnIndex { get; private set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
switch (Column.ColumnType)
|
||||
{
|
||||
case ColumnType.Special:
|
||||
FallbackColumnIndex = "S";
|
||||
break;
|
||||
|
||||
case ColumnType.Odd:
|
||||
FallbackColumnIndex = "1";
|
||||
break;
|
||||
|
||||
case ColumnType.Even:
|
||||
FallbackColumnIndex = "2";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IBindable<T> GetManiaSkinConfig<T>(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null)
|
||||
=> base.GetManiaSkinConfig<T>(skin, lookup, index ?? Column.Index);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// A mania legacy skin element.
|
||||
/// </summary>
|
||||
public class LegacyManiaElement : CompositeDrawable
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieve a per-column-count skin configuration.
|
||||
/// </summary>
|
||||
/// <param name="skin">The skin from which configuration is retrieved.</param>
|
||||
/// <param name="lookup">The value to retrieve.</param>
|
||||
/// <param name="index">If not null, denotes the index of the column to which the entry applies.</param>
|
||||
protected virtual IBindable<T> GetManiaSkinConfig<T>(ISkin skin, LegacyManiaSkinConfigurationLookups lookup, int? index = null)
|
||||
=> skin.GetConfig<ManiaSkinConfigurationLookup, T>(
|
||||
new ManiaSkinConfigurationLookup(lookup, index));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyNotePiece : LegacyManiaColumnElement
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container directionContainer;
|
||||
private Sprite noteSprite;
|
||||
|
||||
private float? minimumColumnWidth;
|
||||
|
||||
public LegacyNotePiece()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
minimumColumnWidth = skin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.MinimumColumnWidth))?.Value;
|
||||
|
||||
InternalChild = directionContainer = new Container
|
||||
{
|
||||
Origin = Anchor.BottomCentre,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Child = noteSprite = new Sprite { Texture = GetTexture(skin) }
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(OnDirectionChanged, true);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (noteSprite.Texture != null)
|
||||
{
|
||||
// The height is scaled to the minimum column width, if provided.
|
||||
float minimumWidth = minimumColumnWidth ?? DrawWidth;
|
||||
|
||||
noteSprite.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), noteSprite.Texture.DisplayWidth);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
directionContainer.Anchor = Anchor.TopCentre;
|
||||
directionContainer.Scale = new Vector2(1, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
directionContainer.Anchor = Anchor.BottomCentre;
|
||||
directionContainer.Scale = Vector2.One;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Texture GetTexture(ISkinSource skin) => GetTextureFromLookup(skin, LegacyManiaSkinConfigurationLookups.NoteImage);
|
||||
|
||||
protected Texture GetTextureFromLookup(ISkin skin, LegacyManiaSkinConfigurationLookups lookup)
|
||||
{
|
||||
string suffix = string.Empty;
|
||||
|
||||
switch (lookup)
|
||||
{
|
||||
case LegacyManiaSkinConfigurationLookups.HoldNoteHeadImage:
|
||||
suffix = "H";
|
||||
break;
|
||||
|
||||
case LegacyManiaSkinConfigurationLookups.HoldNoteTailImage:
|
||||
suffix = "T";
|
||||
break;
|
||||
}
|
||||
|
||||
string noteImage = GetManiaSkinConfig<string>(skin, lookup)?.Value
|
||||
?? $"mania-note{FallbackColumnIndex}{suffix}";
|
||||
|
||||
return skin.GetTexture(noteImage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyStageBackground : LegacyManiaElement
|
||||
{
|
||||
private Drawable leftSprite;
|
||||
private Drawable rightSprite;
|
||||
|
||||
public LegacyStageBackground()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin)
|
||||
{
|
||||
string leftImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.LeftStageImage)?.Value
|
||||
?? "mania-stage-left";
|
||||
|
||||
string rightImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.RightStageImage)?.Value
|
||||
?? "mania-stage-right";
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
leftSprite = new Sprite
|
||||
{
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopRight,
|
||||
X = 0.05f,
|
||||
Texture = skin.GetTexture(leftImage),
|
||||
},
|
||||
rightSprite = new Sprite
|
||||
{
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopLeft,
|
||||
X = -0.05f,
|
||||
Texture = skin.GetTexture(rightImage)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (leftSprite?.Height > 0)
|
||||
leftSprite.Scale = new Vector2(DrawHeight / leftSprite.Height);
|
||||
|
||||
if (rightSprite?.Height > 0)
|
||||
rightSprite.Scale = new Vector2(DrawHeight / rightSprite.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class LegacyStageForeground : LegacyManiaElement
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Drawable sprite;
|
||||
|
||||
public LegacyStageForeground()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
string bottomImage = GetManiaSkinConfig<string>(skin, LegacyManiaSkinConfigurationLookups.BottomStageImage)?.Value
|
||||
?? "mania-stage-bottom";
|
||||
|
||||
sprite = skin.GetAnimation(bottomImage, true, true)?.With(d =>
|
||||
{
|
||||
if (d == null)
|
||||
return;
|
||||
|
||||
d.Scale = new Vector2(1.6f);
|
||||
});
|
||||
|
||||
if (sprite != null)
|
||||
InternalChild = sprite;
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (sprite == null)
|
||||
return;
|
||||
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
sprite.Anchor = sprite.Origin = Anchor.TopCentre;
|
||||
else
|
||||
sprite.Anchor = sprite.Origin = Anchor.BottomCentre;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,15 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
@@ -14,10 +17,32 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
||||
public class ManiaLegacySkinTransformer : ISkin
|
||||
{
|
||||
private readonly ISkin source;
|
||||
private readonly ManiaBeatmap beatmap;
|
||||
|
||||
public ManiaLegacySkinTransformer(ISkin source)
|
||||
private Lazy<bool> isLegacySkin;
|
||||
|
||||
/// <summary>
|
||||
/// Whether texture for the keys exists.
|
||||
/// Used to determine if the mania ruleset is skinned.
|
||||
/// </summary>
|
||||
private Lazy<bool> hasKeyTexture;
|
||||
|
||||
public ManiaLegacySkinTransformer(ISkinSource source, IBeatmap beatmap)
|
||||
{
|
||||
this.source = source;
|
||||
this.beatmap = (ManiaBeatmap)beatmap;
|
||||
|
||||
source.SourceChanged += sourceChanged;
|
||||
sourceChanged();
|
||||
}
|
||||
|
||||
private void sourceChanged()
|
||||
{
|
||||
isLegacySkin = new Lazy<bool>(() => source.GetConfig<LegacySkinConfiguration.LegacySetting, decimal>(LegacySkinConfiguration.LegacySetting.Version) != null);
|
||||
hasKeyTexture = new Lazy<bool>(() => source.GetAnimation(
|
||||
GetConfig<ManiaSkinConfigurationLookup, string>(
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.KeyImage, 0))?.Value
|
||||
?? "mania-key1", true, true) != null);
|
||||
}
|
||||
|
||||
public Drawable GetDrawableComponent(ISkinComponent component)
|
||||
@@ -26,6 +51,45 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
case GameplaySkinComponent<HitResult> resultComponent:
|
||||
return getResult(resultComponent);
|
||||
|
||||
case ManiaSkinComponent maniaComponent:
|
||||
if (!isLegacySkin.Value || !hasKeyTexture.Value)
|
||||
return null;
|
||||
|
||||
switch (maniaComponent.Component)
|
||||
{
|
||||
case ManiaSkinComponents.ColumnBackground:
|
||||
return new LegacyColumnBackground(maniaComponent.TargetColumn == beatmap.TotalColumns - 1);
|
||||
|
||||
case ManiaSkinComponents.HitTarget:
|
||||
return new LegacyHitTarget();
|
||||
|
||||
case ManiaSkinComponents.KeyArea:
|
||||
return new LegacyKeyArea();
|
||||
|
||||
case ManiaSkinComponents.Note:
|
||||
return new LegacyNotePiece();
|
||||
|
||||
case ManiaSkinComponents.HoldNoteHead:
|
||||
return new LegacyHoldNoteHeadPiece();
|
||||
|
||||
case ManiaSkinComponents.HoldNoteTail:
|
||||
return new LegacyHoldNoteTailPiece();
|
||||
|
||||
case ManiaSkinComponents.HoldNoteBody:
|
||||
return new LegacyBodyPiece();
|
||||
|
||||
case ManiaSkinComponents.HitExplosion:
|
||||
return new LegacyHitExplosion();
|
||||
|
||||
case ManiaSkinComponents.StageBackground:
|
||||
return new LegacyStageBackground();
|
||||
|
||||
case ManiaSkinComponents.StageForeground:
|
||||
return new LegacyStageForeground();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -61,7 +125,12 @@ namespace osu.Game.Rulesets.Mania.Skinning
|
||||
|
||||
public SampleChannel GetSample(ISampleInfo sample) => source.GetSample(sample);
|
||||
|
||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) =>
|
||||
source.GetConfig<TLookup, TValue>(lookup);
|
||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup)
|
||||
{
|
||||
if (lookup is ManiaSkinConfigurationLookup maniaLookup)
|
||||
return source.GetConfig<LegacyManiaSkinConfigurationLookup, TValue>(new LegacyManiaSkinConfigurationLookup(beatmap.TotalColumns, maniaLookup.Lookup, maniaLookup.TargetColumn));
|
||||
|
||||
return source.GetConfig<TLookup, TValue>(lookup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Game.Rulesets.Mania.UI;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Skinning
|
||||
{
|
||||
public class ManiaSkinConfigurationLookup
|
||||
{
|
||||
/// <summary>
|
||||
/// The configuration lookup value.
|
||||
/// </summary>
|
||||
public readonly LegacyManiaSkinConfigurationLookups Lookup;
|
||||
|
||||
/// <summary>
|
||||
/// The intended <see cref="Column"/> index for the configuration.
|
||||
/// May be null if the configuration does not apply to a <see cref="Column"/>.
|
||||
/// </summary>
|
||||
public readonly int? TargetColumn;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ManiaSkinConfigurationLookup"/>.
|
||||
/// </summary>
|
||||
/// <param name="lookup">The lookup value.</param>
|
||||
/// <param name="targetColumn">The intended <see cref="Column"/> index for the configuration. May be null if the configuration does not apply to a <see cref="Column"/>.</param>
|
||||
public ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups lookup, int? targetColumn = null)
|
||||
{
|
||||
Lookup = lookup;
|
||||
TargetColumn = targetColumn;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,17 +12,19 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Mania.UI.Components;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
[Cached]
|
||||
public class Column : ScrollingPlayfield, IKeyBindingHandler<ManiaAction>, IHasAccentColour
|
||||
{
|
||||
public const float COLUMN_WIDTH = 80;
|
||||
private const float special_column_width = 70;
|
||||
public const float SPECIAL_COLUMN_WIDTH = 70;
|
||||
|
||||
/// <summary>
|
||||
/// The index of this column as part of the whole playfield.
|
||||
@@ -31,12 +33,9 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
public readonly Bindable<ManiaAction> Action = new Bindable<ManiaAction>();
|
||||
|
||||
private readonly ColumnBackground background;
|
||||
private readonly ColumnKeyArea keyArea;
|
||||
private readonly ColumnHitObjectArea hitObjectArea;
|
||||
|
||||
internal readonly Container TopLevelContainer;
|
||||
private readonly Container explosionContainer;
|
||||
|
||||
public Column(int index)
|
||||
{
|
||||
@@ -45,95 +44,34 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
RelativeSizeAxes = Axes.Y;
|
||||
Width = COLUMN_WIDTH;
|
||||
|
||||
background = new ColumnBackground { RelativeSizeAxes = Axes.Both };
|
||||
|
||||
Container hitTargetContainer;
|
||||
Drawable background = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.ColumnBackground, Index), _ => new DefaultColumnBackground())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
};
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
// For input purposes, the background is added at the highest depth, but is then proxied back below all other elements
|
||||
background.CreateProxy(),
|
||||
hitTargetContainer = new Container
|
||||
hitObjectArea = new ColumnHitObjectArea(Index, HitObjectContainer) { RelativeSizeAxes = Axes.Both },
|
||||
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.KeyArea, Index), _ => new DefaultKeyArea())
|
||||
{
|
||||
Name = "Hit target + hit objects",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
hitObjectArea = new ColumnHitObjectArea(HitObjectContainer)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
explosionContainer = new Container
|
||||
{
|
||||
Name = "Hit explosions",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
}
|
||||
},
|
||||
keyArea = new ColumnKeyArea
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = ManiaStage.HIT_TARGET_POSITION,
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
background,
|
||||
TopLevelContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||
};
|
||||
|
||||
TopLevelContainer.Add(explosionContainer.CreateProxy());
|
||||
|
||||
Direction.BindValueChanged(dir =>
|
||||
{
|
||||
hitTargetContainer.Padding = new MarginPadding
|
||||
{
|
||||
Top = dir.NewValue == ScrollingDirection.Up ? ManiaStage.HIT_TARGET_POSITION : 0,
|
||||
Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0,
|
||||
};
|
||||
|
||||
explosionContainer.Padding = new MarginPadding
|
||||
{
|
||||
Top = dir.NewValue == ScrollingDirection.Up ? NotePiece.NOTE_HEIGHT / 2 : 0,
|
||||
Bottom = dir.NewValue == ScrollingDirection.Down ? NotePiece.NOTE_HEIGHT / 2 : 0
|
||||
};
|
||||
|
||||
keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
||||
}, true);
|
||||
TopLevelContainer.Add(hitObjectArea.Explosions.CreateProxy());
|
||||
}
|
||||
|
||||
public override Axes RelativeSizeAxes => Axes.Y;
|
||||
|
||||
private bool isSpecial;
|
||||
public ColumnType ColumnType { get; set; }
|
||||
|
||||
public bool IsSpecial
|
||||
{
|
||||
get => isSpecial;
|
||||
set
|
||||
{
|
||||
if (isSpecial == value)
|
||||
return;
|
||||
public bool IsSpecial => ColumnType == ColumnType.Special;
|
||||
|
||||
isSpecial = value;
|
||||
|
||||
Width = isSpecial ? special_column_width : COLUMN_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
background.AccentColour = value;
|
||||
keyArea.AccentColour = value;
|
||||
hitObjectArea.AccentColour = value;
|
||||
}
|
||||
}
|
||||
public Color4 AccentColour { get; set; }
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
@@ -168,11 +106,15 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements.Value)
|
||||
return;
|
||||
|
||||
explosionContainer.Add(new HitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick)
|
||||
var explosion = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HitExplosion, Index), _ =>
|
||||
new DefaultHitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick))
|
||||
{
|
||||
Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre,
|
||||
Origin = Anchor.Centre
|
||||
});
|
||||
RelativeSizeAxes = Axes.Both
|
||||
};
|
||||
|
||||
hitObjectArea.Explosions.Add(explosion);
|
||||
|
||||
explosion.Delay(200).Expire(true);
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
@@ -197,6 +139,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
// This probably shouldn't exist as is, but the columns in the stage are separated by a 1px border
|
||||
=> DrawRectangle.Inflate(new Vector2(ManiaStage.COLUMN_SPACING / 2, 0)).Contains(ToLocalSpace(screenSpacePos));
|
||||
=> DrawRectangle.Inflate(new Vector2(Stage.COLUMN_SPACING / 2, 0)).Contains(ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,145 +1,45 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
public class ColumnHitObjectArea : CompositeDrawable, IHasAccentColour
|
||||
public class ColumnHitObjectArea : HitObjectArea
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
public readonly Container Explosions;
|
||||
private readonly Drawable hitTarget;
|
||||
|
||||
public ColumnHitObjectArea(HitObjectContainer hitObjectContainer)
|
||||
public ColumnHitObjectArea(int columnIndex, HitObjectContainer hitObjectContainer)
|
||||
: base(hitObjectContainer)
|
||||
{
|
||||
InternalChildren = new[]
|
||||
AddRangeInternal(new[]
|
||||
{
|
||||
hitTarget = new DefaultHitTarget
|
||||
hitTarget = new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.HitTarget, columnIndex), _ => new DefaultHitTarget())
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Depth = 1
|
||||
},
|
||||
hitObjectContainer
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(dir =>
|
||||
{
|
||||
Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
||||
|
||||
hitTarget.Anchor = hitTarget.Origin = anchor;
|
||||
}, true);
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
if (hitTarget is IHasAccentColour colouredHitTarget)
|
||||
colouredHitTarget.AccentColour = accentColour;
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultHitTarget : CompositeDrawable, IHasAccentColour
|
||||
{
|
||||
private const float hit_target_bar_height = 2;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private readonly Container hitTargetLine;
|
||||
private readonly Drawable hitTargetBar;
|
||||
|
||||
public DefaultHitTarget()
|
||||
{
|
||||
InternalChildren = new[]
|
||||
Explosions = new Container
|
||||
{
|
||||
hitTargetBar = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = NotePiece.NOTE_HEIGHT,
|
||||
Alpha = 0.6f,
|
||||
Colour = Color4.Black
|
||||
},
|
||||
hitTargetLine = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = hit_target_bar_height,
|
||||
Masking = true,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(dir =>
|
||||
{
|
||||
Anchor anchor = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft;
|
||||
|
||||
hitTargetBar.Anchor = hitTargetBar.Origin = anchor;
|
||||
hitTargetLine.Anchor = hitTargetLine.Origin = anchor;
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateColours();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
updateColours();
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = -1,
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateColours()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
protected override void UpdateHitPosition()
|
||||
{
|
||||
base.UpdateHitPosition();
|
||||
|
||||
hitTargetLine.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = 5,
|
||||
Colour = accentColour.Opacity(0.5f),
|
||||
};
|
||||
}
|
||||
if (Direction.Value == ScrollingDirection.Up)
|
||||
hitTarget.Anchor = hitTarget.Origin = Anchor.TopLeft;
|
||||
else
|
||||
hitTarget.Anchor = hitTarget.Origin = Anchor.BottomLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
public class ColumnKeyArea : CompositeDrawable, IKeyBindingHandler<ManiaAction>, IHasAccentColour
|
||||
{
|
||||
private const float key_icon_size = 10;
|
||||
private const float key_icon_corner_radius = 3;
|
||||
|
||||
private readonly IBindable<ManiaAction> action = new Bindable<ManiaAction>();
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container keyIcon;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IBindable<ManiaAction> action, IScrollingInfo scrollingInfo)
|
||||
{
|
||||
this.action.BindTo(action);
|
||||
|
||||
Drawable gradient;
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
gradient = new Box
|
||||
{
|
||||
Name = "Key gradient",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.5f
|
||||
},
|
||||
keyIcon = new Container
|
||||
{
|
||||
Name = "Key icon",
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Size = new Vector2(key_icon_size),
|
||||
Masking = true,
|
||||
CornerRadius = key_icon_corner_radius,
|
||||
BorderThickness = 2,
|
||||
BorderColour = Color4.White, // Not true
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(dir =>
|
||||
{
|
||||
gradient.Colour = ColourInfo.GradientVertical(
|
||||
dir.NewValue == ScrollingDirection.Up ? Color4.Black : Color4.Black.Opacity(0),
|
||||
dir.NewValue == ScrollingDirection.Up ? Color4.Black.Opacity(0) : Color4.Black);
|
||||
}, true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
updateColours();
|
||||
}
|
||||
|
||||
private Color4 accentColour;
|
||||
|
||||
public Color4 AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
if (accentColour == value)
|
||||
return;
|
||||
|
||||
accentColour = value;
|
||||
|
||||
updateColours();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateColours()
|
||||
{
|
||||
if (!IsLoaded)
|
||||
return;
|
||||
|
||||
keyIcon.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = 5,
|
||||
Colour = accentColour.Opacity(0.5f),
|
||||
};
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (action == this.action.Value)
|
||||
keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
if (action == this.action.Value)
|
||||
keyIcon.ScaleTo(1f, 125, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
public class DefaultColumnBackground : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Color4 brightColour;
|
||||
private Color4 dimColour;
|
||||
|
||||
private Box background;
|
||||
private Box backgroundOverlay;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; }
|
||||
|
||||
public DefaultColumnBackground()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
InternalChildren = new[]
|
||||
{
|
||||
background = new Box
|
||||
{
|
||||
Name = "Background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
backgroundOverlay = new Box
|
||||
{
|
||||
Name = "Background Gradient Overlay",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Height = 0.5f,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0
|
||||
}
|
||||
};
|
||||
|
||||
background.Colour = column.AccentColour.Darken(5);
|
||||
brightColour = column.AccentColour.Opacity(0.6f);
|
||||
dimColour = column.AccentColour.Opacity(0);
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.TopLeft;
|
||||
backgroundOverlay.Colour = ColourInfo.GradientVertical(brightColour, dimColour);
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundOverlay.Anchor = backgroundOverlay.Origin = Anchor.BottomLeft;
|
||||
backgroundOverlay.Colour = ColourInfo.GradientVertical(dimColour, brightColour);
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (action == column.Action.Value)
|
||||
backgroundOverlay.FadeTo(1, 50, Easing.OutQuint).Then().FadeTo(0.5f, 250, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
if (action == column.Action.Value)
|
||||
backgroundOverlay.FadeTo(0, 250, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
public class DefaultHitTarget : CompositeDrawable
|
||||
{
|
||||
private const float hit_target_bar_height = 2;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container hitTargetLine;
|
||||
private Drawable hitTargetBar;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; }
|
||||
|
||||
public DefaultHitTarget()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
InternalChildren = new[]
|
||||
{
|
||||
hitTargetBar = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = DefaultNotePiece.NOTE_HEIGHT,
|
||||
Alpha = 0.6f,
|
||||
Colour = Color4.Black
|
||||
},
|
||||
hitTargetLine = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = hit_target_bar_height,
|
||||
Masking = true,
|
||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||
},
|
||||
};
|
||||
|
||||
hitTargetLine.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = 5,
|
||||
Colour = column.AccentColour.Opacity(0.5f),
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
hitTargetBar.Anchor = hitTargetBar.Origin = Anchor.TopLeft;
|
||||
hitTargetLine.Anchor = hitTargetLine.Origin = Anchor.TopLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
hitTargetBar.Anchor = hitTargetBar.Origin = Anchor.BottomLeft;
|
||||
hitTargetLine.Anchor = hitTargetLine.Origin = Anchor.BottomLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
public class DefaultKeyArea : CompositeDrawable, IKeyBindingHandler<ManiaAction>
|
||||
{
|
||||
private const float key_icon_size = 10;
|
||||
private const float key_icon_corner_radius = 3;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private Container directionContainer;
|
||||
private Container keyIcon;
|
||||
private Drawable gradient;
|
||||
|
||||
[Resolved]
|
||||
private Column column { get; set; }
|
||||
|
||||
public DefaultKeyArea()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
InternalChild = directionContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = Stage.HIT_TARGET_POSITION,
|
||||
Children = new[]
|
||||
{
|
||||
gradient = new Box
|
||||
{
|
||||
Name = "Key gradient",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0.5f
|
||||
},
|
||||
keyIcon = new Container
|
||||
{
|
||||
Name = "Key icon",
|
||||
Size = new Vector2(key_icon_size),
|
||||
Origin = Anchor.Centre,
|
||||
Masking = true,
|
||||
CornerRadius = key_icon_corner_radius,
|
||||
BorderThickness = 2,
|
||||
BorderColour = Color4.White, // Not true
|
||||
Children = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
AlwaysPresent = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
keyIcon.EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Glow,
|
||||
Radius = 5,
|
||||
Colour = column.AccentColour.Opacity(0.5f),
|
||||
};
|
||||
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
keyIcon.Anchor = Anchor.BottomCentre;
|
||||
keyIcon.Y = -20;
|
||||
directionContainer.Anchor = directionContainer.Origin = Anchor.TopLeft;
|
||||
gradient.Colour = ColourInfo.GradientVertical(Color4.Black, Color4.Black.Opacity(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
keyIcon.Anchor = Anchor.TopCentre;
|
||||
keyIcon.Y = 20;
|
||||
directionContainer.Anchor = directionContainer.Origin = Anchor.BottomLeft;
|
||||
gradient.Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0), Color4.Black);
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnPressed(ManiaAction action)
|
||||
{
|
||||
if (action == column.Action.Value)
|
||||
keyIcon.ScaleTo(1.4f, 50, Easing.OutQuint).Then().ScaleTo(1.3f, 250, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(ManiaAction action)
|
||||
{
|
||||
if (action == column.Action.Value)
|
||||
keyIcon.ScaleTo(1f, 125, Easing.OutQuint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
public class DefaultStageBackground : CompositeDrawable
|
||||
{
|
||||
public DefaultStageBackground()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
InternalChild = new Box
|
||||
{
|
||||
Name = "Background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI.Components
|
||||
{
|
||||
public class HitObjectArea : SkinReloadableDrawable
|
||||
{
|
||||
protected readonly IBindable<ScrollingDirection> Direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
public HitObjectArea(HitObjectContainer hitObjectContainer)
|
||||
{
|
||||
InternalChildren = new[]
|
||||
{
|
||||
hitObjectContainer,
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
Direction.BindTo(scrollingInfo.Direction);
|
||||
Direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||
{
|
||||
base.SkinChanged(skin, allowFallback);
|
||||
UpdateHitPosition();
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
UpdateHitPosition();
|
||||
}
|
||||
|
||||
protected virtual void UpdateHitPosition()
|
||||
{
|
||||
float hitPosition = CurrentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.HitPosition))?.Value
|
||||
?? Stage.HIT_TARGET_POSITION;
|
||||
|
||||
Padding = Direction.Value == ScrollingDirection.Up
|
||||
? new MarginPadding { Top = hitPosition }
|
||||
: new MarginPadding { Bottom = hitPosition };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,35 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
internal class HitExplosion : CompositeDrawable
|
||||
public class DefaultHitExplosion : CompositeDrawable
|
||||
{
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
private readonly IBindable<ScrollingDirection> direction = new Bindable<ScrollingDirection>();
|
||||
|
||||
private readonly CircularContainer largeFaint;
|
||||
private readonly CircularContainer mainGlow1;
|
||||
|
||||
public HitExplosion(Color4 objectColour, bool isSmall = false)
|
||||
public DefaultHitExplosion(Color4 objectColour, bool isSmall = false)
|
||||
{
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = NotePiece.NOTE_HEIGHT;
|
||||
Height = DefaultNotePiece.NOTE_HEIGHT;
|
||||
|
||||
// scale roughly in-line with visual appearance of notes
|
||||
Scale = new Vector2(1f, 0.6f);
|
||||
@@ -109,6 +116,13 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IScrollingInfo scrollingInfo)
|
||||
{
|
||||
direction.BindTo(scrollingInfo.Direction);
|
||||
direction.BindValueChanged(onDirectionChanged, true);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
const double duration = 200;
|
||||
@@ -122,7 +136,20 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
mainGlow1.ScaleTo(1.4f, duration, Easing.OutQuint);
|
||||
|
||||
this.FadeOut(duration, Easing.Out);
|
||||
Expire(true);
|
||||
}
|
||||
|
||||
private void onDirectionChanged(ValueChangedEvent<ScrollingDirection> direction)
|
||||
{
|
||||
if (direction.NewValue == ScrollingDirection.Up)
|
||||
{
|
||||
Anchor = Anchor.TopCentre;
|
||||
Y = DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Anchor = Anchor.BottomCentre;
|
||||
Y = -DefaultNotePiece.NOTE_HEIGHT / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,10 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Input.Handlers;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
@@ -25,6 +27,16 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
public class DrawableManiaRuleset : DrawableScrollingRuleset<ManiaHitObject>
|
||||
{
|
||||
/// <summary>
|
||||
/// The minimum time range. This occurs at a <see cref="relativeTimeRange"/> of 40.
|
||||
/// </summary>
|
||||
public const double MIN_TIME_RANGE = 150;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum time range. This occurs at a <see cref="relativeTimeRange"/> of 1.
|
||||
/// </summary>
|
||||
public const double MAX_TIME_RANGE = 6000;
|
||||
|
||||
protected new ManiaPlayfield Playfield => (ManiaPlayfield)base.Playfield;
|
||||
|
||||
public new ManiaBeatmap Beatmap => (ManiaBeatmap)base.Beatmap;
|
||||
@@ -46,6 +58,19 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
bool isForCurrentRuleset = Beatmap.BeatmapInfo.Ruleset.Equals(Ruleset.RulesetInfo);
|
||||
|
||||
foreach (var p in ControlPoints)
|
||||
{
|
||||
// Mania doesn't care about global velocity
|
||||
p.Velocity = 1;
|
||||
p.BaseBeatLength *= Beatmap.BeatmapInfo.BaseDifficulty.SliderMultiplier;
|
||||
|
||||
// For non-mania beatmap, speed changes should only happen through timing points
|
||||
if (!isForCurrentRuleset)
|
||||
p.DifficultyPoint = new DifficultyControlPoint();
|
||||
}
|
||||
|
||||
BarLines.ForEach(Playfield.Add);
|
||||
|
||||
Config.BindWith(ManiaRulesetSetting.ScrollDirection, configDirection);
|
||||
@@ -54,6 +79,17 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
Config.BindWith(ManiaRulesetSetting.ScrollTime, TimeRange);
|
||||
}
|
||||
|
||||
protected override void AdjustScrollSpeed(int amount)
|
||||
{
|
||||
this.TransformTo(nameof(relativeTimeRange), relativeTimeRange + amount, 200, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private double relativeTimeRange
|
||||
{
|
||||
get => MAX_TIME_RANGE / TimeRange.Value;
|
||||
set => TimeRange.Value = MAX_TIME_RANGE / value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the column that intersects a screen-space position.
|
||||
/// </summary>
|
||||
@@ -85,5 +121,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
}
|
||||
|
||||
protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new ManiaFramedReplayInputHandler(replay);
|
||||
|
||||
protected override ReplayRecorder CreateReplayRecorder(Replay replay) => new ManiaReplayRecorder(replay);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
@@ -14,9 +15,10 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
[Cached]
|
||||
public class ManiaPlayfield : ScrollingPlayfield
|
||||
{
|
||||
private readonly List<ManiaStage> stages = new List<ManiaStage>();
|
||||
private readonly List<Stage> stages = new List<Stage>();
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => stages.Any(s => s.ReceivePositionalInputAt(screenSpacePos));
|
||||
|
||||
@@ -41,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
for (int i = 0; i < stageDefinitions.Count; i++)
|
||||
{
|
||||
var newStage = new ManiaStage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
||||
var newStage = new Stage(firstColumnIndex, stageDefinitions[i], ref normalColumnAction, ref specialColumnAction);
|
||||
|
||||
playfieldGrid.Content[0][i] = newStage;
|
||||
|
||||
@@ -90,7 +92,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
/// </summary>
|
||||
public int TotalColumns => stages.Sum(s => s.Columns.Count);
|
||||
|
||||
private ManiaStage getStageByColumn(int column)
|
||||
private Stage getStageByColumn(int column)
|
||||
{
|
||||
int sum = 0;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
@@ -13,8 +12,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
Anchor = Anchor.Centre;
|
||||
Origin = Anchor.Centre;
|
||||
|
||||
Size = new Vector2(1, 0.8f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets.Mania.Replays;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.UI
|
||||
{
|
||||
public class ManiaReplayRecorder : ReplayRecorder<ManiaAction>
|
||||
{
|
||||
public ManiaReplayRecorder(Replay replay)
|
||||
: base(replay)
|
||||
{
|
||||
}
|
||||
|
||||
protected override ReplayFrame HandleFrame(Vector2 mousePosition, List<ManiaAction> actions, ReplayFrame previousFrame)
|
||||
=> new ManiaReplayFrame(Time.Current, actions.ToArray());
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Mania.Skinning;
|
||||
using osu.Game.Rulesets.Mania.UI.Components;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@@ -23,30 +24,33 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
/// <summary>
|
||||
/// A collection of <see cref="Column"/>s.
|
||||
/// </summary>
|
||||
public class ManiaStage : ScrollingPlayfield
|
||||
public class Stage : ScrollingPlayfield
|
||||
{
|
||||
public const float COLUMN_SPACING = 1;
|
||||
|
||||
public const float HIT_TARGET_POSITION = 50;
|
||||
public const float HIT_TARGET_POSITION = 110;
|
||||
|
||||
public IReadOnlyList<Column> Columns => columnFlow.Children;
|
||||
private readonly FillFlowContainer<Column> columnFlow;
|
||||
|
||||
private readonly Container barLineContainer;
|
||||
|
||||
public Container<DrawableManiaJudgement> Judgements => judgements;
|
||||
private readonly JudgementContainer<DrawableManiaJudgement> judgements;
|
||||
|
||||
private readonly Drawable barLineContainer;
|
||||
private readonly Container topLevelContainer;
|
||||
|
||||
private List<Color4> normalColumnColours = new List<Color4>();
|
||||
private Color4 specialColumnColour;
|
||||
private readonly Dictionary<ColumnType, Color4> columnColours = new Dictionary<ColumnType, Color4>
|
||||
{
|
||||
{ ColumnType.Even, new Color4(6, 84, 0, 255) },
|
||||
{ ColumnType.Odd, new Color4(94, 0, 57, 255) },
|
||||
{ ColumnType.Special, new Color4(0, 48, 63, 255) }
|
||||
};
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => Columns.Any(c => c.ReceivePositionalInputAt(screenSpacePos));
|
||||
|
||||
private readonly int firstColumnIndex;
|
||||
|
||||
public ManiaStage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction)
|
||||
public Stage(int firstColumnIndex, StageDefinition definition, ref ManiaAction normalColumnStartAction, ref ManiaAction specialColumnStartAction)
|
||||
{
|
||||
this.firstColumnIndex = firstColumnIndex;
|
||||
|
||||
@@ -67,31 +71,17 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
AutoSizeAxes = Axes.X,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageBackground), _ => new DefaultStageBackground())
|
||||
{
|
||||
Name = "Columns mask",
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
columnFlow = new FillFlowContainer<Column>
|
||||
{
|
||||
Name = "Columns",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Masking = true,
|
||||
CornerRadius = 5,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Name = "Background",
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black
|
||||
},
|
||||
columnFlow = new FillFlowContainer<Column>
|
||||
{
|
||||
Name = "Columns",
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
AutoSizeAxes = Axes.X,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Padding = new MarginPadding { Left = COLUMN_SPACING, Right = COLUMN_SPACING },
|
||||
Spacing = new Vector2(COLUMN_SPACING, 0)
|
||||
},
|
||||
}
|
||||
Direction = FillDirection.Horizontal,
|
||||
Padding = new MarginPadding { Left = COLUMN_SPACING, Right = COLUMN_SPACING },
|
||||
},
|
||||
new Container
|
||||
{
|
||||
@@ -102,15 +92,18 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
Width = 1366, // Bar lines should only be masked on the vertical axis
|
||||
BypassAutoSizeAxes = Axes.Both,
|
||||
Masking = true,
|
||||
Child = barLineContainer = new Container
|
||||
Child = barLineContainer = new HitObjectArea(HitObjectContainer)
|
||||
{
|
||||
Name = "Bar lines",
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Child = HitObjectContainer
|
||||
}
|
||||
},
|
||||
new SkinnableDrawable(new ManiaSkinComponent(ManiaSkinComponents.StageForeground), _ => null)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both
|
||||
},
|
||||
judgements = new JudgementContainer<DrawableManiaJudgement>
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
@@ -125,24 +118,52 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
|
||||
for (int i = 0; i < definition.Columns; i++)
|
||||
{
|
||||
var isSpecial = definition.IsSpecialColumn(i);
|
||||
var columnType = definition.GetTypeOfColumn(i);
|
||||
var column = new Column(firstColumnIndex + i)
|
||||
{
|
||||
IsSpecial = isSpecial,
|
||||
Action = { Value = isSpecial ? specialColumnStartAction++ : normalColumnStartAction++ }
|
||||
ColumnType = columnType,
|
||||
AccentColour = columnColours[columnType],
|
||||
Action = { Value = columnType == ColumnType.Special ? specialColumnStartAction++ : normalColumnStartAction++ }
|
||||
};
|
||||
|
||||
AddColumn(column);
|
||||
}
|
||||
}
|
||||
|
||||
Direction.BindValueChanged(dir =>
|
||||
private ISkin currentSkin;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ISkinSource skin)
|
||||
{
|
||||
currentSkin = skin;
|
||||
skin.SourceChanged += onSkinChanged;
|
||||
|
||||
onSkinChanged();
|
||||
}
|
||||
|
||||
private void onSkinChanged()
|
||||
{
|
||||
foreach (var col in columnFlow)
|
||||
{
|
||||
barLineContainer.Padding = new MarginPadding
|
||||
if (col.Index > 0)
|
||||
{
|
||||
Top = dir.NewValue == ScrollingDirection.Up ? HIT_TARGET_POSITION : 0,
|
||||
Bottom = dir.NewValue == ScrollingDirection.Down ? HIT_TARGET_POSITION : 0,
|
||||
};
|
||||
}, true);
|
||||
float spacing = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.ColumnSpacing, col.Index - 1))
|
||||
?.Value ?? COLUMN_SPACING;
|
||||
|
||||
col.Margin = new MarginPadding { Left = spacing };
|
||||
}
|
||||
|
||||
float? width = currentSkin.GetConfig<ManiaSkinConfigurationLookup, float>(
|
||||
new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.ColumnWidth, col.Index))
|
||||
?.Value;
|
||||
|
||||
if (width == null)
|
||||
// only used by default skin (legacy skins get defaults set in LegacyManiaSkinConfiguration)
|
||||
col.Width = col.IsSpecial ? Column.SPECIAL_COLUMN_WIDTH : Column.COLUMN_WIDTH;
|
||||
else
|
||||
col.Width = width.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddColumn(Column c)
|
||||
@@ -195,38 +216,6 @@ namespace osu.Game.Rulesets.Mania.UI
|
||||
});
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
normalColumnColours = new List<Color4>
|
||||
{
|
||||
new Color4(94, 0, 57, 255),
|
||||
new Color4(6, 84, 0, 255)
|
||||
};
|
||||
|
||||
specialColumnColour = new Color4(0, 48, 63, 255);
|
||||
|
||||
// Set the special column + colour + key
|
||||
foreach (var column in Columns)
|
||||
{
|
||||
if (!column.IsSpecial)
|
||||
continue;
|
||||
|
||||
column.AccentColour = specialColumnColour;
|
||||
}
|
||||
|
||||
var nonSpecialColumns = Columns.Where(c => !c.IsSpecial).ToList();
|
||||
|
||||
// We'll set the colours of the non-special columns in a separate loop, because the non-special
|
||||
// column colours are mirrored across their centre and special styles mess with this
|
||||
for (int i = 0; i < Math.Ceiling(nonSpecialColumns.Count / 2f); i++)
|
||||
{
|
||||
Color4 colour = normalColumnColours[i % normalColumnColours.Count];
|
||||
nonSpecialColumns[i].AccentColour = colour;
|
||||
nonSpecialColumns[nonSpecialColumns.Count - 1 - i].AccentColour = colour;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
// Due to masking differences, it is not possible to get the width of the columns container automatically
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Osu.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public abstract class OsuSkinnableTestScene : SkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
typeof(OsuRuleset),
|
||||
typeof(OsuLegacySkinTransformer),
|
||||
};
|
||||
|
||||
protected override Ruleset CreateRulesetForSkinProvider() => new OsuRuleset();
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 23 KiB |
@@ -10,17 +10,16 @@ using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestSceneDrawableJudgement : SkinnableTestScene
|
||||
public class TestSceneDrawableJudgement : OsuSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||
{
|
||||
typeof(DrawableJudgement),
|
||||
typeof(DrawableOsuJudgement)
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
public TestSceneDrawableJudgement()
|
||||
{
|
||||
|
||||
@@ -3,26 +3,32 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing.Input;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Osu.Skinning;
|
||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneGameplayCursor : SkinnableTestScene
|
||||
public class TestSceneGameplayCursor : OsuSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
public override IReadOnlyList<Type> RequiredTypes => base.RequiredTypes.Concat(new[]
|
||||
{
|
||||
typeof(GameplayCursorContainer),
|
||||
typeof(OsuCursorContainer),
|
||||
typeof(OsuCursor),
|
||||
typeof(LegacyCursor),
|
||||
typeof(LegacyCursorTrail),
|
||||
typeof(CursorTrail)
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
[Cached]
|
||||
private GameplayBeatmap gameplayBeatmap;
|
||||
|
||||
@@ -14,12 +14,11 @@ using osu.Game.Rulesets.Mods;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestSceneHitCircle : SkinnableTestScene
|
||||
public class TestSceneHitCircle : OsuSkinnableTestScene
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||
{
|
||||
|
||||
@@ -4,48 +4,43 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class TestSceneHitCircleArea : ManualInputManagerTestScene
|
||||
public class TestSceneHitCircleArea : OsuManualInputManagerTestScene
|
||||
{
|
||||
private HitCircle hitCircle;
|
||||
private DrawableHitCircle drawableHitCircle;
|
||||
private DrawableHitCircle.HitReceptor hitAreaReceptor => drawableHitCircle.HitArea;
|
||||
|
||||
[SetUp]
|
||||
public new void SetUp()
|
||||
public void SetUp() => Schedule(() =>
|
||||
{
|
||||
base.SetUp();
|
||||
|
||||
Schedule(() =>
|
||||
hitCircle = new HitCircle
|
||||
{
|
||||
hitCircle = new HitCircle
|
||||
{
|
||||
Position = new Vector2(100, 100),
|
||||
StartTime = Time.Current + 500
|
||||
};
|
||||
Position = new Vector2(100, 100),
|
||||
StartTime = Time.Current + 500
|
||||
};
|
||||
|
||||
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
hitCircle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
|
||||
|
||||
Child = new SkinProvidingContainer(new DefaultSkin())
|
||||
Child = new SkinProvidingContainer(new DefaultSkin())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = drawableHitCircle = new DrawableHitCircle(hitCircle)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = drawableHitCircle = new DrawableHitCircle(hitCircle)
|
||||
{
|
||||
Size = new Vector2(100)
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
Size = new Vector2(100)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestCircleHitCentre()
|
||||
|
||||