quantum-space-buddies/QSB/RoastingSync/CustomRelativisticParticleSystem.cs
Mister_Nebula 8c1a79b9be cleanup
2021-03-31 15:07:18 +01:00

125 lines
4.5 KiB
C#

using QSB.Player;
using UnityEngine;
namespace QSB.RoastingSync
{
internal class CustomRelativisticParticleSystem : MonoBehaviour
{
private ParticleSystem _particleSystem;
private Transform _simulationSpace;
private Quaternion _rotation;
private ParticleSystem.MainModule _mainModule;
private ParticleSystem.VelocityOverLifetimeModule _velocityOverLifetimeModule;
private ModuleVector _velocityOverLifetimeVector;
private ParticleSystem.LimitVelocityOverLifetimeModule _limitVelocityOverLifetimeModule;
private ModuleVector _limitVelocityOverLifetimeVector;
private ParticleSystem.ForceOverLifetimeModule _forceOverLifetimeModule;
private ModuleVector _forceOverLifetimeVector;
private bool _isReady;
private void Awake()
{
_particleSystem = GetComponent<ParticleSystem>();
_rotation = transform.rotation;
_mainModule = _particleSystem.main;
_mainModule.simulationSpace = ParticleSystemSimulationSpace.Custom;
_mainModule.customSimulationSpace = _simulationSpace;
_velocityOverLifetimeModule = _particleSystem.velocityOverLifetime;
_velocityOverLifetimeVector = new ModuleVector(_velocityOverLifetimeModule.x, _velocityOverLifetimeModule.y, _velocityOverLifetimeModule.z);
_limitVelocityOverLifetimeModule = _particleSystem.limitVelocityOverLifetime;
_limitVelocityOverLifetimeVector = new ModuleVector(_limitVelocityOverLifetimeModule.limitX, _limitVelocityOverLifetimeModule.limitY, _limitVelocityOverLifetimeModule.limitZ);
_forceOverLifetimeModule = _particleSystem.forceOverLifetime;
_forceOverLifetimeVector = new ModuleVector(_forceOverLifetimeModule.x, _forceOverLifetimeModule.y, _forceOverLifetimeModule.z);
}
public void Init(PlayerInfo playerInfo)
{
var space = new GameObject($"{name}_ReferenceFrame");
space.transform.parent = playerInfo.Body.transform;
_simulationSpace = space.transform;
_isReady = true;
}
private void FixedUpdate()
{
if (!QSBCore.HasWokenUp || !_isReady)
{
return;
}
_simulationSpace.rotation = _rotation;
if (!_velocityOverLifetimeModule.enabled
&& (!_limitVelocityOverLifetimeModule.enabled || !_limitVelocityOverLifetimeModule.separateAxes)
&& !_forceOverLifetimeModule.enabled)
{
return;
}
var rotation = Quaternion.Inverse(_rotation) * transform.rotation;
if (_velocityOverLifetimeModule.enabled)
{
_velocityOverLifetimeVector.GetRotatedVector(rotation, out var x, out var y, out var z);
_velocityOverLifetimeModule.x = x;
_velocityOverLifetimeModule.y = y;
_velocityOverLifetimeModule.z = z;
}
if (_limitVelocityOverLifetimeModule.enabled)
{
_limitVelocityOverLifetimeVector.GetRotatedVector(rotation, out var x, out var y, out var z);
_limitVelocityOverLifetimeModule.limitX = x;
_limitVelocityOverLifetimeModule.limitY = y;
_limitVelocityOverLifetimeModule.limitZ = z;
}
if (_forceOverLifetimeModule.enabled)
{
_forceOverLifetimeVector.GetRotatedVector(rotation, out var x, out var y, out var z);
_forceOverLifetimeModule.x = x;
_forceOverLifetimeModule.y = y;
_forceOverLifetimeModule.z = z;
}
}
private struct ModuleVector
{
public ParticleSystem.MinMaxCurve OrigX;
public ParticleSystem.MinMaxCurve OrigY;
public ParticleSystem.MinMaxCurve OrigZ;
public ModuleVector(ParticleSystem.MinMaxCurve x, ParticleSystem.MinMaxCurve y, ParticleSystem.MinMaxCurve z)
{
OrigX = x;
OrigY = y;
OrigZ = z;
}
public void GetRotatedVector(Quaternion rotation, out ParticleSystem.MinMaxCurve x, out ParticleSystem.MinMaxCurve y, out ParticleSystem.MinMaxCurve z)
{
if (OrigX.mode == ParticleSystemCurveMode.Constant)
{
var vector = rotation * new Vector3(OrigX.constant, OrigY.constant, OrigZ.constant);
x = new ParticleSystem.MinMaxCurve(vector.x);
y = new ParticleSystem.MinMaxCurve(vector.y);
z = new ParticleSystem.MinMaxCurve(vector.z);
}
else if (OrigX.mode == ParticleSystemCurveMode.TwoConstants)
{
var vector2 = rotation * new Vector3(OrigX.constantMin, OrigY.constantMin, OrigZ.constantMin);
var vector3 = rotation * new Vector3(OrigX.constantMax, OrigY.constantMax, OrigZ.constantMax);
x = new ParticleSystem.MinMaxCurve(vector2.x, vector3.x);
y = new ParticleSystem.MinMaxCurve(vector2.y, vector3.y);
z = new ParticleSystem.MinMaxCurve(vector2.z, vector3.z);
}
else
{
Debug.LogWarning("Cannot properly rotate Module Curves! Use Constants mode instead, dummy.");
x = OrigX;
y = OrigY;
z = OrigZ;
}
}
}
}
}