private void AutoDetect(ModelRenderer target)
        {
            var skinnedMesh = target.transform.GetComponentInChildren <SkinnedMeshRenderer>();

            if (skinnedMesh == null)
            {
                Debug.LogError("Cannot find SkinnedMeshRenderer in " + target.name);
                return;
            }
            target.Hand = skinnedMesh.gameObject;
            // set finger bones
            SetBone(target, "wrist", 0, 1);
            SetBone(target, "thumb", 1, 4);
            SetBone(target, "index", 5, 4);
            SetBone(target, "middle", 9, 4);
            SetBone(target, "ring", 13, 4);
            SetBone(target, "pinky", 17, 4);

            // check left or right
            int leftCount  = CountName(target, "l_", "_l", "_left", "left_");
            int rightCount = CountName(target, "r_", "_r", "_right", "right_");

            if (leftCount == rightCount)
            {
                Debug.LogErrorFormat("Cannot determine left/right for {0}, use current: {1}",
                                     target.name, target.IsLeft ? "left" : "right");
            }
            else
            {
                target.IsLeft = leftCount > rightCount;
            }

            // set initial rotation
            var upDir    = target.Nodes[9].position - target.Nodes[0].position;
            var indexDir = target.Nodes[5].position - target.Nodes[0].position;
            var palmDir  = target.IsLeft ? Vector3.Cross(indexDir, upDir) : Vector3.Cross(upDir, indexDir);
            var rotation = Quaternion.FromToRotation(upDir, Vector3.up);
            var frontDir = rotation * palmDir;
            var angle    = Vector3.Angle(frontDir, Vector3.forward);
            var sign     = Mathf.Sign(Vector3.Dot(Vector3.up, Vector3.Cross(frontDir, Vector3.forward)));

            rotation = Quaternion.AngleAxis(sign * angle, Vector3.up) * rotation * target.transform.rotation;

            var eulerAngles = rotation.eulerAngles;

            eulerAngles.x = ParseAngle(eulerAngles.x);
            eulerAngles.y = ParseAngle(eulerAngles.y);
            eulerAngles.z = ParseAngle(eulerAngles.z);
            TransformUtils.SetInspectorRotation(target.transform, eulerAngles);
            target.initialRotation = TransformUtils.GetInspectorRotation(target.transform);
        }
        private void SetBone(ModelRenderer target, string name, int boneIndex, int count)
        {
            var bones = target.GetComponentsInChildren <Transform>()
                        .Where(t => t.name.ToLower().Contains(name) && t.GetComponent <SkinnedMeshRenderer>() == null)
                        .OrderBy(t => t.hierarchyCount)
                        .ToList();

            if (bones.Count < count)
            {
                Debug.LogErrorFormat("Requires at least {1} bones for {0} finger, found only {2}", name, count, bones.Count);
                return;
            }
            for (int i = bones.Count - count; i < bones.Count; i++, boneIndex++)
            {
                target.Nodes[boneIndex] = bones[i];
            }
        }
        private int CountName(ModelRenderer target, params string[] names)
        {
            int maxCount = 0;

            foreach (var name in names)
            {
                int count = target.Hand.name.ToLower().Contains(name) ? 1 : 0;
                foreach (var node in target.Nodes)
                {
                    count += node.name.ToLower().Contains(name) ? 1 : 0;
                }
                if (count > maxCount)
                {
                    maxCount = count;
                }
            }
            return(maxCount);
        }