public void Init(GameObject go, SerializedObject so)
        {
            if (go == null)
            {
                return;
            }
            gameObject       = go;
            serializedObject = so; // SerializedObject so = new SerializedObject(assetImporter);
            modelBones       = MyAvatarSetupTool.GetModelBones(gameObject.transform, false, null);

            //m_IsBiped = AvatarBipedMapper.IsBiped(gameObject.transform, null);

            // Handle human bones
            if (m_Bones == null)
            {
                m_Bones = MyAvatarSetupTool.GetHumanBones(serializedObject, modelBones);
            }
            //ValidateMapping();

            //m_CurrentTransformEditorFoldout = true;
            //m_HasSkinnedMesh = (gameObject.GetComponentInChildren<SkinnedMeshRenderer>() != null);

            // Handle pose
            //InitPose();

            //// Repaint
            //SceneView.RepaintAll();
        }
        //protected void PerformAutoMapping()
        //{
        //    AutoMapping();
        //    ValidateMapping();
        //    SceneView.RepaintAll();
        //}

        //protected void PerformBipedMapping()
        //{
        //    BipedMapping();
        //    ValidateMapping();
        //    SceneView.RepaintAll();
        //}

        //protected void AutoMapping()
        //{
        //    Dictionary<int, Transform> mapping = AvatarAutoMapper.MapBones(gameObject.transform, modelBones);
        //    foreach (KeyValuePair<int, Transform> kvp in mapping)
        //    {
        //        MyAvatarSetupTool.BoneWrapper bone = m_Bones[kvp.Key];
        //        bone.bone = kvp.Value;
        //        bone.Serialize(serializedObject);
        //    }
        //}

        //protected void BipedMapping()
        //{
        //    Dictionary<int, Transform> mapping = AvatarBipedMapper.MapBones(gameObject.transform);
        //    foreach (KeyValuePair<int, Transform> kvp in mapping)
        //    {
        //        MyAvatarSetupTool.BoneWrapper bone = m_Bones[kvp.Key];
        //        bone.bone = kvp.Value;
        //        bone.Serialize(serializedObject);
        //    }
        //}

        //protected void ClearMapping()
        //{
        //    if (serializedObject != null)
        //    {
        //        Undo.RegisterCompleteObjectUndo(this, "Clear Mapping");
        //        MyAvatarSetupTool.ClearHumanBoneArray(serializedObject);
        //        ResetBones();
        //        ValidateMapping();
        //        SceneView.RepaintAll();
        //    }
        //}

        //protected Vector4 QuaternionToVector4(Quaternion rot)
        //{
        //    return new Vector4(rot.x, rot.y, rot.z, rot.w);
        //}

        //protected Quaternion Vector4ToQuaternion(Vector4 rot)
        //{
        //    return new Quaternion(rot.x, rot.y, rot.z, rot.w);
        //}

        //protected bool IsAnyBodyPartActive()
        //{
        //    // Avatar body part has nothing to show
        //    for (int i = 1; i < m_BodyPartToggle.Length; i++)
        //    {
        //        if (m_BodyPartToggle[i])
        //            return true;
        //    }
        //    return false;
        //}

        //private void UpdateSelectedBone()
        //{
        //    // Look for selected bone slot
        //    int oldSelectedBoneIndex = s_SelectedBoneIndex;
        //    if (s_SelectedBoneIndex < 0 || s_SelectedBoneIndex >= m_Bones.Length || m_Bones[s_SelectedBoneIndex].bone != Selection.activeTransform)
        //    {
        //        s_SelectedBoneIndex = -1;
        //        if (Selection.activeTransform != null)
        //        {
        //            for (int i = 0; i < m_Bones.Length; i++)
        //            {
        //                if (m_Bones[i].bone == Selection.activeTransform)
        //                {
        //                    s_SelectedBoneIndex = i;
        //                    break;
        //                }
        //            }
        //        }
        //    }
        //    if (s_SelectedBoneIndex != oldSelectedBoneIndex)
        //    {
        //        // If selected bone changed, change visual to show image that contains that bone.
        //        List<int> views = AvatarControl.GetViewsThatContainBone(s_SelectedBoneIndex);
        //        if (views.Count > 0 && !views.Contains(m_BodyView))
        //            m_BodyView = views[0];
        //    }
        //}

        //protected void DisplayFoldout()
        //{
        //    Dictionary<Transform, bool> bones = modelBones;

        //    EditorGUIUtility.SetIconSize(Vector2.one * 16);

        //    // Legend
        //    EditorGUILayout.BeginHorizontal();
        //    GUI.color = Color.grey;
        //    GUILayout.Label(styles.dotFrameDotted.image, GUILayout.ExpandWidth(false));
        //    GUI.color = Color.white;
        //    GUILayout.Label("Optional Bone", GUILayout.ExpandWidth(true));
        //    EditorGUILayout.EndHorizontal();

        //    // Avatar body part has nothing to show
        //    for (int i = 1; i < m_BodyPartToggle.Length; i++)
        //    {
        //        if (m_BodyPartToggle[i])
        //        {
        //            //  Unfold body part ui whenever a new selection is made.
        //            if ((s_DirtySelection == true) && (m_BodyPartFoldout[i] == false))
        //            {
        //                for (int j = 0; j < m_BodyPartHumanBone[i].Length; j++)
        //                {
        //                    int boneIndex = m_BodyPartHumanBone[i][j];
        //                    if (s_SelectedBoneIndex == boneIndex)
        //                        m_BodyPartFoldout[i] = true;
        //                }
        //            }

        //            m_BodyPartFoldout[i] = GUILayout.Toggle(m_BodyPartFoldout[i], styles.BodyPartMapping[i], EditorStyles.foldout);
        //            EditorGUI.indentLevel++;
        //            if (m_BodyPartFoldout[i])
        //            {
        //                for (int j = 0; j < m_BodyPartHumanBone[i].Length; j++)
        //                {
        //                    int boneIndex = m_BodyPartHumanBone[i][j];
        //                    if (boneIndex == -1)
        //                        continue;

        //                    AvatarSetupTool.BoneWrapper bone = m_Bones[boneIndex];
        //                    string displayBoneName = bone.humanBoneName;

        //                    // @TODO@MECANIM: do properly
        //                    if ((BodyPart)i == BodyPart.RightArm || (BodyPart)i == BodyPart.RightFingers || (BodyPart)i == BodyPart.RightLeg)
        //                        displayBoneName = displayBoneName.Replace("Right", "");
        //                    if ((BodyPart)i == BodyPart.LeftArm || (BodyPart)i == BodyPart.LeftFingers || (BodyPart)i == BodyPart.LeftLeg)
        //                        displayBoneName = displayBoneName.Replace("Left", "");

        //                    displayBoneName = ObjectNames.NicifyVariableName(displayBoneName);

        //                    Rect r = EditorGUILayout.GetControlRect();

        //                    Rect selectRect = r;
        //                    selectRect.width -= 15;

        //                    Rect rect = new Rect(r.x + EditorGUI.indent, r.y - 1, AvatarSetupTool.BoneWrapper.kIconSize, AvatarSetupTool.BoneWrapper.kIconSize);

        //                    bone.BoneDotGUI(rect, selectRect, boneIndex, true, false, true, serializedObject, this);
        //                    r.xMin += AvatarSetupTool.BoneWrapper.kIconSize;

        //                    Transform newBoneTransform = EditorGUI.ObjectField(r, new GUIContent(displayBoneName), bone.bone, typeof(Transform), true) as Transform;
        //                    if (newBoneTransform != bone.bone)
        //                    {
        //                        Undo.RegisterCompleteObjectUndo(this, "Avatar mapping modified");
        //                        bone.bone = newBoneTransform;
        //                        bone.Serialize(serializedObject);

        //                        // User adding a bone manually, if it not in the modelBones dict, we must explictly add it
        //                        if (newBoneTransform != null && !bones.ContainsKey(newBoneTransform))
        //                            bones[newBoneTransform] = true;
        //                    }

        //                    if (!string.IsNullOrEmpty(bone.error))
        //                    {
        //                        GUILayout.BeginHorizontal();
        //                        GUILayout.Space(EditorGUI.indent + AvatarSetupTool.BoneWrapper.kIconSize + 4);
        //                        GUILayout.Label(bone.error, s_Styles.errorLabel);
        //                        GUILayout.EndHorizontal();
        //                    }
        //                }
        //            }
        //            EditorGUI.indentLevel--;
        //        }
        //    }

        //    s_DirtySelection = false;

        //    EditorGUIUtility.SetIconSize(Vector2.zero);
        //}

        //bool TransformChanged(Transform tr)
        //{
        //    SerializedProperty bone = MyAvatarSetupTool.FindSkeletonBone(serializedObject, tr, false, false);
        //    if (bone != null)
        //    {
        //        SerializedProperty positionP = bone.FindPropertyRelative(MyAvatarSetupTool.sPosition);
        //        if (positionP != null && positionP.vector3Value != tr.localPosition)
        //            return true;

        //        SerializedProperty rotationP = bone.FindPropertyRelative(MyAvatarSetupTool.sRotation);
        //        if (rotationP != null && rotationP.quaternionValue != tr.localRotation)
        //            return true;

        //        SerializedProperty scaleP = bone.FindPropertyRelative(MyAvatarSetupTool.sScale);
        //        if (scaleP != null && scaleP.vector3Value != tr.localScale)
        //            return true;
        //    }
        //    return false;
        //}

        protected BoneState GetBoneState(int i, out string error)
        {
            error = string.Empty;
            MyAvatarSetupTool.BoneWrapper bone = m_Bones[i];

            if (bone.bone == null)
            {
                return(BoneState.None);
            }

            int ancestorIndex = MyAvatarSetupTool.GetFirstHumanBoneAncestor(m_Bones, i);

            MyAvatarSetupTool.BoneWrapper ancestor = m_Bones[ancestorIndex > 0 ? ancestorIndex : 0];

            if (i == 0 && bone.bone.parent == null)
            {
                error = bone.messageName + " cannot be the root transform";
                return(BoneState.InvalidHierarchy);
            }

            if (ancestor.bone != null && !bone.bone.IsChildOf(ancestor.bone))
            {
                error = bone.messageName + " is not a child of " + ancestor.messageName + ".";
                return(BoneState.InvalidHierarchy);
            }

            if (i == (int)HumanBodyBones.UpperChest)
            {
                MyAvatarSetupTool.BoneWrapper chest = m_Bones[(int)HumanBodyBones.Chest];

                if (chest.bone == null)
                {
                    error = "Chest must be assigned before assigning UpperChest.";
                    return(BoneState.InvalidHierarchy);
                }
            }

            // Hips bone is a special case, for hips GetFirstAnscestor return hips
            if (i != (int)HumanBodyBones.Jaw && ancestor.bone != null && ancestor.bone != bone.bone && (bone.bone.position - ancestor.bone.position).sqrMagnitude < Mathf.Epsilon)
            {
                error = bone.messageName + " has bone length of zero.";
                return(BoneState.BoneLenghtIsZero);
            }

            // Does this transfrom is already set
            //List<BoneWrapper> match = ArrayUtility.FindAll (m_BoneWrappers, delegate (Transform t) { return t == m_BoneWrappers[i].bone; });
            IEnumerable <MyAvatarSetupTool.BoneWrapper> match = m_Bones.Where(f => f.bone == bone.bone);

            // when we search in the list we must add 1 because the bone is in this list
            if (match.Count() > 1)
            {
                error = bone.messageName + " is also assigned to ";
                bool first = true;
                for (int j = 0; j < m_Bones.Length; j++)
                {
                    if (i != j && m_Bones[i].bone == m_Bones[j].bone)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            error += ", ";
                        }
                        error += ObjectNames.NicifyVariableName(m_Bones[j].humanBoneName);
                    }
                }
                error += ".";
                return(BoneState.Duplicate);
            }
            else
            {
                return(BoneState.Valid);
            }
        }
        //private void EnableBodyParts(bool[] toggles, params int[] parts)
        //{
        //    for (int i = 0; i < m_BodyPartToggle.Length; i++)
        //        toggles[i] = false;
        //    foreach (int i in parts)
        //        toggles[i] = true;
        //}

        //private void HandleBodyView(int bodyView)
        //{
        //    if (bodyView == 0)
        //        EnableBodyParts(m_BodyPartToggle, 1, 3, 5, 7, 8);
        //    if (bodyView == 1)
        //        EnableBodyParts(m_BodyPartToggle, 2);
        //    if (bodyView == 2)
        //        EnableBodyParts(m_BodyPartToggle, 4);
        //    if (bodyView == 3)
        //        EnableBodyParts(m_BodyPartToggle, 6);
        //}

        //Vector2 m_FoldoutScroll = Vector2.zero;


        //protected void CopyPrefabPose()
        //{
        //    MyAvatarSetupTool.CopyPose(gameObject, prefab);
        //    AvatarSetupTool.TransferPoseToDescription(serializedObject, root);
        //    m_Inspector.Repaint();
        //}

        //protected void SampleBindPose()
        //{
        //    AvatarSetupTool.SampleBindPose(gameObject);
        //    AvatarSetupTool.TransferPoseToDescription(serializedObject, root);
        //    m_Inspector.Repaint();
        //}

        //protected void BipedPose()
        //{
        //    AvatarBipedMapper.BipedPose(gameObject, m_Bones);

        //    AvatarSetupTool.TransferPoseToDescription(serializedObject, root);
        //    m_Inspector.Repaint();
        //}

        public MyAvatarSetupTool.BoneWrapper[] MakePoseValid()
        {
            MyAvatarSetupTool.MakePoseValid(m_Bones);
            //MyAvatarSetupTool.TransferPoseToDescription(serializedObject, root);
            return(m_Bones);
        }