ThrowBall/Assets/Plugins/RayFire/Scripts/Classes/Rigid/RFReset.cs

780 lines
28 KiB
C#
Raw Normal View History

2024-12-01 20:53:59 +08:00
using System;
using System.Linq;
using UnityEngine;
using Object = UnityEngine.Object;
namespace RayFire
{
[Serializable]
public class RFReset
{
public enum PostDemolitionType
{
DestroyWithDelay = 0,
DeactivateToReset = 1
}
public enum MeshResetType
{
Destroy = 0,
ReuseInputMesh = 2,
ReuseFragmentMeshes = 4
}
public enum FragmentsResetType
{
Destroy = 0,
Reuse = 2,
Preserve = 4
}
// UI
public bool transform;
public bool damage;
public bool connectivity;
public PostDemolitionType action;
public float destroyDelay;
public MeshResetType mesh;
public FragmentsResetType fragments;
// Non serialized
[NonSerialized] public bool toBeDestroyed;
/// /////////////////////////////////////////////////////////
/// Constructor
/// /////////////////////////////////////////////////////////
// Constructor
public RFReset()
{
InitValues();
}
void InitValues()
{
transform = true;
damage = true;
connectivity = false;
action = PostDemolitionType.DestroyWithDelay;
destroyDelay = 1;
mesh = MeshResetType.ReuseFragmentMeshes;
fragments = FragmentsResetType.Destroy;
toBeDestroyed = false;
}
// Pool Reset
public void GlobalReset()
{
InitValues();
}
// Copy from
public void CopyFrom (RFReset source, ObjectType objectType)
{
transform = source.transform;
damage = source.damage;
action = source.action;
destroyDelay = source.destroyDelay;
// Copy to initial object: mesh root copy
if (objectType == ObjectType.MeshRoot)
{
mesh = source.mesh;
fragments = source.fragments;
}
// Copy to cluster shards
else if (objectType == ObjectType.ConnectedCluster)
{
mesh = source.mesh;
fragments = source.fragments;
}
// Copy to demolished mesh fragments
else if (objectType == ObjectType.Mesh)
{
mesh = MeshResetType.Destroy;
fragments = FragmentsResetType.Destroy;
// Do not keep fragments at destroy if parent not going to reuse fragments or getting destroyed
if (source.action == PostDemolitionType.DestroyWithDelay ||
source.fragments == FragmentsResetType.Destroy)
action = PostDemolitionType.DestroyWithDelay;
}
}
/// /////////////////////////////////////////////////////////
/// Rigid Mesh
/// /////////////////////////////////////////////////////////
// Rigid
public static void ResetRigid (RayfireRigid scr)
{
// Object can't be reused
if (ObjectReuseState (scr) == false)
return;
// Mesh Root reset
if (MeshRootReset (scr) == true)
return;
// Save faded/demolished state before reset
int faded = scr.fading.state;
bool demolished = scr.limitations.demolished;
// Reset tm
if (scr.reset.transform == true)
RestoreTransform(scr);
// Reset activation TODO check if it was Kinematic
if (scr.activation.activated == true)
scr.simTp = SimType.Inactive;
// ReSet activation layer. IMPORTANT before Reset()
RFActivation.RestoreActivationLayer (scr);
// Reset rigid props
Reset (scr);
// Stop all cors in case object restarted
scr.StopAllCoroutines();
// Reset if object fading/faded
if (faded >= 1)
ResetFade(scr);
// Demolished. Restore
if (demolished == true)
ResetMeshDemolition (scr);
// Restore cluster even if it was not demolished
ResetClusterDemolition (scr);
// Reset sound
ResetSound(scr.sound);
// Remove particles
DestroyRigidParticles (scr);
// Enable Rigid because of cluster fade and reset
if (scr.enabled == false)
scr.enabled = true;
// Activate if deactivated
if (scr.gameObject.activeSelf == false)
scr.gameObject.SetActive (true);
// Start all coroutines
scr.StartAllCoroutines();
// Restart restrictions cors
if (scr.rest != null)
scr.rest.InitRestriction (scr);
}
// Reset if object fading/faded
public static void ResetFade (RayfireRigid scr)
{
// Was excluded
if (scr.fading.fadeType == FadeType.SimExclude)
{
// Null check because of Planar check fragments without collider
if (scr.physics.mc != null)
scr.physics.mc.enabled = true;// TODO CHECK CLUSTER COLLIDERS
}
// Was fall down
else if (scr.fading.fadeType == FadeType.FallDown)
{
// Null check because of Planar check fragments without collider
if (scr.physics.mc != null)
scr.physics.mc.enabled = true;// TODO CHECK CLUSTER COLLIDERS
scr.gameObject.SetActive (true);
}
// Was scaled down
else if (scr.fading.fadeType == FadeType.ScaleDown)
{
scr.tsf.localScale = scr.physics.initScale;
scr.gameObject.SetActive (true);
}
// Was moved down
if (scr.fading.fadeType == FadeType.MoveDown)
{
// Null check because of Planar check fragments without collider
if (scr.physics.mc != null)
scr.physics.mc.enabled = true; // TODO CHECK CLUSTER COLLIDERS
// Reset gravity
if (scr.simTp != SimType.Inactive)
scr.physics.rb.useGravity = scr.physics.gr;
scr.gameObject.SetActive (true);
}
// Was destroyed
else if (scr.fading.fadeType == FadeType.Destroy)
scr.gameObject.SetActive (true);
// Was set static
if (scr.fading.fadeType == FadeType.SetStatic)
scr.gameObject.SetActive (true);
// Was set static
if (scr.fading.fadeType == FadeType.SetKinematic)
scr.gameObject.SetActive (true);
}
/// /////////////////////////////////////////////////////////
/// Rigid Mesh Root
/// /////////////////////////////////////////////////////////
// Mesh Root
static bool MeshRootReset (RayfireRigid scr)
{
// Not mesh root
if (scr.objTp != ObjectType.MeshRoot)
return false;
// Cleanup destroyed/faded fragments
if (MeshRootCleanup (scr) == false)
return true;
// Destroy particles
DestroyMeshRootParticles (scr);
// Reset tm
scr.physics.LoadInitTransform (scr.transform);
// Reset fragments first
foreach (var fragment in scr.fragments)
{
// Add rigid body to Rigid if it was deleted because of clustering
if (fragment.physics.rb == null)
fragment.physics.rb = fragment.gameObject.AddComponent<Rigidbody>();
// Set object type back in case of clustering->demolition
fragment.simTp = scr.simTp;
// Set parent in case of clustering->demolition
fragment.tsf.parent = scr.tsf;
// Reset rigid
ResetRigid (fragment);
// Set density. After collider defined TODO save mass at first apply, reuse now
RFPhysic.SetDensity (fragment);
// Set drag properties
RFPhysic.SetDrag (fragment);
// Destroy parent connected cluster if rigid was clustered
if (fragment.rtP != null)
Object.Destroy (fragment.rtP.gameObject);
// TODO Test fragments reuse with transform state copied to fragments
}
// Reset uny data
RayfireUnyielding.SetMeshRootUnyState (scr.transform, null);
// Restore connectivity cluster
RFBackupCluster.RestoreConnectivity (scr.activation.cnt);
return true;
}
// Cleanup and check for mesh root fragments
static bool MeshRootCleanup (RayfireRigid scr)
{
// Cleanup destroyed/faded fragments
for (int i = scr.fragments.Count - 1; i >= 0; i--)
if (scr.fragments[i] == null)
{
Debug.Log (scr.name + ": Mesh Root Fragment destroyed", scr.gameObject);
scr.fragments.RemoveAt (i);
}
// Check after cleanup
if (scr.HasFragments == false)
return false;
return true;
}
// Destroy particles
static void DestroyMeshRootParticles (RayfireRigid scr)
{
if (scr.particleList.Count > 0)
{
for (int i = scr.particleList.Count - 1; i >= 0; i--)
if (scr.particleList[i] != null)
RayfireMan.DestroyGo (scr.particleList[i].gameObject);
scr.particleList.Clear();
}
}
/// /////////////////////////////////////////////////////////
/// Reset Rigid Root
/// /////////////////////////////////////////////////////////
// Reinit demolished mesh object
public static void RigidRootReset (RayfireRigidRoot scr)
{
// Stop all cors in case object restarted
scr.StopAllCoroutines();
scr.corState = false;
scr.activation.inactiveCorState = false;
scr.fading.offsetCorState = false;
if (scr.activation.cnt != null)
{
scr.activation.cnt.StopAllCoroutines();
RFCollapse.StopCollapse (scr.activation.cnt);
RFStress.StopStress (scr.activation.cnt);
}
// Reset activation
scr.activation.LocalReset();
// TODO CHECK FOR RESET STATES
// TODO CLEANUP
// Destroy particle roots
DestroyRigidRootParticles (scr);
// Reset tm
scr.transform.position = scr.cluster.pos;
scr.transform.rotation = scr.cluster.rot;
scr.transform.localScale = scr.cluster.scl;
// Set object type back in case of clustering->demolition
ResetSimType (scr);
// ReSet parents for all shards
ResetParentAndTm (scr);
// Reset shards
for (int i = 0; i < scr.cluster.shards.Count; i++)
{
// Shard faded
if (scr.cluster.shards[i].fade != 0)
{
// Enable collider
if (scr.cluster.shards[i].col.enabled == false)
scr.cluster.shards[i].col.enabled = true;
// Reset fading
scr.cluster.shards[i].fade = 0;
}
// TODO Destroy parent connected cluster if rigid was clustered
// Activate
if (scr.cluster.shards[i].tm.gameObject.activeSelf == false)
scr.cluster.shards[i].tm.gameObject.SetActive (true);
}
// ReSet layer for activated shards
RFActivation.RestoreActivationLayer (scr);
// Set physics properties for shards
RFPhysic.SetPhysics(scr.cluster.shards, scr.physics);
/* TODO check if should be here
// Reset shards with Rigid
for (int i = 0; i < scr.cluster.shards.Count; i++)
if (scr.cluster.shards[i].rigid != null)
scr.cluster.shards[i].rigid.ResetRigid();
*/
// Setup list for activation shards
scr.SetInactiveList ();
// Setup list with fade by offset shards
RFFade.SetOffsetFadeList (scr);
// Destroy child clusters if they were created
DestroyClusters (scr);
// Restore connectivity cluster
RFBackupCluster.RestoreConnectivity (scr.activation.cnt);
// Reset sound
ResetSound(scr.sound);
// Start coroutines
scr.StartAllCoroutines();
}
// ReSet parents and transform for all shards
static void ResetParentAndTm(RayfireRigidRoot scr)
{
// TODO null checks
for (int i = 0; i < scr.cluster.shards.Count; i++)
{
scr.cluster.shards[i].tm.SetParent (null);
scr.cluster.shards[i].tm.SetPositionAndRotation (scr.cluster.shards[i].pos, scr.cluster.shards[i].rot);
scr.cluster.shards[i].tm.SetParent (scr.parentList[i], true);
scr.cluster.shards[i].tm.localScale = scr.cluster.shards[i].scl;
}
}
// Set object type back in case of clustering->demolition
static void ResetSimType(RayfireRigidRoot scr)
{
// Reset by RigidRoot and Rigid components
for (int i = 0; i < scr.cluster.shards.Count; i++)
{
if (scr.cluster.shards[i].rigid == null)
scr.cluster.shards[i].sm = scr.simTp;
else
{
if (scr.cluster.shards[i].rigid.objTp == ObjectType.MeshRoot)
scr.cluster.shards[i].sm = scr.cluster.shards[i].rigid.simTp;
else if (scr.cluster.shards[i].rigid.objTp == ObjectType.Mesh)
scr.cluster.shards[i].rigid.ResetRigid();
}
// Reset velocity
if (scr.cluster.shards[i].rb != null)
{
scr.cluster.shards[i].rb.velocity = Vector3.zero;
scr.cluster.shards[i].rb.angularVelocity = Vector3.zero;
}
}
// Reset uny states and sim state
for (int i = 0; i < scr.unyList.Length; i++)
scr.unyList[i].SetRigidRootUnyShardList();
}
// Destroy particles
static void DestroyRigidRootParticles (RayfireRigidRoot scr)
{
if (scr.particleList.Count > 0)
{
for (int i = scr.particleList.Count - 1; i >= 0; i--)
if (scr.particleList[i] != null)
RayfireMan.DestroyGo (scr.particleList[i].gameObject);
scr.particleList.Clear();
}
}
// Destroy clusters
static void DestroyClusters (RayfireRigidRoot scr)
{
for (int i = 0; i < scr.clusters.Count; i++)
if (scr.clusters[i].tm != null)
RayfireMan.DestroyGo (scr.clusters[i].tm.gameObject);
scr.clusters.Clear();
}
/// /////////////////////////////////////////////////////////
/// Demolition reset
/// /////////////////////////////////////////////////////////
// Reinit demolished mesh object
public static void ResetMeshDemolition (RayfireRigid scr)
{
// Edit meshes and fragments only if object was demolished
if (scr.objTp == ObjectType.Mesh)
{
// Reset input shatter
if (scr.reset.mesh != MeshResetType.ReuseInputMesh)
scr.mshDemol.rfShatter = null;
// Reset Meshes
if (scr.reset.mesh != MeshResetType.ReuseFragmentMeshes)
scr.meshes = null;
// Fragments need to be reused
if (scr.reset.fragments == FragmentsResetType.Reuse)
{
// Can be reused. Destroyed if can not
if (FragmentReuseState (scr) == true)
ReuseFragments (scr);
else
DestroyFragments (scr);
}
// Destroy fragments
else if (scr.reset.fragments == FragmentsResetType.Destroy)
DestroyFragments (scr);
// Fragments should be kept in scene. Forget about them
else if (scr.reset.fragments == FragmentsResetType.Preserve)
PreserveFragments (scr);
}
// Activate
scr.gameObject.SetActive (true);
}
// Destroy fragments and root // TODO send to pool
static void DestroyFragments (RayfireRigid scr)
{
// Destroy fragments
if (scr.HasFragments == true)
{
// Get amount of fragments
int fragmentNum = scr.fragments.Count (t => t != null);
// Destroy fragments and root
for (int i = scr.fragments.Count - 1; i >= 0; i--)
{
if (scr.fragments[i] != null)
{
// Destroy particles
DestroyRigidParticles (scr.fragments[i]);
// Destroy fragment
scr.fragments[i].gameObject.SetActive (false);
RayfireMan.DestroyGo (scr.fragments[i].gameObject);
// Destroy root
if (scr.fragments[i].rtP != null)
{
scr.fragments[i].rtP.gameObject.SetActive (false);
RayfireMan.DestroyGo (scr.fragments[i].rtP.gameObject);
}
}
}
// Nullify
scr.fragments = null;
// Subtract amount of deleted fragments
RayfireMan.inst.advancedDemolitionProperties.ChangeCurrentAmount (-fragmentNum);
// Destroy descendants
if (scr.limitations.desc != null && scr.limitations.desc.Count > 0)
{
// Get amount of descendants
int descendantNum = scr.limitations.desc.Count (t => t != null);
// Destroy fragments and root
for (int i = 0; i < scr.limitations.desc.Count; i++)
{
if (scr.limitations.desc[i] != null)
{
// Destroy fragment
scr.limitations.desc[i].gameObject.SetActive (false);
RayfireMan.DestroyGo (scr.limitations.desc[i].gameObject);
// Destroy root
if (scr.limitations.desc[i].rtP != null)
{
scr.limitations.desc[i].rtP.gameObject.SetActive (false);
RayfireMan.DestroyGo (scr.limitations.desc[i].rtP.gameObject);
}
}
}
// Clear
scr.limitations.desc.Clear();
// Subtract amount of deleted fragments
RayfireMan.inst.advancedDemolitionProperties.ChangeCurrentAmount (-descendantNum);
}
}
}
// Destroy particles // TODO send to pool
static void DestroyRigidParticles (RayfireRigid scr)
{
// Destroy debris
if (scr.HasDebris == true)
for (int d = 0; d < scr.debrisList.Count; d++)
if (scr.debrisList[d].hostTm != null)
{
scr.debrisList[d].hostTm.gameObject.SetActive (false);
RayfireMan.DestroyGo (scr.debrisList[d].hostTm.gameObject);
}
// Destroy debris
if (scr.HasDust == true)
for (int d = 0; d < scr.dustList.Count; d++)
if (scr.dustList[d].hostTm != null)
{
scr.dustList[d].hostTm.gameObject.SetActive (false);
RayfireMan.DestroyGo (scr.dustList[d].hostTm.gameObject);
}
}
// Fragments need and can be reused
static void ReuseFragments (RayfireRigid scr)
{
// Sub amount
RayfireMan.inst.advancedDemolitionProperties.ChangeCurrentAmount (-scr.fragments.Count);
// Activate root
if (scr.rtC != null)
{
scr.rtC.gameObject.SetActive (false);
scr.rtC.position = scr.tsf.position;
scr.rtC.rotation = scr.tsf.rotation;
}
// Reset fragments tm
for (int i = scr.fragments.Count - 1; i >= 0; i--)
{
// Destroy particles
DestroyRigidParticles (scr.fragments[i]);
scr.fragments[i].tsf.localScale = scr.fragments[i].physics.initScale;
scr.fragments[i].tsf.position = scr.tsf.position + scr.pivots[i];
scr.fragments[i].tsf.rotation = Quaternion.identity;
// Reset activation TODO check if it was Kinematic
if (scr.fragments[i].activation.activated == true)
scr.fragments[i].simTp = SimType.Inactive;
// Reset fading
if (scr.fragments[i].fading.state >= 1)
ResetFade(scr.fragments[i]);
// Reset rigid props
Reset (scr.fragments[i]);
}
// Clear descendants
scr.limitations.desc.Clear();
}
// Preserve Fragments
static void PreserveFragments (RayfireRigid scr)
{
scr.fragments = null;
scr.rtC = null;
scr.limitations.desc.Clear();
}
// Reinit demolished mesh object
static void ResetClusterDemolition (RayfireRigid scr)
{
if (scr.objTp == ObjectType.ConnectedCluster || scr.objTp == ObjectType.NestedCluster)
{
RFBackupCluster.ResetRigidCluster (scr);
}
}
/// /////////////////////////////////////////////////////////
/// Reuse state
/// /////////////////////////////////////////////////////////
// Check fragments reuse state
static bool ObjectReuseState (RayfireRigid scr)
{
// Mesh Root reset
if (scr.objTp == ObjectType.MeshRoot)
return true;
// Excluded from sim
if (scr.physics.exclude == true)
{
Debug.Log ("Demolished " + scr.objTp.ToString() + " reset not supported yet.");
return false;
}
// Not mesh object type
if (scr.objTp == ObjectType.Mesh
|| scr.objTp == ObjectType.ConnectedCluster
|| scr.objTp == ObjectType.NestedCluster)
return true;
// Object can be reused
return false;
}
// Check fragments reuse state
static bool FragmentReuseState (RayfireRigid scr)
{
// Do not reuse reference demolition
if (scr.dmlTp == DemolitionType.ReferenceDemolition)
return false;
// Fragments list null or empty
if (scr.HasFragments == false)
return false;
// One of the fragment null
if (scr.fragments.Any (t => t == null))
return false;
// One of the fragment going to be destroyed TODO make reusable
if (scr.fragments.Any (t => t.reset.toBeDestroyed == true))
return false;
// One of the fragment demolished TODO make reusable
if (scr.fragments.Any (t => t.limitations.demolished == true))
return false;
// Fragments can be reused
return true;
}
/// /////////////////////////////////////////////////////////
/// Other
/// /////////////////////////////////////////////////////////
// Restore transform or initial
static void RestoreTransform (RayfireRigid scr)
{
// Restore tm
scr.physics.LoadInitTransform (scr.tsf);
scr.physics.velocity = Vector3.zero;
// Restore rigidbody TODO save initial velocity into vars and reset to them
if (scr.physics.rb != null)
{
scr.physics.rb.velocity = Vector3.zero;
scr.physics.rb.angularVelocity = Vector3.zero;
}
}
// Restore rigid properties
static void Reset (RayfireRigid scr)
{
// Reset caching if it is on
scr.mshDemol.ch.StopRuntimeCaching();
scr.physics.LocalReset();
scr.activation.LocalReset();
if (scr.rest != null)
scr.rest.Reset();
scr.limitations.LocalReset();
scr.mshDemol.LocalReset();
scr.clsDemol.LocalReset();
scr.fading.LocalReset();
if (scr.reset.damage == true)
scr.damage.LocalReset();
// Set physical simulation type. Important. Should after collider material define
RFPhysic.SetSimulationType (scr.physics.rb, scr.simTp, scr.objTp, scr.physics.gr, scr.physics.si, scr.physics.st);
// Set sleeping state TODO
if (scr.simTp == SimType.Sleeping)
{
scr.physics.velocity = Vector3.zero;
scr.physics.rb.velocity = Vector3.zero;
scr.physics.rb.angularVelocity = Vector3.zero;
scr.physics.rb.Sleep();
}
}
// Reset sound
static void ResetSound (RayfireSound scr)
{
if (scr != null)
{
scr.initialization.played = false;
scr.activation.played = false;
scr.demolition.played = false;
}
}
}
}