public static void RotatePivotForMeshless(GameObject meshlessObject, Quaternion newRotation, bool preserveState)
        {
            if (preserveState)
            {
                childrenStatesBeforePivotMod = UtilityServices.SaveChildrenStates(meshlessObject);
            }

            meshlessObject.transform.rotation = newRotation;

            //new UtilityServices().RunAfter(()=> { RestoreChildrenStates(); }, new WaitForEndOfFrame());

            if (preserveState)
            {
                UtilityServices.RestoreChildrenStates(childrenStatesBeforePivotMod);
            }
        }
        public static GameObject CreateChildNavMeshObs(GameObject forObject, bool forPosition)
        {
            string navMeshObsName = "";

            var navMeshObstacle = forObject.GetComponent <NavMeshObstacle>();

            if (navMeshObstacle == null)
            {
                return(null);
            }


            navMeshObsName = forObject.name + "_NavMeshObstacle";
            navMeshObsName = "**" + navMeshObsName + "_DON'T DELETE**";

            GameObject childNavMeshObs = UtilityServices.DuplicateGameObject(forObject, navMeshObsName, false, false);

            foreach (Component component in childNavMeshObs.GetComponents <Component>())
            {
                if (component is Transform || component is NavMeshObstacle)
                {
                    continue;
                }

                DestroyImmediate(component);
            }

            navMeshObstacle.enabled = false;

            childNavMeshObs.transform.position = forObject.transform.position;
            childNavMeshObs.transform.rotation = forObject.transform.rotation;

            childNavMeshObs.transform.parent = forObject.transform;
            childNavMeshObs.AddComponent <NavObsRecognize>();


            return(childNavMeshObs);
        }
        public static GameObject CreateChildCollider(GameObject forObject, bool forPosition, Vector3?newPivotPos, Quaternion?newPivotRot)
        {
            string colliderName = "";

            var colliders = forObject.GetComponents <Collider>();

            if (colliders == null || colliders.Length == 0)
            {
                return(null);
            }


            #region Setting name of the child collider and disabling original colliders

            ColliderType lastType = ColliderType.None;

            foreach (Collider collider in colliders)
            {
                ColliderType currentType;
                //collider.enabled = false;


                if (collider is BoxCollider)
                {
                    currentType  = ColliderType.BoxCollider;
                    colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType);

                    if (lastType != ColliderType.None)
                    {
                        if (lastType != currentType)
                        {
                            colliderName = forObject.name + "_MixedColliders";
                            break;
                        }

                        else
                        {
                            colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType) + "s";
                        }
                    }

                    lastType = currentType;
                }

                else if (collider is CapsuleCollider)
                {
                    currentType  = ColliderType.CapsuleCollider;
                    colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType);

                    if (lastType != ColliderType.None)
                    {
                        if (lastType != currentType)
                        {
                            colliderName = forObject.name + "_MixedColliders";
                            break;
                        }

                        else
                        {
                            colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType) + "s";
                        }
                    }

                    lastType = currentType;
                }

                else if (collider is SphereCollider)
                {
                    currentType  = ColliderType.SphereCollider;
                    colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType);

                    if (lastType != ColliderType.None)
                    {
                        if (lastType != currentType)
                        {
                            colliderName = forObject.name + "_MixedColliders";
                            break;
                        }

                        else
                        {
                            colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType) + "s";
                        }
                    }

                    lastType = currentType;
                }

                else if (collider is MeshCollider)
                {
                    currentType  = ColliderType.MeshCollider;
                    colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType);

                    if (lastType != ColliderType.None)
                    {
                        if (lastType != currentType)
                        {
                            colliderName = forObject.name + "_MixedColliders";
                            break;
                        }

                        else
                        {
                            colliderName = forObject.name + "_" + Enum.GetName(typeof(ColliderType), currentType) + "s";
                        }
                    }

                    lastType = currentType;
                }
            }

            #endregion Setting name of the child collider and disabling original colliders


            colliderName = "**" + colliderName + "_DON'T DELETE**";
            GameObject childCollider = UtilityServices.DuplicateGameObject(forObject, colliderName, false, false);

            foreach (Component component in childCollider.GetComponents <Component>())
            {
                if (component is Transform || component is Collider)
                {
                    continue;
                }

                DestroyImmediate(component);
            }



            foreach (Collider collider in forObject.GetComponents <Collider>())
            {
                if (collider.enabled && forPosition)
                {
                    collider.enabled = true;
                }

                else
                {
                    collider.enabled = false;
                }
            }

            childCollider.transform.parent = forObject.transform;
            childCollider.AddComponent <CollRecognize>();

            Collider coll = forObject.GetComponent <Collider>();

            if (coll && coll is MeshCollider)
            {
                if (newPivotPos != null)
                {
                    //childCollider.transform.position = (Vector3)newPivotPos;
                }

                else if (newPivotRot != null)
                {
                    //childCollider.transform.rotation = (Quaternion)newPivotRot;
                }
            }

            return(childCollider);
        }
        public static void RotatePivot(GameObject forObject, Quaternion newRotation, bool preserveState)
        {
            RecognizeObject(forObject);

            if (!CheckObject(forObject))
            {
                return;
            }


            // Transform.TransformPoint and InversetransformPoint have high performance implications


            if (preserveState)
            {
                var collRecognize   = forObject.GetComponentsInChildren <CollRecognize>();
                var navObsRecognize = forObject.GetComponentsInChildren <NavObsRecognize>();


                if (collRecognize == null || collRecognize.Length == 0)
                {
                    GameObject childColl = UtilityServices.CreateChildCollider(forObject, false, null, newRotation);
                    if (childColl)
                    {
                        Debug.Log(string.Format("<b><i><color=#0080ffff>The Collider(s) on \"{0}\" has been disabled.Due to pivot modification colliders get incorrectly oriented.To preserve the same collider orientation as the one before pivot modification, the original collider has been added to a child GameObject \"{1}\" use that as the collider for this GameObject. Please don't delete this child object otherwise any subsequent changes made to modify pivot cannot guarantee correct collider orientation. </color></i></b>", forObject.name, childColl.name));
                    }
                }


                if (navObsRecognize == null || navObsRecognize.Length == 0)
                {
                    GameObject childNavObs = UtilityServices.CreateChildNavMeshObs(forObject, true);
                    if (childNavObs)
                    {
                        Debug.Log(string.Format("<b><i><color=#0080ffff>The NavMeshObstacle on \"{0}\" has been disabled.Due to pivot modifcation NavMeshObstacles get incorrectly oriented.To preserve the same orientation as the one before pivot modification, the original NavMeshObstacle has been added to a child GameObject \"{1}\" use that as the NavMeshObstacle for this GameObject. Please don't delete this child object otherwise any subsequent changes made to modify pivot cannot guarantee correct NavMeshObstacle orientation. </color></i></b>", forObject.name, childNavObs.name));
                    }
                }

                // Save children positions before pivotal modifications
                childrenStatesBeforePivotMod = UtilityServices.SaveChildrenStates(forObject);
                // Save the postion and rotation of the collider before pivotal modification
                //SaveColliderState();
            }



            GameObject tempObject = new GameObject();

            tempObject.transform.parent   = forObject.transform;
            tempObject.transform.rotation = newRotation;
            Quaternion inverseRotation = Quaternion.Inverse(tempObject.transform.localRotation);


            Quaternion prevRotation = forObject.transform.rotation;

            DestroyImmediate(tempObject);


            //Vector3 oldScale = forObject.transform.localScale;
            //forObject.transform.localScale = new Vector3(1, 1, 1);

            Matrix4x4 transformationMatrix = Matrix4x4.Rotate(inverseRotation);

            forObject.transform.rotation = newRotation;

            Vector3[] vertices = selectedObjectMesh.vertices;
            Vector3[] normals  = selectedObjectMesh.normals;


            //Debug.Log("submeshes count  " + forObject.GetComponent<MeshFilter>().sharedMesh.subMeshCount + "  vertex count   "  + vertices.Length);


            for (int a = 0; a < vertices.Length; a++)
            {
                vertices[a] = transformationMatrix.MultiplyPoint3x4(vertices[a]);
                normals[a]  = transformationMatrix.MultiplyPoint3x4(normals[a]);
            }

            selectedObjectMesh.vertices = vertices;
            selectedObjectMesh.normals  = normals;

            selectedObjectMesh.RecalculateBounds();



            if (preserveState)
            {
                // Restore children positions and rotations as they were before pivotal modifications
                //new UtilityServices().RunAfter(() => { RestoreChildrenStates(); }, new WaitForEndOfFrame);
                UtilityServices.RestoreChildrenStates(childrenStatesBeforePivotMod);
            }
        }
        public static void MovePivot(GameObject forObject, Vector3 moveTo, bool preserveState)
        {
            RecognizeObject(forObject);

            if (!CheckObject(forObject))
            {
                return;
            }

            NavMeshObstacle      obs   = forObject.GetComponent <NavMeshObstacle>();
            NavMeshObstacleShape shape = NavMeshObstacleShape.Box;

            if (preserveState)
            {
                var collRecognize   = forObject.GetComponentsInChildren <CollRecognize>();
                var navObsRecognize = forObject.GetComponentsInChildren <NavObsRecognize>();

                if (collRecognize == null || collRecognize.Length == 0)
                {
                    GameObject childColl = UtilityServices.CreateChildCollider(forObject, true, moveTo, null);
                    if (childColl)
                    {
                        Debug.Log(string.Format("<b><i><color=#0080ffff>The Collider(s) on \"{0}\" has been disabled.Due to pivot modification colliders get incorrectly oriented.To preserve the same collider orientation as the one before pivot modification, the original collider has been added to a child GameObject \"{1}\" use that as the collider for this GameObject. Please don't delete this child object otherwise any subsequent changes made to modify pivot cannot guarantee correct collider orientation. </color></i></b>", forObject.name, childColl.name));
                    }
                }


                if (navObsRecognize == null || navObsRecognize.Length == 0)
                {
                    GameObject childNavObs = UtilityServices.CreateChildNavMeshObs(forObject, true);
                    if (childNavObs)
                    {
                        Debug.Log(string.Format("<b><i><color=#0080ffff>The NavMeshObstacle on \"{0}\" has been disabled.Due to pivot modifcation NavMeshObstacles get incorrectly oriented.To preserve the same orientation as the one before pivot modification, the original NavMeshObstacle has been added to a child GameObject \"{1}\" use that as the NavMeshObstacle for this GameObject. Please don't delete this child object otherwise any subsequent changes made to modify pivot cannot guarantee correct NavMeshObstacle orientation. </color></i></b>", forObject.name, childNavObs.name));
                    }
                }


                // Save children positions before pivotal modifications
                childrenStatesBeforePivotMod = UtilityServices.SaveChildrenStates(forObject);

                // Save the position and rotation of the collider before pivotal modification
                collStateBeforeMod = UtilityServices.SaveColliderState(forObject);

                if (obs)
                {
                    shape = obs.shape;
                    if (shape == NavMeshObstacleShape.Box)
                    {
                        obs.shape = NavMeshObstacleShape.Capsule;
                    }
                    else
                    {
                        obs.shape = NavMeshObstacleShape.Box;
                    }
                }
            }



            Vector3[] vertices = selectedObjectMesh.vertices;

            //Vector3 objCenterWorldSpace = selectedObject.transform.TransformPoint(selectedObjCenterLocalSpace);   // The world space position where the pivot will be moved and centered to the object

            Vector3 pivotOffsetLocalSpace = forObject.transform.InverseTransformVector(forObject.transform.position - moveTo);

            Matrix4x4 transformationMatrix = Matrix4x4.Translate(pivotOffsetLocalSpace);

            //var stopWatch = new System.Diagnostics.Stopwatch();
            //stopWatch.Start();


            for (int a = 0; a < vertices.Length; a++)
            {
                vertices[a] = transformationMatrix.MultiplyPoint3x4(vertices[a]);
            }


            //stopWatch.Stop();
            //UnityEngine.Debug.Log("Editor time for pivot centralization  " + stopWatch.ElapsedMilliseconds + "  for iterations  " + vertices.Length);

            selectedObjectMesh.vertices = vertices;    //Assign the vertex array back to the mesh

            selectedObjectMesh.RecalculateBounds();



            forObject.transform.position = moveTo;   // Move the object to the previous position


            if (preserveState)
            {
                if (obs)
                {
                    obs.shape = shape;
                }

                UtilityServices.RestoreColliderState(forObject, collStateBeforeMod);
                // Restore children positions and rotations as they were before pivotal modifications
                //new UtilityServices().RunAfter(()=> { RestoreChildrenStates();  }, new WaitForEndOfFrame);
                UtilityServices.RestoreChildrenStates(childrenStatesBeforePivotMod);
            }
        }