You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
17 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace RayFire
{
[Serializable]
public class RFLimitations
{
public bool byCollision;
public float solidity;
public string tag;
public int depth;
public float time;
public float size;
public bool visible;
public bool sliceByBlade;
// Non serialized
[NonSerialized] public List<Vector3> slicePlanes;
[NonSerialized] public ContactPoint contactPoint;
[NonSerialized] public Vector3 contactVector3;
[NonSerialized] public Vector3 contactNormal;
[NonSerialized] public bool demolitionShould;
[NonSerialized] public bool demolished;
[NonSerialized] public float birthTime;
[NonSerialized] public float bboxSize;
[NonSerialized] public int currentDepth;
[NonSerialized] public bool demolishableCorState;
// Blade props
[NonSerialized] public float sliceForce;
[NonSerialized] public bool affectInactive;
// Family data. Do not nullify in Reset
[NonSerialized] public RayfireRigid ancestor;
[NonSerialized] public List<RayfireRigid> descendants;
// Hidden
[HideInInspector] public Bounds bound;
static string rootStr = "_root";
public static string rigidStr = "RayFire Rigid: ";
/// /////////////////////////////////////////////////////////
/// Constructor
/// /////////////////////////////////////////////////////////
// Constructor
public RFLimitations()
{
byCollision = true;
solidity = 0.1f;
depth = 1;
time = 0.2f;
size = 0.1f;
tag = "Untagged";
visible = false;
sliceByBlade = false;
sliceForce = 0;
currentDepth = 0;
birthTime = 0f;
bboxSize = 0f;
ancestor = null;
descendants = null;
Reset();
}
// Copy from
public void CopyFrom (RFLimitations limitations)
{
byCollision = limitations.byCollision;
solidity = limitations.solidity;
depth = limitations.depth;
time = limitations.time;
size = limitations.size;
tag = limitations.tag;
visible = limitations.visible;
sliceByBlade = limitations.sliceByBlade;
// Do not copy currentDepth. Set in other place
Reset();
}
// Reset
public void Reset()
{
slicePlanes = new List<Vector3>();
contactVector3 = Vector3.zero;
contactNormal = Vector3.down;
demolitionShould = false;
demolished = false;
demolishableCorState = false;
currentDepth = 0;
birthTime = 0f;
sliceForce = 0;
}
/// /////////////////////////////////////////////////////////
/// Static
/// /////////////////////////////////////////////////////////
// Cache velocity for fragments
public IEnumerator DemolishableCor(RayfireRigid scr)
{
// Stop if running
if (demolishableCorState == true)
yield break;
// Set running state
demolishableCorState = true;
while (scr.demolitionType != DemolitionType.None)
{
// Max depth reached
if (scr.limitations.depth > 0 && scr.limitations.currentDepth >= scr.limitations.depth)
scr.demolitionType = DemolitionType.None;
// Init demolition
if (scr.limitations.demolitionShould == true)
{
scr.Demolish();
}
// Check for slicing planes and init slicing
else if (scr.limitations.sliceByBlade == true && scr.limitations.slicePlanes.Count > 1)
scr.Slice();
yield return null;
}
// Set state
demolishableCorState = false;
}
/// /////////////////////////////////////////////////////////
/// Static
/// /////////////////////////////////////////////////////////
// Check for user mistakes
public static void Checks (RayfireRigid scr)
{
// TODO planar mesh -> set none collider
// TODO static and cluster
if (scr.objectType == ObjectType.Mesh)
{
}
// ////////////////
// Sim Type
// ////////////////
// Static and demolishable
if (scr.simulationType == SimType.Static)
{
if (scr.demolitionType != DemolitionType.None)
{
Debug.Log (rigidStr + scr.name + " Simulation Type set to " + scr.simulationType.ToString() + " but Demolition Type is not None. Static object can not be demolished. Demolition Type set to None.", scr.gameObject);
scr.demolitionType = DemolitionType.None;
}
}
// Non static simulation but static property
if (scr.simulationType != SimType.Static)
{
if (scr.gameObject.isStatic == true)
{
Debug.Log (rigidStr + scr.name + " Simulation Type set to " + scr.simulationType.ToString() + " but object is Static. Turn off Static checkbox in Inspector.", scr.gameObject);
}
}
// ////////////////
// Object Type
// ////////////////
// Object can not be simulated as mesh
if (scr.objectType == ObjectType.Mesh)
{
// Has no mesh
if (scr.meshFilter == null || scr.meshFilter.sharedMesh == null)
{
Debug.Log (rigidStr + scr.name + " Object Type set to " + scr.objectType.ToString() + " but object has no mesh. Object Excluded from simulation.", scr.gameObject);
scr.physics.exclude = true;
}
// Not readable mesh
if (scr.demolitionType != DemolitionType.None && scr.demolitionType != DemolitionType.ReferenceDemolition)
{
if (scr.meshFilter != null && scr.meshFilter.sharedMesh != null && scr.meshFilter.sharedMesh.isReadable == false)
{
Debug.Log (rigidStr + scr.name + " Mesh is not readable. Demolition type set to None. Open Import Settings and turn On Read/Write Enabled property", scr.meshFilter.gameObject);
scr.demolitionType = DemolitionType.None;
scr.meshDemolition.badMesh = 10;
}
}
}
// Object can not be simulated as cluster
else if (scr.objectType == ObjectType.NestedCluster || scr.objectType == ObjectType.ConnectedCluster)
{
if (scr.transForm.childCount == 0)
{
Debug.Log (rigidStr + scr.name + " Object Type set to " + scr.objectType.ToString() + " but object has no children. Object Excluded from simulation.", scr.gameObject);
scr.physics.exclude = true;
}
}
// Object can not be simulated as mesh
else if (scr.objectType == ObjectType.SkinnedMesh)
{
if (scr.skinnedMeshRend == null)
Debug.Log (rigidStr + scr.name + " Object Type set to " + scr.objectType.ToString() + " but object has no SkinnedMeshRenderer. Object Excluded from simulation.", scr.gameObject);
// Excluded from sim by default
scr.physics.exclude = true;
}
// ////////////////
// Demolition Type
// ////////////////
// Demolition checks
if (scr.demolitionType != DemolitionType.None)
{
// // Static
// if (scr.simulationType == SimType.Static)
// {
// Debug.Log (rigidStr + scr.name + " Simulation Type set to " + scr.simulationType.ToString() + " but Demolition Type is " + scr.demolitionType.ToString() + ". Demolition Type set to None.", scr.gameObject);
// scr.demolitionType = DemolitionType.None;
// }
// Set runtime demolition for clusters and skinned mesh
if (scr.objectType == ObjectType.SkinnedMesh ||
scr.objectType == ObjectType.NestedCluster ||
scr.objectType == ObjectType.ConnectedCluster)
{
if (scr.demolitionType != DemolitionType.Runtime && scr.demolitionType != DemolitionType.ReferenceDemolition)
{
Debug.Log (rigidStr + scr.name + " Object Type set to " + scr.objectType.ToString() + " but Demolition Type is " + scr.demolitionType.ToString() + ". Demolition Type set to Runtime.", scr.gameObject);
scr.demolitionType = DemolitionType.Runtime;
}
}
// No Shatter component for runtime demolition with Use Shatter on
if (scr.meshDemolition.scrShatter == null && scr.meshDemolition.useShatter == true)
{
if (scr.demolitionType == DemolitionType.Runtime ||
scr.demolitionType == DemolitionType.AwakePrecache ||
scr.demolitionType == DemolitionType.AwakePrefragment)
{
Debug.Log (rigidStr + scr.name + "Demolition Type is " + scr.demolitionType.ToString() + ". Has no Shatter component, but Use Shatter property is On. Use Shatter property was turned Off.", scr.gameObject);
scr.meshDemolition.useShatter = false;
}
}
}
// None check
if (scr.demolitionType == DemolitionType.None)
{
if (scr.HasMeshes == true)
{
Debug.Log (rigidStr + scr.name + " Demolition Type set to None. Had precached meshes which were destroyed.", scr.gameObject);
scr.DeleteCache();
}
if (scr.objectType == ObjectType.Mesh && scr.HasFragments == true)
{
Debug.Log (rigidStr + scr.name + " Demolition Type set to None. Had prefragmented objects which were destroyed.", scr.gameObject);
scr.DeleteFragments();
}
if (scr.HasRfMeshes == true)
{
Debug.Log (rigidStr + scr.name + " Demolition Type set to None. Had precached serialized meshes which were destroyed.", scr.gameObject);
scr.DeleteCache();
}
}
// Runtime check
else if (scr.demolitionType == DemolitionType.Runtime)
{
if (scr.HasMeshes == true)
{
Debug.Log (rigidStr + scr.name + " Demolition Type set to Runtime. Had precached meshes which were destroyed.", scr.gameObject);
scr.DeleteCache();
}
if (scr.objectType == ObjectType.Mesh && scr.HasFragments == true)
{
Debug.Log (rigidStr + scr.name + " Demolition Type set to Runtime. Had prefragmented objects which were destroyed.", scr.gameObject);
scr.DeleteFragments();
}
if (scr.HasRfMeshes == true)
{
Debug.Log ("RayFire Rigid:" + scr.name + " Demolition Type set to Runtime. Had precached serialized meshes which were destroyed.", scr.gameObject);
scr.DeleteCache();
}
// No runtime caching for rigid with shatter with tets/slices/glue
if (scr.meshDemolition.useShatter == true && scr.meshDemolition.runtimeCaching.type != CachingType.Disable)
{
if (scr.meshDemolition.scrShatter.type == FragType.Decompose ||
scr.meshDemolition.scrShatter.type == FragType.Tets ||
scr.meshDemolition.scrShatter.type == FragType.Slices ||
scr.meshDemolition.scrShatter.clusters.enable == true)
{
Debug.Log (rigidStr + scr.name + " Demolition Type is Runtime, Use Shatter is On. Unsupported fragments type. Runtime Caching supports only Voronoi, Splinters, Slabs and Radial fragmentation types. Runtime Caching was Disabled.", scr.gameObject);
scr.meshDemolition.runtimeCaching.type = CachingType.Disable;
}
}
}
// Awake precache check
else if (scr.demolitionType == DemolitionType.AwakePrecache)
{
if (scr.HasMeshes == true)
Debug.Log (rigidStr + scr.name + " Demolition Type set to Awake Precache. Had manually precached Unity meshes which were overwritten.", scr.gameObject);
if (scr.HasFragments == true)
{
Debug.Log (rigidStr + scr.name + " Demolition Type set to Awake Precache. Had manually prefragmented objects which were destroyed.", scr.gameObject);
scr.DeleteFragments();
}
if (scr.HasRfMeshes == true)
{
Debug.Log ("RayFire Rigid:" + scr.name + " Demolition Type set to Awake Precache. Has manually precached serialized meshes.", scr.gameObject);
}
}
// Awake prefragmented check
else if (scr.demolitionType == DemolitionType.AwakePrefragment)
{
if (scr.HasFragments == true)
Debug.Log (rigidStr + scr.name + " Demolition Type set to Awake Prefragment. Has manually prefragmented objects", scr.gameObject);
if (scr.HasMeshes == true)
Debug.Log (rigidStr + scr.name + " Demolition Type set to Awake Prefragment. Has manually precached Unity meshes.", scr.gameObject);
if (scr.HasRfMeshes == true)
Debug.Log (rigidStr + scr.name + " Demolition Type set to Awake Prefragment. Has manually precached serialized meshes.", scr.gameObject);
}
// Reference demolition
else if (scr.demolitionType == DemolitionType.ReferenceDemolition) {}
// TODO Tag and Layer check
}
// Set bound and size
public static void SetBound (RayfireRigid scr)
{
if (scr.objectType == ObjectType.Mesh)
scr.limitations.bound = scr.meshRenderer.bounds;
else if (scr.objectType == ObjectType.SkinnedMesh)
scr.limitations.bound = scr.skinnedMeshRend.bounds;
else if (scr.objectType == ObjectType.NestedCluster || scr.objectType == ObjectType.ConnectedCluster)
scr.limitations.bound = RFCluster.GetChildrenBound (scr.transForm);
scr.limitations.bboxSize = scr.limitations.bound.size.magnitude;
}
// Set ancestor
public static void SetAncestor (RayfireRigid scr)
{
// Set ancestor to this if it is ancestor
if (scr.limitations.ancestor == null)
for (int i = 0; i < scr.fragments.Count; i++)
scr.fragments[i].limitations.ancestor = scr;
else
for (int i = 0; i < scr.fragments.Count; i++)
scr.fragments[i].limitations.ancestor = scr.limitations.ancestor;
}
// Set descendants
public static void SetDescendants (RayfireRigid scr)
{
if (scr.reset.action == RFReset.PostDemolitionType.DestroyWithDelay)
return;
if (scr.limitations.ancestor == null)
scr.limitations.descendants.AddRange (scr.fragments);
else
scr.limitations.ancestor.limitations.descendants.AddRange (scr.fragments);
}
// Create root
public static void CreateRoot (RayfireRigid rfScr)
{
GameObject root = new GameObject(rfScr.gameObject.name + rootStr);
rfScr.rootChild = root.transform;
rfScr.rootChild.position = rfScr.transForm.position;
rfScr.rootChild.rotation = rfScr.transForm.rotation;
rfScr.rootChild.SetParent (rfScr.gameObject.transform.parent);
}
}
}