void OnEnable()
    {
        if (!EditorGUIUtility.isProSkin)
        {
            logo = (Texture2D)EditorGUIUtility.Load("Rogo Digital/Eye Controller/Light/EyeController_logo.png");
        }
        else
        {
            logo = (Texture2D)EditorGUIUtility.Load("Rogo Digital/Eye Controller/Dark/EyeController_logo.png");
        }

        myTarget = (EyeController)target;

        blendSystemNumber = BlendSystemEditor.FindBlendSystems(myTarget);

        boneUpdateAnimation = serializedObject.FindProperty("boneUpdateAnimation");

        blinkingEnabled     = serializedObject.FindProperty("blinkingEnabled");
        blinkingControlMode = serializedObject.FindProperty("blinkingControlMode");

        leftEyeBlinkBlendshape  = serializedObject.FindProperty("leftEyeBlinkBlendable");
        rightEyeBlinkBlendshape = serializedObject.FindProperty("rightEyeBlinkBlendable");

        minimumBlinkGap = serializedObject.FindProperty("minimumBlinkGap");
        maximumBlinkGap = serializedObject.FindProperty("maximumBlinkGap");
        blinkDuration   = serializedObject.FindProperty("blinkDuration");

        leftEyeLookAtBone  = serializedObject.FindProperty("_leftEyeLookAtBone");
        rightEyeLookAtBone = serializedObject.FindProperty("_rightEyeLookAtBone");
        eyeRotationRangeX  = serializedObject.FindProperty("eyeRotationRangeX");
        eyeRotationRangeY  = serializedObject.FindProperty("eyeRotationRangeY");

        eyeLookOffset  = serializedObject.FindProperty("eyeLookOffset");
        eyeForwardAxis = serializedObject.FindProperty("eyeForwardAxis");
        eyeTurnSpeed   = serializedObject.FindProperty("eyeTurnSpeed");

        randomLookingEnabled = serializedObject.FindProperty("randomLookingEnabled");
        lookingControlMode   = serializedObject.FindProperty("lookingControlMode");

        minimumChangeDirectionGap = serializedObject.FindProperty("minimumChangeDirectionGap");
        maximumChangeDirectionGap = serializedObject.FindProperty("maximumChangeDirectionGap");

        targetEnabled = serializedObject.FindProperty("targetEnabled");

        viewTarget   = serializedObject.FindProperty("viewTarget");
        targetWeight = serializedObject.FindProperty("targetWeight");

        autoTarget         = serializedObject.FindProperty("autoTarget");
        autoTargetTag      = serializedObject.FindProperty("autoTargetTag");
        autoTargetDistance = serializedObject.FindProperty("autoTargetDistance");

        showBlinking               = new AnimBool(myTarget.blinkingEnabled, Repaint);
        showRandomLook             = new AnimBool(myTarget.randomLookingEnabled, Repaint);
        showLookTarget             = new AnimBool(myTarget.targetEnabled, Repaint);
        showAutoTarget             = new AnimBool(myTarget.autoTarget, Repaint);
        showLookShared             = new AnimBool(myTarget.randomLookingEnabled || myTarget.targetEnabled, Repaint);
        showBlinkingClassicControl = new AnimBool(myTarget.blinkingControlMode == EyeController.ControlMode.Classic, Repaint);
        showLookingClassicControl  = new AnimBool(myTarget.lookingControlMode == EyeController.ControlMode.Classic, Repaint);

        if (myTarget.blendSystem != null)
        {
            if (myTarget.blendSystem.isReady)
            {
                myTarget.blendSystem.onBlendablesChanged += GetBlendShapes;
                GetBlendShapes();
                BlendSystemEditor.GetBlendSystemButtons(myTarget.blendSystem);
            }
        }
    }
    public override void OnInspectorGUI()
    {
        // Create styles if necesarry
        if (inlineToolbar == null)
        {
            inlineToolbar             = new GUIStyle((GUIStyle)"TE toolbarbutton");
            inlineToolbar.fixedHeight = 0;
            inlineToolbar.fixedWidth  = 0;
        }

        LipSyncEditorExtensions.BeginPaddedHorizontal();
        GUILayout.Box(logo, GUIStyle.none);
        LipSyncEditorExtensions.EndPaddedHorizontal();

        GUILayout.Space(20);

        serializedObject.Update();

        Rect lineRect;

        EditorGUILayout.HelpBox("Enable or disable Eye Controller functionality below.", MessageType.Info);

        GUILayout.Space(10);

        blendSystemNumber = BlendSystemEditor.DrawBlendSystemEditor(myTarget, blendSystemNumber, "EyeController requires a blend system to function.");

        if (myTarget.blendSystem != null)
        {
            if (myTarget.blendSystem.isReady)
            {
                if (blendables == null)
                {
                    myTarget.blendSystem.onBlendablesChanged += GetBlendShapes;
                    GetBlendShapes();
                }

                EditorGUILayout.PropertyField(boneUpdateAnimation, new GUIContent("Account for Animation", "If true, will calculate relative bone positions/rotations each frame. Improves results when using animation, but will cause errors when not."));
                GUILayout.Space(10);
                BlendSystemEditor.DrawBlendSystemButtons(myTarget.blendSystem);
                GUILayout.Space(10);

                // Blinking
                lineRect = EditorGUILayout.BeginHorizontal();
                GUI.Box(lineRect, "", (GUIStyle)"flow node 0");
                GUILayout.Space(10);
                blinkingEnabled.boolValue = EditorGUILayout.ToggleLeft("Blinking", blinkingEnabled.boolValue, EditorStyles.largeLabel, GUILayout.ExpandWidth(true), GUILayout.Height(24));
                showBlinking.target       = blinkingEnabled.boolValue;
                GUILayout.FlexibleSpace();
                blinkingControlMode.enumValueIndex = GUILayout.Toolbar(blinkingControlMode.enumValueIndex, System.Enum.GetNames(typeof(EyeController.ControlMode)), inlineToolbar, GUILayout.MaxWidth(300), GUILayout.Height(24));
                showBlinkingClassicControl.target  = blinkingControlMode.enumValueIndex == (int)EyeController.ControlMode.Classic;
                EditorGUILayout.EndHorizontal();
                EditorGUI.indentLevel++;
                if (EditorGUILayout.BeginFadeGroup(showBlinking.faded))
                {
                    GUILayout.Space(5);

                    // Classic Mode
                    if (EditorGUILayout.BeginFadeGroup(showBlinkingClassicControl.faded))
                    {
                        if (blendables != null)
                        {
                            leftEyeBlinkBlendshape.intValue  = EditorGUILayout.Popup("Left Eye Blink Blendshape", leftEyeBlinkBlendshape.intValue, blendables, GUILayout.MaxWidth(500));
                            rightEyeBlinkBlendshape.intValue = EditorGUILayout.Popup("Right Eye Blink Blendshape", rightEyeBlinkBlendshape.intValue, blendables, GUILayout.MaxWidth(500));
                        }
                    }
                    LipSyncEditorExtensions.FixedEndFadeGroup(showBlinkingClassicControl.faded);

                    // Pose Mode
                    if (EditorGUILayout.BeginFadeGroup(1 - showBlinkingClassicControl.faded))
                    {
                        this.DrawShapeEditor(myTarget.blendSystem, blendables, true, true, myTarget.blinkingShape, "Blinking", 0);
                    }
                    LipSyncEditorExtensions.FixedEndFadeGroup(1 - showBlinkingClassicControl.faded);

                    GUILayout.Space(10);

                    float minGap = minimumBlinkGap.floatValue;
                    float maxGap = maximumBlinkGap.floatValue;

                    MinMaxSliderWithNumbers(new GUIContent("Blink Gap", "Time, in seconds, between blinks."), ref minGap, ref maxGap, 0.1f, 20);

                    minimumBlinkGap.floatValue = minGap;
                    maximumBlinkGap.floatValue = maxGap;

                    EditorGUILayout.PropertyField(blinkDuration, new GUIContent("Blink Duration", "How long each blink takes."));
                    GUILayout.Space(10);
                }
                LipSyncEditorExtensions.FixedEndFadeGroup(showBlinking.faded);
                EditorGUI.indentLevel--;
                GUILayout.Space(2);
                // Random Look Direction
                lineRect = EditorGUILayout.BeginHorizontal();
                GUI.Box(lineRect, "", (GUIStyle)"flow node 0");
                GUILayout.Space(10);
                randomLookingEnabled.boolValue = EditorGUILayout.ToggleLeft("Random Looking", randomLookingEnabled.boolValue, EditorStyles.largeLabel, GUILayout.ExpandWidth(true), GUILayout.Height(24));
                showRandomLook.target          = randomLookingEnabled.boolValue;
                GUILayout.FlexibleSpace();
                lookingControlMode.enumValueIndex = GUILayout.Toolbar(lookingControlMode.enumValueIndex, System.Enum.GetNames(typeof(EyeController.ControlMode)), inlineToolbar, GUILayout.MaxWidth(300), GUILayout.Height(24));
                showLookingClassicControl.target  = lookingControlMode.enumValueIndex == (int)EyeController.ControlMode.Classic;
                EditorGUILayout.EndHorizontal();
                EditorGUI.indentLevel++;
                if (EditorGUILayout.BeginFadeGroup(showRandomLook.faded))
                {
                    GUILayout.Space(5);

                    float minGap = minimumChangeDirectionGap.floatValue;
                    float maxGap = maximumChangeDirectionGap.floatValue;

                    MinMaxSliderWithNumbers(new GUIContent("Change Direction Gap", "Time, in seconds, between the eyes turning to a new direction."), ref minGap, ref maxGap, 1f, 30);

                    minimumChangeDirectionGap.floatValue = minGap;
                    maximumChangeDirectionGap.floatValue = maxGap;

                    GUILayout.Space(10);
                }
                LipSyncEditorExtensions.FixedEndFadeGroup(showRandomLook.faded);
                EditorGUI.indentLevel--;

                // Look Targets
                lineRect = EditorGUILayout.BeginHorizontal();
                GUI.Box(lineRect, "", (GUIStyle)"flow node 0");
                GUILayout.Space(10);
                EditorGUI.BeginDisabledGroup(lookingControlMode.enumValueIndex == (int)EyeController.ControlMode.PoseBased);
                targetEnabled.boolValue = EditorGUILayout.ToggleLeft("Look At Target", targetEnabled.boolValue, EditorStyles.largeLabel, GUILayout.ExpandWidth(true), GUILayout.Height(24)) && lookingControlMode.enumValueIndex == (int)EyeController.ControlMode.Classic;
                showLookTarget.target   = targetEnabled.boolValue;
                EditorGUI.EndDisabledGroup();
                GUILayout.FlexibleSpace();
                GUILayout.Space(24);
                EditorGUILayout.EndHorizontal();
                EditorGUI.indentLevel++;
                if (EditorGUILayout.BeginFadeGroup(showLookTarget.faded))
                {
                    GUILayout.Space(5);
                    if (EditorGUILayout.BeginFadeGroup(1 - showAutoTarget.faded))
                    {
                        EditorGUILayout.PropertyField(viewTarget, new GUIContent("Target", "Transform to look at."));
                        GUILayout.Space(10);
                    }
                    LipSyncEditorExtensions.FixedEndFadeGroup(1 - showAutoTarget.faded);
                    EditorGUILayout.PropertyField(autoTarget, new GUIContent("Use Auto Target"));
                    showAutoTarget.target = myTarget.autoTarget;
                    if (EditorGUILayout.BeginFadeGroup(showAutoTarget.faded))
                    {
                        EditorGUI.indentLevel++;
                        EditorGUILayout.PropertyField(autoTargetTag, new GUIContent("Auto Target Tag", "Tag to use when searching for targets."));
                        EditorGUILayout.PropertyField(autoTargetDistance, new GUIContent("Auto Target Distance", "The maximum distance between a target and the character for it to be targeted."));
                        EditorGUI.indentLevel--;
                        GUILayout.Space(10);
                    }
                    LipSyncEditorExtensions.FixedEndFadeGroup(showAutoTarget.faded);
                    EditorGUILayout.Slider(targetWeight, 0, 1, new GUIContent("Look At Amount"));
                    GUILayout.Space(10);
                }
                LipSyncEditorExtensions.FixedEndFadeGroup(showLookTarget.faded);
                if (lookingControlMode.enumValueIndex == (int)EyeController.ControlMode.PoseBased)
                {
                    EditorGUILayout.HelpBox("Targeting is only available in classic mode.", MessageType.Warning);
                }
                EditorGUI.indentLevel--;

                // Shared Look Controls
                GUILayout.Space(-2);
                lineRect = EditorGUILayout.BeginHorizontal();
                GUI.Box(lineRect, "", (GUIStyle)"flow node 0");
                GUILayout.Space(24);
                GUILayout.Label("Looking (Shared)", EditorStyles.largeLabel, GUILayout.ExpandWidth(true), GUILayout.Height(24));
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
                showLookShared.target = myTarget.targetEnabled || myTarget.randomLookingEnabled;
                EditorGUI.indentLevel++;
                if (EditorGUILayout.BeginFadeGroup(showLookShared.faded))
                {
                    GUILayout.Space(5);

                    // Classic Mode
                    if (EditorGUILayout.BeginFadeGroup(showLookingClassicControl.faded))
                    {
                        EditorGUI.BeginChangeCheck();
                        EditorGUILayout.PropertyField(leftEyeLookAtBone);
                        EditorGUILayout.PropertyField(rightEyeLookAtBone);
                        if (EditorGUI.EndChangeCheck())
                        {
                            myTarget.LeftEyeLookAtBone  = (Transform)leftEyeLookAtBone.objectReferenceValue;
                            myTarget.RightEyeLookAtBone = (Transform)rightEyeLookAtBone.objectReferenceValue;
                        }
                        GUILayout.Space(5);
                        MinMaxSliderWithNumbers(new GUIContent("X Axis Range"), eyeRotationRangeX, -90, 90);
                        MinMaxSliderWithNumbers(new GUIContent("Y Axis Range"), eyeRotationRangeY, -90, 90);
                        GUILayout.Space(5);
                        EditorGUILayout.PropertyField(eyeLookOffset);
                        EditorGUILayout.PropertyField(eyeForwardAxis);
                    }
                    LipSyncEditorExtensions.FixedEndFadeGroup(showLookingClassicControl.faded);

                    // Pose Mode
                    if (EditorGUILayout.BeginFadeGroup(1 - showLookingClassicControl.faded))
                    {
                        this.DrawShapeEditor(myTarget.blendSystem, blendables, true, true, myTarget.lookingUpShape, "Looking Up", 1);
                        this.DrawShapeEditor(myTarget.blendSystem, blendables, true, true, myTarget.lookingDownShape, "Looking Down", 2);
                        this.DrawShapeEditor(myTarget.blendSystem, blendables, true, true, myTarget.lookingLeftShape, "Looking Left", 3);
                        this.DrawShapeEditor(myTarget.blendSystem, blendables, true, true, myTarget.lookingRightShape, "Looking Right", 4);
                    }
                    LipSyncEditorExtensions.FixedEndFadeGroup(1 - showLookingClassicControl.faded);
                    GUILayout.Space(5);
                    EditorGUILayout.PropertyField(eyeTurnSpeed, new GUIContent("Eye Turn Speed", "The speed at which eyes rotate."));
                    GUILayout.Space(10);
                }
                LipSyncEditorExtensions.FixedEndFadeGroup(showLookShared.faded);
                EditorGUI.indentLevel--;
                GUILayout.Space(10);
            }

            if (LipSyncEditorExtensions.oldToggle != LipSyncEditorExtensions.currentToggle && LipSyncEditorExtensions.currentTarget == myTarget)
            {
                Shape oldShape = null;
                Shape newShape = null;

                switch (LipSyncEditorExtensions.oldToggle)
                {
                case 0:
                    oldShape = myTarget.blinkingShape;
                    break;

                case 1:
                    oldShape = myTarget.lookingUpShape;
                    break;

                case 2:
                    oldShape = myTarget.lookingDownShape;
                    break;

                case 3:
                    oldShape = myTarget.lookingLeftShape;
                    break;

                case 4:
                    oldShape = myTarget.lookingRightShape;
                    break;
                }

                switch (LipSyncEditorExtensions.currentToggle)
                {
                case 0:
                    newShape = myTarget.blinkingShape;
                    break;

                case 1:
                    newShape = myTarget.lookingUpShape;
                    break;

                case 2:
                    newShape = myTarget.lookingDownShape;
                    break;

                case 3:
                    newShape = myTarget.lookingLeftShape;
                    break;

                case 4:
                    newShape = myTarget.lookingRightShape;
                    break;
                }

                if (LipSyncEditorExtensions.oldToggle > -1)
                {
                    if (oldShape != null)
                    {
                        foreach (BoneShape boneshape in oldShape.bones)
                        {
                            if (boneshape.bone != null)
                            {
                                boneshape.bone.localPosition    = boneshape.neutralPosition;
                                boneshape.bone.localEulerAngles = boneshape.neutralRotation;
                            }
                        }

                        foreach (int blendable in oldShape.blendShapes)
                        {
                            myTarget.blendSystem.SetBlendableValue(blendable, 0);
                        }
                    }
                }

                if (LipSyncEditorExtensions.currentToggle > -1)
                {
                    foreach (BoneShape boneshape in newShape.bones)
                    {
                        if (boneshape.bone != null)
                        {
                            boneshape.bone.localPosition    = boneshape.endPosition;
                            boneshape.bone.localEulerAngles = boneshape.endRotation;
                        }
                    }

                    for (int b = 0; b < newShape.blendShapes.Count; b++)
                    {
                        myTarget.blendSystem.SetBlendableValue(newShape.blendShapes[b], newShape.weights[b]);
                    }
                }

                LipSyncEditorExtensions.oldToggle = LipSyncEditorExtensions.currentToggle;
            }

            if (GUI.changed)
            {
                if (blendables == null)
                {
                    GetBlendShapes();
                }

                Shape newShape = null;

                switch (LipSyncEditorExtensions.currentToggle)
                {
                case 0:
                    newShape = myTarget.blinkingShape;
                    break;

                case 1:
                    newShape = myTarget.lookingUpShape;
                    break;

                case 2:
                    newShape = myTarget.lookingDownShape;
                    break;

                case 3:
                    newShape = myTarget.lookingLeftShape;
                    break;

                case 4:
                    newShape = myTarget.lookingRightShape;
                    break;
                }

                if (LipSyncEditorExtensions.currentToggle > -1 && LipSyncEditorExtensions.currentTarget == myTarget)
                {
                    for (int b = 0; b < newShape.blendShapes.Count; b++)
                    {
                        myTarget.blendSystem.SetBlendableValue(newShape.blendShapes[b], newShape.weights[b]);
                    }
                }

                EditorUtility.SetDirty(myTarget);
                serializedObject.SetIsDifferentCacheDirty();
            }

            serializedObject.ApplyModifiedProperties();
        }
    }