1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 01:27:29 +08:00

Move LegacySmoke animation implementation to Smoke

This commit is contained in:
Alden Wu 2022-10-04 00:17:00 -07:00
parent eaab0deef3
commit b0a948df45
5 changed files with 121 additions and 207 deletions

3
WeatherConfig.dat Normal file
View File

@ -0,0 +1,3 @@
5363943
La Jolla,US
F

View File

@ -1,65 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Graphics;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Rulesets.Osu.Skinning.Default namespace osu.Game.Rulesets.Osu.Skinning.Default
{ {
public class DefaultSmoke : Smoke public class DefaultSmoke : Smoke
{ {
private const double fade_out_delay = 8000;
private const double fade_out_speed = 3;
private const double fade_out_duration = 50;
private const float alpha = 0.5f;
public override double LifetimeEnd => SmokeEndTime + fade_out_delay + fade_out_duration + (SmokeEndTime - SmokeStartTime) / fade_out_speed;
public DefaultSmoke() public DefaultSmoke()
{ {
Radius = 2; Radius = 2;
} }
protected override DrawNode CreateDrawNode() => new DefaultSmokeDrawNode(this);
private class DefaultSmokeDrawNode : SmokeDrawNode
{
private double fadeOutTime;
public DefaultSmokeDrawNode(ITexturedShaderDrawable source)
: base(source)
{
}
public override void ApplyState()
{
base.ApplyState();
fadeOutTime = SmokeStartTime + fade_out_speed * (CurrentTime - (SmokeEndTime + fade_out_delay));
}
protected override Color4 PointColour(SmokePoint point)
{
var color = Color4.White;
color.A = alpha;
double timeDoingFadeOut = fadeOutTime - point.Time;
if (timeDoingFadeOut > 0)
{
float fraction = Math.Clamp((float)(1 - (timeDoingFadeOut / fade_out_duration)), 0, 1);
fraction = MathF.Pow(fraction, 5);
color.A *= fraction;
}
return color;
}
protected override float PointScale(SmokePoint point) => 1f;
protected override Vector2 PointDirection(SmokePoint point) => point.Direction;
}
} }
} }

View File

