public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (!Init(hashNames, hashes))
            {
                return;
            }

            int startingIndent = EditorGUI.indentLevel;

            EditorGUI.BeginProperty(position, label, property);

            string thisHashName = property.FindPropertyRelative("_hashName").stringValue;

            var currRect = new Rect(position.xMin, position.yMin, position.width, EditorGUIUtility.singleLineHeight);

            string betterLabel = label.text;

            if (property.FindPropertyRelative("_property").enumDisplayNames[property.FindPropertyRelative("_property").enumValueIndex] != "")
            {
                betterLabel += " (" + property.FindPropertyRelative("_property").enumDisplayNames[property.FindPropertyRelative("_property").enumValueIndex] + ")";
            }

            List <string> boneNames = new List <string>();

            if (bonesInSkeleton != null)
            {
                boneNames = new List <string>(bonesInSkeleton);
            }
            else
            {
                boneNames = new List <string>(hashNames);
            }

            int hashNameIndex = boneNames.IndexOf(thisHashName);

            //Warn about current Bone not being available in active Avatar if we are in playMode (i.e. got sent BonesInSkeleton)
            if (hashNameIndex == -1 && bonesInSkeleton != null)
            {
                boneNames.Insert(0, thisHashName + " (missing)");
                hashNameIndex = 0;
                var warningRect    = new Rect((currRect.xMin), currRect.yMin, 20f, currRect.height);
                var warningIconGUI = new GUIContent("", thisHashName + " was not a bone in the Avatars Skeleton. Please choose another bone for this modifier or delete it.");
                warningIconGUI.image = warningIcon;
                betterLabel         += " (missing)";
                GUI.Label(warningRect, warningIconGUI, warningStyle);
            }
            //Draw the foldout- toolbar-ish style here?
            property.isExpanded = EditorGUI.Foldout(currRect, property.isExpanded, betterLabel, true);
            if (property.isExpanded)
            {
                EditorGUI.indentLevel++;

                //THE BONE NAME FIELD
                currRect = new Rect(currRect.xMin, currRect.yMax + padding, currRect.width, EditorGUIUtility.singleLineHeight);
                if (boneNames.Count > 0)
                {
                    int newHashNameIndex = hashNameIndex;
                    EditorGUI.BeginChangeCheck();
                    newHashNameIndex = EditorGUI.Popup(currRect, "Bone Name", hashNameIndex, boneNames.ToArray());
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (newHashNameIndex != hashNameIndex)
                        {
                            property.FindPropertyRelative("_hashName").stringValue = boneNames[newHashNameIndex];
                            property.FindPropertyRelative("_hash").intValue        = UMAUtils.StringToHash(boneNames[newHashNameIndex]);
                            property.serializedObject.ApplyModifiedProperties();
                        }
                    }
                }
                else
                {
                    //make sure the hash is changed if the name is edited
                    EditorGUI.BeginChangeCheck();
                    EditorGUI.PropertyField(currRect, property.FindPropertyRelative("_hashName"), new GUIContent("Bone Name"));
                    if (EditorGUI.EndChangeCheck())
                    {
                        property.FindPropertyRelative("_hash").intValue = UMAUtils.StringToHash(property.FindPropertyRelative("_hashName").stringValue);
                    }
                }

                //THE PROPERTY FIELD
                currRect = new Rect(currRect.xMin, currRect.yMax + padding, currRect.width, EditorGUIUtility.singleLineHeight);
                EditorGUI.PropertyField(currRect, property.FindPropertyRelative("_property"));


                //X/Y/Z VALUES TABS

                SerializedProperty subValsToOpen = null;
                var valuesX = property.FindPropertyRelative("_valuesX");
                var valuesY = property.FindPropertyRelative("_valuesY");
                var valuesZ = property.FindPropertyRelative("_valuesZ");

                tabsArea = currRect = new Rect(currRect.xMin + (EditorGUI.indentLevel * 10f), currRect.yMax + padding, currRect.width - (EditorGUI.indentLevel * 10f), EditorGUIUtility.singleLineHeight);

                //activeTab = valuesX.isExpanded ? 0 : (valuesY.isExpanded ? 1 : (valuesZ.isExpanded ? 2 : 0));
                //subValsToOpen = valuesX.isExpanded ? valuesX : (valuesY.isExpanded ? valuesY : (valuesZ.isExpanded ? valuesZ : valuesX));
                activeTab               = 0;
                subValsToOpen           = valuesX;
                valueLabel.text         = "X Value";
                valueOverrideLabel.text = "Intitial X Value Override";
                if (!valuesX.isExpanded)
                {
                    if (valuesY.isExpanded)
                    {
                        activeTab               = 1;
                        subValsToOpen           = valuesY;
                        valueLabel.text         = "Y Value";
                        valueOverrideLabel.text = "Intitial Y Value Override";
                    }
                    else if (valuesZ.isExpanded)
                    {
                        activeTab               = 2;
                        subValsToOpen           = valuesZ;
                        valueLabel.text         = "Z Value";
                        valueOverrideLabel.text = "Intitial Z Value Override";
                    }
                    else
                    {
                        valuesX.isExpanded = true;
                    }
                }

                EditorGUI.BeginChangeCheck();
                activeTab = GUI.Toolbar(tabsArea, activeTab, tabsLabels, EditorStyles.toolbarButton);
                if (EditorGUI.EndChangeCheck())
                {
                    //make sure any focussed text areas dont prevent the tab from switching
                    GUI.FocusControl(null);
                    if (activeTab == 0)
                    {
                        valuesX.isExpanded      = true;
                        valuesY.isExpanded      = false;
                        valuesZ.isExpanded      = false;
                        valueLabel.text         = "X Value";
                        valueOverrideLabel.text = "Intitial X Value Override";
                    }
                    else if (activeTab == 1)
                    {
                        valuesX.isExpanded      = false;
                        valuesY.isExpanded      = true;
                        valuesZ.isExpanded      = false;
                        subValsToOpen           = valuesY;
                        valueLabel.text         = "Y Value";
                        valueOverrideLabel.text = "Intitial Y Value Override";
                    }
                    else if (activeTab == 2)
                    {
                        valuesX.isExpanded      = false;
                        valuesY.isExpanded      = false;
                        valuesZ.isExpanded      = true;
                        subValsToOpen           = valuesZ;
                        valueLabel.text         = "Z Value";
                        valueOverrideLabel.text = "Intitial Z Value Override";
                    }
                }

                //VALUES TAB CONTENT
                if (subValsToOpen != null)
                {
                    var subValuesVal = subValsToOpen.FindPropertyRelative("_val");
                    var subValuesMin = subValsToOpen.FindPropertyRelative("_min");
                    var subValuesMax = subValsToOpen.FindPropertyRelative("_max");

                    valMinMaxArea = currRect = new Rect(tabsArea.xMin, tabsArea.yMax, tabsArea.width, EditorGUIUtility.singleLineHeight + (padding * 4f));
                    valBox        = new Rect(valMinMaxArea.xMin, valMinMaxArea.yMin + (padding * 2f), valMinMaxArea.width / 3f, valMinMaxArea.height - (padding * 4f));
                    minBox        = new Rect(valBox.xMax, valBox.yMin, valBox.width, valBox.height);
                    maxBox        = new Rect(minBox.xMax, minBox.yMin, minBox.width, minBox.height);
                    valLabel      = new Rect(valBox.xMin + (padding * 6f), valBox.yMin, valLabelWidth, valBox.height);
                    valVal        = new Rect(valLabel.xMax + (padding), valLabel.yMin, (valBox.width - valLabelWidth) - (padding * 10f), valLabel.height);
                    minLabel      = new Rect(minBox.xMin + (padding * 2f), minBox.yMin, minMaxLabelWidth, minBox.height);
                    minVal        = new Rect(minLabel.xMax, minLabel.yMin, (minBox.width - minMaxLabelWidth) - (padding * 4f), minLabel.height);
                    maxLabel      = new Rect(maxBox.xMin + (padding * 2f), maxBox.yMin, minMaxLabelWidth, maxBox.height);
                    maxVal        = new Rect(maxLabel.xMax, maxLabel.yMin, (maxBox.width - minMaxLabelWidth) - (padding * 4f), maxLabel.height);

                    if (subValuesVal.isExpanded)
                    {
                        valMinMaxArea.height += EditorGUIUtility.singleLineHeight + padding;
                    }
                    //VALUE/MIN/MAX FIELDS

                    EditorGUI.DrawRect(valMinMaxArea, new Color32(255, 255, 255, 100));
                    var prevIndent = EditorGUI.indentLevel;
                    EditorGUI.indentLevel = 0;

                    //Value Field

                    //Show another line here if this is expanded that lets the user change the starting value
                    subValuesVal.isExpanded = EditorGUI.Foldout(valLabel, subValuesVal.isExpanded, valueLabel, true);
                    EditorGUI.BeginDisabledGroup(true);
                    subValuesVal.FindPropertyRelative("_value").floatValue = EditorGUI.FloatField(valVal, subValuesVal.FindPropertyRelative("_value").floatValue);
                    EditorGUI.EndDisabledGroup();
                    if (subValuesVal.isExpanded)
                    {
                        var subValuesValRect = new Rect(tabsArea.xMin + (padding * 4f), tabsArea.yMax + (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing * 8), tabsArea.width - (padding * 8f), EditorGUIUtility.singleLineHeight);
                        subValuesVal.FindPropertyRelative("_value").floatValue = EditorGUI.FloatField(subValuesValRect, valueOverrideLabel, subValuesVal.FindPropertyRelative("_value").floatValue);
                    }

                    //Min Field
                    EditorGUI.LabelField(minLabel, "Min");
                    subValuesMin.floatValue = EditorGUI.FloatField(minVal, subValuesMin.floatValue);

                    //Max Field
                    EditorGUI.LabelField(maxLabel, "Max");
                    subValuesMax.floatValue = EditorGUI.FloatField(maxVal, subValuesMax.floatValue);
                    //EditorGUI.indentLevel = prevIndent;

                    //VALUE MODIFIERS AREA

                    var legacyModifiersProp  = subValuesVal.FindPropertyRelative("_modifiers");
                    var legacyModifiersCount = legacyModifiersProp.arraySize;

                    var modifyingDNAProp  = subValuesVal.FindPropertyRelative("_modifyingDNA");
                    var modifyingDNACount = modifyingDNAProp.FindPropertyRelative("_dnaEvaluators").arraySize;

                    currRect      = new Rect(currRect.xMin, valMinMaxArea.yMax + 2f, currRect.width, EditorGUIUtility.singleLineHeight);
                    modifiersArea = new Rect(currRect.xMin, currRect.yMin, currRect.width, ((EditorGUIUtility.singleLineHeight + padding) * (legacyModifiersCount + 2)));                    //plus 2 for label and add button

                    if (modifyingDNACount != 0 || !_allowLegacyDNADrawer)
                    {
                        modifiersArea = new Rect(currRect.xMin, currRect.yMin, currRect.width, (EditorGUI.GetPropertyHeight(modifyingDNAProp) + padding));
                    }

                    EditorGUI.DrawRect(modifiersArea, new Color32(255, 255, 255, 100));

                    //Pad the current Rect
                    currRect.xMin  += padding * 2f;
                    currRect.width -= padding * 2f;

                    //When modifiers get upgraded to _modifyingDNA they get cleared
                    //But for now
                    if (modifyingDNACount == 0 && _allowLegacyDNADrawer)
                    {
                        //EditorGUI.indentLevel++;
                        EditorGUI.LabelField(currRect, "Value Modifiers");
                        //EditorGUI.indentLevel--;

                        //Draw modifiers list
                        for (int i = 0; i < legacyModifiersCount; i++)
                        {
                            currRect       = new Rect(currRect.xMin, currRect.yMax + padding, currRect.width, EditorGUIUtility.singleLineHeight);
                            modifiersProps = new Rect(currRect.xMin, currRect.yMin, currRect.width - delButWidth, EditorGUIUtility.singleLineHeight);
                            modifiersDel   = new Rect(modifiersProps.xMax, currRect.yMin, delButWidth, EditorGUIUtility.singleLineHeight);
                            thisSpValDrawer.OnGUI(modifiersProps, legacyModifiersProp.GetArrayElementAtIndex(i), new GUIContent(""));
                            if (GUI.Button(modifiersDel, "X"))
                            {
                                legacyModifiersProp.DeleteArrayElementAtIndex(i);
                            }
                        }

                        //Draw the add button
                        modifiersAdd = new Rect(currRect.xMax - addButWidth, currRect.yMax + padding, addButWidth, EditorGUIUtility.singleLineHeight);

                        if (GUI.Button(modifiersAdd, "Add"))
                        {
                            legacyModifiersProp.InsertArrayElementAtIndex(legacyModifiersCount);
                        }
                        legacyModifiersProp.serializedObject.ApplyModifiedProperties();
                    }
                    else
                    {
                        var thisModifyingDNARect = new Rect(currRect.xMin, currRect.yMin, currRect.width, position.height - currRect.yMax);
                        EditorGUI.PropertyField(thisModifyingDNARect, modifyingDNAProp);
                    }
                }
            }
            EditorGUI.indentLevel = startingIndent;
            EditorGUI.EndProperty();
        }
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            int startingIndent = EditorGUI.indentLevel;

            EditorGUI.BeginProperty(position, label, property);
            var    valR        = new Rect(position.xMin, position.yMin, position.width, EditorGUIUtility.singleLineHeight);
            string betterLabel = label.text;

            if (property.FindPropertyRelative("property").enumDisplayNames[property.FindPropertyRelative("property").enumValueIndex] != "")
            {
                betterLabel += " (" + property.FindPropertyRelative("property").enumDisplayNames[property.FindPropertyRelative("property").enumValueIndex] + ")";
            }
            List <string> boneNames = new List <string>();

            if (bonesInSkeleton != null)
            {
                boneNames = new List <string>(bonesInSkeleton);
            }
            else
            {
                boneNames = new List <string>(hashNames);
            }
            string thisHashName  = property.FindPropertyRelative("hashName").stringValue;
            int    hashNameIndex = boneNames.IndexOf(thisHashName);

            if (hashNameIndex == -1 && bonesInSkeleton != null)
            {
                boneNames.Insert(0, thisHashName + " (missing)");
                hashNameIndex = 0;
                var warningRect    = new Rect((valR.xMin), valR.yMin, 20f, valR.height);
                var warningIconGUI = new GUIContent("", thisHashName + " was not a bone in the Avatars Skeleton. Please choose another bone for this modifier or delete it.");
                warningIconGUI.image = warningIcon;
                betterLabel         += " (missing)";
                GUI.Label(warningRect, warningIconGUI, warningStyle);
            }
            property.isExpanded = EditorGUI.Foldout(valR, property.isExpanded, betterLabel, true);
            if (property.isExpanded)
            {
                EditorGUI.indentLevel++;
                valR = new Rect(valR.xMin, valR.yMax + padding, valR.width, EditorGUIUtility.singleLineHeight);
                if (boneNames.Count > 0)
                {
                    int newHashNameIndex = hashNameIndex;
                    EditorGUI.BeginChangeCheck();
                    newHashNameIndex = EditorGUI.Popup(valR, "Hash Name", hashNameIndex, boneNames.ToArray());
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (newHashNameIndex != hashNameIndex)
                        {
                            property.FindPropertyRelative("hashName").stringValue = boneNames[newHashNameIndex];
                            property.FindPropertyRelative("hash").intValue        = UMAUtils.StringToHash(boneNames[newHashNameIndex]);
                            property.serializedObject.ApplyModifiedProperties();
                        }
                    }
                }
                else
                {
                    EditorGUI.PropertyField(valR, property.FindPropertyRelative("hashName"));
                }
                valR = new Rect(valR.xMin, valR.yMax + padding, valR.width, EditorGUIUtility.singleLineHeight);
                EditorGUI.PropertyField(valR, property.FindPropertyRelative("property"));
                valR = new Rect(valR.xMin, valR.yMax + padding, valR.width, EditorGUIUtility.singleLineHeight);
                var valXR = valR;
                var valYR = valR;
                var valZR = valR;
                valXR.width = valYR.width = valZR.width = valR.width / 3;
                valYR.x     = valYR.x + valXR.width;
                valZR.x     = valZR.x + valXR.width + valYR.width;
                SerializedProperty subValsToOpen = null;
                var valuesX = property.FindPropertyRelative("valuesX");
                var valuesY = property.FindPropertyRelative("valuesY");
                var valuesZ = property.FindPropertyRelative("valuesZ");
                if (valuesX.isExpanded)
                {
                    var valXRB = valXR;
                    valXRB.x     = valXRB.x + (EditorGUI.indentLevel * 10f);
                    valXRB.width = valXRB.width - (EditorGUI.indentLevel * 10f);
                    EditorGUI.DrawRect(valXRB, new Color32(255, 255, 255, 100));
                }
                valuesX.isExpanded = EditorGUI.Foldout(valXR, valuesX.isExpanded, "ValuesX", true);
                if (valuesX.isExpanded)
                {
                    valuesY.isExpanded = false;
                    valuesZ.isExpanded = false;
                    subValsToOpen      = valuesX;
                }
                if (valuesY.isExpanded)
                {
                    EditorGUI.DrawRect(valYR, new Color32(255, 255, 255, 100));
                }
                valuesY.isExpanded = EditorGUI.Foldout(valYR, valuesY.isExpanded, "ValuesY", true);
                if (valuesY.isExpanded)
                {
                    valuesX.isExpanded = false;
                    valuesZ.isExpanded = false;
                    subValsToOpen      = valuesY;
                }
                if (valuesZ.isExpanded)
                {
                    EditorGUI.DrawRect(valZR, new Color32(255, 255, 255, 100));
                }
                valuesZ.isExpanded = EditorGUI.Foldout(valZR, valuesZ.isExpanded, "ValuesZ", true);
                if (valuesZ.isExpanded)
                {
                    valuesX.isExpanded = false;
                    valuesY.isExpanded = false;
                    subValsToOpen      = valuesZ;
                }
                if (subValsToOpen != null)
                {
                    valR       = new Rect(valR.xMin, valR.yMax + padding + 4f, valR.width, EditorGUIUtility.singleLineHeight);
                    valR.width = valR.width - 30;
                    var boxR1 = valR;
                    boxR1.x      = boxR1.x + EditorGUI.indentLevel * 10f;
                    boxR1.y      = boxR1.y - 6;
                    boxR1.height = boxR1.height + 12;
                    //topbox
                    EditorGUI.DrawRect(boxR1, new Color32(255, 255, 255, 100));
                    var valSXR = valR;
                    var valSYR = valR;
                    var valSZR = valR;
                    valSXR.width = valSYR.width = valSZR.width = valR.width / 3;
                    valSYR.x     = valSYR.x + valSXR.width;
                    valSZR.x     = valSZR.x + valSXR.width + valSYR.width;
                    var subValuesVal = subValsToOpen.FindPropertyRelative("val");
                    var subValuesMin = subValsToOpen.FindPropertyRelative("min");
                    var subValuesMax = subValsToOpen.FindPropertyRelative("max");
                    var valSXRF      = valSXR;
                    valSXRF.x     = valSXRF.x + 38f;
                    valSXRF.width = valSXRF.width - 35f;
                    if (!enableSkelModValueEditing)
                    {
                        EditorGUI.BeginDisabledGroup(true);
                    }
                    EditorGUI.LabelField(valSXR, "Value");
                    subValuesVal.FindPropertyRelative("value").floatValue = EditorGUI.FloatField(valSXRF, subValuesVal.FindPropertyRelative("value").floatValue);
                    subValuesVal.serializedObject.ApplyModifiedProperties();
                    if (!enableSkelModValueEditing)
                    {
                        EditorGUI.EndDisabledGroup();
                    }
                    var valSYRF = valSYR;
                    valSYRF.x     = valSYRF.x + 30f;
                    valSYRF.width = valSYRF.width - 30f;
                    EditorGUI.LabelField(valSYR, "Min");
                    subValuesMin.floatValue = EditorGUI.FloatField(valSYRF, subValuesMin.floatValue);
                    var valSZRF = valSZR;
                    valSZRF.x     = valSZRF.x + 30f;
                    valSZRF.width = valSZRF.width - 30f;
                    EditorGUI.LabelField(valSZR, "Max");
                    subValuesMax.floatValue = EditorGUI.FloatField(valSZRF, subValuesMax.floatValue);
                    var thisModifiersProp = subValuesVal.FindPropertyRelative("modifiers");
                    var modifiersi        = thisModifiersProp.arraySize;
                    valR = new Rect(valR.xMin, valR.yMax + padding + 4f, valR.width, EditorGUIUtility.singleLineHeight);
                    var boxR = valR;
                    boxR.y      = boxR.y - 2f;
                    boxR.x      = boxR.x + EditorGUI.indentLevel * 10f;
                    boxR.height = boxR.height + 6f + ((EditorGUIUtility.singleLineHeight + padding) * (modifiersi + 1));
                    //bottombox
                    EditorGUI.DrawRect(boxR, new Color32(255, 255, 255, 100));
                    EditorGUI.LabelField(valR, "Value Modifiers");
                    for (int i = 0; i < modifiersi; i++)
                    {
                        valR = new Rect(valR.xMin, valR.yMax + padding, valR.width, EditorGUIUtility.singleLineHeight);
                        var propsR = valR;
                        propsR.width = valR.width;
                        var valRBut = new Rect((propsR.width + 35f), valR.y, 20f, EditorGUIUtility.singleLineHeight);
                        thisSpValDrawer.OnGUI(propsR, thisModifiersProp.GetArrayElementAtIndex(i), new GUIContent(""));
                        if (GUI.Button(valRBut, "X"))
                        {
                            thisModifiersProp.DeleteArrayElementAtIndex(i);
                        }
                    }
                    var addBut = new Rect(valR.xMin, valR.yMax + padding, valR.width, EditorGUIUtility.singleLineHeight);
                    addBut.x     = addBut.xMax - 35f;
                    addBut.width = 60f;
                    if (GUI.Button(addBut, "Add"))
                    {
                        thisModifiersProp.InsertArrayElementAtIndex(modifiersi);
                    }
                    thisModifiersProp.serializedObject.ApplyModifiedProperties();
                }
            }
            EditorGUI.indentLevel = startingIndent;
            EditorGUI.EndProperty();
        }