//********************************************************************************
        // Private Methods
        //********************************************************************************

        private void OnGUI()
        {
            bool hasAnActiveError = false;

            if (h1Style == null)
            {
                h1Style           = new GUIStyle(GUI.skin.label);
                h1Style.alignment = TextAnchor.MiddleCenter;
                h1Style.fontStyle = FontStyle.Bold;
                h1Style.fontSize  = 14;
            }

            GUILayout.Space(5);

            GUILayout.Label("Animation Converter", h1Style);

            GUILayout.BeginHorizontal();
            {
                GUILayout.FlexibleSpace();
                GUILayout.Label("V" + AnimationConverter.GetVersion());
                GUILayout.FlexibleSpace();
            }
            GUILayout.EndHorizontal();
            GUILayout.Space(8);

            GUILayout.BeginHorizontal();
            {
                if (GUILayout.Button("Reset Configuration"))
                {
                    if (EditorUtility.DisplayDialog("Animation Converter - Reset Configuration", "Do you really want to reset the current configuration?\r\n\r\nAll changes will be lost!", "Yes", "No"))
                    {
                        configuration = new AnimationConverter.Configuration();
                        clipsToConvertList.Clear();
                    }
                }
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Manual"))
                {
                    AnimationConverter.BrowseManual();
                }
                if (GUILayout.Button("Support"))
                {
                    AnimationConverter.BrowseSupport();
                }
            }
            GUILayout.EndHorizontal();

            if (configuration.Prefabs == null)
            {
                configuration.Prefabs = new AnimationConverter.PrefabPair[1];
            }

            GUILayout.Space(4);

            DrawLine(1000, 2, 0, 0, Color.black);

            GUILayout.Space(10);

            AnimationConverter.AnimationType inputAnimationType = AnimationConverter.AnimationType.Legacy;
            bool inputAnimationTypeValid         = false;
            bool multipleDifferentAnimationTypes = false;

            // ---------------------
            // Input
            // ---------------------
            clipsToConvertFoldout = EditorGUILayout.Foldout(clipsToConvertFoldout, "Input");
            if (clipsToConvertFoldout)
            {
                EditorGUI.indentLevel++;

                int  indexToDelete = -1;
                bool anyClipNull   = false;
                GUILayout.BeginHorizontal();
                {
                    GUILayout.Space(20);
                    inputScrollView = EditorGUILayout.BeginScrollView(inputScrollView, GUI.skin.box, GUILayout.Height(150));
                    {
                        for (int index = 0; index < clipsToConvertList.Count; index++)
                        {
                            GUILayout.BeginHorizontal();
                            {
                                GUILayout.BeginVertical(GUILayout.Width(20));
                                {
                                    if (GUILayout.Button("-"))
                                    {
                                        indexToDelete = index;
                                    }
                                }
                                GUILayout.EndVertical();

                                AnimationClip clip = clipsToConvertList[index];
                                if (clip != null)
                                {
                                    AnimationConverter.AnimationType animType = AnimationConverter.GetAnimationType(clip);
                                    if (!inputAnimationTypeValid)
                                    {
                                        inputAnimationType      = animType;
                                        inputAnimationTypeValid = true;
                                    }
                                    else
                                    {
                                        if (animType != inputAnimationType)
                                        {
                                            multipleDifferentAnimationTypes = true;
                                        }
                                    }

                                    GUILayout.Label(animType.ToString(), GUILayout.Width(70));
                                }
                                else
                                {
                                    GUILayout.Label("", GUILayout.Width(70));

                                    anyClipNull = true;
                                }

                                clipsToConvertList[index] = (AnimationClip)EditorGUILayout.ObjectField(clip, typeof(AnimationClip), false);
                            }
                            GUILayout.EndHorizontal();
                        }
                    }
                    EditorGUILayout.EndScrollView();
                }
                GUILayout.EndHorizontal();

                if (indexToDelete >= 0)
                {
                    clipsToConvertList.RemoveAt(indexToDelete);
                }

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Space(20);
                    GUILayout.BeginHorizontal(GUI.skin.box, GUILayout.Height(40));
                    {
                        GUILayout.FlexibleSpace();
                        GUILayout.BeginVertical();
                        {
                            GUILayout.FlexibleSpace();
                            GUILayout.Label("Drag & Drop Animation Clips Here");
                            GUILayout.FlexibleSpace();
                        }
                        GUILayout.EndVertical();
                        GUILayout.FlexibleSpace();
                    }
                    GUILayout.EndHorizontal();

                    Rect     lastRect       = GUILayoutUtility.GetLastRect();
                    Object[] droppedObjects = DragAndDropReceiver(lastRect, new System.Type[] { typeof(AnimationClip), typeof(GameObject) }, true);
                    if (droppedObjects != null)
                    {
                        foreach (Object droppedObj in droppedObjects)
                        {
                            AnimationClip animationClip = droppedObj as AnimationClip;

                            if (animationClip != null)
                            {
                                clipsToConvertList.Add(animationClip);
                            }
                            else
                            {
                                string assetPath = AssetDatabase.GetAssetPath(droppedObj);

                                Object[] allAssets = AssetDatabase.LoadAllAssetsAtPath(assetPath);

                                foreach (Object asset in allAssets)
                                {
                                    animationClip = asset as AnimationClip;
                                    if ((animationClip != null) && !animationClip.name.StartsWith("__preview__"))
                                    {
                                        clipsToConvertList.Add(animationClip);
                                    }
                                }
                            }
                        }
                    }
                }
                GUILayout.EndHorizontal();

                if (anyClipNull)
                {
                    EditorGUILayout.HelpBox("Entries with no clip assigned need to be removed.", MessageType.Error);

                    hasAnActiveError = true;
                }

                List <string> clipsWithDuplicateNames = GetClipsWithDuplicateNames(clipsToConvertList);
                if (clipsWithDuplicateNames.Count > 0)
                {
                    string helpText = "The following clip names are not unique:";
                    foreach (string clipName in clipsWithDuplicateNames)
                    {
                        helpText += string.Format("\r\n\"{0}\"", clipName);
                    }
                    EditorGUILayout.HelpBox(helpText, MessageType.Error);

                    hasAnActiveError = true;
                }

                if (multipleDifferentAnimationTypes)
                {
                    EditorGUILayout.HelpBox("All clips need to be of the same animation type.", MessageType.Error);

                    hasAnActiveError = true;
                }

                EditorGUI.indentLevel--;
            }

            // ---------------------
            // Output
            // ---------------------
            GUILayout.Space(10);
            convertToFoldout = EditorGUILayout.Foldout(convertToFoldout, "Output");
            if (convertToFoldout)
            {
                EditorGUI.indentLevel++;
                float originalLabelWidth = EditorGUIUtility.labelWidth;
                EditorGUIUtility.labelWidth = 125;

                configuration.DestinationAnimationType = (AnimationConverter.AnimationType)EditorGUILayout.EnumPopup(animationTypeContent, configuration.DestinationAnimationType);

                if (inputAnimationTypeValid && (configuration.DestinationAnimationType == inputAnimationType))
                {
                    EditorGUILayout.HelpBox("The output anmiation type must be different then the input animation type.", MessageType.Error);

                    hasAnActiveError = true;
                }

                GUILayout.BeginHorizontal();
                {
                    configuration.OutputDirectory = EditorGUILayout.TextField(outputDirectoryContent, configuration.OutputDirectory);

                    GUILayout.BeginVertical(GUILayout.Width(40));
                    {
                        if (GUILayout.Button("..."))
                        {
                            configuration.OutputDirectory = BrowseDirectory("Open Folder", configuration.OutputDirectory);
                        }
                    }
                    GUILayout.EndVertical();
                }
                GUILayout.EndHorizontal();

                if (!AssetDatabase.IsValidFolder(configuration.OutputDirectory))
                {
                    EditorGUILayout.HelpBox("Invalid output directory. The directory needs to be a child of the \"Assets\" folder.", MessageType.Error);

                    hasAnActiveError = true;
                }

                EditorGUIUtility.labelWidth = originalLabelWidth;
                EditorGUI.indentLevel--;
            }

            // ---------------------
            // Settings
            // ---------------------

            GUILayout.Space(10);
            settingsFoldout = EditorGUILayout.Foldout(settingsFoldout, "Settings");
            if (settingsFoldout)
            {
                EditorGUI.indentLevel++;

                if (inputAnimationTypeValid)
                {
                    float originalLabelWidth = EditorGUIUtility.labelWidth;
                    EditorGUIUtility.labelWidth = 170;

                    bool anySettingsShow = false;
                    if ((inputAnimationType == AnimationConverter.AnimationType.Humanoid) ||
                        (configuration.DestinationAnimationType == AnimationConverter.AnimationType.Humanoid))
                    {
                        configuration.KeyReduction = (AnimationConverter.KeyReductionMode)EditorGUILayout.EnumPopup(keyReductionContent, configuration.KeyReduction);
                        if (configuration.KeyReduction == AnimationConverter.KeyReductionMode.Lossy)
                        {
                            configuration.KeyReductionPositionError = EditorGUILayout.FloatField(positionErrorContent, configuration.KeyReductionPositionError);
                            configuration.KeyReductionRotationError = EditorGUILayout.FloatField(rotationErrorContent, configuration.KeyReductionRotationError);
                            configuration.KeyReductionScaleError    = EditorGUILayout.FloatField(scaleErrorContent, configuration.KeyReductionScaleError);
                        }

                        anySettingsShow = true;
                    }

                    if (configuration.DestinationAnimationType == AnimationConverter.AnimationType.Humanoid)
                    {
                        configuration.HumanoidKeepExtraGenericBones = EditorGUILayout.Toggle(keepExtraBonesContent, configuration.HumanoidKeepExtraGenericBones);

                        anySettingsShow = true;
                    }
                    else if (inputAnimationType == AnimationConverter.AnimationType.Humanoid)
                    {
                        configuration.SampleHumanoidHandIK = EditorGUILayout.Toggle(humanoidHandIkContent, configuration.SampleHumanoidHandIK);
                        configuration.SampleHumanoidFootIK = EditorGUILayout.Toggle(humanoidFootIkContent, configuration.SampleHumanoidFootIK);

                        GUILayout.BeginHorizontal();
                        {
                            GUILayout.Space(20);
                            GUILayout.Label(constrainRootPositionContent, GUILayout.Width(150));
                            configuration.ConstrainRootMotionPosition.ConstrainX = GUILayout.Toggle(configuration.ConstrainRootMotionPosition.ConstrainX, "X");
                            configuration.ConstrainRootMotionPosition.ConstrainY = GUILayout.Toggle(configuration.ConstrainRootMotionPosition.ConstrainY, "Y");
                            configuration.ConstrainRootMotionPosition.ConstrainZ = GUILayout.Toggle(configuration.ConstrainRootMotionPosition.ConstrainZ, "Z");
                            GUILayout.FlexibleSpace();
                        }
                        GUILayout.EndHorizontal();

                        GUILayout.BeginHorizontal();
                        {
                            GUILayout.Space(20);
                            GUILayout.Label(constrainRootRotationContent, GUILayout.Width(150));
                            configuration.ConstrainRootMotionRotation.ConstrainX = GUILayout.Toggle(configuration.ConstrainRootMotionRotation.ConstrainX, "X");
                            configuration.ConstrainRootMotionRotation.ConstrainY = GUILayout.Toggle(configuration.ConstrainRootMotionRotation.ConstrainY, "Y");
                            configuration.ConstrainRootMotionRotation.ConstrainZ = GUILayout.Toggle(configuration.ConstrainRootMotionRotation.ConstrainZ, "Z");
                            GUILayout.FlexibleSpace();
                        }
                        GUILayout.EndHorizontal();

                        anySettingsShow = true;
                    }

                    EditorGUIUtility.labelWidth = originalLabelWidth;

                    if (!anySettingsShow)
                    {
                        EditorGUILayout.LabelField("No settings require");
                    }
                }
                else
                {
                    EditorGUILayout.HelpBox("Please assign the input clip(s) first.", MessageType.Warning);
                }
                EditorGUI.indentLevel--;
            }

            // ---------------------
            // Prefabs
            // ---------------------
            GUILayout.Space(10);
            gameObjectsFoldout = EditorGUILayout.Foldout(gameObjectsFoldout, "Prefabs");
            if (gameObjectsFoldout)
            {
                EditorGUI.indentLevel++;
                string helpText = string.Format("The model related to the animation clips needs to be assigned once using the animation type of the source clips and once using the destination animation type.\r\n\r\n1) Duplicate the original model in Unity's Project Window.\r\n\r\n2) Change the animation type of the duplicated model to the desired animation type and click on Apply.\r\n\r\n3) Drag & Drop the duplicated model to the appropriate field:", configuration.DestinationAnimationType);
                EditorGUILayout.HelpBox(helpText, MessageType.Info);
                EditorGUI.indentLevel--;

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Space(20);

                    int removePrefabIndex = -1;
                    if (configuration.Prefabs.Length > 1)
                    {
                        GUILayout.BeginVertical(GUILayout.Width(20));
                        {
                            GUILayout.Space(38);
                            for (int prefabIndex = 1; prefabIndex < configuration.Prefabs.Length; prefabIndex++)
                            {
                                if (GUILayout.Button("-", GUILayout.Height(15)))
                                {
                                    removePrefabIndex = prefabIndex;
                                }
                            }
                        }
                        GUILayout.EndVertical();
                    }

                    GUILayout.BeginVertical();
                    {
                        if (inputAnimationTypeValid)
                        {
                            inputPrefabContent.text = string.Format("Input ({0})", inputAnimationType);
                        }
                        else
                        {
                            inputPrefabContent.text = "Input";
                        }
                        GUILayout.Label(inputPrefabContent);

                        for (int prefabIndex = 0; prefabIndex < configuration.Prefabs.Length; prefabIndex++)
                        {
                            AnimationConverter.PrefabPair prefabPair = configuration.Prefabs[prefabIndex];

                            prefabPair.SourcePrefab = (GameObject)EditorGUILayout.ObjectField("", prefabPair.SourcePrefab, typeof(GameObject), false, GUILayout.MinWidth(100), GUILayout.ExpandWidth(true));

                            if (inputAnimationTypeValid && (prefabPair.SourcePrefab != null))
                            {
                                string errorMessage;
                                AnimationConverter.AnimationType sourceAnimationType = DetermineAnimationType(prefabPair.SourcePrefab, out errorMessage);

                                if (!string.IsNullOrEmpty(errorMessage))
                                {
                                    EditorGUILayout.HelpBox(errorMessage, MessageType.Error);
                                    hasAnActiveError = true;
                                }
                                else if (sourceAnimationType != inputAnimationType)
                                {
                                    EditorGUILayout.HelpBox(string.Format("The prefab's animation type is {0} but should be {1}", sourceAnimationType, inputAnimationType), MessageType.Error);
                                    hasAnActiveError = true;
                                }
                            }

                            configuration.Prefabs[prefabIndex] = prefabPair;
                        }
                    }
                    GUILayout.EndVertical();

                    GUILayout.BeginVertical();
                    {
                        outputPrefabContent.text = string.Format("Output ({0})", configuration.DestinationAnimationType);
                        GUILayout.Label(outputPrefabContent);

                        for (int prefabIndex = 0; prefabIndex < configuration.Prefabs.Length; prefabIndex++)
                        {
                            AnimationConverter.PrefabPair prefabPair = configuration.Prefabs[prefabIndex];

                            prefabPair.DestinationPrefab = (GameObject)EditorGUILayout.ObjectField("", prefabPair.DestinationPrefab, typeof(GameObject), false, GUILayout.MinWidth(100), GUILayout.ExpandWidth(true));

                            if (prefabPair.DestinationPrefab != null)
                            {
                                string errorMessage;
                                AnimationConverter.AnimationType animationType = DetermineAnimationType(prefabPair.DestinationPrefab, out errorMessage);

                                if (!string.IsNullOrEmpty(errorMessage))
                                {
                                    EditorGUILayout.HelpBox(errorMessage, MessageType.Error);
                                    hasAnActiveError = true;
                                }
                                else if (animationType != configuration.DestinationAnimationType)
                                {
                                    EditorGUILayout.HelpBox(string.Format("The prefab's animation type is {0} but should be {1}", animationType, configuration.DestinationAnimationType), MessageType.Error);
                                    hasAnActiveError = true;
                                }
                            }

                            configuration.Prefabs[prefabIndex] = prefabPair;
                        }
                    }
                    GUILayout.EndVertical();

                    if (removePrefabIndex >= 0)
                    {
                        List <AnimationConverter.PrefabPair> prefabsList = configuration.Prefabs.ToList();
                        prefabsList.RemoveAt(removePrefabIndex);
                        configuration.Prefabs = prefabsList.ToArray();
                    }
                }
                GUILayout.EndHorizontal();

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Space(20);

                    if (GUILayout.Button("Add Row"))
                    {
                        System.Array.Resize(ref configuration.Prefabs, configuration.Prefabs.Length + 1);
                    }
                }
                GUILayout.EndHorizontal();
            }

            GUILayout.Space(10);

            // ---------------------
            // Convert Button
            // ---------------------

            if (GUILayout.Button("Convert", GUILayout.Height(30)))
            {
                if (clipsToConvertList.Count <= 0)
                {
                    EditorUtility.DisplayDialog("Animation Converter - Couldn't start Conversion", "No clips to convert.", "OK");
                }
                else if (hasAnActiveError)
                {
                    EditorUtility.DisplayDialog("Animation Converter - Couldn't start Conversion", "Please fix all errors first.", "OK");
                }
                else if ((configuration.Prefabs[0].SourcePrefab == null) ||
                         (configuration.Prefabs[0].DestinationPrefab == null))
                {
                    EditorUtility.DisplayDialog("Animation Converter - Couldn't start Conversion", "Please assign the correct prefabs first.", "OK");
                }
                else
                {
                    string errorMessage             = "This action would overwrite the following input clips:";
                    bool   wouldOverwriteInputClips = false;
                    foreach (AnimationClip clip in clipsToConvertList)
                    {
                        string path = AssetDatabase.GetAssetPath(clip);

                        if (System.IO.Path.GetDirectoryName(path) == configuration.OutputDirectory)
                        {
                            errorMessage            += string.Format("\r\n\"{0}.anim\"", clip.name);
                            wouldOverwriteInputClips = true;
                        }
                    }

                    if (wouldOverwriteInputClips)
                    {
                        errorMessage += "\r\n\r\nPlease choose a different output directory.";
                        EditorUtility.DisplayDialog("Animation Converter - Couldn't start Conversion", errorMessage, "OK");
                    }
                    else
                    {
                        try
                        {
                            string logMessages;
                            AnimationConverter.Convert(clipsToConvertList.ToArray(), configuration, out logMessages);

                            AnimationConverterLogWindow.ShowDialog(logMessages);
                        }
                        catch (System.Exception ex)
                        {
                            Debug.LogException(ex);

                            EditorUtility.DisplayDialog("Animation Converter - An Error Occured", ex.Message + "\r\n\r\nA detailed error message is printed to the console.", "OK");
                        }
                    }
                }
            }
        }