public void OnDetach(object o)
        {
            FracturedChunk chunk = o as FracturedChunk;
            var            destructibleObject = MapObjectUtility.GetMapObjectOfFracturedChunk(chunk);

            if (destructibleObject == null)
            {
                var evt = ChunkSyncEvent.Allocate();
                evt.EType   = TriggerObjectSyncEventType.DetachChunk;
                evt.ChunkId = chunk.ChunkId;
                MapObjectUtility.StoreTriggerObjectEvent(chunk.FracturedObjectSource.gameObject, evt);
            }
            if (destructibleObject != null)
            {
                var data    = destructibleObject.destructibleData;
                var chunkId = chunk.ChunkId;
                if (data.IsInDestructionState(chunkId))
                {
                    return;
                }

                data.SetDestruction(chunk.ChunkId);

                //synchronization delay for vehicle-collidable destructible object
                if (chunk.FracturedObjectSource.EnableVehicleCollision)
                {
                    data.SyncDelay = SYNC_DELAY_TIME;
                }

                //notify server to destory destructible object
                SendDetachChunkEventToServer(destructibleObject, chunk.ChunkId);
            }
        }
Esempio n. 2
0
 public CollisionInfo(FracturedChunk chunk, Collision collisionInfo, bool bIsMain)
 {
     this.chunk            = chunk;
     this.collisionInfo    = collisionInfo;
     this.bIsMain          = bIsMain;
     bCancelCollisionEvent = false;
 }
Esempio n. 3
0
 public CollisionInfo(FracturedChunk chunk, Vector3 collisionPoint, bool bIsMain)
 {
     this.chunk            = chunk;
     this.collisionPoint   = collisionPoint;
     this.bIsMain          = bIsMain;
     bCancelCollisionEvent = false;
 }
Esempio n. 4
0
    public void DisconnectFrom(FracturedChunk chunk)
    {
        if (chunk)
        {
            if (chunk.IsConnectedTo(this))
            {
                for (int i = 0; i < ListAdjacentChunks.Count; i++)
                {
                    if (ListAdjacentChunks[i].chunk == chunk)
                    {
                        ListAdjacentChunks.RemoveAt(i);
                        break;
                    }
                }

                for (int i = 0; i < chunk.ListAdjacentChunks.Count; i++)
                {
                    if (chunk.ListAdjacentChunks[i].chunk == this)
                    {
                        chunk.ListAdjacentChunks.RemoveAt(i);
                        break;
                    }
                }
            }
        }
    }
    public void NotifyChunkDetach(FracturedChunk chunk)
    {
        if (m_bDetached == false)
        {
            // Disable all triggerse in them so that free chunks will collide also with static non-free chunks

            foreach (FracturedChunk chunkInstance in ListFracturedChunks)
            {
                if (chunkInstance != null)
                {
                    Collider colliderComponent = chunkInstance.GetComponent <Collider>();

                    if (colliderComponent != null)
                    {
                        colliderComponent.isTrigger = false;
                    }
                }
            }
        }

        m_bDetached = true;
        SetSingleMeshVisibility(false);

        if (EventDetachedAnyCallMethod.Length > 0 && EventDetachedAnyCallGameObject != null)
        {
            EventDetachedAnyCallGameObject.SendMessage(EventDetachedAnyCallMethod);
        }
    }
Esempio n. 6
0
 public CollisionInfo(FracturedChunk chunk, Collision collisionInfo, bool bIsMain)
 {
     this.chunk            = chunk;
     this.collisionInfo    = collisionInfo;
     this.bIsMain          = bIsMain;
     bCancelCollisionEvent = false;
 }
Esempio n. 7
0
    private static void ComputeRandomConnectionBreaksRecursive(FracturedChunk chunk, List <FracturedChunk> listBreaksOut, int nLevel)
    {
        if (chunk.Visited == true)
        {
            return;
        }

        chunk.Visited = true;

        foreach (FracturedChunk.AdjacencyInfo adjacency in chunk.ListAdjacentChunks)
        {
            if (adjacency.chunk)
            {
                if (chunk.FracturedObjectSource != null && adjacency.chunk.Visited == false && adjacency.chunk.IsDestructibleChunk())
                {
                    bool bConnected = adjacency.fArea > chunk.FracturedObjectSource.ChunkConnectionMinArea;

                    if (bConnected)
                    {
                        float fRandom = UnityEngine.Random.value;

                        if (fRandom > (chunk.FracturedObjectSource.ChunkConnectionStrength * nLevel))
                        {
                            ComputeRandomConnectionBreaksRecursive(adjacency.chunk, listBreaksOut, nLevel + 1);
                            listBreaksOut.Add(adjacency.chunk);
                        }
                    }
                }
            }
        }
    }
    void OnFreeChunkCollision(FracturedChunk.CollisionInfo info)
    {
        // We can cancel the collision processing here
        info.bCancelCollisionEvent = false;

        // Simply increase a counter for each collision
        nChunkCollisions++;
    } 
    void OnChunkDetach(FracturedChunk.CollisionInfo info)
    {
        // We can cancel the collision processing here
        info.bCancelCollisionEvent = false;

        // Simply increase a counter for each chunk detached
        nChunksDetached++;
    } 
Esempio n. 10
0
    public void NotifyChunkDetach(FracturedChunk chunk)
    {
        m_bDetached = true;
        SetSingleMeshVisibility(false);

        if (EventDetachedAnyCallMethod.Length > 0 && EventDetachedAnyCallGameObject != null)
        {
            EventDetachedAnyCallGameObject.SendMessage(EventDetachedAnyCallMethod);
        }
    }
        public void OnDetach(object o)
        {
            FracturedChunk chunk = o as FracturedChunk;
            var            destructibleObject = MapObjectUtility.GetMapObjectOfFracturedChunk(chunk);

            if (destructibleObject != null)
            {
                var data = destructibleObject.destructibleData;
                data.SetDestruction(chunk.ChunkId);
                data.LastSyncDestructionState = data.DestructionState;
                destructibleObject.flagImmutability.LastModifyServerTime = _currentTime.CurrentTime;
            }
        }
Esempio n. 12
0
    public void ConnectTo(FracturedChunk chunk, float fArea)
    {
        if (chunk)
        {
            if (chunk.IsConnectedTo(this))
            {
                return;
            }

            ListAdjacentChunks.Add(new AdjacencyInfo(chunk, fArea));
            chunk.ListAdjacentChunks.Add(new AdjacencyInfo(this, fArea));
        }
    }
Esempio n. 13
0
    public void ConnectTo(FracturedChunk chunk, float fArea)
    {
        if(chunk)
        {
            if(chunk.IsConnectedTo(this))
            {
                return;
            }

            ListAdjacentChunks.Add(new AdjacencyInfo(chunk, fArea));
            chunk.ListAdjacentChunks.Add(new AdjacencyInfo(this, fArea));
        }
    }
Esempio n. 14
0
        public override IEnumerator Behavior()
        {
            Collider[] cols = Physics.OverlapSphere(transform.position, radious);
            foreach (Collider col in cols)
            {
                FracturedChunk chunk = col.GetComponent <FracturedChunk>();
                if (chunk == null)
                {
                    continue;
                }
                chunk.Impact(transform.position, force, radious, true);
                chunk.FracturedObjectSource.SetSingleMeshVisibility(false);
            }

            yield break;
        }
