OldBlueWater/BlueWater/Assets/RayFire/Scripts/Classes/Rigid/RFFade.cs

804 lines
28 KiB
C#
Raw Normal View History

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace RayFire
{
[Serializable]
public class RFFade
{
// UI
public bool onDemolition;
public bool onActivation;
public float byOffset;
public RFFadeLifeType lifeType;
public float lifeTime;
public float lifeVariation;
public FadeType fadeType;
public float fadeTime;
public float sizeFilter;
public int shardAmount;
// Non Serialized
[NonSerialized] public int state; // 1-Living, 2-Fading, 3-Faded
[NonSerialized] public bool stop;
[NonSerialized] public bool offsetCorState;
[NonSerialized] public IEnumerator offsetEnum;
// Event
public RFFadingEvent fadingEvent = new RFFadingEvent();
/// /////////////////////////////////////////////////////////
/// Constructor
/// /////////////////////////////////////////////////////////
// Constructor
public RFFade()
{
InitValues();
LocalReset();
}
void InitValues()
{
onDemolition = true;
onActivation = false;
byOffset = 0f;
lifeType = RFFadeLifeType.ByLifeTime;
lifeTime = 7f;
lifeVariation = 3f;
fadeType = FadeType.None;
fadeTime = 5f;
sizeFilter = 0f;
shardAmount = 5;
}
// Reset
public void LocalReset()
{
state = 0;
stop = false;
offsetCorState = false;
offsetEnum = null;
}
// Pool Reset
public void GlobalReset()
{
InitValues();
LocalReset();
fadingEvent = new RFFadingEvent();
}
// Copy from
public void CopyFrom (RFFade source)
{
onDemolition = source.onDemolition;
onActivation = source.onActivation;
byOffset = source.byOffset;
lifeType = source.lifeType;
lifeTime = source.lifeTime;
lifeVariation = source.lifeVariation;
fadeType = source.fadeType;
fadeTime = source.fadeTime;
sizeFilter = source.sizeFilter;
shardAmount = source.shardAmount;
LocalReset();
}
/// /////////////////////////////////////////////////////////
/// Fade for demolished fragments
/// /////////////////////////////////////////////////////////
// Fading init from parent node
public void DemolitionFade (List<RayfireRigid> fadeObjects)
{
// No fading
if (fadeType == FadeType.None)
return;
// No objects
if (fadeObjects.Count == 0)
return;
// Add Fade script and init fading
for (int i = 0; i < fadeObjects.Count; i++)
{
// Check for null
if (fadeObjects[i] == null)
continue;
// Init fading
FadeRigid (fadeObjects[i]);
}
}
/// /////////////////////////////////////////////////////////
/// Offset fade coroutine
/// /////////////////////////////////////////////////////////
// Check offset for fade
public static IEnumerator FadeOffsetCor (RayfireRigid scr)
{
// Object living, fading or faded
if (scr.fading.state > 0)
yield break;
// Stop if running
if (scr.fading.offsetCorState == true)
yield break;
// Repeat check time
WaitForSeconds delay = new WaitForSeconds (2f);
// Random start
yield return new WaitForSeconds (Random.Range(0f, 2f));
// Set running state
scr.fading.offsetCorState = true;
// Check
while (scr.fading.state == 0 && scr.fading.byOffset > 0)
{
if (Vector3.Distance (scr.transForm.position, scr.physics.initPosition) > scr.fading.byOffset)
{
scr.Fade();
break;
}
yield return delay;
}
// Set state
scr.fading.offsetCorState = false;
}
// Check offset for fade
public static IEnumerator FadeOffsetCor (RayfireRigidRoot scr)
{
// Stop if running
if (scr.fading.offsetCorState == true)
yield break;
// Repeat check time
WaitForSeconds delay = new WaitForSeconds (2f);
// Random start
yield return new WaitForSeconds (Random.Range(0f, 2f));
// Set running state
scr.fading.offsetCorState = true;
// Check all shards
while (scr.offsetFadeShards.Count > 0)
{
for (int i = scr.offsetFadeShards.Count - 1; i >= 0; i--)
{
// Remove if shards was clustered by Connectivity into Connected Cluster
if (scr.offsetFadeShards[i].fade == -1)
{
scr.offsetFadeShards.RemoveAt (i);
continue;
}
// Calculate offset distance and fade if big enough, remove from list
if (Vector3.Distance (scr.offsetFadeShards[i].tm.position, scr.offsetFadeShards[i].pos) > scr.offsetFadeShards[i].fo)
{
FadeShard (scr, scr.offsetFadeShards[i]);
scr.offsetFadeShards.RemoveAt (i);
}
}
yield return delay;
}
// Set state
scr.fading.offsetCorState = false;
}
/// /////////////////////////////////////////////////////////
/// Object Fade init
/// /////////////////////////////////////////////////////////
// Fading init for Rigid object
public static void FadeRigid (RayfireRigid scr)
{
// No fading
if (scr.fading.fadeType == FadeType.None)
return;
// Object inactive, Skip
if (scr.gameObject.activeSelf == false)
return;
// Initialize if not
if (scr.initialized == false)
scr.Initialize();
// Size check
if (scr.fading.sizeFilter > 0 && scr.limitations.bboxSize > scr.fading.sizeFilter)
return;
// Shard amount check
if (scr.fading.shardAmount > 0 && scr.objectType == ObjectType.ConnectedCluster)
if (scr.clusterDemolition.cluster.shards.Count > scr.fading.shardAmount)
return;
// Object living, fading or faded
if (scr.fading.state > 0)
return;
// Start life coroutine
scr.StartCoroutine (LivingCor (scr));
// Stop Physics data cor. Not for nested clusters TODO use if rigid is not going to be reset
//if (scr.objectType != ObjectType.NestedCluster && scr.physics.physicsEnum != null)
// scr.StopCoroutine (scr.physics.physicsEnum);
}
// Fading init for Shard object
public static void FadeShard (RayfireRigidRoot scr, RFShard shard)
{
// No fading
if (scr.fading.fadeType == FadeType.None)
return;
// Shard living, fading or faded
if (shard.fade > 0)
return;
// Size check
if (scr.fading.sizeFilter > 0 && shard.sz > scr.fading.sizeFilter)
return;
// Start life coroutine
scr.StartCoroutine (LivingCor (scr, shard));
}
// Fade Cluster's detached rigid fragments or Shards if cluster has RigidRoot parent
public static void FadeClusterShards(RayfireRigid scr, List<RFShard> fadeShards)
{
if (scr.fading.onDemolition == true)
{
// Fading for detached fragments
if (scr.rigidRoot == null)
scr.fading.DemolitionFade (scr.fragments);
// Fading for detached shards because has Rigid Root
else
for (int i = 0; i < fadeShards.Count; i++)
FadeShard (scr.rigidRoot, fadeShards[i]);
// Self fade for main cluster
scr.Fade();
}
}
/// /////////////////////////////////////////////////////////
/// Living
/// /////////////////////////////////////////////////////////
// Start life coroutine
static IEnumerator LivingCor (RayfireRigid scr)
{
// Set living
scr.fading.state = 1;
// Wait for simulation get rest
if (scr.fading.lifeType == RFFadeLifeType.BySimulationAndLifeTime)
yield return scr.StartCoroutine(SimulationLivingCor (scr.transForm));
// Get final life duration
float lifeDuration = scr.fading.lifeTime;
if (scr.fading.lifeVariation > 0)
lifeDuration += Random.Range (0f, scr.fading.lifeVariation);
// Wait life time
if (lifeDuration > 0)
yield return new WaitForSeconds (lifeDuration);
// Stop fading
if (scr.fading.stop == true)
{
scr.fading.LocalReset();
yield break;
}
// Set fading
scr.fading.state = 2;
// Event
scr.fading.fadingEvent.InvokeLocalEvent (scr.transform);
RFFadingEvent.InvokeGlobalEvent (scr.transform);
// Exclude from simulation and keep object in scene
if (scr.fading.fadeType == FadeType.SimExclude)
FadeExclude (scr);
// Fall under ground, destroy
else if (scr.fading.fadeType == FadeType.FallDown)
scr.StartCoroutine (FallDownCor (scr));
// Start scale down and destroy
else if (scr.fading.fadeType == FadeType.ScaleDown)
scr.StartCoroutine (ScaleDownCor (scr));
// Exclude from simulation, Move down and destroy
else if (scr.fading.fadeType == FadeType.MoveDown)
scr.StartCoroutine (FadeMoveDownCor (scr));
// Destroy object
else if (scr.fading.fadeType == FadeType.Destroy)
{
// Set faded and destroy
scr.fading.state = 3;
RayfireMan.DestroyFragment (scr, scr.rootParent);
}
// Static object
else if (scr.fading.fadeType == FadeType.SetStatic)
{
// Set faded and destroy rigidbody
scr.fading.state = 3;
Object.Destroy (scr.physics.rigidBody);
scr.physics.rigidBody = null;
}
// Kinematic object
else if (scr.fading.fadeType == FadeType.SetKinematic)
{
// Set faded and set kinematic
scr.fading.state = 3;
scr.physics.rigidBody.isKinematic = true;
}
}
// Start life coroutine
static IEnumerator LivingCor (RayfireRigidRoot root, RFShard shard)
{
// Wait for simulation get rest
if (root.fading.lifeType == RFFadeLifeType.BySimulationAndLifeTime)
yield return root.StartCoroutine(SimulationLivingCor (shard.tm));
// Set living
shard.fade = 1;
// Get final life duration
float lifeDuration = root.fading.lifeTime;
if (root.fading.lifeVariation > 0)
lifeDuration += Random.Range (0f, root.fading.lifeVariation);
// Wait life time
if (lifeDuration > 0)
yield return new WaitForSeconds (lifeDuration);
// Set fading
shard.fade = 2;
// Event
root.fading.fadingEvent.InvokeLocalEvent (shard.tm);
RFFadingEvent.InvokeGlobalEvent (shard.tm);
// Exclude from simulation and keep object in scene
if (root.fading.fadeType == FadeType.SimExclude)
FadeExclude (root, shard);
// Exclude from simulation, fall under ground, destroy
else if (root.fading.fadeType == FadeType.FallDown)
root.StartCoroutine (FallDownCor (root, shard));
// Start scale down and destroy
else if (root.fading.fadeType == FadeType.ScaleDown)
root.StartCoroutine (ScaleDownCor (root, shard));
// Exclude from simulation, Move down and destroy
else if (root.fading.fadeType == FadeType.MoveDown)
root.StartCoroutine (FadeMoveDownCor (root, shard));
// // Destroy/Deactivate
else if (root.fading.fadeType == FadeType.Destroy)
{
// Set faded and destroy
shard.fade = 3;
RayfireMan.DestroyShard (root, shard);
}
// Static object
else if (root.fading.fadeType == FadeType.SetStatic)
{
// Set faded and destroy rigidbody
shard.fade = 3;
Object.Destroy (shard.rb);
}
// Kinematic object
else if (root.fading.fadeType == FadeType.SetKinematic)
{
// Set faded and set kinematic
shard.fade = 3;
shard.rb.isKinematic = true;
}
}
// Check for simulation state
static IEnumerator SimulationLivingCor (Transform tm)
{
float timeStep = Random.Range (2.5f, 3.5f);
Vector3 oldPos;
float distanceThreshold = 0.15f;
// Wait
WaitForSeconds wait = new WaitForSeconds (timeStep);
while (true)
{
// Save position
oldPos = tm.position;
// Wait step time
yield return wait;
if (Vector3.Distance (tm.position, oldPos) < distanceThreshold)
break;
}
}
/// /////////////////////////////////////////////////////////
/// Exclude
/// /////////////////////////////////////////////////////////
// Exclude from simulation and keep object in scene
static void FadeExclude (RayfireRigid rigid)
{
// Set faded
rigid.fading.state = 3;
// Not going to be reused
if (rigid.reset.action == RFReset.PostDemolitionType.DestroyWithDelay)
{
UnityEngine.Object.Destroy (rigid.physics.rigidBody);
UnityEngine.Object.Destroy (rigid.physics.meshCollider);
UnityEngine.Object.Destroy (rigid);
}
// Going to be reused
else if (rigid.reset.action == RFReset.PostDemolitionType.DeactivateToReset)
{
// Set kinematic
rigid.physics.rigidBody.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
rigid.physics.rigidBody.isKinematic = true;
// Disable mesh collider // Null check because of Planar check fragments without collider
if (rigid.objectType == ObjectType.Mesh && rigid.physics.meshCollider != null)
rigid.physics.meshCollider.enabled = false;
// Disable cluster colliders TODO test nested cluster
else if (rigid.objectType == ObjectType.ConnectedCluster || rigid.objectType == ObjectType.NestedCluster)
for (int i = 0; i < rigid.physics.clusterColliders.Count; i++)
rigid.physics.clusterColliders[i].enabled = false;
// Stop all cors
rigid.StopAllCoroutines();
}
}
// Exclude from simulation and keep object in scene
static void FadeExclude (RayfireRigidRoot root, RFShard shard)
{
// Faded
shard.fade = 3;
// Not going to be reused
if (root.reset.action == RFReset.PostDemolitionType.DestroyWithDelay)
{
UnityEngine.Object.Destroy (shard.rb);
UnityEngine.Object.Destroy (shard.col);
}
// Going to be reused
else if (root.reset.action == RFReset.PostDemolitionType.DeactivateToReset)
{
shard.rb.isKinematic = true;
shard.col.enabled = false;
}
}
/// /////////////////////////////////////////////////////////
/// Fall Down
/// /////////////////////////////////////////////////////////
// Exclude from simulation, fall under ground, destroy
static IEnumerator FallDownCor (RayfireRigid rigid)
{
// Activate inactive
if (rigid.simulationType == SimType.Inactive)
rigid.Activate();
// Wake up if sleeping
rigid.physics.rigidBody.WakeUp();
// Turn off collider
if (rigid.objectType == ObjectType.Mesh && rigid.physics.meshCollider != null)
rigid.physics.meshCollider.enabled = false;
else if (rigid.objectType == ObjectType.ConnectedCluster || rigid.objectType == ObjectType.NestedCluster)
DisableClusterColliders (rigid);
// Wait to fall down
yield return new WaitForSeconds (rigid.fading.fadeTime);
// Set faded
rigid.fading.state = 3;
// Check if fragment is the last child in root and delete root as well
RayfireMan.DestroyFragment (rigid, rigid.rootParent);
}
// Exclude from simulation, move under ground, destroy
static IEnumerator FallDownCor (RayfireRigidRoot root, RFShard shard)
{
// Activate inactive
if (shard.sm == SimType.Inactive)
RFActivation.ActivateShard (shard, root);
// Wake up if sleeping
shard.rb.WakeUp();
// Turn off collider
if (shard.col != null)
shard.col.enabled = false;
// Wait to fall down
yield return new WaitForSeconds (root.fading.fadeTime);
// Faded
shard.fade = 3;
// Destroy/Deactivate
RayfireMan.DestroyShard (root, shard);
}
/// /////////////////////////////////////////////////////////
/// Scale Down
/// /////////////////////////////////////////////////////////
// Exclude from simulation, move under ground, destroy
static IEnumerator ScaleDownCor (RayfireRigid scr)
{
// Scale object down during fade time
float waitStep = 0.04f;
int steps = (int)(scr.fading.fadeTime / waitStep);
Vector3 vectorStep = scr.transForm.localScale / steps;
// Wait
WaitForSeconds wait = new WaitForSeconds (waitStep);
// Repeat
while (steps > 0)
{
steps--;
// Scale down
scr.transForm.localScale -= vectorStep;
// Wait
yield return wait;
// Destroy when too small
if (steps < 4)
{
// Set faded
scr.fading.state = 3;
// Destroy
RayfireMan.DestroyFragment (scr, scr.rootParent);
yield break;
}
}
}
// Exclude from simulation, move under ground, destroy
static IEnumerator ScaleDownCor (RayfireRigidRoot root, RFShard shard)
{
// Scale object down during fade time
float waitStep = 0.04f;
int steps = (int)(root.fading.fadeTime / waitStep);
Vector3 vectorStep = shard.tm.localScale / steps;
// Wait
WaitForSeconds wait = new WaitForSeconds (waitStep);
// Repeat
while (steps > 0)
{
if (shard.tm == null)
break;
steps--;
// Scale down
shard.tm.localScale -= vectorStep;
// Wait
yield return wait;
// Destroy when too small
if (steps < 4)
{
// Faded
shard.fade = 3;
// Destroy/Deactivate
RayfireMan.DestroyShard (root, shard);
yield break;
}
}
}
/// /////////////////////////////////////////////////////////
/// Move Down
/// /////////////////////////////////////////////////////////
// Exclude from simulation, fall under ground, destroy
static IEnumerator FadeMoveDownCor (RayfireRigid rigid)
{
// Stop simulation
rigid.physics.rigidBody.useGravity = false;
rigid.physics.rigidBody.velocity = Vector3.zero;
rigid.physics.rigidBody.angularVelocity = Vector3.zero;
// Scale object down during fade time
float extraSize = 1.2f;
float waitStep = 0.03f;
int steps = (int)(rigid.fading.fadeTime / waitStep);
Vector3 vectorStep = rigid.limitations.bboxSize * extraSize / steps * Vector3.down;
// Turn off collider
if (rigid.objectType == ObjectType.Mesh && rigid.physics.meshCollider != null)
{
// Disable colliders
rigid.physics.meshCollider.enabled = false;
// Set correct vector by renderer size
vectorStep = rigid.meshRenderer.bounds.size.y * extraSize / steps * Vector3.down;
}
else if (rigid.objectType == ObjectType.ConnectedCluster || rigid.objectType == ObjectType.NestedCluster)
DisableClusterColliders (rigid);
// Wait
WaitForSeconds wait = new WaitForSeconds (waitStep);
// Move down for size distance
while (steps > 0)
{
steps--;
// Scale down
rigid.transForm.Translate (vectorStep, Space.World);
// Wait
yield return wait;
// Destroy when too small
if (steps < 4)
{
// Set faded
rigid.fading.state = 3;
// Destroy
RayfireMan.DestroyFragment (rigid, rigid.rootParent);
yield break;
}
}
}
// Exclude from simulation, move under ground, destroy
static IEnumerator FadeMoveDownCor (RayfireRigidRoot root, RFShard shard)
{
// Stop simulation
shard.rb.useGravity = false;
shard.rb.velocity = Vector3.zero;
shard.rb.angularVelocity = Vector3.zero;
// Scale object down during fade time
float extraSize = 1.2f;
float waitStep = 0.03f;
int steps = (int)(root.fading.fadeTime / waitStep);
Vector3 vectorStep = shard.sz * extraSize / steps * Vector3.down;
// Turn off collider
if (shard.col != null)
shard.col.enabled = false;
// Wait
WaitForSeconds wait = new WaitForSeconds (waitStep);
// Wait to fall down
yield return new WaitForSeconds (root.fading.fadeTime);
// Move down for size distance
while (steps > 0)
{
steps--;
// Scale down
shard.tm.Translate (vectorStep, Space.World);
// Wait
yield return wait;
// Destroy when too small
if (steps < 4)
{
// Set faded
shard.fade = 3;
// Destroy
RayfireMan.DestroyShard (root, shard);
yield break;
}
}
}
/// /////////////////////////////////////////////////////////
/// Methods
/// /////////////////////////////////////////////////////////
// Disable cluster colliders and set fade state for shards
static void DisableClusterColliders (RayfireRigid rigid)
{
if (rigid.physics.HasClusterColliders == true)
{
// Disable colliders
for (int i = 0; i < rigid.physics.clusterColliders.Count; i++)
if (rigid.physics.clusterColliders[i] != null)
rigid.physics.clusterColliders[i].enabled = false;
// Set fade state for shards
for (int i = 0; i < rigid.clusterDemolition.cluster.shards.Count; i++)
rigid.clusterDemolition.cluster.shards[i].fade = 3;
}
}
// Setup offset fading shards for rigid root
static public void SetOffsetFadeList (RayfireRigidRoot root)
{
// Setup offset fade list
if (root.offsetFadeShards == null)
root.offsetFadeShards = new List<RFShard>();
else
root.offsetFadeShards.Clear();
// Collect rigidRoot shards with offset fade
if (root.fading.byOffset > 0)
{
root.offsetFadeShards.Capacity = root.rigidRootShards.Count;
for (int i = 0; i < root.rigidRootShards.Count; i++)
{
root.rigidRootShards[i].fo = root.fading.byOffset;
root.rigidRootShards[i].pos = root.rigidRootShards[i].tm.position;
root.rigidRootShards[i].los = root.rigidRootShards[i].tm.localPosition;
root.offsetFadeShards.Add (root.rigidRootShards[i]);
}
}
// Collect meshRoot shards with offset fade
for (int i = 0; i < root.meshRootShards.Count; i++)
if (root.meshRootShards[i].rigid.fading.byOffset > 0)
{
root.meshRootShards[i].fo = root.meshRootShards[i].rigid.fading.byOffset;
root.meshRootShards[i].pos = root.meshRootShards[i].tm.position;
root.meshRootShards[i].los = root.meshRootShards[i].tm.localPosition;
root.offsetFadeShards.Add (root.meshRootShards[i]);
}
}
}
}