1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-18 19:32:58 +08:00
osu-lazer/osu.Game/Rulesets/Mods/ModFlashlight.cs

200 lines
6.7 KiB
C#
Raw Normal View History

// 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.
2018-04-13 17:19:50 +08:00
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
2019-02-21 18:04:31 +08:00
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Batches;
using osu.Framework.Graphics.OpenGL.Vertices;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Shaders;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps.Timing;
2018-04-13 17:19:50 +08:00
using osu.Game.Graphics;
using osu.Game.Graphics.OpenGL.Vertices;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
2018-11-20 15:51:59 +08:00
using osuTK;
using osuTK.Graphics;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Rulesets.Mods
{
2018-11-30 13:48:19 +08:00
public abstract class ModFlashlight : Mod
2018-04-13 17:19:50 +08:00
{
public override string Name => "Flashlight";
public override string Acronym => "FL";
public override IconUsage Icon => OsuIcon.ModFlashlight;
2018-04-13 17:19:50 +08:00
public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Restricted view area.";
public override bool Ranked => true;
2018-11-30 13:48:19 +08:00
internal ModFlashlight()
{
}
}
public abstract class ModFlashlight<T> : ModFlashlight, IApplicableToDrawableRuleset<T>, IApplicableToScoreProcessor
2018-11-30 13:48:19 +08:00
where T : HitObject
{
public const double FLASHLIGHT_FADE_DURATION = 800;
protected readonly BindableInt Combo = new BindableInt();
public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
{
Combo.BindTo(scoreProcessor.Combo);
}
public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank;
2019-03-20 10:22:34 +08:00
public virtual void ApplyToDrawableRuleset(DrawableRuleset<T> drawableRuleset)
{
var flashlight = CreateFlashlight();
flashlight.Combo = Combo;
flashlight.RelativeSizeAxes = Axes.Both;
flashlight.Colour = Color4.Black;
2019-03-20 10:22:34 +08:00
drawableRuleset.KeyBindingInputManager.Add(flashlight);
2019-03-20 10:22:34 +08:00
flashlight.Breaks = drawableRuleset.Beatmap.Breaks;
}
public abstract Flashlight CreateFlashlight();
public abstract class Flashlight : Drawable
{
internal BindableInt Combo;
2019-03-07 17:30:18 +08:00
private IShader shader;
2019-04-02 10:56:22 +08:00
protected override DrawNode CreateDrawNode() => new FlashlightDrawNode(this);
public override bool RemoveCompletedTransforms => false;
public List<BreakPeriod> Breaks;
[BackgroundDependencyLoader]
private void load(ShaderManager shaderManager)
{
shader = shaderManager.Load("PositionAndColour", FragmentShader);
}
protected override void LoadComplete()
{
base.LoadComplete();
Combo.ValueChanged += OnComboChange;
using (BeginAbsoluteSequence(0))
{
foreach (var breakPeriod in Breaks)
{
if (breakPeriod.Duration < FLASHLIGHT_FADE_DURATION * 2) continue;
this.Delay(breakPeriod.StartTime + FLASHLIGHT_FADE_DURATION).FadeOutFromOne(FLASHLIGHT_FADE_DURATION);
this.Delay(breakPeriod.EndTime - FLASHLIGHT_FADE_DURATION).FadeInFromZero(FLASHLIGHT_FADE_DURATION);
}
}
}
2019-02-21 17:56:34 +08:00
protected abstract void OnComboChange(ValueChangedEvent<int> e);
protected abstract string FragmentShader { get; }
private Vector2 flashlightPosition;
2019-02-28 12:31:40 +08:00
protected Vector2 FlashlightPosition
{
get => flashlightPosition;
set
{
if (flashlightPosition == value) return;
flashlightPosition = value;
Invalidate(Invalidation.DrawNode);
}
}
private Vector2 flashlightSize;
2019-02-28 12:31:40 +08:00
protected Vector2 FlashlightSize
{
get => flashlightSize;
set
{
if (flashlightSize == value) return;
flashlightSize = value;
Invalidate(Invalidation.DrawNode);
}
}
2019-04-12 10:23:40 +08:00
private float flashlightDim;
2019-04-12 10:23:40 +08:00
public float FlashlightDim
{
2019-04-12 10:23:40 +08:00
get => flashlightDim;
set
{
2019-04-12 10:23:40 +08:00
if (flashlightDim == value) return;
2019-04-12 10:23:40 +08:00
flashlightDim = value;
Invalidate(Invalidation.DrawNode);
}
}
2019-04-02 10:56:22 +08:00
private class FlashlightDrawNode : DrawNode
{
2019-04-02 10:56:22 +08:00
protected new Flashlight Source => (Flashlight)base.Source;
2019-04-02 10:56:22 +08:00
private IShader shader;
private Quad screenSpaceDrawQuad;
private Vector2 flashlightPosition;
private Vector2 flashlightSize;
private float flashlightDim;
private readonly VertexBatch<PositionAndColourVertex> quadBatch = new QuadBatch<PositionAndColourVertex>(1, 1);
private readonly Action<TexturedVertex2D> addAction;
2019-04-02 10:56:22 +08:00
public FlashlightDrawNode(Flashlight source)
: base(source)
{
addAction = v => quadBatch.Add(new PositionAndColourVertex
{
Position = v.Position,
Colour = v.Colour
});
2019-04-02 10:56:22 +08:00
}
2019-04-02 10:56:22 +08:00
public override void ApplyState()
{
base.ApplyState();
shader = Source.shader;
screenSpaceDrawQuad = Source.ScreenSpaceDrawQuad;
flashlightPosition = Vector2Extensions.Transform(Source.FlashlightPosition, DrawInfo.Matrix);
flashlightSize = Source.FlashlightSize * DrawInfo.Matrix.ExtractScale().Xy;
flashlightDim = Source.FlashlightDim;
2019-04-02 10:56:22 +08:00
}
public override void Draw(Action<TexturedVertex2D> vertexAction)
{
base.Draw(vertexAction);
2019-04-02 10:56:22 +08:00
shader.Bind();
2019-04-02 10:56:22 +08:00
shader.GetUniform<Vector2>("flashlightPos").UpdateValue(ref flashlightPosition);
shader.GetUniform<Vector2>("flashlightSize").UpdateValue(ref flashlightSize);
2019-05-07 11:07:45 +08:00
shader.GetUniform<float>("flashlightDim").UpdateValue(ref flashlightDim);
DrawQuad(Texture.WhitePixel, screenSpaceDrawQuad, DrawColourInfo.Colour, vertexAction: addAction);
2019-04-02 10:56:22 +08:00
shader.Unbind();
}
}
}
2018-04-13 17:19:50 +08:00
}
}