889 lines
35 KiB
C#
889 lines
35 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace RayFire
|
|
{
|
|
public class RFPoolingEmitter
|
|
{
|
|
public int id;
|
|
public bool enable;
|
|
public int cap;
|
|
public int rate;
|
|
public bool skip;
|
|
public bool reuse;
|
|
public int over;
|
|
|
|
public bool empty;
|
|
public bool need;
|
|
public Transform root;
|
|
public Queue<ParticleSystem> queue;
|
|
public List<Transform> scripts;
|
|
|
|
public ParticleSystem psMain;
|
|
|
|
// Constructor
|
|
RFPoolingEmitter (RFParticlePool pool)
|
|
{
|
|
id = pool.id;
|
|
enable = pool.enable;
|
|
cap = pool.cap;
|
|
rate = pool.rate;
|
|
skip = pool.skip;
|
|
reuse = pool.reuse;
|
|
over = pool.over;
|
|
empty = false;
|
|
need = pool.enable; // In order to start pooling should be = enable
|
|
queue = new Queue<ParticleSystem>(cap);
|
|
scripts = new List<Transform>();
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Set host / Demolition
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Init particles on demolition
|
|
public static void SetHostDemolition(RayfireRigid rigid)
|
|
{
|
|
// No frags. Reference demolition can create debris without fragments
|
|
if (rigid.dmlTp != DemolitionType.ReferenceDemolition && rigid.HasFragments == false)
|
|
return;
|
|
|
|
// Convert. Do not emit for mesh replaced by converted setup
|
|
if (rigid.objTp == ObjectType.Mesh && rigid.mshDemol.cnv != RFDemolitionMesh.ConvertType.Disabled)
|
|
return;
|
|
|
|
// Create debris particles
|
|
if (rigid.HasDebris == true)
|
|
SetHostDemolitionDebris (rigid);
|
|
|
|
// Create dust particles
|
|
if (rigid.HasDust == true)
|
|
SetHostDemolitionDust (rigid);
|
|
|
|
// Detach child particles in case object has child particles and about to be deleted
|
|
DetachParticles(rigid);
|
|
}
|
|
|
|
// Create debris particle system
|
|
static void SetHostDemolitionDebris(RayfireRigid rigid)
|
|
{
|
|
// Has no fragments
|
|
if (rigid.HasFragments == false)
|
|
return;
|
|
|
|
for (int f = 0; f < rigid.fragments.Count; f++)
|
|
{
|
|
// Create only for mesh rigid
|
|
if (rigid.fragments[f].objTp != ObjectType.Mesh)
|
|
continue;
|
|
|
|
if (rigid.fragments[f].HasDebris == true)
|
|
{
|
|
for (int d = 0; d < rigid.fragments[f].debrisList.Count; d++)
|
|
{
|
|
// Demolition particle disabled
|
|
if (rigid.fragments[f].debrisList[d].onDemolition != true)
|
|
continue;
|
|
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > rigid.fragments[f].debrisList[d].limitations.percentage)
|
|
continue;
|
|
|
|
// Set particle to fragment
|
|
SetHostDebris (
|
|
rigid.fragments[f].debrisList[d],
|
|
rigid.fragments[f].tsf,
|
|
rigid.fragments[f].mFlt,
|
|
rigid.fragments[f].mRnd,
|
|
rigid.fragments[f].limitations.bboxSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create debris particle system
|
|
static void SetHostDemolitionDust(RayfireRigid rigid)
|
|
{
|
|
// Has no fragments
|
|
if (rigid.HasFragments == false)
|
|
return;
|
|
|
|
for (int f = 0; f < rigid.fragments.Count; f++)
|
|
{
|
|
// Create only for mesh rigid
|
|
if (rigid.fragments[f].objTp != ObjectType.Mesh)
|
|
continue;
|
|
|
|
if (rigid.fragments[f].HasDust == true)
|
|
{
|
|
for (int d = 0; d < rigid.fragments[f].dustList.Count; d++)
|
|
{
|
|
// Demolition particle disabled
|
|
if (rigid.fragments[f].dustList[d].onDemolition != true)
|
|
continue;
|
|
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > rigid.fragments[f].dustList[d].limitations.percentage)
|
|
continue;
|
|
|
|
// Set particle to fragment
|
|
SetHostDust (
|
|
rigid.fragments[f].dustList[d],
|
|
rigid.fragments[f].tsf,
|
|
rigid.fragments[f].mFlt,
|
|
rigid.fragments[f].mRnd,
|
|
rigid.fragments[f].limitations.bboxSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Detach child particles in case object has child particles and about to be deleted
|
|
static void DetachParticles(RayfireRigid rigid)
|
|
{
|
|
// Detach debris particle system if fragment was already demolished/activated before
|
|
if (rigid.HasDebris == true)
|
|
{
|
|
for (int i = 0; i < rigid.debrisList.Count; i++)
|
|
{
|
|
if (rigid.debrisList[i].hostTm != null)
|
|
{
|
|
rigid.debrisList[i].hostTm.parent = RayfireMan.inst.transForm;
|
|
rigid.debrisList[i].hostTm.localScale = Vector3.one;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Detach dust particle system if fragment was already demolished/activated before
|
|
if (rigid.HasDust == true)
|
|
{
|
|
for (int i = 0; i < rigid.dustList.Count; i++)
|
|
{
|
|
if (rigid.dustList[i].hostTm != null)
|
|
{
|
|
rigid.dustList[i].hostTm.parent = RayfireMan.inst.transForm;
|
|
rigid.dustList[i].hostTm.localScale = Vector3.one;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Set host / Impact
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Set Impact tm
|
|
public static void SetHostImpact (List<RayfireDebris> debrisList, Vector3 impactPos, Vector3 impactNormal)
|
|
{
|
|
// No Debris
|
|
if (debrisList == null || debrisList.Count == 0)
|
|
return;
|
|
|
|
for (int i = 0; i < debrisList.Count; i++)
|
|
if (debrisList[i] != null && debrisList[i].onImpact == true)
|
|
SetHostImpact (debrisList[i].pool,
|
|
debrisList[i].limitations.visible,
|
|
debrisList[i].emission.burstAmount,
|
|
debrisList[i].emission.burstVar,
|
|
impactPos, impactNormal);
|
|
}
|
|
|
|
// Set Impact tm
|
|
public static void SetHostImpact (List<RayfireDust> dustList, Vector3 impactPos, Vector3 impactNormal)
|
|
{
|
|
// No dust
|
|
if (dustList == null || dustList.Count == 0)
|
|
return;
|
|
|
|
for (int i = 0; i < dustList.Count; i++)
|
|
if (dustList[i] != null && dustList[i].onImpact == true)
|
|
SetHostImpact (dustList[i].pool,
|
|
dustList[i].limitations.visible,
|
|
dustList[i].emission.burstAmount,
|
|
dustList[i].emission.burstVar,
|
|
impactPos, impactNormal);
|
|
}
|
|
|
|
// Get particle from emitter pool and set to host
|
|
static void SetHostImpact (RFParticlePool pool, bool visible, int burstAmount, int burstVar, Vector3 impactPos, Vector3 impactNormal)
|
|
{
|
|
// Skip if no pool particles available
|
|
if (pool.emitter.ShouldSkip == true)
|
|
return;
|
|
|
|
// Visibility check
|
|
if (VisibilityCheck(visible, Camera.current, impactPos) == false)
|
|
return;
|
|
|
|
// Set particle system to impact position without host
|
|
ParticleSystem pSystem = pool.emitter.GetPoolObject(null);
|
|
|
|
// Move and rotate at impact position
|
|
pSystem.transform.position = impactPos;
|
|
pSystem.transform.LookAt (impactPos + impactNormal);
|
|
|
|
// Set host specific amount
|
|
RFParticles.SetEmission(pSystem.emission, 0, burstAmount, burstVar);
|
|
|
|
// Set host specific emitter shape if mesh
|
|
RFParticles.SetShapeHemisphere(pSystem.shape);
|
|
|
|
// Set Reuse, Activate and play
|
|
ReuseActivatePlay (pSystem, pool.emitter);
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Set host / Activation / RigidRoot / Rigid
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Init Shard particles on activation
|
|
public static void SetHostRigidrootShardAct (RayfireRigidRoot rigidRoot, RFShard shard)
|
|
{
|
|
// RigidRoot shard
|
|
if (shard.rigid == null)
|
|
{
|
|
// Create debris particles
|
|
if (rigidRoot.HasDebris == true)
|
|
for (int i = 0; i < rigidRoot.debrisList.Count; i++)
|
|
if (rigidRoot.debrisList[i].onActivation == true)
|
|
{
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > rigidRoot.debrisList[i].limitations.percentage)
|
|
continue;
|
|
|
|
// Set host
|
|
SetHostDebris (rigidRoot.debrisList[i], shard.tm, shard.mf, null, shard.sz);
|
|
|
|
// Collect particles to reset them
|
|
rigidRoot.particleList.Add (rigidRoot.debrisList[i].hostTm);
|
|
}
|
|
|
|
// Create dust particles
|
|
if (rigidRoot.HasDust == true)
|
|
for (int i = 0; i < rigidRoot.dustList.Count; i++)
|
|
if (rigidRoot.dustList[i].onActivation == true)
|
|
{
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > rigidRoot.dustList[i].limitations.percentage)
|
|
continue;
|
|
|
|
// Set host
|
|
SetHostDust (rigidRoot.dustList[i], shard.tm, shard.mf, null, shard.sz);
|
|
|
|
// Collect particles to reset them
|
|
rigidRoot.particleList.Add (rigidRoot.dustList[i].hostTm);
|
|
}
|
|
}
|
|
|
|
// RigidRoot -> MeshRoot shard
|
|
else if (shard.rigid.objTp == ObjectType.MeshRoot)
|
|
{
|
|
// Create debris particles
|
|
if (shard.rigid.HasDebris == true)
|
|
for (int i = 0; i < shard.rigid.debrisList.Count; i++)
|
|
if (shard.rigid.debrisList[i].onActivation == true)
|
|
{
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > rigidRoot.debrisList[i].limitations.percentage)
|
|
continue;
|
|
|
|
// Set host
|
|
SetHostDebris (shard.rigid.debrisList[i], shard.tm, shard.mf, null, shard.sz);
|
|
|
|
// Collect particles to reset them
|
|
rigidRoot.particleList.Add (rigidRoot.debrisList[i].hostTm);
|
|
}
|
|
|
|
// Create dust particles
|
|
if (shard.rigid.HasDust == true)
|
|
for (int i = 0; i < shard.rigid.dustList.Count; i++)
|
|
if (shard.rigid.dustList[i].onActivation == true)
|
|
{
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > rigidRoot.dustList[i].limitations.percentage)
|
|
continue;
|
|
|
|
// Set host
|
|
SetHostDust (shard.rigid.dustList[i], shard.tm, shard.mf, null, shard.sz);
|
|
|
|
// Collect particles to reset them
|
|
rigidRoot.particleList.Add (rigidRoot.debrisList[i].hostTm);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Init Rigid particles on activation
|
|
public static void SetHostRigidAct (RayfireRigid rigid)
|
|
{
|
|
// Create debris particles
|
|
if (rigid.HasDebris == true)
|
|
{
|
|
for (int i = 0; i < rigid.debrisList.Count; i++)
|
|
if (rigid.debrisList[i].onActivation == true)
|
|
{
|
|
if (rigid.objTp == ObjectType.Mesh)
|
|
SetHostDebris (rigid.debrisList[i], rigid.tsf, rigid.mFlt, rigid.mRnd, rigid.limitations.bboxSize);
|
|
else if (rigid.IsCluster == true)
|
|
SetHostDebrisCluster (rigid, rigid.debrisList[i]);
|
|
}
|
|
}
|
|
|
|
// Create dust particles
|
|
if (rigid.HasDust == true)
|
|
for (int i = 0; i < rigid.dustList.Count; i++)
|
|
if (rigid.dustList[i].onActivation == true)
|
|
{
|
|
if (rigid.objTp == ObjectType.Mesh)
|
|
SetHostDust (rigid.dustList[i], rigid.tsf, rigid.mFlt, rigid.mRnd, rigid.limitations.bboxSize);
|
|
else if (rigid.IsCluster == true)
|
|
SetHostDustCluster (rigid, rigid.dustList[i]);
|
|
}
|
|
}
|
|
|
|
/// //////////////////////////////////////////////////////////////////////////////////
|
|
/// Set host / Activation / Runtime Connected Cluster from RigidRoot or MeshRoot
|
|
/// //////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Create single debris particle system for Connected Cluster
|
|
static void SetHostDebrisCluster(RayfireRigid rigid, RayfireDebris debris)
|
|
{
|
|
for (int j = rigid.clsDemol.cluster.shards.Count - 1; j >= 0; j--)
|
|
{
|
|
// If has detached neib shard
|
|
if (rigid.clsDemol.cluster.shards[j].neibShards.Count < rigid.clsDemol.cluster.shards[j].nAm)
|
|
{
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > debris.limitations.percentage)
|
|
continue;
|
|
|
|
// Cluster crated by RigidRoot shards
|
|
if (rigid.rigidRoot != null)
|
|
{
|
|
SetHostDebris (debris,
|
|
rigid.clsDemol.cluster.shards[j].tm,
|
|
rigid.clsDemol.cluster.shards[j].mf, null,
|
|
rigid.clsDemol.cluster.shards[j].sz);
|
|
|
|
// Collect particles to reset them
|
|
rigid.rigidRoot.particleList.Add (debris.hostTm);
|
|
}
|
|
|
|
// Cluster created by MeshRoot fragments
|
|
else if (rigid.meshRoot != null)
|
|
{
|
|
SetHostDebris (debris,
|
|
rigid.clsDemol.cluster.shards[j].tm,
|
|
rigid.clsDemol.cluster.shards[j].mf,
|
|
rigid.clsDemol.cluster.shards[j].rigid.mRnd,
|
|
rigid.clsDemol.cluster.shards[j].sz);
|
|
|
|
// Collect particles to reset them
|
|
rigid.meshRoot.particleList.Add (debris.hostTm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create single dust particle system for Connected Cluster
|
|
static void SetHostDustCluster(RayfireRigid rigid, RayfireDust dust)
|
|
{
|
|
for (int j = rigid.clsDemol.cluster.shards.Count - 1; j >= 0; j--)
|
|
{
|
|
// If has detached neib shard
|
|
if (rigid.clsDemol.cluster.shards[j].neibShards.Count < rigid.clsDemol.cluster.shards[j].nAm)
|
|
{
|
|
// Filter by percentage
|
|
if (Random.Range(0, 100) > dust.limitations.percentage)
|
|
continue;
|
|
|
|
// Cluster crated by RigidRoot shards
|
|
if (rigid.rigidRoot != null)
|
|
{
|
|
SetHostDust (dust,
|
|
rigid.clsDemol.cluster.shards[j].tm,
|
|
rigid.clsDemol.cluster.shards[j].mf, null,
|
|
rigid.clsDemol.cluster.shards[j].sz);
|
|
|
|
// Collect particles to reset them
|
|
rigid.rigidRoot.particleList.Add (dust.hostTm);
|
|
}
|
|
|
|
// Cluster created by MeshRoot fragments
|
|
else if (rigid.meshRoot != null)
|
|
{
|
|
SetHostDust (dust,
|
|
rigid.clsDemol.cluster.shards[j].tm,
|
|
rigid.clsDemol.cluster.shards[j].mf, null,
|
|
rigid.clsDemol.cluster.shards[j].sz);
|
|
|
|
// Collect particles to reset them
|
|
rigid.meshRoot.particleList.Add (dust.hostTm);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Set host / Main / Set host Specific props
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Get particle from emitter pool and set to host
|
|
public static void SetHostDebris (RayfireDebris debris, Transform tm, MeshFilter mf, MeshRenderer mr = null, float size = 1f)
|
|
{
|
|
// Skip if no pool particles available
|
|
if (debris.pool.emitter.ShouldSkip == true)
|
|
return;
|
|
|
|
// Filter by size threshold
|
|
if (size < debris.limitations.sizeThreshold)
|
|
return;
|
|
|
|
// Visibility check
|
|
if (VisibilityCheck(debris.limitations.visible, tm, mr) == false)
|
|
return;
|
|
|
|
// Get final amount for current host
|
|
int hostBurstAmount = GetHostFinalAmount (size, debris.emission.burstType, debris.emission.burstAmount);
|
|
|
|
// Low host burst amount
|
|
if (debris.limitations.minParticles > 0 && hostBurstAmount < debris.limitations.minParticles)
|
|
return;
|
|
|
|
// Set particle system to host
|
|
ParticleSystem pSystem = debris.pool.emitter.GetPoolObject(tm);
|
|
|
|
// Set host specific amount
|
|
RFParticles.SetEmission(pSystem.emission, debris.emission.distanceRate, hostBurstAmount, debris.emission.burstVar);
|
|
|
|
// Set host specific emitter shape if mesh
|
|
RFParticles.SetShapeMesh (pSystem.shape, mf, tm, mr, debris.emissionMaterial);
|
|
|
|
// Set Reuse, Activate and play
|
|
ReuseActivatePlay (pSystem, debris.pool.emitter);
|
|
|
|
// Set particle script host
|
|
debris.hostTm = pSystem.transform;
|
|
|
|
// Collect particle
|
|
RayfireMan.inst.particles.resetList.Add (pSystem);
|
|
}
|
|
|
|
// Get particle from emitter pool and set to host
|
|
public static void SetHostDust (RayfireDust dust, Transform tm, MeshFilter mf, MeshRenderer mr = null, float size = 1f)
|
|
{
|
|
// Skip if no pool particles available
|
|
if (dust.pool.emitter.ShouldSkip == true)
|
|
return;
|
|
|
|
// Filter by size threshold
|
|
if (size < dust.limitations.sizeThreshold)
|
|
return;
|
|
|
|
// Visibility check
|
|
if (VisibilityCheck(dust.limitations.visible, tm, mr) == false)
|
|
return;
|
|
|
|
// Get final amount for current host
|
|
int hostBurstAmount = GetHostFinalAmount (size, dust.emission.burstType, dust.emission.burstAmount);
|
|
|
|
// Low host burst amount
|
|
if (dust.emission.distanceRate > 0 && hostBurstAmount < dust.limitations.minParticles)
|
|
return;
|
|
|
|
// Set particle system to host
|
|
ParticleSystem pSystem = dust.pool.emitter.GetPoolObject(tm);
|
|
|
|
// Set host specific amount
|
|
RFParticles.SetEmission(pSystem.emission, dust.emission.distanceRate, hostBurstAmount, dust.emission.burstVar);
|
|
|
|
// Set host emitter shape to mesh
|
|
RFParticles.SetShapeMesh (pSystem.shape, mf, tm, mr, dust.emissionMaterial);
|
|
|
|
// Set Reuse, Activate and play
|
|
ReuseActivatePlay (pSystem, dust.pool.emitter);
|
|
|
|
// Set particle script host
|
|
dust.hostTm = pSystem.transform;
|
|
|
|
// Collect particle
|
|
RayfireMan.inst.particles.resetList.Add (pSystem);
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Set emitters and first reference
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Create debris ps emitter
|
|
public static void CreateEmitterDebris(RayfireDebris scr, Transform sourceTm)
|
|
{
|
|
// Check for exiting of specific emitter pool id
|
|
if (EmitterCheck(scr.pool, scr.transform) == true)
|
|
return;
|
|
|
|
// Create new pool emitter
|
|
RFPoolingEmitter emitter = new RFPoolingEmitter(scr.pool);
|
|
|
|
// Create emitter root and set as child for main emitter root
|
|
CreateRoot (RayfireMan.inst.particles.root, emitter, sourceTm.name + "_Dbr_" + scr.debrisReference.name);
|
|
|
|
// Get object from pool or create
|
|
emitter.psMain = CreateEmitterParticle(emitter);
|
|
|
|
// Set edited debris ps properties
|
|
SetPsDebris (scr, emitter.psMain);
|
|
|
|
// Renderer
|
|
RFParticles.SetParticleRendererDebris(emitter.psMain.GetComponent<ParticleSystemRenderer>(), scr);
|
|
|
|
// Common emitter ops
|
|
SetupEmitter (emitter, scr.pool, scr.transform);
|
|
}
|
|
|
|
// Set edited debris ps properties
|
|
static void SetPsDebris (RayfireDebris scr, ParticleSystem ps)
|
|
{
|
|
// Set main module
|
|
RFParticles.SetMain(ps.main, scr.emission.lifeMin, scr.emission.lifeMax, scr.emission.sizeMin,
|
|
scr.emission.sizeMax, scr.dynamic.gravityMin, scr.dynamic.gravityMax, scr.dynamic.speedMin,
|
|
scr.dynamic.speedMax, 3.1f, scr.limitations.maxParticles, scr.emission.duration);
|
|
|
|
// Set default emitter shape to hemisphere in case host won't have mesh
|
|
RFParticles.SetShapeHemisphere(ps.shape);
|
|
|
|
// Emission over distance
|
|
RFParticles.SetEmission(ps.emission, scr.emission.distanceRate, scr.emission.burstAmount, scr.emission.burstVar);
|
|
|
|
// Inherit velocity
|
|
RFParticles.SetVelocity(ps.inheritVelocity, scr.dynamic);
|
|
|
|
// Size over lifetime
|
|
RFParticles.SetSizeOverLifeTime(ps.sizeOverLifetime);
|
|
|
|
// Rotation by speed
|
|
RFParticles.SetRotationBySpeed(ps.rotationBySpeed, scr.dynamic.rotationSpeed);
|
|
|
|
// Noise
|
|
RFParticles.SetNoise (ps.noise, scr.noise);
|
|
|
|
// Collision
|
|
RFParticles.SetCollisionDebris(ps.collision, scr.collision);
|
|
}
|
|
|
|
// Create dust ps emitter
|
|
public static void CreateEmitterDust(RayfireDust scr, Transform sourceTm)
|
|
{
|
|
// Check for exiting of specific emitter pool id
|
|
if (EmitterCheck(scr.pool, scr.transform) == true)
|
|
return;
|
|
|
|
// Create new pool emitter
|
|
RFPoolingEmitter emitter = new RFPoolingEmitter(scr.pool);
|
|
|
|
// Create emitter root and set as child for main emitter root
|
|
CreateRoot (RayfireMan.inst.particles.root, emitter, sourceTm.name + "_Dst_");
|
|
|
|
// Get object from pool or create
|
|
emitter.psMain = CreateEmitterParticle(emitter);
|
|
|
|
// Set edited debris ps properties
|
|
SetPsDust (scr, emitter.psMain);
|
|
|
|
// Renderer
|
|
RFParticles.SetParticleRendererDust(emitter.psMain.GetComponent<ParticleSystemRenderer>(), scr);
|
|
|
|
// Common emitter ops
|
|
SetupEmitter (emitter, scr.pool, scr.transform);
|
|
}
|
|
|
|
// Set edited debris ps properties
|
|
static void SetPsDust (RayfireDust scr, ParticleSystem ps)
|
|
{
|
|
// Set main module
|
|
RFParticles.SetMain(ps.main, scr.emission.lifeMin, scr.emission.lifeMax, scr.emission.sizeMin,
|
|
scr.emission.sizeMax, scr.dynamic.gravityMin, scr.dynamic.gravityMax, scr.dynamic.speedMin,
|
|
scr.dynamic.speedMax, 6f, scr.limitations.maxParticles, scr.emission.duration);
|
|
|
|
// Set default emitter shape to hemisphere in case host won't have mesh
|
|
RFParticles.SetShapeHemisphere(ps.shape);
|
|
|
|
// Emission over distance
|
|
RFParticles.SetEmission(ps.emission, scr.emission.distanceRate, scr.emission.burstAmount, scr.emission.burstVar);
|
|
|
|
// Collision
|
|
RFParticles.SetCollisionDust(ps.collision, scr.collision);
|
|
|
|
// Color over life time
|
|
RFParticles.SetColorOverLife(ps.colorOverLifetime, scr.opacity);
|
|
|
|
// Rotation over lifetime
|
|
RFParticles.SetRotationOverLifeTime (ps.rotationOverLifetime, scr.dynamic);
|
|
|
|
// Noise
|
|
RFParticles.SetNoise(ps.noise, scr.noise);
|
|
}
|
|
|
|
// Common emitter ops
|
|
static void SetupEmitter(RFPoolingEmitter emitter, RFParticlePool pool, Transform tm)
|
|
{
|
|
// Set to particle emitter
|
|
pool.emitter = emitter;
|
|
|
|
// Collect particle tm to clean emitters
|
|
pool.emitter.scripts.Add (tm);
|
|
|
|
// Collect emitter to manager
|
|
RayfireMan.inst.particles.emitters.Add (pool.emitter);
|
|
|
|
// Warmup and start pooling
|
|
if (pool.enable == true)
|
|
{
|
|
// Create all pool references in awake
|
|
if (pool.warmup == true)
|
|
Warmup(pool.emitter);
|
|
|
|
// Start Emitter Pooling
|
|
RayfireMan.inst.StartEmitterPooling();
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Edit emitter particles
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Edit emitter particles
|
|
public static void EditEmitterParticles(RFPoolingEmitter emitter, RayfireDebris scr)
|
|
{
|
|
SetPsDebris (scr, emitter.psMain);
|
|
if (emitter.queue.Count > 1)
|
|
{
|
|
ParticleSystem[] psArray = emitter.queue.ToArray();
|
|
for (int i = 0; i < psArray.Length; i++)
|
|
if (psArray[i] != null)
|
|
SetPsDebris (scr, psArray[i]);
|
|
}
|
|
}
|
|
|
|
// Edit emitter particles
|
|
public static void EditEmitterParticles(RFPoolingEmitter emitter, RayfireDust scr)
|
|
{
|
|
SetPsDust (scr, emitter.psMain);
|
|
if (emitter.queue.Count > 0)
|
|
{
|
|
ParticleSystem[] psArray = emitter.queue.ToArray();
|
|
for (int i = 0; i < psArray.Length; i++)
|
|
if (psArray[i] != null)
|
|
SetPsDust (scr, psArray[i]);
|
|
}
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Get pool particle and instantiation
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Instantiate first ps
|
|
ParticleSystem InstantiateToHost(Transform hostTm)
|
|
{
|
|
ParticleSystem ps = Object.Instantiate (psMain, hostTm.position, hostTm.rotation, hostTm);
|
|
ps.name = "ps";
|
|
return ps;
|
|
}
|
|
|
|
// Instantiate first ps
|
|
public void InstantiateToPool()
|
|
{
|
|
ParticleSystem ps = Object.Instantiate (psMain, root.position, root.rotation, root);
|
|
ps.name = "ps";
|
|
queue.Enqueue (ps);
|
|
SetNeed(false);
|
|
}
|
|
|
|
// Get pool object
|
|
ParticleSystem GetPoolObject (Transform hostTm)
|
|
{
|
|
// Set need state
|
|
need = true;
|
|
|
|
// Instantiate main ps on the host if empty
|
|
if (queue.Count == 0)
|
|
return InstantiateMainPs (hostTm);
|
|
|
|
// Clean queue ps destroyed by user somehow
|
|
QueueNullClean();
|
|
|
|
// Set transform to host to avoid double set parent and tm change
|
|
if (hostTm != null)
|
|
{
|
|
queue.Peek().transform.position = hostTm.position;
|
|
queue.Peek().transform.SetParent (hostTm);
|
|
}
|
|
|
|
// Out from queue
|
|
return queue.Dequeue();
|
|
}
|
|
|
|
// Get last available ps. leave last in queue
|
|
ParticleSystem InstantiateMainPs(Transform hostTm)
|
|
{
|
|
// Set default tm in case Impact host without transform
|
|
if (hostTm == null)
|
|
hostTm = root;
|
|
|
|
empty = true;
|
|
return InstantiateToHost (hostTm);
|
|
}
|
|
|
|
// Clean queue destroyed by user particle systems
|
|
void QueueNullClean()
|
|
{
|
|
// Next ps is not null
|
|
if (queue.Peek() != null)
|
|
return;
|
|
|
|
// Recollect
|
|
ParticleSystem[] array = queue.ToArray();
|
|
queue.Clear();
|
|
for (int i = 0; i < array.Length; i++)
|
|
if (array[i] != null)
|
|
queue.Enqueue (array[i]);
|
|
|
|
// All ps was null. Create at least new ps in pool
|
|
if (queue.Count == 0)
|
|
InstantiateToPool();
|
|
}
|
|
|
|
/// /////////////////////////////////////////////////////////
|
|
/// Other
|
|
/// /////////////////////////////////////////////////////////
|
|
|
|
// Check if emitter should skip send particle to host
|
|
bool ShouldSkip
|
|
{
|
|
get {return enable == true && skip == true && empty == true;}
|
|
}
|
|
|
|
// Check for exiting of specific emitter pool id
|
|
static bool EmitterCheck(RFParticlePool pool, Transform tm)
|
|
{
|
|
// Already has connected emitter
|
|
if (pool.emitter != null)
|
|
return true;
|
|
|
|
// Check for exiting emitter with the same pool id
|
|
if (pool.id > 0)
|
|
{
|
|
int emitterIndex = RayfireMan.inst.particles.GetEmitterIndexById (pool.id);
|
|
if (emitterIndex >= 0)
|
|
{
|
|
pool.emitter = RayfireMan.inst.particles.emitters[emitterIndex];
|
|
pool.emitter.scripts.Add (tm);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Set Reuse, Activate and play
|
|
static void ReuseActivatePlay(ParticleSystem pSystem, RFPoolingEmitter emitter)
|
|
{
|
|
RFParticles.Reuse (pSystem, emitter);
|
|
pSystem.gameObject.SetActive (true);
|
|
pSystem.Play();
|
|
}
|
|
|
|
// Object visibility check
|
|
static bool VisibilityCheck(bool checkNeed, Transform tm, MeshRenderer mr)
|
|
{
|
|
// Visibility check disabled
|
|
if (checkNeed == false)
|
|
return true;
|
|
|
|
// Object has no renderer
|
|
if (mr == null)
|
|
{
|
|
mr = tm.GetComponent<MeshRenderer>();
|
|
if (mr == null)
|
|
return true;
|
|
}
|
|
|
|
return mr.isVisible;
|
|
}
|
|
|
|
// Object visibility check
|
|
static bool VisibilityCheck(bool checkNeed, Camera camera, Vector3 pos)
|
|
{
|
|
// Visibility check disabled
|
|
if (checkNeed == false)
|
|
return true;
|
|
|
|
// Check if in frustum
|
|
Vector3 p = camera.WorldToViewportPoint(pos);
|
|
return p.x > 0 && p.x < 1 && p.y > 0 && p.y < 1;
|
|
}
|
|
|
|
// Set need state
|
|
public void SetNeed(bool startPooling)
|
|
{
|
|
need = queue.Count < cap;
|
|
|
|
// Start pooling
|
|
if (startPooling == true && need == true)
|
|
RayfireMan.inst.StartEmitterPooling();
|
|
}
|
|
|
|
// Create all pool references in awake
|
|
static void Warmup(RFPoolingEmitter emitter)
|
|
{
|
|
for (int i = 1; i < emitter.cap; i++)
|
|
emitter.InstantiateToPool();
|
|
}
|
|
|
|
// Create root for all ps instances
|
|
static void CreateRoot(Transform emitterParent, RFPoolingEmitter emitter, string name)
|
|
{
|
|
GameObject rootGo = new GameObject (name);
|
|
emitter.root = rootGo.transform;
|
|
emitter.root.position = emitterParent.position;
|
|
emitter.root.parent = emitterParent;
|
|
}
|
|
|
|
// Create dummy particle system object
|
|
static ParticleSystem CreateEmitterParticle(RFPoolingEmitter emitter)
|
|
{
|
|
// Create object with ps
|
|
GameObject go = new GameObject("psMain");
|
|
go.SetActive (false);
|
|
ParticleSystem ps = go.AddComponent<ParticleSystem>();
|
|
ps.Stop();
|
|
|
|
// Set ps transform
|
|
Transform psTm = ps.transform;
|
|
psTm.SetPositionAndRotation (emitter.root.position, emitter.root.rotation);
|
|
psTm.SetParent (emitter.root);
|
|
psTm.localScale = Vector3.one;
|
|
|
|
return ps;
|
|
}
|
|
|
|
// Get amount list
|
|
static int GetHostFinalAmount(float sz, RFParticles.BurstType burstType, int burstAmount)
|
|
{
|
|
// No burst
|
|
if (burstType == RFParticles.BurstType.None)
|
|
return 0;
|
|
|
|
// Same burst amount for every fragment
|
|
if (burstType == RFParticles.BurstType.AmountAndVariation)
|
|
return burstAmount;
|
|
|
|
// Burst amount per particles per fragment size
|
|
if (burstType == RFParticles.BurstType.AmountPerUnit)
|
|
return (int)(burstAmount * sz);
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|