Esempio n. 15
0
    public bool IsConnectedTo(FracturedChunk chunk)
    {
        foreach (AdjacencyInfo info in ListAdjacentChunks)
        {
            bool bHasMinArea = true;

            if (info.chunk.FracturedObjectSource)
            {
                bHasMinArea = info.fArea > info.chunk.FracturedObjectSource.ChunkConnectionMinArea;
            }

            if (info.chunk == chunk)
            {
                return(bHasMinArea);
            }
        }

        return(false);
    }
    public void OnSceneGUI()
    {
        FracturedChunk fracturedChunk = target as FracturedChunk;

        if (fracturedChunk == null)
        {
            return;
        }

        FracturedObject fracturedObject = fracturedChunk.FracturedObjectSource;

        // Chunk connections

        bool bDrawLines = true;

        if (fracturedObject != null)
        {
            bDrawLines = fracturedObject.ShowChunkConnectionLines;
        }

        if (bDrawLines)
        {
            Color handlesColor = Handles.color;
            Handles.color = new Color32(155, 89, 182, 255);

            if (fracturedChunk.ListAdjacentChunks.Count > 0)
            {
                Handles.DotHandleCap(0, fracturedChunk.transform.position, Quaternion.identity, HandleUtility.GetHandleSize(fracturedChunk.transform.position) * 0.03f, Event.current.type);
            }

            foreach (FracturedChunk.AdjacencyInfo chunkAdjacency in fracturedChunk.ListAdjacentChunks)
            {
                if (chunkAdjacency.chunk)
                {
                    Handles.DotHandleCap(0, chunkAdjacency.chunk.transform.position, Quaternion.identity, HandleUtility.GetHandleSize(chunkAdjacency.chunk.transform.position) * 0.03f, Event.current.type);
                    Handles.DrawLine(fracturedChunk.transform.position, chunkAdjacency.chunk.transform.position);
                }
            }

            Handles.color = handlesColor;
        }
    }
Esempio n. 17
0
    public static FracturedChunk ChunkRaycast(Vector3 v3Pos, Vector3 v3Forward, out RaycastHit hitInfo)
    {
        FracturedChunk chunk = null;

        if (Physics.Raycast(v3Pos, v3Forward, out hitInfo))
        {
            // Intersection found, try to check if it has a FracturedChunk component

            chunk = hitInfo.collider.GetComponent <FracturedChunk>();

            if (chunk == null && hitInfo.collider.transform.parent != null)
            {
                // Not found, but concave collider creates child nodes, we have to take this into account as well.
                // In this case the FracturedChunk should be in its parent
                chunk = hitInfo.collider.transform.parent.GetComponent <FracturedChunk>();
            }
        }

        return(chunk);
    }
Esempio n. 18
0
    void FireWeapon()
    {
        bool holdingDownFire = Input.GetKey(KeyCode.Mouse0);

        if (holdingDownFire)
        {
            _shootingTime += Time.deltaTime;

            _fireTimer += Time.deltaTime;
            if (_fireTimer > _fireInterval)
            {
                _fireTimer = 0.0f;

                RaycastHit hitInfo;

                FracturedChunk chunkRaycast = FracturedChunk.ChunkRaycast(_cameraTransform.position, _cameraTransform.forward, out hitInfo);
                if (chunkRaycast)
                {
                    chunkRaycast.FromCenterImpact(hitInfo.point, _fromCenterForce, _fromCenterRadius, true);
                }
                GameAudio.PlayOneShot("GunShot");
            }
        }

        if (!holdingDownFire && _previouslyShooting)
        {
            //if the previous shot was true and current is false
            //the player just stopped shooting
            GameAudio.PlayOneShot("ShellDrop", new Dictionary <string, float>()
            {
                { "Shots", _shootingTime }
            });
            _shootingTime = 0.0f;
        }

        _previouslyShooting = holdingDownFire;
    }
    private static bool AreSupportedChunksRecursive(FracturedChunk chunk, List <FracturedChunk> listChunksVisited, List <FracturedChunk> listChunksSupport)
    {
        if (chunk.Visited)
        {
            return(false);
        }

        chunk.Visited = true;
        listChunksVisited.Add(chunk);

        if (chunk.IsSupportChunk)
        {
            listChunksSupport.Add(chunk);
        }

        bool bAnyConnectedIsSupport = false;

        foreach (FracturedChunk.AdjacencyInfo adjacencyInfo in chunk.ListAdjacentChunks)
        {
            if (adjacencyInfo.chunk)
            {
                if (adjacencyInfo.chunk.FracturedObjectSource)
                {
                    if (adjacencyInfo.fArea >= adjacencyInfo.chunk.FracturedObjectSource.ChunkConnectionMinArea)
                    {
                        if (AreSupportedChunksRecursive(adjacencyInfo.chunk, listChunksVisited, listChunksSupport))
                        {
                            bAnyConnectedIsSupport = true;
                        }
                    }
                }
            }
        }

        return(chunk.IsSupportChunk || bAnyConnectedIsSupport);
    }
Esempio n. 20
0
    public void NotifyDetachChunkCollision(FracturedChunk.CollisionInfo collisionInfo)
    {
        // This one will be called internally from FracturedChunk from within a collision

        if(EventDetachCollisionCallGameObject != null && EventDetachCollisionCallMethod.Length > 0)
        {
            EventDetachCollisionCallGameObject.SendMessage(EventDetachCollisionCallMethod, collisionInfo);
        }

        if(collisionInfo.bCancelCollisionEvent == false)
        {
            NotifyDetachChunkCollision(collisionInfo.collisionInfo.contacts[0].point, collisionInfo.bIsMain);
        }
    }
Esempio n. 21
0
 public AdjacencyInfo(FracturedChunk chunk, float fArea)
 {
     this.chunk = chunk;
     this.fArea = fArea;
 }
Esempio n. 22
0
    public void NotifyFreeChunkCollision(FracturedChunk.CollisionInfo collisionInfo)
    {
        if(EventDetachedCollisionCallGameObject != null && EventDetachedCollisionCallMethod.Length > 0)
        {
            EventDetachedCollisionCallGameObject.SendMessage(EventDetachedCollisionCallMethod, collisionInfo);
        }

        if(collisionInfo.bCancelCollisionEvent == false)
        {
            if(EventDetachedSoundArray.Length > 0)
            {
                int nFreeSound = -1;

                for(int nSound = 0; nSound < m_afFreeChunkSoundTimers.Length; nSound++)
                {
                    if(m_afFreeChunkSoundTimers[nSound] <= 0.0f)
                    {
                        nFreeSound = nSound;
                        break;
                    }
                }

                if(nFreeSound != -1)
                {
                    AudioClip clip = EventDetachedSoundArray[UnityEngine.Random.Range(0, EventDetachedSoundArray.Length)];

                    if(clip != null)
                    {
                        AudioSource.PlayClipAtPoint(clip, collisionInfo.collisionInfo.contacts[0].point);
                    }

                    m_afFreeChunkSoundTimers[nFreeSound] = clip.length;
                }
            }

            if(EventDetachedPrefabsArray.Length > 0)
            {
                FracturedObject.PrefabInfo prefab = EventDetachedPrefabsArray[UnityEngine.Random.Range(0, EventDetachedPrefabsArray.Length)];

                if(prefab != null)
                {
                    int nFreePrefab = -1;

                    for(int nPrefab = 0; nPrefab < m_afFreeChunkPrefabTimers.Length; nPrefab++)
                    {
                        if(m_afFreeChunkPrefabTimers[nPrefab] <= 0.0f)
                        {
                            nFreePrefab = nPrefab;
                            break;
                        }
                    }

                    if(nFreePrefab != -1)
                    {
                        GameObject newGameObject = Instantiate(prefab.GameObject, collisionInfo.collisionInfo.contacts[0].point, prefab.GameObject.transform.rotation) as GameObject;

                        if(Mathf.Approximately(prefab.MinLifeTime, 0.0f) == false || Mathf.Approximately(prefab.MaxLifeTime, 0.0f) == false)
                        {
                            DieTimer timer = newGameObject.AddComponent<DieTimer>();
                            timer.SecondsToDie = UnityEngine.Random.Range(prefab.MinLifeTime, prefab.MaxLifeTime);

                            m_afFreeChunkPrefabTimers[nFreePrefab] = timer.SecondsToDie;
                        }
                        else
                        {
                            m_afFreeChunkPrefabTimers[nFreePrefab] = float.MaxValue;
                        }
                    }
                }
            }
        }
    }
