/// <summary>
    /// This function is called when the scriptable object goes out of scope.
    /// </summary>
    private void OnDisable()
    {
        // If the skeleton editor is no longer enabled, we don't want
        // the skeleton's motors to run (when in edit mode)
        for (int i = 0; i < mSkeleton.Motors.Count; i++)
        {
            //mSkeleton.Motors[i].IsEditorEnabled = false;
        }

        // Clear the current bone rotations so we go back to the
        // bind pose.
        //
        // NOTE: This causes the scene to be flagged as dirty
        //mSkeleton.ClearBoneRotations();

        // Force an update
        mSkeleton.LateUpdate();

        // Re-enable the skinned mesh we hid. This test first ensures that the object
        // wasn't deleted. If it wasn't we don't need to do anything.
        if (target != null)
        {
            SkinnedMeshRenderer lRenderer = mSkeleton.gameObject.GetComponent <SkinnedMeshRenderer>();
            if (lRenderer == null)
            {
                lRenderer = mSkeleton.gameObject.GetComponentInChildren <SkinnedMeshRenderer>();
            }

#if (UNITY_4 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4)
            EditorUtility.SetSelectedWireframeHidden(lRenderer, false);
#else
            EditorUtility.SetSelectedRenderState(lRenderer, EditorSelectedRenderState.Hidden);
#endif
        }

        // Clear any selected bones
        SelectBone(null);

        // Clear the hot control so we can select other things
        GUIUtility.hotControl = 0;
    }
    /// <summary>
    /// Called when the script object is loaded
    /// </summary>
    private void OnEnable()
    {
        // Grab the serialized objects
        mSkeleton   = (BoneController)target;
        mSkeletonSO = new SerializedObject(target);

        // Load the textures
        if (mBackground == null)
        {
            mBackground = Resources.Load <Texture>("IKBackground");
        }
        if (mItemSelector == null)
        {
            mItemSelector = Resources.Load <Texture>("IKDot");
        }

        // Styles for selected rows
        if (mTitleRowStyle == null)
        {
            mTitleRowStyle = new GUIStyle();
            mTitleRowStyle.normal.background = (Texture2D)Resources.Load <Texture>("IKTitle");
            mTitleRowStyle.border            = new RectOffset(1, 1, 1, 1);
            mTitleRowStyle.margin            = new RectOffset(0, 0, 0, 0);
            mTitleRowStyle.padding           = new RectOffset(0, 0, 0, 0);
        }

        if (mRowStyle == null)
        {
            mRowStyle         = new GUIStyle();
            mRowStyle.border  = new RectOffset(1, 1, 1, 1);
            mRowStyle.margin  = new RectOffset(0, 0, 0, 0);
            mRowStyle.padding = new RectOffset(0, 0, 0, 0);
        }

        if (mSelectedRowStyle == null)
        {
            mSelectedRowStyle = new GUIStyle();
            mSelectedRowStyle.normal.background = (Texture2D)Resources.Load <Texture>("IKBorder");
            mSelectedRowStyle.border            = new RectOffset(1, 1, 1, 1);
            mSelectedRowStyle.margin            = new RectOffset(0, 0, 0, 0);
            mSelectedRowStyle.padding           = new RectOffset(0, 0, 0, 0);
        }

        if (mRedXStyle == null)
        {
            mRedXStyle = new GUIStyle();
            mRedXStyle.normal.background = Resources.Load <Texture2D>(EditorGUIUtility.isProSkin ? "RedSquareX" : "RedSquareX_Light");
            mRedXStyle.margin            = new RectOffset(0, 0, 2, 0);
        }

        if (mGreenPlusStyle == null)
        {
            mGreenPlusStyle = new GUIStyle();
            mGreenPlusStyle.normal.background = Resources.Load <Texture2D>("BlueSquareMinus");
            mGreenPlusStyle.margin            = new RectOffset(0, 0, 2, 0);
        }

        if (mBluePlusStyle == null)
        {
            mBluePlusStyle = new GUIStyle();
            mBluePlusStyle.normal.background = Resources.Load <Texture2D>(EditorGUIUtility.isProSkin ? "BlueSquarePlus" : "BlueSquarePlus_Light");
            mBluePlusStyle.margin            = new RectOffset(0, 0, 2, 0);
        }

        if (mBlueGearStyle == null)
        {
            mBlueGearStyle = new GUIStyle();
            mBlueGearStyle.normal.background = Resources.Load <Texture2D>(EditorGUIUtility.isProSkin ? "BlueSquareGear" : "BlueSquareGear_Light");
            mBlueGearStyle.margin            = new RectOffset(0, 0, 2, 0);
        }

        // Refresh the layers in case they were updated
        EditorHelper.RefreshLayers();

        // Grab the list of motion types
        mMotorTypes.Clear();
        mMotorNames.Clear();

        // CDL 07/03/2018 - this only scans the the assembly containing BoneController
        //// Generate the list of motions to display
        //Assembly lAssembly = Assembly.GetAssembly(typeof(BoneController));
        //foreach (Type lType in lAssembly.GetTypes())
        //{
        //    if (!lType.IsAbstract && lType != typeof(BoneControllerMotor) && typeof(BoneControllerMotor).IsAssignableFrom(lType))
        //    {
        //        mMotorTypes.Add(lType);

        //        string lTypeName = lType.Name;
        //        object[] lAttributes = lType.GetCustomAttributes(typeof(IKNameAttribute), true);
        //        foreach (IKNameAttribute lAttribute in lAttributes) { lTypeName = lAttribute.Name; }

        //        mMotorNames.Add(lTypeName);
        //    }
        //}

        // CDL 07/03/2018 - look in all assemblies for bone motors
        // Generate the list of bone motors to display
        List <Type> lFoundTypes = AssemblyHelper.FoundTypes;

        foreach (Type lType in lFoundTypes)
        {
            if (!lType.IsAbstract && lType != typeof(BoneControllerMotor) && typeof(BoneControllerMotor).IsAssignableFrom(lType))
            {
                mMotorTypes.Add(lType);

                string   lTypeName   = lType.Name;
                object[] lAttributes = lType.GetCustomAttributes(typeof(IKNameAttribute), true);
                foreach (IKNameAttribute lAttribute in lAttributes)
                {
                    lTypeName = lAttribute.Name;
                }

                mMotorNames.Add(lTypeName);
            }
        }

        // If the skeleton editor is active, we'll allow the motors to
        // run (when in edit mode)
        //for (int i = 0; i < mSkeleton.Motors.Count; i++)
        //{
        //    mSkeleton.Motors[i].IsEditorEnabled = true;
        //}

        mSkeleton.LateUpdate();

        // Hide the skinned mesh. It just gets in the way visually.
        SkinnedMeshRenderer lRenderer = mSkeleton.gameObject.GetComponent <SkinnedMeshRenderer>();

        if (lRenderer == null)
        {
            lRenderer = mSkeleton.gameObject.GetComponentInChildren <SkinnedMeshRenderer>();
        }

#if (UNITY_4 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4)
        EditorUtility.SetSelectedWireframeHidden(lRenderer, true);
#else
        EditorUtility.SetSelectedRenderState(lRenderer, EditorSelectedRenderState.Highlight);
#endif
    }