mirror of
https://github.com/ppy/osu
synced 2024-12-25 16:22:23 +00:00
Move flashlight code from OsuModFlashlight to ModFlashlight and implement other modes and break time
This commit is contained in:
parent
5c09662c14
commit
023924396d
@ -1,12 +1,78 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Catch.Objects;
|
||||
using osu.Game.Rulesets.Catch.UI;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Mods
|
||||
{
|
||||
public class CatchModFlashlight : ModFlashlight
|
||||
public class CatchModFlashlight : ModFlashlight<CatchHitObject>
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
|
||||
private const float default_flashlight_size = 350;
|
||||
|
||||
public override Flashlight CreateFlashlight() => new CatchFlashlight(playfield);
|
||||
|
||||
private CatchPlayfield playfield;
|
||||
|
||||
public override void ApplyToRulesetContainer(RulesetContainer<CatchHitObject> rulesetContainer)
|
||||
{
|
||||
playfield = (CatchPlayfield)rulesetContainer.Playfield;
|
||||
base.ApplyToRulesetContainer(rulesetContainer);
|
||||
}
|
||||
|
||||
private class CatchFlashlight : Flashlight
|
||||
{
|
||||
private readonly CatchPlayfield playfield;
|
||||
|
||||
public CatchFlashlight(CatchPlayfield playfield)
|
||||
{
|
||||
this.playfield = playfield;
|
||||
MousePosWrapper.CircularFlashlightSize = getSizeFor(0);
|
||||
MousePosWrapper.Rectangular = false;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
MousePosWrapper.FlashlightPosition = (playfield.CatcherArea.MovableCatcher.ScreenSpaceDrawQuad.TopLeft + playfield.CatcherArea.MovableCatcher.ScreenSpaceDrawQuad.TopRight) / 2;
|
||||
MousePosWrapper.FlashlightPositionChanged = true;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private float flashlightSize
|
||||
{
|
||||
set
|
||||
{
|
||||
if (MousePosWrapper.CircularFlashlightSize == value) return;
|
||||
|
||||
MousePosWrapper.CircularFlashlightSize = value;
|
||||
MousePosWrapper.CircularFlashlightSizeChanged = true;
|
||||
}
|
||||
|
||||
get => MousePosWrapper.CircularFlashlightSize;
|
||||
}
|
||||
|
||||
private float getSizeFor(int combo)
|
||||
{
|
||||
if (combo > 200)
|
||||
return default_flashlight_size * 0.8f;
|
||||
else if (combo > 100)
|
||||
return default_flashlight_size * 0.9f;
|
||||
else
|
||||
return default_flashlight_size;
|
||||
}
|
||||
|
||||
protected override void OnComboChange(int newCombo)
|
||||
{
|
||||
this.TransformTo(nameof(flashlightSize), getSizeFor(newCombo), FLASHLIGHT_FADE_DURATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public const float BASE_WIDTH = 512;
|
||||
|
||||
private readonly CatcherArea catcherArea;
|
||||
internal readonly CatcherArea CatcherArea;
|
||||
|
||||
protected override bool UserScrollSpeedAdjustment => false;
|
||||
|
||||
@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
catcherArea = new CatcherArea(difficulty)
|
||||
CatcherArea = new CatcherArea(difficulty)
|
||||
{
|
||||
GetVisualRepresentation = getVisualRepresentation,
|
||||
ExplodingFruitTarget = explodingFruitContainer,
|
||||
@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
VisibleTimeRange.Value = BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
|
||||
}
|
||||
|
||||
public bool CheckIfWeCanCatch(CatchHitObject obj) => catcherArea.AttemptCatch(obj);
|
||||
public bool CheckIfWeCanCatch(CatchHitObject obj) => CatcherArea.AttemptCatch(obj);
|
||||
|
||||
public override void Add(DrawableHitObject h)
|
||||
{
|
||||
@ -72,6 +72,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
}
|
||||
|
||||
private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
|
||||
=> catcherArea.OnResult((DrawableCatchHitObject)judgedObject, result);
|
||||
=> CatcherArea.OnResult((DrawableCatchHitObject)judgedObject, result);
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
{
|
||||
public const float CATCHER_SIZE = 100;
|
||||
|
||||
protected readonly Catcher MovableCatcher;
|
||||
protected internal readonly Catcher MovableCatcher;
|
||||
|
||||
public Func<CatchHitObject, DrawableHitObject<CatchHitObject>> GetVisualRepresentation;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
@ -16,6 +17,6 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Description => @"Keys appear out of nowhere!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight<ManiaHitObject>) };
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,59 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public class ManiaModFlashlight : ModFlashlight
|
||||
public class ManiaModFlashlight : ModFlashlight<ManiaHitObject>
|
||||
{
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModHidden) };
|
||||
|
||||
private const float default_flashlight_size = 180;
|
||||
|
||||
public override Flashlight CreateFlashlight() => new ManiaFlashlight();
|
||||
|
||||
private class ManiaFlashlight : Flashlight
|
||||
{
|
||||
public ManiaFlashlight()
|
||||
{
|
||||
MousePosWrapper.Rectangular = true;
|
||||
MousePosWrapper.RectangularFlashlightSize = new Vector2(0, default_flashlight_size);
|
||||
}
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
MousePosWrapper.RectangularFlashlightSize.X = DrawWidth;
|
||||
MousePosWrapper.RectangularFlashlightSizeChanged = true;
|
||||
|
||||
MousePosWrapper.FlashlightPosition = ScreenSpaceDrawQuad.Centre;
|
||||
MousePosWrapper.FlashlightPositionChanged = true;
|
||||
});
|
||||
}
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
}
|
||||
|
||||
protected override void OnComboChange(int newCombo)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
MousePosWrapper.RectangularFlashlightSize.X = DrawWidth;
|
||||
MousePosWrapper.RectangularFlashlightSizeChanged = true;
|
||||
|
||||
MousePosWrapper.FlashlightPosition = ScreenSpaceDrawQuad.Centre;
|
||||
MousePosWrapper.FlashlightPositionChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
@ -10,6 +11,6 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public override string Description => @"Keys fade out before you hit them!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight<ManiaHitObject>) };
|
||||
}
|
||||
}
|
||||
|
@ -1,95 +1,65 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shaders;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModFlashlight : ModFlashlight, IApplicableToRulesetContainer<OsuHitObject>
|
||||
public class OsuModFlashlight : ModFlashlight<OsuHitObject>
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
|
||||
public void ApplyToRulesetContainer(RulesetContainer<OsuHitObject> rulesetContainer)
|
||||
private const float default_flashlight_size = 180;
|
||||
|
||||
public override Flashlight CreateFlashlight() => new OsuFlashlight();
|
||||
|
||||
private class OsuFlashlight : Flashlight, IRequireHighFrequencyMousePosition
|
||||
{
|
||||
rulesetContainer.KeyBindingInputManager.Add(new Flashlight
|
||||
public OsuFlashlight()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
});
|
||||
}
|
||||
|
||||
private class Flashlight : Drawable, IRequireHighFrequencyMousePosition
|
||||
{
|
||||
private Shader shader;
|
||||
private readonly MousePositionWrapper mousePosWrapper = new MousePositionWrapper
|
||||
{
|
||||
FlashlightSize = 300f
|
||||
};
|
||||
|
||||
protected override DrawNode CreateDrawNode() => new FlashlightDrawNode();
|
||||
|
||||
protected override void ApplyDrawNode(DrawNode node)
|
||||
{
|
||||
base.ApplyDrawNode(node);
|
||||
|
||||
var flashNode = (FlashlightDrawNode)node;
|
||||
|
||||
flashNode.Shader = shader;
|
||||
flashNode.ScreenSpaceDrawQuad = ScreenSpaceDrawQuad;
|
||||
flashNode.MousePosWrapper = mousePosWrapper;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ShaderManager shaderManager)
|
||||
{
|
||||
shader = shaderManager.Load(VertexShaderDescriptor.POSITION, "Flashlight");
|
||||
MousePosWrapper.CircularFlashlightSize = getSizeFor(0);
|
||||
MousePosWrapper.Rectangular = false;
|
||||
}
|
||||
|
||||
protected override bool OnMouseMove(MouseMoveEvent e)
|
||||
{
|
||||
mousePosWrapper.MousePosition = e.ScreenSpaceMousePosition;
|
||||
MousePosWrapper.FlashlightPosition = e.ScreenSpaceMousePosition;
|
||||
MousePosWrapper.FlashlightPositionChanged = true;
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
}
|
||||
|
||||
private class MousePositionWrapper
|
||||
{
|
||||
public Vector2 MousePosition;
|
||||
public float FlashlightSize;
|
||||
public bool FlashlightUniformUpdated;
|
||||
}
|
||||
|
||||
private class FlashlightDrawNode : DrawNode
|
||||
{
|
||||
public Shader Shader;
|
||||
public Quad ScreenSpaceDrawQuad;
|
||||
public MousePositionWrapper MousePosWrapper;
|
||||
|
||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
||||
[UsedImplicitly]
|
||||
private float flashlightSize
|
||||
{
|
||||
base.Draw(vertexAction);
|
||||
set
|
||||
{
|
||||
if (MousePosWrapper.CircularFlashlightSize == value) return;
|
||||
|
||||
Shader.Bind();
|
||||
// ReSharper disable once AssignmentInConditionalExpression
|
||||
if(MousePosWrapper.FlashlightUniformUpdated = !MousePosWrapper.FlashlightUniformUpdated)
|
||||
Shader.GetUniform<float>("flashlightSize").UpdateValue(ref MousePosWrapper.FlashlightSize);
|
||||
MousePosWrapper.CircularFlashlightSize = value;
|
||||
MousePosWrapper.CircularFlashlightSizeChanged = true;
|
||||
}
|
||||
|
||||
Shader.GetUniform<Vector2>("mousePos").UpdateValue(ref MousePosWrapper.MousePosition);
|
||||
get => MousePosWrapper.CircularFlashlightSize;
|
||||
}
|
||||
|
||||
Texture.WhitePixel.DrawQuad(ScreenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction);
|
||||
private float getSizeFor(int combo)
|
||||
{
|
||||
if (combo > 200)
|
||||
return default_flashlight_size * 0.8f;
|
||||
else if (combo > 100)
|
||||
return default_flashlight_size * 0.9f;
|
||||
else
|
||||
return default_flashlight_size;
|
||||
}
|
||||
|
||||
Shader.Unbind();
|
||||
protected override void OnComboChange(int newCombo)
|
||||
{
|
||||
this.TransformTo(nameof(flashlightSize), getSizeFor(newCombo), FLASHLIGHT_FADE_DURATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.Taiko.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
{
|
||||
@ -82,7 +84,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
if (mods.Any(m => m is ModHidden))
|
||||
strainValue *= 1.025;
|
||||
|
||||
if (mods.Any(m => m is ModFlashlight))
|
||||
if (mods.Any(m => m is ModFlashlight<TaikoHitObject>))
|
||||
// Apply length bonus again if flashlight is on simply because it becomes a lot harder on longer maps.
|
||||
strainValue *= 1.05 * lengthBonus;
|
||||
|
||||
|
@ -1,12 +1,93 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Taiko.Objects;
|
||||
using osu.Game.Rulesets.Taiko.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
public class TaikoModFlashlight : ModFlashlight
|
||||
public class TaikoModFlashlight : ModFlashlight<TaikoHitObject>
|
||||
{
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
|
||||
private const float default_flashlight_size = 250;
|
||||
|
||||
public override Flashlight CreateFlashlight() => new TaikoFlashlight(playfield);
|
||||
|
||||
private TaikoPlayfield playfield;
|
||||
|
||||
public override void ApplyToRulesetContainer(RulesetContainer<TaikoHitObject> rulesetContainer)
|
||||
{
|
||||
playfield = (TaikoPlayfield)rulesetContainer.Playfield;
|
||||
base.ApplyToRulesetContainer(rulesetContainer);
|
||||
}
|
||||
|
||||
private class TaikoFlashlight : Flashlight
|
||||
{
|
||||
private readonly TaikoPlayfield taikoPlayfield;
|
||||
|
||||
public TaikoFlashlight(TaikoPlayfield taikoPlayfield)
|
||||
{
|
||||
this.taikoPlayfield = taikoPlayfield;
|
||||
MousePosWrapper.CircularFlashlightSize = getSizeFor(0);
|
||||
MousePosWrapper.Rectangular = false;
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private float flashlightSize
|
||||
{
|
||||
set
|
||||
{
|
||||
if (MousePosWrapper.CircularFlashlightSize == value) return;
|
||||
|
||||
MousePosWrapper.CircularFlashlightSize = value;
|
||||
MousePosWrapper.CircularFlashlightSizeChanged = true;
|
||||
}
|
||||
|
||||
get => MousePosWrapper.CircularFlashlightSize;
|
||||
}
|
||||
|
||||
private float getSizeFor(int combo)
|
||||
{
|
||||
if (combo > 200)
|
||||
return default_flashlight_size * 0.8f;
|
||||
else if (combo > 100)
|
||||
return default_flashlight_size * 0.9f;
|
||||
else
|
||||
return default_flashlight_size;
|
||||
}
|
||||
|
||||
protected override void OnComboChange(int newCombo)
|
||||
{
|
||||
this.TransformTo(nameof(flashlightSize), getSizeFor(newCombo), FLASHLIGHT_FADE_DURATION);
|
||||
}
|
||||
|
||||
public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true)
|
||||
{
|
||||
if ((invalidation & Invalidation.DrawSize) > 0)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
MousePosWrapper.FlashlightPosition = taikoPlayfield.HitExplosionContainer.ScreenSpaceDrawQuad.Centre;
|
||||
MousePosWrapper.FlashlightPositionChanged = true;
|
||||
});
|
||||
}
|
||||
|
||||
return base.Invalidate(invalidation, source, shallPropagate);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
MousePosWrapper.FlashlightPosition = taikoPlayfield.HitExplosionContainer.ScreenSpaceDrawQuad.Centre;
|
||||
MousePosWrapper.FlashlightPositionChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
protected override SpeedChangeVisualisationMethod VisualisationMethod => SpeedChangeVisualisationMethod.Overlapping;
|
||||
|
||||
private readonly Container<HitExplosion> hitExplosionContainer;
|
||||
internal readonly Container<HitExplosion> HitExplosionContainer;
|
||||
private readonly Container<KiaiHitExplosion> kiaiExplosionContainer;
|
||||
private readonly JudgementContainer<DrawableTaikoJudgement> judgementContainer;
|
||||
|
||||
@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
hitExplosionContainer = new Container<HitExplosion>
|
||||
HitExplosionContainer = new Container<HitExplosion>
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
FillMode = FillMode.Fit,
|
||||
@ -243,7 +243,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
case TaikoStrongJudgement _:
|
||||
if (result.IsHit)
|
||||
hitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).MainObject)?.VisualiseSecondHit();
|
||||
HitExplosionContainer.Children.FirstOrDefault(e => e.JudgedObject == ((DrawableStrongNestedHit)judgedObject).MainObject)?.VisualiseSecondHit();
|
||||
break;
|
||||
default:
|
||||
judgementContainer.Add(new DrawableTaikoJudgement(result, judgedObject)
|
||||
@ -259,7 +259,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
bool isRim = judgedObject.HitObject is RimHit;
|
||||
|
||||
hitExplosionContainer.Add(new HitExplosion(judgedObject, isRim));
|
||||
HitExplosionContainer.Add(new HitExplosion(judgedObject, isRim));
|
||||
|
||||
if (judgedObject.HitObject.Kiai)
|
||||
kiaiExplosionContainer.Add(new KiaiHitExplosion(judgedObject, isRim));
|
||||
|
@ -1,11 +1,27 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Shaders;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public abstract class ModFlashlight : Mod
|
||||
public abstract class ModFlashlight<T> : Mod, IApplicableToRulesetContainer<T>, IApplicableToScoreProcessor
|
||||
where T : HitObject
|
||||
{
|
||||
public override string Name => "Flashlight";
|
||||
public override string ShortenedName => "FL";
|
||||
@ -13,5 +29,130 @@ namespace osu.Game.Rulesets.Mods
|
||||
public override ModType Type => ModType.DifficultyIncrease;
|
||||
public override string Description => "Restricted view area.";
|
||||
public override bool Ranked => true;
|
||||
|
||||
public const double FLASHLIGHT_FADE_DURATION = 800;
|
||||
protected readonly BindableInt Combo = new BindableInt();
|
||||
|
||||
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
|
||||
{
|
||||
Combo.BindTo(scoreProcessor.Combo);
|
||||
}
|
||||
|
||||
public virtual void ApplyToRulesetContainer(RulesetContainer<T> rulesetContainer)
|
||||
{
|
||||
var flashlight = CreateFlashlight();
|
||||
flashlight.Combo = Combo;
|
||||
flashlight.RelativeSizeAxes = Axes.Both;
|
||||
flashlight.Colour = Color4.Black;
|
||||
rulesetContainer.KeyBindingInputManager.Add(flashlight);
|
||||
|
||||
flashlight.Breaks = rulesetContainer.Beatmap.Breaks;
|
||||
}
|
||||
|
||||
public abstract Flashlight CreateFlashlight();
|
||||
|
||||
public abstract class Flashlight : Drawable
|
||||
{
|
||||
internal BindableInt Combo;
|
||||
private Shader shader;
|
||||
protected readonly FlashlightUniformWrapper MousePosWrapper = new FlashlightUniformWrapper();
|
||||
|
||||
protected override DrawNode CreateDrawNode() => new FlashlightDrawNode();
|
||||
|
||||
public override bool RemoveCompletedTransforms => false;
|
||||
|
||||
public List<BreakPeriod> Breaks;
|
||||
|
||||
protected override void ApplyDrawNode(DrawNode node)
|
||||
{
|
||||
base.ApplyDrawNode(node);
|
||||
|
||||
var flashNode = (FlashlightDrawNode)node;
|
||||
|
||||
flashNode.Shader = shader;
|
||||
flashNode.ScreenSpaceDrawQuad = ScreenSpaceDrawQuad;
|
||||
flashNode.MousePosWrapper = MousePosWrapper;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(ShaderManager shaderManager)
|
||||
{
|
||||
shader = shaderManager.Load("PositionAndColour", "Flashlight");
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Combo.ValueChanged += OnComboChange;
|
||||
|
||||
this.FadeInFromZero(FLASHLIGHT_FADE_DURATION);
|
||||
|
||||
foreach (var breakPeriod in Breaks)
|
||||
{
|
||||
this.Delay(breakPeriod.StartTime + FLASHLIGHT_FADE_DURATION).FadeOutFromOne(FLASHLIGHT_FADE_DURATION);
|
||||
this.Delay(breakPeriod.EndTime - FLASHLIGHT_FADE_DURATION).FadeInFromZero(FLASHLIGHT_FADE_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void OnComboChange(int newCombo);
|
||||
}
|
||||
|
||||
public class FlashlightUniformWrapper
|
||||
{
|
||||
public bool Rectangular;
|
||||
public bool RectangularChanged = true;
|
||||
|
||||
public Vector2 FlashlightPosition;
|
||||
public bool FlashlightPositionChanged = true;
|
||||
|
||||
public float CircularFlashlightSize;
|
||||
public bool CircularFlashlightSizeChanged = true;
|
||||
|
||||
public Vector2 RectangularFlashlightSize;
|
||||
public bool RectangularFlashlightSizeChanged = true;
|
||||
}
|
||||
|
||||
private class FlashlightDrawNode : DrawNode
|
||||
{
|
||||
public Shader Shader;
|
||||
public Quad ScreenSpaceDrawQuad;
|
||||
public FlashlightUniformWrapper MousePosWrapper;
|
||||
|
||||
public override void Draw(Action<TexturedVertex2D> vertexAction)
|
||||
{
|
||||
base.Draw(vertexAction);
|
||||
|
||||
Shader.Bind();
|
||||
|
||||
if (MousePosWrapper.RectangularChanged)
|
||||
{
|
||||
Shader.GetUniform<bool>("rectangular").UpdateValue(ref MousePosWrapper.Rectangular);
|
||||
MousePosWrapper.RectangularChanged = false;
|
||||
}
|
||||
|
||||
if (MousePosWrapper.FlashlightPositionChanged)
|
||||
{
|
||||
Shader.GetUniform<Vector2>("flashlightPos").UpdateValue(ref MousePosWrapper.FlashlightPosition);
|
||||
MousePosWrapper.FlashlightPositionChanged = false;
|
||||
}
|
||||
|
||||
if (MousePosWrapper.CircularFlashlightSizeChanged)
|
||||
{
|
||||
Shader.GetUniform<float>("circularFlashlightSize").UpdateValue(ref MousePosWrapper.CircularFlashlightSize);
|
||||
MousePosWrapper.CircularFlashlightSizeChanged = false;
|
||||
}
|
||||
|
||||
if (MousePosWrapper.RectangularFlashlightSizeChanged)
|
||||
{
|
||||
Shader.GetUniform<Vector2>("rectangularFlashlightSize").UpdateValue(ref MousePosWrapper.RectangularFlashlightSize);
|
||||
MousePosWrapper.RectangularFlashlightSizeChanged = false;
|
||||
}
|
||||
|
||||
Texture.WhitePixel.DrawQuad(ScreenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: vertexAction);
|
||||
|
||||
Shader.Unbind();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user