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 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 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(); 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); } } }