@ -1,157 +1,19 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // 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. // See the LICENCE file in the repository root for full licence text.
using System; using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Utils;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK;
using osuTK.Graphics;
namespace osu.Game.Rulesets.Osu.Skinning.Legacy namespace osu.Game.Rulesets.Osu.Skinning.Legacy
{ {
public class LegacySmoke : Smoke public class LegacySmoke : Smoke
{ {
// fade values [BackgroundDependencyLoader]
private const double initial_fade_out_duration = 4000; private void load(ISkinSource skin)
private const double re_fade_in_speed = 3;
private const double re_fade_in_duration = 50;
private const double final_fade_out_speed = 2;
private const double final_fade_out_duration = 8000;
private const float initial_alpha = 0.6f;
private const float re_fade_in_alpha = 1f;
// scale values
private const double scale_duration = 1200;
private const float initial_scale = 0.65f;
private const float final_scale = 1f;
// rotation values
private const double rotation_duration = 500;
private const float max_rotation = 0.25f;
protected int RotationSeed { get; set; } = RNG.Next();
public override double LifetimeEnd
{
get
{
double initialFadeOutDurationTrunc = Math.Min(initial_fade_out_duration, SmokeEndTime - SmokeStartTime);
return SmokeEndTime + final_fade_out_duration + initialFadeOutDurationTrunc / re_fade_in_speed + initialFadeOutDurationTrunc / final_fade_out_speed;
}
}
private readonly ISkin skin;
public LegacySmoke(ISkin skin)
{
this.skin = skin;
}
protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
Texture = skin.GetTexture("cursor-smoke"); Texture = skin.GetTexture("cursor-smoke");
} }
protected override DrawNode CreateDrawNode() => new LegacySmokeDrawNode(this);
protected class LegacySmokeDrawNode : SmokeDrawNode
{
protected new LegacySmoke Source => (LegacySmoke)base.Source;
private double initialFadeOutDurationTrunc;
private double firstVisiblePointTime;
private double initialFadeOutTime;
private double reFadeInTime;
private double finalFadeOutTime;
private int rotationSeed;
private Random rotationRNG = new Random();
public LegacySmokeDrawNode(ITexturedShaderDrawable source)
: base(source)
{
}
public override void ApplyState()
{
base.ApplyState();
rotationSeed = Source.RotationSeed;
rotationRNG = new Random(rotationSeed);
initialFadeOutDurationTrunc = Math.Min(initial_fade_out_duration, SmokeEndTime - SmokeStartTime);
firstVisiblePointTime = SmokeEndTime - initialFadeOutDurationTrunc;
initialFadeOutTime = CurrentTime;
reFadeInTime = CurrentTime - initialFadeOutDurationTrunc - firstVisiblePointTime * (1 - 1 / re_fade_in_speed);
finalFadeOutTime = CurrentTime - initialFadeOutDurationTrunc - firstVisiblePointTime * (1 - 1 / final_fade_out_speed);
}
protected override Color4 PointColour(SmokePoint point)
{
var color = Color4.White;
double timeDoingInitialFadeOut = Math.Min(initialFadeOutTime, SmokeEndTime) - point.Time;
if (timeDoingInitialFadeOut > 0)
{
float fraction = Math.Clamp((float)(timeDoingInitialFadeOut / initial_fade_out_duration), 0, 1);
color.A = (1 - fraction) * initial_alpha;
}
if (color.A > 0)
{
double timeDoingReFadeIn = reFadeInTime - point.Time / re_fade_in_speed;
double timeDoingFinalFadeOut = finalFadeOutTime - point.Time / final_fade_out_speed;
if (timeDoingFinalFadeOut > 0)
{
float fraction = Math.Clamp((float)(timeDoingFinalFadeOut / final_fade_out_duration), 0, 1);
fraction = MathF.Pow(fraction, 5);
color.A = (1 - fraction) * re_fade_in_alpha;
}
else if (timeDoingReFadeIn > 0)
{
float fraction = Math.Clamp((float)(timeDoingReFadeIn / re_fade_in_duration), 0, 1);
fraction = 1 - MathF.Pow(1 - fraction, 5);
color.A = fraction * (re_fade_in_alpha - color.A) + color.A;
}
}
return color;
}
protected override float PointScale(SmokePoint point)
{
double timeDoingScale = CurrentTime - point.Time;
float fraction = Math.Clamp((float)(timeDoingScale / scale_duration), 0, 1);
fraction = 1 - MathF.Pow(1 - fraction, 5);
return fraction * (final_scale - initial_scale) + initial_scale;
}
protected override Vector2 PointDirection(SmokePoint point)
{
float initialAngle = MathF.Atan2(point.Direction.Y, point.Direction.X);
float finalAngle = initialAngle + nextRotation();
double timeDoingRotation = CurrentTime - point.Time;
float fraction = Math.Clamp((float)(timeDoingRotation / rotation_duration), 0, 1);
fraction = 1 - MathF.Pow(1 - fraction, 5);
float angle = fraction * (finalAngle - initialAngle) + initialAngle;
return new Vector2(MathF.Sin(angle), -MathF.Cos(angle));
}
private float nextRotation() => max_rotation * ((float)rotationRNG.NextDouble() * 2 - 1);
}
} }
} }

View File

@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
case OsuSkinComponents.Smoke: case OsuSkinComponents.Smoke:
if (GetTexture("cursor-smoke") != null) if (GetTexture("cursor-smoke") != null)
return new LegacySmoke(this); return new LegacySmoke();
return null; return null;

View File