Esempio n. 23
0
    void Update()
    {
        if (ShootMode == Mode.FromCenter)
        {
            // Raycast

            if (Weapon)
            {
                Weapon.GetComponent <Renderer> ().enabled = true;
            }

            bool bShot = ShouldShoot();
            if (bShot)
            {
                _shootingTime += Time.deltaTime;
            }

            bool holdingDownFire = Input.GetKey(KeyCode.Space);
            if (!holdingDownFire && _previousShot)
            {
                //if the previous shot was true and current is false
                //the player just stopped shooting
                GameAudio.PlayOneShot("ShellDrop", new Dictionary <string, float>()
                {
                    { "Shots", _shootingTime }
                });
                _shootingTime = 0.0f;
            }

            if (bShot)
            {
                m_fRecoilTimer = RecoilDuration;
                if (AudioWeaponShot)
                {
                    AudioSource.PlayClipAtPoint(AudioWeaponShot, transform.position, WeaponShotVolume);
                }
            }

            m_bRaycastFound = false;

            RaycastHit hitInfo;

            FracturedChunk chunkRaycast = FracturedChunk.ChunkRaycast(transform.position, transform.forward, out hitInfo);

            if (chunkRaycast)
            {
                m_bRaycastFound = true;

                if (bShot)
                {
                    // Hit it!
                    chunkRaycast.FromCenterImpact(hitInfo.point, FromCenterForce, FromCenterRadius, true);
                }
            }

            _previousShot = holdingDownFire;
        }
        // Mouse-aim

        if (Input.GetMouseButton(0) && Input.GetMouseButtonDown(0) == false)
        {
            this.transform.Rotate(-(Input.mousePosition.y - m_v3MousePosition.y) * MouseSpeed, 0.0f, 0.0f);
            this.transform.RotateAround(this.transform.position, Vector3.up, (Input.mousePosition.x - m_v3MousePosition.x) * MouseSpeed);
        }

        m_v3MousePosition = Input.mousePosition;
    }
Esempio n. 24
0
    void OnCollisionEnter(Collision collision)
    {
        if (FracturedObjectSource == null || collision == null)
        {
            return;
        }

        if (collision.contacts == null)
        {
            return;
        }

        if (collision.contacts.Length == 0)
        {
            return;
        }

        if (collision.gameObject)
        {
            FracturedChunk otherChunk = collision.gameObject.GetComponent <FracturedChunk>();

            if (otherChunk)
            {
                if (otherChunk.rigidbody.isKinematic && IsDetachedChunk == false)
                {
                    // Just intersecting with other chunk in kinematic state
                    return;
                }
            }
        }

        float fMass = Mathf.Infinity; // If there is no rigidbody we consider it static

        if (collision.rigidbody)
        {
            fMass = collision.rigidbody.mass;
        }

        if (IsDetachedChunk == false)
        {
            // Chunk still attached.
            // We are going to check if the collision is against a free chunk of the same object. This way we prevent chunks pushing each other out, we want to control
            // this only through the FractureObject.InterconnectionStrength variable

            bool bOtherIsFreeChunkFromSameObject = false;

            FracturedChunk otherChunk = collision.gameObject.GetComponent <FracturedChunk>();

            if (otherChunk != null)
            {
                if (otherChunk.IsDetachedChunk == true && otherChunk.FracturedObjectSource == FracturedObjectSource)
                {
                    bOtherIsFreeChunkFromSameObject = true;
                }
            }

            if (bOtherIsFreeChunkFromSameObject == false && collision.relativeVelocity.magnitude > FracturedObjectSource.EventDetachMinVelocity && fMass > FracturedObjectSource.EventDetachMinMass && rigidbody != null && IsDestructibleChunk())
            {
                CollisionInfo collisionInfo = new CollisionInfo(this, collision, true);
                FracturedObjectSource.NotifyDetachChunkCollision(collisionInfo);

                if (collisionInfo.bCancelCollisionEvent == false)
                {
                    List <FracturedChunk> listBreaks = new List <FracturedChunk>();

                    // Impact enough to make it detach. Compute random list of connected chunks that are detaching as well (we'll use the ConnectionStrength parameter).
                    listBreaks = ComputeRandomConnectionBreaks();
                    listBreaks.Add(this);
                    DetachFromObject();

                    foreach (FracturedChunk chunk in listBreaks)
                    {
                        collisionInfo.chunk   = chunk;
                        collisionInfo.bIsMain = false;
                        collisionInfo.bCancelCollisionEvent = false;

                        if (chunk != this)
                        {
                            FracturedObjectSource.NotifyDetachChunkCollision(collisionInfo);
                        }

                        if (collisionInfo.bCancelCollisionEvent == false)
                        {
                            chunk.DetachFromObject();
                            chunk.rigidbody.AddExplosionForce(collision.relativeVelocity.magnitude * FracturedObjectSource.EventDetachExitForce, collision.contacts[0].point, 0.0f, FracturedObjectSource.EventDetachUpwardsModifier);
                        }
                    }
                }
            }
        }
        else
        {
            // Free chunk

            if (collision.relativeVelocity.magnitude > FracturedObjectSource.EventDetachedMinVelocity && fMass > FracturedObjectSource.EventDetachedMinMass)
            {
                FracturedObjectSource.NotifyFreeChunkCollision(new CollisionInfo(this, collision, true));
            }
        }
    }
