Files
Quentin Bray 6ffa63b923 Apply R# clean-up for reliability (#877)
* Apply R# clean-up for reliability

- Migrate to NUnit4 Assert.That
- Update dependencise versions
- Fix LangVersion to 9.0 (until net core migration)
- Reformat code
- Apply 'var' style (easier for refactoring)
- Remove redundant parentheses
- Add braces on every condition blocks (1 line)
- Uses new null checking patterns
- Uses AutoProperties when possible
- Uses string scalar type instead of class
- Clean usings
- Add .orig files in git ignore
- Rename some properties to respect defined conventions and US format definition
	- ID -> Id
	- BPM -> Bpm
	- Finish -> End

* Update R# settings according to the clean-up made
2026-06-22 19:52:06 +02:00

287 lines
8.8 KiB
C#

#region license
// This file is part of Vocaluxe.
//
// Vocaluxe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Vocaluxe is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
using System.Diagnostics;
using VocaluxeLib.Draw;
namespace VocaluxeLib.Menu
{
class CParticle
{
#region private vars
private readonly int _PartyModeId;
private readonly string _TextureName;
private readonly CTextureRef _Texture;
private SRectF _Rect;
private float _Size;
private SColorF _Color;
private float _Angle; //0..360°
private readonly float _MaxAge; //[s]
private float _Age; //[s]
private readonly float _Vx; //movement speed in x-axis [pix/s]
private readonly float _Vy; //movement speed in y-axis [pix/s]
private readonly float _Vr; //rotation speed [rpm]
private readonly float _Rotation; //start rotation 0..360°
private readonly float _Vsize; //size changing speed: period [s]
private float _LastTime;
private readonly EParticleType _Type;
private readonly Stopwatch _Timer = new Stopwatch();
#endregion private vars
#region public vars
//public bool Visible;
public float Alpha2 = 1f;
public float X
{
get { return _Rect.X; }
set { _Rect.X = value; }
}
public float Y
{
get { return _Rect.Y; }
set { _Rect.Y = value; }
}
public float Size
{
get { return _Size; }
set
{
_Rect.W = value;
_Rect.H = value;
_Size = value;
}
}
public float Alpha { get; set; } = 1;
public SColorF Color
{
get { return _Color; }
set { _Color = value; }
}
public bool IsAlive
{
get { return _Age < _MaxAge || Math.Abs(_MaxAge) < float.Epsilon; }
}
#endregion public vars
#region Constructors
public CParticle(int partyModeId, string textureName, SColorF color, float x, float y, float size, float maxage, float z, float vx, float vy, float vr, float vsize,
EParticleType type)
{
_PartyModeId = partyModeId;
_TextureName = textureName;
_Color = color;
_Rect = new SRectF(x, y, size, size, z);
_Size = size;
_Vx = vx;
_Vy = vy;
_Vr = vr;
_Vsize = vsize;
_Type = type;
_MaxAge = maxage;
_Rotation = (float)(CBase.Game.GetRandomDouble() * 360.0);
}
public CParticle(int partyModeId, CTextureRef texture, SColorF color, float x, float y, float size, float maxage, float z, float vx, float vy, float vr, float vsize,
EParticleType type)
{
_PartyModeId = partyModeId;
_TextureName = string.Empty;
_Texture = texture;
_Color = color;
_Rect = new SRectF(x, y, size, size, z);
_Size = size;
_Vx = vx;
_Vy = vy;
_Vr = vr;
_Vsize = vsize;
_Type = type;
_MaxAge = maxage;
_Rotation = (float)(CBase.Game.GetRandomDouble() * 360.0);
}
#endregion Constructors
public void Update()
{
if (!IsAlive)
{
return;
}
if (!_Timer.IsRunning)
{
_Timer.Start();
}
var currentTime = _Timer.ElapsedMilliseconds / 1000f;
var timediff = currentTime - _LastTime;
_Age = currentTime;
// update alpha
if (_MaxAge > 0f)
{
switch (_Type)
{
case EParticleType.Twinkle:
Alpha = 1f - _Age / _MaxAge;
break;
case EParticleType.Star:
Alpha = 1f - _Age / _MaxAge;
break;
case EParticleType.Snow:
Alpha = (float)Math.Sqrt((Math.Sin(_Age / _MaxAge * Math.PI * 2 - 0.5 * Math.PI) + 1) / 2);
break;
case EParticleType.Flare:
Alpha = 1f - _Age / _MaxAge;
break;
case EParticleType.PerfNoteStar:
Alpha = 1f - _Age / _MaxAge;
break;
}
}
// update position
switch (_Type)
{
case EParticleType.Twinkle:
X += _Vx * timediff;
Y += _Vy * timediff;
break;
case EParticleType.Star:
X += _Vx * timediff;
Y += _Vy * timediff;
break;
case EParticleType.Snow:
var maxy = (int)Math.Round(CBase.Settings.GetRenderH() - _Size * 0.4f);
if (Math.Round(Y) < maxy)
{
var vdx = 0f;
if (Math.Abs(_Vx) > float.Epsilon)
{
vdx = (float)Math.Sin(currentTime / _Vx * Math.PI);
}
X += _Vx * timediff * (0.5f + vdx);
Y += _Vy * timediff * (vdx * vdx / 2f + 0.5f);
if (Y >= maxy)
{
Y = maxy;
}
}
break;
case EParticleType.Flare:
X += _Vx * timediff;
Y += _Vy * timediff;
break;
case EParticleType.PerfNoteStar:
X += _Vx * timediff;
Y += _Vy * timediff;
break;
}
// update size
if (Math.Abs(_Vsize) > float.Epsilon)
{
var size = _Size;
switch (_Type)
{
case EParticleType.Twinkle:
size = _Size * (1f - currentTime / _Vsize);
break;
case EParticleType.Star:
size = _Size * (1f - currentTime / _Vsize);
break;
case EParticleType.Snow:
size = _Size * (float)Math.Sqrt((Math.Sin(currentTime / _Vsize * Math.PI * 2 - 0.5 * Math.PI) + 1) / 2);
break;
case EParticleType.Flare:
size = _Size * (1f - currentTime / _Vsize);
break;
case EParticleType.PerfNoteStar:
size = _Size * (1f - currentTime / _Vsize);
break;
}
_Rect.X += (_Rect.W - size) / 2f;
_Rect.Y += (_Rect.H - size) / 2f;
_Rect.W = size;
_Rect.H = size;
}
// update rotation
if (Math.Abs(_Vr) > 0.01)
{
var r = currentTime * _Vr / 60f;
_Angle = _Rotation + 360f * (r - (float)Math.Floor(r));
_Rect.Rotation = _Angle;
}
_LastTime = currentTime;
}
public void Pause()
{
_Timer.Stop();
}
public void Resume()
{
_Timer.Start();
}
public void Draw(bool allMonitors = true)
{
// ReSharper disable ConvertIfStatementToConditionalTernaryExpression
if (!string.IsNullOrEmpty(_TextureName))
// ReSharper restore ConvertIfStatementToConditionalTernaryExpression
{
CBase.Drawing.DrawTexture(CBase.Themes.GetSkinTexture(_TextureName, _PartyModeId), _Rect, new SColorF(_Color.R, _Color.G, _Color.B, _Color.A * Alpha2 * Alpha),
allMonitors);
}
else
{
CBase.Drawing.DrawTexture(_Texture, _Rect, new SColorF(_Color.R, _Color.G, _Color.B, _Color.A * Alpha2 * Alpha), allMonitors);
}
}
}
}