@ -25,6 +25,15 @@ namespace osu.Game.Rulesets.Osu.Skinning
public IShader? TextureShader { get; private set; } public IShader? TextureShader { get; private set; }
public IShader? RoundedTextureShader { get; private set; } public IShader? RoundedTextureShader { get; private set; }
public override double LifetimeEnd
{
get
{
double initialFadeOutDurationTrunc = Math.Min(initial_fade_out_duration, SmokeEndTime - SmokeStartTime);
return SmokeEndTime + final_fade_out_duration + initialFadeOutDurationTrunc / re_fade_in_speed + initialFadeOutDurationTrunc / final_fade_out_speed;
}
}
private float? radius; private float? radius;
protected float Radius protected float Radius
@ -39,21 +48,45 @@ namespace osu.Game.Rulesets.Osu.Skinning
protected double SmokeEndTime { get; private set; } = double.MaxValue; protected double SmokeEndTime { get; private set; } = double.MaxValue;
protected virtual float PointInterval => Radius * 7f / 8;
protected readonly List<SmokePoint> SmokePoints = new List<SmokePoint>(); protected readonly List<SmokePoint> SmokePoints = new List<SmokePoint>();
protected virtual float PointInterval => Radius * 7f / 8;
private float totalDistance; private float totalDistance;
private Vector2? lastPosition; private Vector2? lastPosition;
private SmokeContainer? smokeContainer;
private const int max_point_count = 18_000; private const int max_point_count = 18_000;
[Resolved(CanBeNull = true)] // fade anim values
private SmokeContainer? smokeContainer { get; set; } private const double initial_fade_out_duration = 4000;
private const double re_fade_in_speed = 3;
private const double re_fade_in_duration = 50;
private const double final_fade_out_speed = 2;
private const double final_fade_out_duration = 8000;
private const float initial_alpha = 0.6f;
private const float re_fade_in_alpha = 1f;
private readonly int rotationSeed = RNG.Next();
// scale anim values
private const double scale_duration = 1200;
private const float initial_scale = 0.65f;
private const float final_scale = 1f;
// rotation anim values
private const double rotation_duration = 500;
private const float max_rotation = 0.25f;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(ShaderManager shaders) private void load(SmokeContainer container, ShaderManager shaders)
{ {
smokeContainer = container;
RoundedTextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED); RoundedTextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE_ROUNDED);
TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE); TextureShader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, FragmentShaderDescriptor.TEXTURE);
} }
@ -128,8 +161,6 @@ namespace osu.Game.Rulesets.Osu.Skinning
onSmokeEnded(time); onSmokeEnded(time);
} }
public abstract override double LifetimeEnd { get; }
private void onSmokeEnded(double time) private void onSmokeEnded(double time)
{ {
if (smokeContainer != null) if (smokeContainer != null)
@ -141,7 +172,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
SmokeEndTime = time; SmokeEndTime = time;
} }
protected abstract override DrawNode CreateDrawNode(); protected override DrawNode CreateDrawNode() => new SmokeDrawNode(this);
protected override void Update() protected override void Update()
{ {
@ -181,7 +212,7 @@ namespace osu.Game.Rulesets.Osu.Skinning
} }
} }
protected abstract class SmokeDrawNode : TexturedShaderDrawNode protected class SmokeDrawNode : TexturedShaderDrawNode
{ {
protected new Smoke Source => (Smoke)base.Source; protected new Smoke Source => (Smoke)base.Source;
@ -195,7 +226,17 @@ namespace osu.Game.Rulesets.Osu.Skinning
private Vector2 drawSize; private Vector2 drawSize;
private Texture? texture; private Texture? texture;
protected SmokeDrawNode(ITexturedShaderDrawable source) // anim calculation vars (color, scale, direction)
private double initialFadeOutDurationTrunc;
private double firstVisiblePointTime;
private double initialFadeOutTime;
private double reFadeInTime;
private double finalFadeOutTime;
private Random rotationRNG = new Random();
public SmokeDrawNode(ITexturedShaderDrawable source)
: base(source) : base(source)
{ {
} }
@ -214,6 +255,15 @@ namespace osu.Game.Rulesets.Osu.Skinning
SmokeStartTime = Source.SmokeStartTime; SmokeStartTime = Source.SmokeStartTime;
SmokeEndTime = Source.SmokeEndTime; SmokeEndTime = Source.SmokeEndTime;
CurrentTime = Source.Clock.CurrentTime; CurrentTime = Source.Clock.CurrentTime;
rotationRNG = new Random(Source.rotationSeed);
initialFadeOutDurationTrunc = Math.Min(initial_fade_out_duration, SmokeEndTime - SmokeStartTime);
firstVisiblePointTime = SmokeEndTime - initialFadeOutDurationTrunc;
initialFadeOutTime = CurrentTime;
reFadeInTime = CurrentTime - initialFadeOutDurationTrunc - firstVisiblePointTime * (1 - 1 / re_fade_in_speed);
finalFadeOutTime = CurrentTime - initialFadeOutDurationTrunc - firstVisiblePointTime * (1 - 1 / final_fade_out_speed);
} }
public sealed override void Draw(IRenderer renderer) public sealed override void Draw(IRenderer renderer)
@ -246,11 +296,62 @@ namespace osu.Game.Rulesets.Osu.Skinning
? ((SRGBColour)DrawColourInfo.Colour).Linear ? ((SRGBColour)DrawColourInfo.Colour).Linear
: DrawColourInfo.Colour.Interpolate(Vector2.Divide(localPos, drawSize)).Linear; : DrawColourInfo.Colour.Interpolate(Vector2.Divide(localPos, drawSize)).Linear;
protected abstract Color4 PointColour(SmokePoint point); protected virtual Color4 PointColour(SmokePoint point)
{
var color = Color4.White;
protected abstract float PointScale(SmokePoint point); double timeDoingInitialFadeOut = Math.Min(initialFadeOutTime, SmokeEndTime) - point.Time;
protected abstract Vector2 PointDirection(SmokePoint point); if (timeDoingInitialFadeOut > 0)
{
float fraction = Math.Clamp((float)(timeDoingInitialFadeOut / initial_fade_out_duration), 0, 1);
color.A = (1 - fraction) * initial_alpha;
}
if (color.A > 0)
{
double timeDoingReFadeIn = reFadeInTime - point.Time / re_fade_in_speed;
double timeDoingFinalFadeOut = finalFadeOutTime - point.Time / final_fade_out_speed;
if (timeDoingFinalFadeOut > 0)
{
float fraction = Math.Clamp((float)(timeDoingFinalFadeOut / final_fade_out_duration), 0, 1);
fraction = MathF.Pow(fraction, 5);
color.A = (1 - fraction) * re_fade_in_alpha;
}
else if (timeDoingReFadeIn > 0)
{
float fraction = Math.Clamp((float)(timeDoingReFadeIn / re_fade_in_duration), 0, 1);
fraction = 1 - MathF.Pow(1 - fraction, 5);
color.A = fraction * (re_fade_in_alpha - color.A) + color.A;
}
}
return color;
}
protected virtual float PointScale(SmokePoint point)
{
double timeDoingScale = CurrentTime - point.Time;
float fraction = Math.Clamp((float)(timeDoingScale / scale_duration), 0, 1);
fraction = 1 - MathF.Pow(1 - fraction, 5);
return fraction * (final_scale - initial_scale) + initial_scale;
}
protected virtual Vector2 PointDirection(SmokePoint point)
{
float initialAngle = MathF.Atan2(point.Direction.Y, point.Direction.X);
float finalAngle = initialAngle + nextRotation();
double timeDoingRotation = CurrentTime - point.Time;
float fraction = Math.Clamp((float)(timeDoingRotation / rotation_duration), 0, 1);
fraction = 1 - MathF.Pow(1 - fraction, 5);
float angle = fraction * (finalAngle - initialAngle) + initialAngle;
return new Vector2(MathF.Sin(angle), -MathF.Cos(angle));
}
private float nextRotation() => max_rotation * ((float)rotationRNG.NextDouble() * 2 - 1);
private void drawPointQuad(SmokePoint point, RectangleF textureRect) private void drawPointQuad(SmokePoint point, RectangleF textureRect)
{ {