Esempio n. 25
0
    public void NotifyChunkDetach(FracturedChunk chunk)
    {
        if(m_bDetached == false)
        {
            // Disable all triggerse in them so that free chunks will collide also with static non-free chunks

            foreach(FracturedChunk chunkInstance in ListFracturedChunks)
            {
                if(chunkInstance != null)
                {
                    Collider colliderComponent = chunkInstance.GetComponent<Collider>();

                    if(colliderComponent != null)
                    {
                        colliderComponent.isTrigger = false;
                    }
                }
            }
        }

        m_bDetached = true;
        SetSingleMeshVisibility(false);

        if(EventDetachedAnyCallMethod.Length > 0 && EventDetachedAnyCallGameObject != null)
        {
            EventDetachedAnyCallGameObject.SendMessage(EventDetachedAnyCallMethod);
        }
    }
    public override void OnInspectorGUI()
    {
        bool bCheckDetachNonSupportedChunks = false;
        bool bMarkNonSupportedChunks        = false;

        Color colorGUI = GUI.color;

        // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.

        serializedObject.Update();

        FracturedChunk fracturedChunk = serializedObject.targetObject as FracturedChunk;

        PropDontDeleteAfterBroken.boolValue = EditorGUILayout.Toggle(new GUIContent("Don't Delete If Broken", "Will prevent this chunk to be deleted (due to lifetime parameters configured on the FracturedObject panel) after being broken off from the object."), PropDontDeleteAfterBroken.boolValue);
        EditorGUI.BeginChangeCheck();
        PropIsSupportChunk.boolValue = EditorGUILayout.Toggle(new GUIContent("Is Support Chunk", "Chunks that are tagged as support can't be destroyed and will hold the object together. A chunk needs to be connected to a support chunk (directly or through other chunks) or otherwise it will fall. This prevents chunks from staying static in the air and enables realistic collapsing behavior."), PropIsSupportChunk.boolValue);
        if (EditorGUI.EndChangeCheck())
        {
            if (fracturedChunk.FracturedObjectSource)
            {
                if (Application.isPlaying)
                {
                    bCheckDetachNonSupportedChunks = true;
                }

                bMarkNonSupportedChunks = true;
            }
        }

        // Apply changes to the serializedProperty.

        serializedObject.ApplyModifiedProperties();

        if (bCheckDetachNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.CheckDetachNonSupportedChunks();
        }

        if (bMarkNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.MarkNonSupportedChunks();
        }

        if (bCheckDetachNonSupportedChunks || bMarkNonSupportedChunks)
        {
            SceneView.RepaintAll();
        }

        bCheckDetachNonSupportedChunks = false;
        bMarkNonSupportedChunks        = false;

        EditorGUILayout.Space();

        if (serializedObject.targetObjects.Length == 1)
        {
            EditorGUILayout.LabelField(new GUIContent("Chunk Attached To Object: " + (fracturedChunk.IsDetachedChunk ? "No" : "Yes"), "Is the chunk attached to the object or has it been detached?"));
            EditorGUILayout.LabelField(new GUIContent("Chunk Connected To Support: " + (fracturedChunk.IsNonSupportedChunk ? "No" : "Yes"), "Is the chunk directly or indirectly connected to a support chunk?"));
            EditorGUILayout.LabelField(new GUIContent("Chunk Volume: " + string.Format("{0} ({1:0.##}% of total)", fracturedChunk.Volume, fracturedChunk.RelativeVolume * 100.0f), "The chunk volume and % of volume with respect to the object"));
            EditorGUILayout.LabelField(new GUIContent("Concave Collider Generated: " + (fracturedChunk.HasConcaveCollider ? "Yes" : "No"), "Does this chunk have one or more colliders generated by the Concave Collider utility?"));
        }
        else
        {
            GUI.color = new Color(0.5f, 1.0f, 0.0f, 1.0f);
            EditorGUILayout.LabelField("Multiselection mode");
            GUI.color = colorGUI;
        }

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        Vector4 v4GUIColor = GUI.color;

        EditorGUILayout.BeginHorizontal();
        SelectedManuallyAddChunk = EditorGUILayout.ObjectField(new GUIContent("Manually Add Connection"), SelectedManuallyAddChunk, typeof(FracturedChunk), true) as FracturedChunk;
        if (GUILayout.Button(new GUIContent("Connect", "Connects this chunk to the selected one."), GUILayout.Width(80)))
        {
            if (SelectedManuallyAddChunk)
            {
                if (serializedObject.targetObjects.Length == 1)
                {
                    if (fracturedChunk.FracturedObjectSource != SelectedManuallyAddChunk.FracturedObjectSource)
                    {
                        EditorUtility.DisplayDialog("Chunks not of the same object", "The two chunks belong to different fractured objects.", "OK");
                    }
                    else if (fracturedChunk.IsConnectedTo(SelectedManuallyAddChunk))
                    {
                        EditorUtility.DisplayDialog("Chunks already connected", "The two chunks are already connected.", "OK");
                    }
                    else
                    {
                        fracturedChunk.ConnectTo(SelectedManuallyAddChunk, Mathf.Min(Mathf.Sqrt(fracturedChunk.Volume), Mathf.Sqrt(SelectedManuallyAddChunk.Volume)));
                        bCheckDetachNonSupportedChunks = true;
                        bMarkNonSupportedChunks        = true;
                    }
                }
                else
                {
                    // Multi-edit

                    foreach (Object objectMultiselection in serializedObject.targetObjects)
                    {
                        FracturedChunk chunkMultiSelected = objectMultiselection as FracturedChunk;

                        chunkMultiSelected.ConnectTo(SelectedManuallyAddChunk, Mathf.Min(Mathf.Sqrt(chunkMultiSelected.Volume), Mathf.Sqrt(SelectedManuallyAddChunk.Volume)));
                        bCheckDetachNonSupportedChunks = true;
                        bMarkNonSupportedChunks        = true;
                    }
                }
            }
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        if (serializedObject.targetObjects.Length == 1)
        {
            GUILayout.Label("Connections to other chunks:");
        }
        else
        {
            GUILayout.Label("Common connections to other chunks:");
        }

        FracturedChunk chunkToDisconnectFrom = null;

        // Compute common connections in multi-edit mode

        List <FracturedChunk> listConnectedChunks = new List <FracturedChunk>();
        List <float>          listAreas           = new List <float>();

        for (int nConnectedChunk = 0; nConnectedChunk < fracturedChunk.ListAdjacentChunks.Count; nConnectedChunk++)
        {
            FracturedChunk.AdjacencyInfo info = fracturedChunk.ListAdjacentChunks[nConnectedChunk];

            if (info.chunk)
            {
                listConnectedChunks.Add(info.chunk);
                listAreas.Add(info.fArea);
            }
        }

        if (serializedObject.targetObjects.Length > 1)
        {
            // Multi-edit, only finish with those that are shared among all selected chunks

            foreach (Object objectMultiselection in serializedObject.targetObjects)
            {
                FracturedChunk chunkMultiSelected = objectMultiselection as FracturedChunk;

                List <FracturedChunk> listCommonChunks = new List <FracturedChunk>();

                foreach (FracturedChunk.AdjacencyInfo info in chunkMultiSelected.ListAdjacentChunks)
                {
                    if (listConnectedChunks.Contains(info.chunk))
                    {
                        listCommonChunks.Add(info.chunk);
                    }
                }

                listConnectedChunks = listCommonChunks;
            }
        }


        for (int nConnectedChunk = 0; nConnectedChunk < listConnectedChunks.Count; nConnectedChunk++)
        {
            FracturedChunk chunk = listConnectedChunks[nConnectedChunk];
            float          fArea = listAreas[nConnectedChunk];

            if (chunk)
            {
                EditorGUILayout.BeginHorizontal();
                if (chunk.IsSupportChunk)
                {
                    GUI.color = new Color(0.6f, 0.6f, 1.0f, 1.0f);
                }
                GUILayout.Label(string.Format("{0} (Surface {1})", chunk.name, serializedObject.targetObjects.Length == 1 ? fArea.ToString("F3") : ""));
                GUI.color = v4GUIColor;
                GUILayout.FlexibleSpace();
                if (GUILayout.Button(new GUIContent("Disconnect", "Disconnects the currently selected chunk from this one"), GUILayout.Width(80)))
                {
                    if (fracturedChunk.FracturedObjectSource != null)
                    {
                        chunkToDisconnectFrom = chunk;
                    }
                }
                if (GUILayout.Button(new GUIContent("Select", "Changes the active selection to this chunk"), GUILayout.Width(80)))
                {
                    if (fracturedChunk.FracturedObjectSource != null)
                    {
                        UnityEditor.Selection.activeGameObject = chunk.gameObject;
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
        }

        if (chunkToDisconnectFrom != null)
        {
            foreach (Object objectMultiselection in serializedObject.targetObjects)
            {
                FracturedChunk chunkMultiSelected = objectMultiselection as FracturedChunk;
                chunkMultiSelected.DisconnectFrom(chunkToDisconnectFrom);
            }

            bCheckDetachNonSupportedChunks = true;
            bMarkNonSupportedChunks        = true;
        }

        if (bCheckDetachNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.CheckDetachNonSupportedChunks();
        }

        if (bMarkNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.MarkNonSupportedChunks();
        }

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        int nButtonWidth = 200;

        GUI.enabled = serializedObject.targetObjects.Length == 1;

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if (GUILayout.Button(new GUIContent("Go To Fractured Object", "Selects the FracturedObject this chunk comes from"), GUILayout.Width(nButtonWidth)))
        {
            if (fracturedChunk.FracturedObjectSource != null)
            {
                UnityEditor.Selection.activeGameObject = fracturedChunk.FracturedObjectSource.gameObject;
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if (GUILayout.Button(new GUIContent("Show Non-Connected Chunks", "Enables the MeshRenderer of all the chunks that are not directly connected to this chunk."), GUILayout.Width(nButtonWidth)))
        {
            if (fracturedChunk.FracturedObjectSource != null)
            {
                foreach (FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if (chunk)
                    {
                        if (fracturedChunk.IsConnectedTo(chunk) == false)
                        {
                            chunk.GetComponent <Renderer>().enabled = true;
                        }
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if (GUILayout.Button(new GUIContent("Hide Non-Connected Chunks", "Disables the MeshRenderer of all the chunks that are not directly connected to this chunk."), GUILayout.Width(nButtonWidth)))
        {
            if (fracturedChunk.FracturedObjectSource != null)
            {
                foreach (FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if (chunk)
                    {
                        if (fracturedChunk.IsConnectedTo(chunk) == false && fracturedChunk != chunk)
                        {
                            chunk.GetComponent <Renderer>().enabled = false;
                        }
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if (GUILayout.Button(new GUIContent("Show All Other Chunks", "Enables the MeshRenderer of all the other chunks in the object."), GUILayout.Width(nButtonWidth)))
        {
            if (fracturedChunk.FracturedObjectSource != null)
            {
                foreach (FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if (chunk && fracturedChunk != chunk)
                    {
                        chunk.GetComponent <Renderer>().enabled = true;
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if (GUILayout.Button(new GUIContent("Hide All Other Chunks", "Disables the MeshRenderer of all the other chunks in the object."), GUILayout.Width(nButtonWidth)))
        {
            if (fracturedChunk.FracturedObjectSource != null)
            {
                foreach (FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if (chunk && fracturedChunk != chunk)
                    {
                        chunk.GetComponent <Renderer>().enabled = false;
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        GUI.enabled = true;

        if (bCheckDetachNonSupportedChunks || bMarkNonSupportedChunks)
        {
            SceneView.RepaintAll();
        }
    }
    public void Explode(Vector3 v3ExplosionPosition, float fExplosionForce)
    {
        // Explodes all chunks

        if (m_bExploded == true)
        {
            return;
        }

        // Play sound

        if (EventExplosionSound)
        {
            AudioSource.PlayClipAtPoint(EventExplosionSound, v3ExplosionPosition);
        }

        // Instance prefabs on random positions

        if (EventExplosionPrefabsArray.Length > 0 && EventExplosionPrefabsInstanceCount > 0 && ListFracturedChunks.Count > 0)
        {
            for (int i = 0; i < EventExplosionPrefabsInstanceCount; i++)
            {
                FracturedObject.PrefabInfo prefab = EventExplosionPrefabsArray[UnityEngine.Random.Range(0, EventExplosionPrefabsArray.Length)];

                if (prefab != null)
                {
                    FracturedChunk chunkRandom = null;

                    while (chunkRandom == null)
                    {
                        chunkRandom = ListFracturedChunks[UnityEngine.Random.Range(0, ListFracturedChunks.Count)];
                    }

                    GameObject newGameObject = Instantiate(prefab.GameObject, chunkRandom.transform.position, prefab.GameObject.transform.rotation) as GameObject;

                    if (Mathf.Approximately(prefab.MinLifeTime, 0.0f) == false || Mathf.Approximately(prefab.MaxLifeTime, 0.0f) == false)
                    {
                        DieTimer timer = newGameObject.AddComponent <DieTimer>();
                        timer.SecondsToDie = UnityEngine.Random.Range(prefab.MinLifeTime, prefab.MaxLifeTime);
                    }
                }
            }
        }

        // Explode chunks

        foreach (FracturedChunk chunk in ListFracturedChunks)
        {
            if (chunk)
            {
                chunk.ListAdjacentChunks.Clear();

                if (chunk.IsDestructibleChunk() && chunk.IsDetachedChunk == false)
                {
                    chunk.DetachFromObject(false);
                    chunk.GetComponent <Rigidbody>().AddExplosionForce(fExplosionForce, v3ExplosionPosition, 0.0f, 0.0f);
                }
            }
        }

        m_bExploded = true;
    }
Esempio n. 28
0
        public static MapObjectEntity GetMapObjectOfFracturedChunk(FracturedChunk chunk)
        {
            var mapObject = GetMapObjectOfFracturedChunk <FracturedChunk, FracturedObject>(chunk);

            return(mapObject != null && mapObject.hasDestructibleData ? mapObject : null);
        }
Esempio n. 29
0
    public bool IsConnectedTo(FracturedChunk chunk)
    {
        foreach(AdjacencyInfo info in ListAdjacentChunks)
        {
            bool bHasMinArea = true;

            if(info.chunk.FracturedObjectSource)
            {
                bHasMinArea = info.fArea > info.chunk.FracturedObjectSource.ChunkConnectionMinArea;
            }

            if(info.chunk == chunk)
            {
                return bHasMinArea;
            }
        }

        return false;
    }
Esempio n. 30
0
    private static void ComputeRandomConnectionBreaksRecursive(FracturedChunk chunk, List<FracturedChunk> listBreaksOut, int nLevel)
    {
        if(chunk.Visited == true)
        {
            return;
        }

        chunk.Visited = true;

        foreach(FracturedChunk.AdjacencyInfo adjacency in chunk.ListAdjacentChunks)
        {
            if(adjacency.chunk)
            {
                if(chunk.FracturedObjectSource != null && adjacency.chunk.Visited == false && adjacency.chunk.IsDestructibleChunk())
                {
                    bool bConnected = adjacency.fArea > chunk.FracturedObjectSource.ChunkConnectionMinArea;

                    if(bConnected)
                    {
                        float fRandom = UnityEngine.Random.value;

                        if(fRandom > (chunk.FracturedObjectSource.ChunkConnectionStrength * nLevel))
                        {
                            ComputeRandomConnectionBreaksRecursive(adjacency.chunk, listBreaksOut, nLevel + 1);
                            listBreaksOut.Add(adjacency.chunk);
                        }
                    }
                }
            }
        }
    }
Esempio n. 31
0
    public void DisconnectFrom(FracturedChunk chunk)
    {
        if(chunk)
        {
            if(chunk.IsConnectedTo(this))
            {
                for(int i = 0; i < ListAdjacentChunks.Count; i++)
                {
                    if(ListAdjacentChunks[i].chunk == chunk)
                    {
                        ListAdjacentChunks.RemoveAt(i);
                        break;
                    }
                }

                for(int i = 0; i < chunk.ListAdjacentChunks.Count; i++)
                {
                    if(chunk.ListAdjacentChunks[i].chunk == this)
                    {
                        chunk.ListAdjacentChunks.RemoveAt(i);
                        break;
                    }
                }
            }
        }            
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            ShootMode = ShootMode == Mode.ExplodeRaycast ? Mode.ShootObjects : Mode.ExplodeRaycast;
        }

        if (ObjectToShoot != null && ShootMode == Mode.ShootObjects)
        {
            // Shoot objects

            if (Weapon)
            {
                Weapon.GetComponent <Renderer>().enabled = false;
            }

            if (Input.GetKeyDown(KeyCode.Space))
            {
                GameObject newObject = GameObject.Instantiate(ObjectToShoot) as GameObject;
                newObject.transform.position                          = this.transform.position;
                newObject.transform.localScale                        = new Vector3(ObjectScale, ObjectScale, ObjectScale);
                newObject.GetComponent <Rigidbody>().mass             = ObjectMass;
                newObject.GetComponent <Rigidbody>().solverIterations = 255;
                newObject.GetComponent <Rigidbody>().AddForce(this.transform.forward * InitialObjectSpeed, ForceMode.VelocityChange);

                //DieTimer dieTimer = newObject.AddComponent<DieTimer>() as DieTimer;
                //dieTimer.SecondsToDie = ObjectLife;
            }
        }

        if (ShootMode == Mode.ExplodeRaycast)
        {
            // Raycast

            if (Weapon)
            {
                Weapon.GetComponent <Renderer>().enabled = true;
            }

            bool bShot = Input.GetKeyDown(KeyCode.Space);

            if (bShot)
            {
                m_fRecoilTimer = RecoilDuration;
                if (AudioWeaponShot)
                {
                    AudioSource.PlayClipAtPoint(AudioWeaponShot, transform.position, WeaponShotVolume);
                }
            }

            m_bRaycastFound = false;

            RaycastHit hitInfo;

            FracturedChunk chunkRaycast = FracturedChunk.ChunkRaycast(transform.position, transform.forward, out hitInfo);

            if (chunkRaycast)
            {
                m_bRaycastFound = true;

                if (bShot)
                {
                    // Hit it!
                    chunkRaycast.Impact(hitInfo.point, ExplosionForce, ExplosionRadius, true);
                }
            }
        }

        // Update recoil

        if (m_fRecoilTimer > 0.0f)
        {
            if (Weapon)
            {
                // Some rudimentary recoil animation here
                Weapon.transform.localPosition = m_v3InitialWeaponPos + new Vector3(0.0f, 0.0f, (-m_fRecoilTimer / RecoilDuration) * RecoilIntensity);
                Weapon.transform.localRotation = m_qInitialWeaponRot * Quaternion.Euler(new Vector3((m_fRecoilTimer / RecoilDuration) * 360.0f * RecoilIntensity * 0.1f, 0.0f, 0.0f));
            }

            m_fRecoilTimer -= Time.deltaTime;
        }
        else
        {
            if (Weapon)
            {
                Weapon.transform.localPosition = m_v3InitialWeaponPos;
                Weapon.transform.localRotation = m_qInitialWeaponRot;
            }
        }

        // Mouse-aim

        if (Input.GetMouseButton(0) && Input.GetMouseButtonDown(0) == false)
        {
            this.transform.Rotate(-(Input.mousePosition.y - m_v3MousePosition.y) * MouseSpeed, 0.0f, 0.0f);
            this.transform.RotateAround(this.transform.position, Vector3.up, (Input.mousePosition.x - m_v3MousePosition.x) * MouseSpeed);
        }

        m_v3MousePosition = Input.mousePosition;
    }
Esempio n. 33
0
 public AdjacencyInfo(FracturedChunk chunk, float fArea)
 {
     this.chunk = chunk;
     this.fArea = fArea;
 }
Esempio n. 34
0
    public void NotifyChunkDetach(FracturedChunk chunk)
    {
        m_bDetached = true;
        SetSingleMeshVisibility(false);

        if(EventDetachedAnyCallMethod.Length > 0 && EventDetachedAnyCallGameObject != null)
        {
            EventDetachedAnyCallGameObject.SendMessage(EventDetachedAnyCallMethod);
        }
    }
Esempio n. 35
0
    public override void OnInspectorGUI()
    {
        bool bCheckDetachNonSupportedChunks = false;
        bool bMarkNonSupportedChunks        = false;

        Color colorGUI = GUI.color;

        // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.

        serializedObject.Update();

        FracturedChunk fracturedChunk = serializedObject.targetObject as FracturedChunk;

        PropDontDeleteAfterBroken.boolValue = EditorGUILayout.Toggle(new GUIContent("Don't Delete If Broken", "Will prevent this chunk to be deleted (due to lifetime parameters configured on the FracturedObject panel) after being broken off from the object."), PropDontDeleteAfterBroken.boolValue);
        EditorGUI.BeginChangeCheck();
        PropIsSupportChunk.boolValue = EditorGUILayout.Toggle(new GUIContent("Is Support Chunk", "Chunks that are tagged as support can't be destroyed and will hold the object together. A chunk needs to be connected to a support chunk (directly or through other chunks) or otherwise it will fall. This prevents chunks from staying static in the air and enables realistic collapsing behavior."), PropIsSupportChunk.boolValue);
        if(EditorGUI.EndChangeCheck())
        {
            if(fracturedChunk.FracturedObjectSource)
            {
                if(Application.isPlaying)
                {
                    bCheckDetachNonSupportedChunks = true;
                }

                bMarkNonSupportedChunks = true;
            }
        }

        // Apply changes to the serializedProperty.

        serializedObject.ApplyModifiedProperties();

        if(bCheckDetachNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.CheckDetachNonSupportedChunks();
        }

        if(bMarkNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.MarkNonSupportedChunks();
        }

        if(bCheckDetachNonSupportedChunks || bMarkNonSupportedChunks)
        {
            SceneView.RepaintAll();
        }

        bCheckDetachNonSupportedChunks = false;
        bMarkNonSupportedChunks        = false;

        EditorGUILayout.Space();

        if(serializedObject.targetObjects.Length == 1)
        {
            EditorGUILayout.LabelField(new GUIContent("Chunk Attached To Object: " + (fracturedChunk.IsDetachedChunk ? "No" : "Yes"), "Is the chunk attached to the object or has it been detached?"));
            EditorGUILayout.LabelField(new GUIContent("Chunk Connected To Support: " + (fracturedChunk.IsNonSupportedChunk ? "No" : "Yes"), "Is the chunk directly or indirectly connected to a support chunk?"));
            EditorGUILayout.LabelField(new GUIContent("Chunk Volume: " + string.Format("{0} ({1:0.##}% of total)", fracturedChunk.Volume, fracturedChunk.RelativeVolume * 100.0f), "The chunk volume and % of volume with respect to the object"));
            EditorGUILayout.LabelField(new GUIContent("Concave Collider Generated: " + (fracturedChunk.HasConcaveCollider ? "Yes" : "No"), "Does this chunk have one or more colliders generated by the Concave Collider utility?"));
        }
        else
        {
            GUI.color = new Color(0.5f, 1.0f, 0.0f, 1.0f);
            EditorGUILayout.LabelField("Multiselection mode");
            GUI.color = colorGUI;
        }

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        Vector4 v4GUIColor = GUI.color;

        EditorGUILayout.BeginHorizontal();
        SelectedManuallyAddChunk = EditorGUILayout.ObjectField(new GUIContent("Manually Add Connection"), SelectedManuallyAddChunk, typeof(FracturedChunk), true) as FracturedChunk;
        if(GUILayout.Button(new GUIContent("Connect", "Connects this chunk to the selected one."), GUILayout.Width(80)))
        {
            if(SelectedManuallyAddChunk)
            {
                if(serializedObject.targetObjects.Length == 1)
                {
                    if(fracturedChunk.FracturedObjectSource != SelectedManuallyAddChunk.FracturedObjectSource)
                    {
                        EditorUtility.DisplayDialog("Chunks not of the same object", "The two chunks belong to different fractured objects.", "OK");
                    }
                    else if(fracturedChunk.IsConnectedTo(SelectedManuallyAddChunk))
                    {
                        EditorUtility.DisplayDialog("Chunks already connected", "The two chunks are already connected.", "OK");
                    }
                    else
                    {
                        fracturedChunk.ConnectTo(SelectedManuallyAddChunk, Mathf.Min(Mathf.Sqrt(fracturedChunk.Volume), Mathf.Sqrt(SelectedManuallyAddChunk.Volume)));
                        bCheckDetachNonSupportedChunks = true;
                        bMarkNonSupportedChunks        = true;
                    }
                }
                else
                {
                    // Multi-edit

                    foreach(Object objectMultiselection in serializedObject.targetObjects)
                    {
                        FracturedChunk chunkMultiSelected = objectMultiselection as FracturedChunk;

                        chunkMultiSelected.ConnectTo(SelectedManuallyAddChunk, Mathf.Min(Mathf.Sqrt(chunkMultiSelected.Volume), Mathf.Sqrt(SelectedManuallyAddChunk.Volume)));
                        bCheckDetachNonSupportedChunks = true;
                        bMarkNonSupportedChunks        = true;
                    }
                }
            }
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        if(serializedObject.targetObjects.Length == 1)
        {
            GUILayout.Label("Connections to other chunks:");
        }
        else
        {
            GUILayout.Label("Common connections to other chunks:");
        }

        FracturedChunk chunkToDisconnectFrom = null;

        // Compute common connections in multi-edit mode

        List<FracturedChunk> listConnectedChunks = new List<FracturedChunk>();
        List<float>          listAreas           = new List<float>();

        for(int nConnectedChunk = 0; nConnectedChunk < fracturedChunk.ListAdjacentChunks.Count; nConnectedChunk++)
        {
            FracturedChunk.AdjacencyInfo info = fracturedChunk.ListAdjacentChunks[nConnectedChunk];

            if(info.chunk)
            {
                listConnectedChunks.Add(info.chunk);
                listAreas.Add(info.fArea);
            }
        }

        if(serializedObject.targetObjects.Length > 1)
        {
            // Multi-edit, only finish with those that are shared among all selected chunks

            foreach(Object objectMultiselection in serializedObject.targetObjects)
            {
                FracturedChunk chunkMultiSelected = objectMultiselection as FracturedChunk;

                List<FracturedChunk> listCommonChunks = new List<FracturedChunk>();

                foreach(FracturedChunk.AdjacencyInfo info in chunkMultiSelected.ListAdjacentChunks)
                {
                    if(listConnectedChunks.Contains(info.chunk))
                    {
                        listCommonChunks.Add(info.chunk);
                    }
                }

                listConnectedChunks = listCommonChunks;
            }
        }


        for(int nConnectedChunk = 0; nConnectedChunk < listConnectedChunks.Count; nConnectedChunk++)
        {
            FracturedChunk chunk = listConnectedChunks[nConnectedChunk];
            float          fArea = listAreas[nConnectedChunk];

            if(chunk)
            {
                EditorGUILayout.BeginHorizontal();
                if(chunk.IsSupportChunk)
                {
                    GUI.color = new Color(0.6f, 0.6f, 1.0f, 1.0f);
                }
                GUILayout.Label(string.Format("{0} (Surface {1})", chunk.name, serializedObject.targetObjects.Length == 1 ? fArea.ToString("F3") : ""));
                GUI.color = v4GUIColor;
                GUILayout.FlexibleSpace();
                if(GUILayout.Button(new GUIContent("Disconnect", "Disconnects the currently selected chunk from this one"), GUILayout.Width(80)))
                {
                    if(fracturedChunk.FracturedObjectSource != null)
                    {
                        chunkToDisconnectFrom = chunk;
                    }
                }
                if(GUILayout.Button(new GUIContent("Select", "Changes the active selection to this chunk"), GUILayout.Width(80)))
                {
                    if(fracturedChunk.FracturedObjectSource != null)
                    {
                        UnityEditor.Selection.activeGameObject = chunk.gameObject;
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
        }

        if(chunkToDisconnectFrom != null)
        {
            foreach(Object objectMultiselection in serializedObject.targetObjects)
            {
                FracturedChunk chunkMultiSelected = objectMultiselection as FracturedChunk;
                chunkMultiSelected.DisconnectFrom(chunkToDisconnectFrom);
            }

            bCheckDetachNonSupportedChunks = true;
            bMarkNonSupportedChunks        = true;
        }

        if(bCheckDetachNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.CheckDetachNonSupportedChunks();
        }

        if(bMarkNonSupportedChunks)
        {
            fracturedChunk.FracturedObjectSource.MarkNonSupportedChunks();
        }

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        int nButtonWidth = 200;

        GUI.enabled = serializedObject.targetObjects.Length == 1;

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if(GUILayout.Button(new GUIContent("Go To Fractured Object", "Selects the FracturedObject this chunk comes from"), GUILayout.Width(nButtonWidth)))
        {
            if(fracturedChunk.FracturedObjectSource != null)
            {
                UnityEditor.Selection.activeGameObject = fracturedChunk.FracturedObjectSource.gameObject;
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if(GUILayout.Button(new GUIContent("Show Non-Connected Chunks", "Enables the MeshRenderer of all the chunks that are not directly connected to this chunk."), GUILayout.Width(nButtonWidth)))
        {
            if(fracturedChunk.FracturedObjectSource != null)
            {
                foreach(FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if(chunk)
                    {
                        if(fracturedChunk.IsConnectedTo(chunk) == false)
                        {
                            chunk.GetComponent<Renderer>().enabled = true;
                        }
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if(GUILayout.Button(new GUIContent("Hide Non-Connected Chunks", "Disables the MeshRenderer of all the chunks that are not directly connected to this chunk."), GUILayout.Width(nButtonWidth)))
        {
            if(fracturedChunk.FracturedObjectSource != null)
            {
                foreach(FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if(chunk)
                    {
                        if(fracturedChunk.IsConnectedTo(chunk) == false && fracturedChunk != chunk)
                        {
                            chunk.GetComponent<Renderer>().enabled = false;
                        }
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if(GUILayout.Button(new GUIContent("Show All Other Chunks", "Enables the MeshRenderer of all the other chunks in the object."), GUILayout.Width(nButtonWidth)))
        {
            if(fracturedChunk.FracturedObjectSource != null)
            {
                foreach(FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if(chunk && fracturedChunk != chunk)
                    {
                        chunk.GetComponent<Renderer>().enabled = true;
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label(" ");
        if(GUILayout.Button(new GUIContent("Hide All Other Chunks", "Disables the MeshRenderer of all the other chunks in the object."), GUILayout.Width(nButtonWidth)))
        {
            if(fracturedChunk.FracturedObjectSource != null)
            {
                foreach(FracturedChunk chunk in fracturedChunk.FracturedObjectSource.ListFracturedChunks)
                {
                    if(chunk && fracturedChunk != chunk)
                    {
                        chunk.GetComponent<Renderer>().enabled = false;
                    }
                }
            }
        }
        GUILayout.Label(" ");
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space();
        EditorGUILayout.Space();

        GUI.enabled = true;

        if(bCheckDetachNonSupportedChunks || bMarkNonSupportedChunks)
        {
            SceneView.RepaintAll();
        }
    }
 void Start()
 {
     vio             = gameObject.GetComponent <VRTK_InteractableObject> ();
     cScript         = gameObject.GetComponent <FracturedChunk>();
     vio.isGrabbable = false;
 }
Esempio n. 37
0
    private static bool AreSupportedChunksRecursive(FracturedChunk chunk, List<FracturedChunk> listChunksVisited, List<FracturedChunk> listChunksSupport)
    {
        if(chunk.Visited)
        {
            return false;
        }

        chunk.Visited = true;
        listChunksVisited.Add(chunk);

        if(chunk.IsSupportChunk)
        {
            listChunksSupport.Add(chunk);
        }

        bool bAnyConnectedIsSupport = false;

        foreach(FracturedChunk.AdjacencyInfo adjacencyInfo in chunk.ListAdjacentChunks)
        {
            if(adjacencyInfo.chunk)
            {
                if(adjacencyInfo.chunk.FracturedObjectSource)
                {
                    if(adjacencyInfo.fArea >= adjacencyInfo.chunk.FracturedObjectSource.ChunkConnectionMinArea)
                    {
                        if(AreSupportedChunksRecursive(adjacencyInfo.chunk, listChunksVisited, listChunksSupport))
                        {
                            bAnyConnectedIsSupport = true;
                        }
                    }
                }
            }
        }

        return chunk.IsSupportChunk || bAnyConnectedIsSupport;
    }
Esempio n. 38
0
        public Vector3 collisionPoint; // The collision point

        #endregion Fields

        #region Constructors

        public CollisionInfo(FracturedChunk chunk, Vector3 collisionPoint, bool bIsMain)
        {
            this.chunk            = chunk;
            this.collisionPoint   = collisionPoint;
            this.bIsMain          = bIsMain;
            bCancelCollisionEvent = false;
        }
Esempio n. 39
0
    void HandleCollision(Collider other, Vector3 v3CollisionPos, float relativeSpeed)
    {
        if (FracturedObjectSource == null || other == null)
        {
            return;
        }

        if (other.gameObject)
        {
            FracturedChunk otherChunk = other.gameObject.GetComponent <FracturedChunk>();

            if (otherChunk && (other.attachedRigidbody != null))
            {
                if (other.attachedRigidbody.isKinematic && IsDetachedChunk == false)
                {
                    // Just intersecting with other chunk in kinematic state
                    return;
                }
            }
        }

        float fMass = Mathf.Infinity; // If there is no rigidbody we consider it static

        Rigidbody otherRigidbody = other.attachedRigidbody;

        if (otherRigidbody != null)
        {
            fMass = otherRigidbody.mass;
        }

        if (IsDetachedChunk == false)
        {
            // Chunk still attached.
            // We are going to check if the collision is against a free chunk of the same object. This way we prevent chunks pushing each other out, we want to control
            // this only through the FractureObject.InterconnectionStrength variable

            bool bOtherIsFreeChunkFromSameObject = false;

            FracturedChunk otherChunk = other.gameObject.GetComponent <FracturedChunk>();

            if (otherChunk != null)
            {
                if (otherChunk.IsDetachedChunk == true && otherChunk.FracturedObjectSource == FracturedObjectSource)
                {
                    bOtherIsFreeChunkFromSameObject = true;
                }
            }

            if (bOtherIsFreeChunkFromSameObject == false && relativeSpeed > FracturedObjectSource.EventDetachMinVelocity && fMass > FracturedObjectSource.EventDetachMinMass && (GetComponent <Collider>() != null && GetComponent <Collider>().attachedRigidbody) && IsDestructibleChunk())
            {
                CollisionInfo collisionInfo = new CollisionInfo(this, v3CollisionPos, true);
                FracturedObjectSource.NotifyDetachChunkCollision(collisionInfo);

                if (collisionInfo.bCancelCollisionEvent == false)
                {
                    List <FracturedChunk> listBreaks = new List <FracturedChunk>();

                    // Impact enough to make it detach. Compute random list of connected chunks that are detaching as well (we'll use the ConnectionStrength parameter).
                    listBreaks = ComputeRandomConnectionBreaks();
                    listBreaks.Add(this);
                    DetachFromObject();

                    foreach (FracturedChunk chunk in listBreaks)
                    {
                        collisionInfo.chunk   = chunk;
                        collisionInfo.bIsMain = false;
                        collisionInfo.bCancelCollisionEvent = false;

                        if (chunk != this)
                        {
                            FracturedObjectSource.NotifyDetachChunkCollision(collisionInfo);
                        }

                        if (collisionInfo.bCancelCollisionEvent == false)
                        {
                            chunk.DetachFromObject();
                            chunk.GetComponent <Collider>().attachedRigidbody.AddExplosionForce(relativeSpeed * FracturedObjectSource.EventDetachExitForce, otherRigidbody.transform.position, 0.0f, FracturedObjectSource.EventDetachUpwardsModifier);
                        }
                    }
                }
            }
        }
        else
        {
            // Free chunk

            Rigidbody myRigidbody = GetComponent <Collider>().attachedRigidbody;

            Vector3 otherVelocity     = otherRigidbody != null ? otherRigidbody.velocity : Vector3.zero;
            float   relativeSpeedFree = (otherVelocity - myRigidbody.velocity).magnitude;

            if (relativeSpeedFree > FracturedObjectSource.EventDetachedMinVelocity && fMass > FracturedObjectSource.EventDetachedMinMass)
            {
                FracturedObjectSource.NotifyFreeChunkCollision(new CollisionInfo(this, v3CollisionPos, true));
            }
        }
    }