273 lines
11 KiB
C#
273 lines
11 KiB
C#
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using Ichni.RhythmGame.Beatmap;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using Object = UnityEngine.Object;
|
|||
|
|
|
|||
|
|
namespace Ichni.RhythmGame
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
public partial class ParticleEmitter : GameElement, IHaveParticles, IHaveTimeDurationSubmodule, IHaveTransformSubmodule, IHaveColorSubmodule
|
|||
|
|
{
|
|||
|
|
public ParticleSystem particle { get; set; }
|
|||
|
|
private IHaveParticles particlesContainer => this;
|
|||
|
|
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
|||
|
|
public TransformSubmodule transformSubmodule { get; set; }
|
|||
|
|
public ColorSubmodule colorSubmodule { get; set; }
|
|||
|
|
public bool haveBaseColor => true;
|
|||
|
|
public bool haveEmissionColor => true;
|
|||
|
|
|
|||
|
|
private List<string> themeBundleList;
|
|||
|
|
private List<string> materialNameList;
|
|||
|
|
public string themeBundleName;
|
|||
|
|
public string materialName;
|
|||
|
|
|
|||
|
|
public bool prewarm;
|
|||
|
|
public float playTime;
|
|||
|
|
public float stopTime;
|
|||
|
|
|
|||
|
|
public ParticleSystemSimulationSpace simulationSpace;
|
|||
|
|
public float density;
|
|||
|
|
public float lifeTime;
|
|||
|
|
public float speed;
|
|||
|
|
public float radius;
|
|||
|
|
|
|||
|
|
public bool isAutoOrient;
|
|||
|
|
public Vector3 particleRotation;
|
|||
|
|
|
|||
|
|
public static ParticleEmitter GenerateElement(string elementName, Guid id, List<string> tags,
|
|||
|
|
bool isFirstGenerated, GameElement parentElement, string themeBundleName, string materialName,
|
|||
|
|
bool prewarm, float playTime, float stopTime, ParticleSystemSimulationSpace simulationSpace,
|
|||
|
|
float density, float lifeTime, float speed, float radius,
|
|||
|
|
bool isAutoOrient, Vector3 particleRotation)
|
|||
|
|
{
|
|||
|
|
ParticleEmitter particleEmitter = Instantiate(GameManager.instance.basePrefabs.particleEmitter, parentElement.transform)
|
|||
|
|
.GetComponent<ParticleEmitter>();
|
|||
|
|
particleEmitter.particle = particleEmitter.GetComponent<ParticleSystem>();
|
|||
|
|
particleEmitter.Initialize(elementName, id, tags, isFirstGenerated, parentElement);
|
|||
|
|
particleEmitter.playTime = playTime;
|
|||
|
|
particleEmitter.stopTime = stopTime;
|
|||
|
|
particleEmitter.themeBundleList = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName);
|
|||
|
|
particleEmitter.materialNameList = new List<string>();
|
|||
|
|
particleEmitter.themeBundleName = themeBundleName;
|
|||
|
|
particleEmitter.materialName = materialName;
|
|||
|
|
particleEmitter.particlesContainer.SetParticleMaterial(themeBundleName, materialName);
|
|||
|
|
particleEmitter.SetParticleSettings(prewarm, simulationSpace, density, lifeTime, speed, radius, isAutoOrient, particleRotation, false);
|
|||
|
|
return particleEmitter;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetParticleSettings(bool prewarm, ParticleSystemSimulationSpace simulationSpace,
|
|||
|
|
float density, float lifeTime, float speed, float radius, bool isAutoOrient, Vector3 particleRotation, bool mark)
|
|||
|
|
{
|
|||
|
|
//这个Mark没有任何作用,只是为了让解释器把interface中的函数和这个函数区分开。否则会Stackoverflow。
|
|||
|
|
this.prewarm = prewarm;
|
|||
|
|
this.simulationSpace = simulationSpace;
|
|||
|
|
this.density = density;
|
|||
|
|
this.lifeTime = lifeTime;
|
|||
|
|
this.speed = speed;
|
|||
|
|
this.radius = radius;
|
|||
|
|
this.isAutoOrient = isAutoOrient;
|
|||
|
|
this.particleRotation = particleRotation;
|
|||
|
|
(this as IHaveParticles).SetParticleSettings(prewarm, simulationSpace, density, lifeTime, speed, radius, isAutoOrient, particleRotation);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void SetDefaultSubmodules()
|
|||
|
|
{
|
|||
|
|
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
|||
|
|
transformSubmodule = new TransformSubmodule(this);
|
|||
|
|
colorSubmodule = new ColorSubmodule(this, Color.white, true, Color.white, 0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public partial class ParticleEmitter
|
|||
|
|
{
|
|||
|
|
private void Update()
|
|||
|
|
{
|
|||
|
|
float songTime = GameManager.instance.songTime;
|
|||
|
|
if (playTime > songTime || stopTime < songTime)
|
|||
|
|
{
|
|||
|
|
particle.Stop();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (!particle.isPlaying)
|
|||
|
|
{
|
|||
|
|
particle.Play();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void Refresh()
|
|||
|
|
{
|
|||
|
|
base.Refresh();
|
|||
|
|
ParticleSystemRenderer particleSystemRenderer = particle.GetComponent<ParticleSystemRenderer>();
|
|||
|
|
particleSystemRenderer.material.SetColor("_BaseColor", colorSubmodule.currentBaseColor);
|
|||
|
|
if (colorSubmodule.emissionEnabled)
|
|||
|
|
{
|
|||
|
|
particleSystemRenderer.material.EnableKeyword("_EMISSION_ON");
|
|||
|
|
particleSystemRenderer.material.SetColor("_EmissionColor", colorSubmodule.GetCurrentEmissionColor());
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
particleSystemRenderer.material.DisableKeyword("_EMISSION_ON");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public partial class ParticleEmitter
|
|||
|
|
{
|
|||
|
|
public override void SaveBM()
|
|||
|
|
{
|
|||
|
|
matchedBM = new ParticleEmitter_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
|||
|
|
prewarm, playTime, stopTime, simulationSpace, density, lifeTime, speed, radius,
|
|||
|
|
isAutoOrient, particleRotation, themeBundleName, materialName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
namespace Beatmap
|
|||
|
|
{
|
|||
|
|
public class ParticleEmitter_BM : GameElement_BM
|
|||
|
|
{
|
|||
|
|
public bool prewarm = false;
|
|||
|
|
public float playTime = 0f;
|
|||
|
|
public float stopTime = 1f;
|
|||
|
|
|
|||
|
|
public ParticleSystemSimulationSpace simulationSpace;
|
|||
|
|
public float density = 10;
|
|||
|
|
public float lifeTime = 5;
|
|||
|
|
public float speed;
|
|||
|
|
public float radius;
|
|||
|
|
|
|||
|
|
public bool isAutoOrient = true;
|
|||
|
|
public Vector3 particleRotation = Vector3.zero;
|
|||
|
|
|
|||
|
|
public string materialThemeBundleName = string.Empty;
|
|||
|
|
public string materialName = string.Empty;
|
|||
|
|
|
|||
|
|
public ParticleEmitter_BM()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public ParticleEmitter_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM attachedElement,
|
|||
|
|
bool prewarm, float playTime, float stopTime, ParticleSystemSimulationSpace simulationSpace,
|
|||
|
|
float density, float lifeTime, float speed, float radius, bool isAutoOrient, Vector3 particleRotation,
|
|||
|
|
string materialThemeBundleName, string materialName) :
|
|||
|
|
base(elementName, elementGuid, tags, attachedElement)
|
|||
|
|
{
|
|||
|
|
this.prewarm = prewarm;
|
|||
|
|
this.playTime = playTime;
|
|||
|
|
this.stopTime = stopTime;
|
|||
|
|
this.simulationSpace = simulationSpace;
|
|||
|
|
this.density = density;
|
|||
|
|
this.lifeTime = lifeTime;
|
|||
|
|
this.speed = speed;
|
|||
|
|
this.radius = radius;
|
|||
|
|
this.isAutoOrient = isAutoOrient;
|
|||
|
|
this.particleRotation = particleRotation;
|
|||
|
|
this.materialThemeBundleName = materialThemeBundleName;
|
|||
|
|
this.materialName = materialName;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public override void ExecuteBM()
|
|||
|
|
{
|
|||
|
|
matchedElement = ParticleEmitter.GenerateElement(elementName, elementGuid, tags, false,
|
|||
|
|
GetElement(attachedElementGuid), materialThemeBundleName, materialName,
|
|||
|
|
prewarm, playTime, stopTime, simulationSpace, density, lifeTime, speed, radius,
|
|||
|
|
isAutoOrient, particleRotation);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public interface IHaveParticles
|
|||
|
|
{
|
|||
|
|
public ParticleSystem particle { get; set; }
|
|||
|
|
|
|||
|
|
public virtual void SetParticleMaterial(string themeBundleName, string materialName)
|
|||
|
|
{
|
|||
|
|
Material material = ThemeBundleManager.instance.GetObject<Material>(themeBundleName, materialName);
|
|||
|
|
if (material == null)
|
|||
|
|
{
|
|||
|
|
material = ThemeBundleManager.instance.GetObject<Material>("basic", "Basic_Track_Default");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Renderer particleRenderer = particle.GetComponent<Renderer>();
|
|||
|
|
particleRenderer.material = Object.Instantiate(material);
|
|||
|
|
particleRenderer.InitializeShader();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public virtual void SetParticleSettings(bool prewarm, ParticleSystemSimulationSpace simulationSpace, float density, float lifeTime,
|
|||
|
|
float speed, float radius, bool isAutoOrient, Vector3 particleRotation)
|
|||
|
|
{
|
|||
|
|
SetPrewarm(prewarm);
|
|||
|
|
SetSimulationSpace(simulationSpace);
|
|||
|
|
SetDensity(density);
|
|||
|
|
SetLifeTime(lifeTime);
|
|||
|
|
SetSpeed(speed);
|
|||
|
|
SetRadius(radius);
|
|||
|
|
SetAlignment(isAutoOrient, particleRotation);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetPrewarm(bool prewarm)
|
|||
|
|
{
|
|||
|
|
var mainModule = particle.main;
|
|||
|
|
mainModule.prewarm = prewarm;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetSimulationSpace(ParticleSystemSimulationSpace simulationSpace)
|
|||
|
|
{
|
|||
|
|
var mainModule = particle.main;
|
|||
|
|
mainModule.simulationSpace = simulationSpace;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetDensity(float density)
|
|||
|
|
{
|
|||
|
|
var emission = particle.emission;
|
|||
|
|
emission.rateOverTime = density;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetLifeTime(float lifeTime)
|
|||
|
|
{
|
|||
|
|
var mainModule = particle.main;
|
|||
|
|
mainModule.startLifetime = lifeTime;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetSpeed(float speed)
|
|||
|
|
{
|
|||
|
|
var mainModule = particle.main;
|
|||
|
|
mainModule.startSpeed = speed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetRadius(float radius)
|
|||
|
|
{
|
|||
|
|
var shapeModule = particle.shape;
|
|||
|
|
shapeModule.radius = radius;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetAlignment(bool isAutoOrient, Vector3 particleRotation = default)
|
|||
|
|
{
|
|||
|
|
ParticleSystemRenderer particleSystemRenderer = particle.GetComponent<ParticleSystemRenderer>();
|
|||
|
|
var mainModule = particle.main;
|
|||
|
|
if (isAutoOrient)
|
|||
|
|
{
|
|||
|
|
particleSystemRenderer.alignment = ParticleSystemRenderSpace.View;
|
|||
|
|
mainModule.startRotation3D = false; // 禁用3D旋转
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
particleSystemRenderer.alignment = ParticleSystemRenderSpace.Local;
|
|||
|
|
mainModule.startRotation3D = true; // 启用3D旋转
|
|||
|
|
SetParticleRotation(particleRotation);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetParticleRotation(Vector3 particleRotation)
|
|||
|
|
{
|
|||
|
|
Vector3 vector3Rotation = particleRotation * Mathf.Deg2Rad;
|
|||
|
|
var mainModule = particle.main;
|
|||
|
|
mainModule.startRotationX = vector3Rotation.x;
|
|||
|
|
mainModule.startRotationY = vector3Rotation.y;
|
|||
|
|
mainModule.startRotationZ = vector3Rotation.z;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|