public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            EditorGUI.BeginChangeCheck();
            EditorGUI.BeginProperty(position, label, property);

            var variant = EditorHelper.GetTargetObjectOfProperty(property) as VariantReference;
            if (variant == null)
            {
                variant = new VariantReference();
                EditorHelper.SetTargetObjectOfProperty(property, variant);
                property.serializedObject.ApplyModifiedProperties();
            }

            var totalRect = EditorGUI.PrefixLabel(position, label);
            this.DrawValueField(totalRect, property);

            EditorGUI.EndProperty();
            if (EditorGUI.EndChangeCheck()) property.serializedObject.Update();
        }
        public void DrawValueField(Rect position, SerializedObject serializedObject, VariantReference variant)
        {
            var r0 = new Rect(position.xMin, position.yMin, 90.0f, EditorGUIUtility.singleLineHeight);
            var r1 = new Rect(r0.xMax, position.yMin, position.xMax - r0.xMax, EditorGUIUtility.singleLineHeight);

            var bCache = GUI.enabled;
            if (this.RestrictVariantType) GUI.enabled = false;
            variant.ValueType = (VariantReference.VariantType)EditorGUI.EnumPopup(r0, GUIContent.none, variant.ValueType);
            GUI.enabled = bCache;

            switch (variant.ValueType)
            {
                case VariantReference.VariantType.Null:
                    GUI.enabled = false;
                    EditorGUI.TextField(r1, "Null");
                    GUI.enabled = true;
                    break;
                case VariantReference.VariantType.String:
                    variant.StringValue = EditorGUI.TextField(r1, variant.StringValue);
                    break;
                case VariantReference.VariantType.Boolean:
                    variant.BoolValue = EditorGUI.Toggle(r1, variant.BoolValue);
                    break;
                case VariantReference.VariantType.Integer:
                    variant.IntValue = EditorGUI.IntField(r1, variant.IntValue);
                    break;
                case VariantReference.VariantType.Float:
                    variant.FloatValue = EditorGUI.FloatField(r1, variant.FloatValue);
                    break;
                case VariantReference.VariantType.Double:
                    variant.DoubleValue = ConvertUtil.ToDouble(EditorGUI.TextField(r1, variant.DoubleValue.ToString()));
                    break;
                case VariantReference.VariantType.Vector2:
                    variant.Vector2Value = EditorGUI.Vector2Field(r1, GUIContent.none, variant.Vector2Value);
                    break;
                case VariantReference.VariantType.Vector3:
                    variant.Vector3Value = EditorGUI.Vector3Field(r1, GUIContent.none, variant.Vector3Value);
                    break;
                case VariantReference.VariantType.Quaternion:
                    variant.QuaternionValue = SPEditorGUI.QuaternionField(r1, GUIContent.none, variant.QuaternionValue);
                    break;
                case VariantReference.VariantType.Color:
                    variant.ColorValue = EditorGUI.ColorField(r1, variant.ColorValue);
                    break;
                case VariantReference.VariantType.DateTime:
                    variant.DateValue = ConvertUtil.ToDate(EditorGUI.TextField(r1, variant.DateValue.ToString()));
                    break;
                case VariantReference.VariantType.GameObject:
                    variant.GameObjectValue = EditorGUI.ObjectField(r1, variant.GameObjectValue, typeof(GameObject), true) as GameObject;
                    break;
                case VariantReference.VariantType.Component:
                    if (_forcedComponentType == null)
                    {
                        var totalMax = r1.xMax;
                        r1 = new Rect(r1.xMin, r1.yMin, Mathf.Max(100f, r1.width - 100f), r1.height);
                        var r2 = new Rect(r1.xMax, r1.yMin, totalMax - r1.xMax, r1.height);
                        if (_selectedComponentType == null && variant.ComponentValue != null)
                        {
                            _selectedComponentType = variant.ComponentValue.GetType();
                        }
                        _selectedComponentType = SPEditorGUI.TypeDropDown(r2, GUIContent.none, typeof(Component), _selectedComponentType, false, false, null, TypeDropDownListingStyle.ComponentMenu);
                        if (_selectedComponentType != null)
                        {
                            variant.ComponentValue = EditorGUI.ObjectField(r1, variant.ComponentValue, _selectedComponentType, true) as Component;

                            //DefaultFromSelfAttribute done here because DefaultFromSelfAttribute class can't do it itself
                            if (variant.ComponentValue == null && GameObjectUtil.IsGameObjectSource(serializedObject) && this.fieldInfo.GetCustomAttributes(typeof(com.spacepuppy.DefaultFromSelfAttribute), false).Count() > 0)
                            {
                                var go = GameObjectUtil.GetGameObjectFromSource(serializedObject);
                                variant.ComponentValue = go.GetComponent(_selectedComponentType);
                            }
                        }
                        else
                        {
                            //EditorGUI.LabelField(r1, "Select Component Type");
                            r1.xMin += 10.0f;
                            EditorGUI.HelpBox(r1, "Select Component Type", MessageType.Info);
                        }
                    }
                    else
                    {
                        variant.ComponentValue = EditorGUI.ObjectField(r1, variant.ComponentValue, _forcedComponentType, true) as Component;

                        //DefaultFromSelfAttribute done here because DefaultFromSelfAttribute class can't do it itself
                        if (variant.ComponentValue == null && GameObjectUtil.IsGameObjectSource(serializedObject) && this.fieldInfo.GetCustomAttributes(typeof(com.spacepuppy.DefaultFromSelfAttribute), false).Count() > 0)
                        {
                            var go = GameObjectUtil.GetGameObjectFromSource(serializedObject);
                            variant.ComponentValue = go.GetComponent(_forcedComponentType);
                        }
                    }

                    break;
                case VariantReference.VariantType.Object:
                    variant.ObjectValue = EditorGUI.ObjectField(r1, variant.ObjectValue, typeof(UnityEngine.Object), true);
                    break;
            }
        }
            public VariantReference AddEntry()
            {
                if (_coll == null) return null;

                int cnt = _coll._table.Count + 1;
                string key = "Entry " + cnt.ToString();
                while(_coll._table.ContainsKey(key))
                {
                    cnt++;
                    key = "Entry " + cnt.ToString();
                }

                var v = new VariantReference();
                _coll._table.Add(key, v);
                return v;
            }
 public VariantReference Clone()
 {
     var c = new VariantReference();
     c._value = _value;
     c._type = _type;
     return c;
 }
 public static void CopyValuesFromHelper(SerializedProperty property, VariantReference.EditorHelper helper)
 {
     property.FindPropertyRelative("_mode").SetEnumValue(helper._mode);
     property.FindPropertyRelative("_type").SetEnumValue(helper._type);
     property.FindPropertyRelative("_x").floatValue = helper._x;
     property.FindPropertyRelative("_y").floatValue = helper._y;
     property.FindPropertyRelative("_z").floatValue = helper._z;
     property.FindPropertyRelative("_w").doubleValue = helper._w;
     property.FindPropertyRelative("_string").stringValue = helper._string;
     property.FindPropertyRelative("_unityObjectReference").objectReferenceValue = helper._unityObjectReference;
 }
        private Rect DrawRefModeSelectionDropDown(Rect position, SerializedProperty property, VariantReference.EditorHelper helper)
        {
            var r0 = new Rect(position.xMin, position.yMin, Mathf.Min(REF_SELECT_WIDTH, position.width), position.height);

            EditorGUI.BeginChangeCheck();
            var mode = (VariantReference.RefMode)EditorGUI.EnumPopup(r0, GUIContent.none, _helper._mode);
            if (EditorGUI.EndChangeCheck())
            {
                _helper.PrepareForRefModeChange(mode);
                CopyValuesFromHelper(property, helper);
            }

            return new Rect(r0.xMax, r0.yMin, position.width - r0.width, r0.height);
        }
 public static void CopyValuesToHelper(SerializedProperty property, VariantReference.EditorHelper helper)
 {
     helper._mode = property.FindPropertyRelative("_mode").GetEnumValue<VariantReference.RefMode>();
     helper._type = property.FindPropertyRelative("_type").GetEnumValue<VariantType>();
     helper._x = property.FindPropertyRelative("_x").floatValue;
     helper._y = property.FindPropertyRelative("_y").floatValue;
     helper._z = property.FindPropertyRelative("_z").floatValue;
     helper._w = property.FindPropertyRelative("_w").doubleValue;
     helper._string = property.FindPropertyRelative("_string").stringValue;
     helper._unityObjectReference = property.FindPropertyRelative("_unityObjectReference").objectReferenceValue;
 }
        private void DrawValueFieldInEvalMode(Rect position, SerializedProperty property, VariantReference.EditorHelper helper)
        {
            _selectComponentDrawer.AllowNonComponents = true;
            _selectComponentDrawer.RestrictionType = null;
            _selectComponentDrawer.ShowXButton = false;
            var targProp = property.FindPropertyRelative("_unityObjectReference");
            var evalProp = property.FindPropertyRelative("_string");

            var r1 = new Rect(position.xMin, position.yMin, position.width * 0.4f, position.height);
            var r2 = new Rect(r1.xMax, position.yMin, position.width - r1.width, position.height);
            _selectComponentDrawer.OnGUI(r1, targProp);
            evalProp.stringValue = EditorGUI.TextField(r2, evalProp.stringValue);
        }
        private void DrawValueFieldInValueMode(Rect position, SerializedProperty property, VariantReference.EditorHelper helper)
        {
            if (helper.Target == null) return;
            var variant = helper.Target;

            if (this.RestrictVariantType && helper._type != this.VariantTypeRestrictedTo)
            {
                helper.PrepareForValueTypeChange(this.VariantTypeRestrictedTo);
                GUI.changed = true; //force change
            }

            var r0 = new Rect(position.xMin, position.yMin, 90.0f, EditorGUIUtility.singleLineHeight);
            var r1 = new Rect(r0.xMax, position.yMin, position.xMax - r0.xMax, EditorGUIUtility.singleLineHeight);

            if (this.RestrictVariantType) GUI.enabled = false;

            EditorGUI.BeginChangeCheck();
            var valueType = (VariantType)EditorGUI.EnumPopup(r0, GUIContent.none, variant.ValueType);
            if (EditorGUI.EndChangeCheck())
            {
                helper.PrepareForValueTypeChange(valueType);
            }

            if (this.RestrictVariantType) GUI.enabled = true;

            switch (valueType)
            {
                case VariantType.Null:
                    GUI.enabled = false;
                    EditorGUI.TextField(r1, "Null");
                    GUI.enabled = true;
                    break;
                case VariantType.String:
                    variant.StringValue = EditorGUI.TextField(r1, variant.StringValue);
                    break;
                case VariantType.Boolean:
                    variant.BoolValue = EditorGUI.Toggle(r1, variant.BoolValue);
                    break;
                case VariantType.Integer:
                    variant.IntValue = EditorGUI.IntField(r1, variant.IntValue);
                    break;
                case VariantType.Float:
                    variant.FloatValue = EditorGUI.FloatField(r1, variant.FloatValue);
                    break;
                case VariantType.Double:
                    variant.DoubleValue = ConvertUtil.ToDouble(EditorGUI.TextField(r1, variant.DoubleValue.ToString()));
                    break;
                case VariantType.Vector2:
                    variant.Vector2Value = EditorGUI.Vector2Field(r1, GUIContent.none, variant.Vector2Value);
                    break;
                case VariantType.Vector3:
                    variant.Vector3Value = EditorGUI.Vector3Field(r1, GUIContent.none, variant.Vector3Value);
                    break;
                case VariantType.Vector4:
                    variant.Vector4Value = EditorGUI.Vector4Field(r1, null, variant.Vector4Value);
                    break;
                case VariantType.Quaternion:
                    variant.QuaternionValue = SPEditorGUI.QuaternionField(r1, GUIContent.none, variant.QuaternionValue);
                    break;
                case VariantType.Color:
                    variant.ColorValue = EditorGUI.ColorField(r1, variant.ColorValue);
                    break;
                case VariantType.DateTime:
                    variant.DateValue = ConvertUtil.ToDate(EditorGUI.TextField(r1, variant.DateValue.ToString()));
                    break;
                case VariantType.GameObject:
                    variant.GameObjectValue = EditorGUI.ObjectField(r1, variant.GameObjectValue, typeof(GameObject), true) as GameObject;
                    break;
                case VariantType.Component:
                    {
                        _selectComponentDrawer.AllowNonComponents = false;
                        _selectComponentDrawer.RestrictionType = _forcedObjectType;
                        _selectComponentDrawer.ShowXButton = true;
                        var targProp = property.FindPropertyRelative("_unityObjectReference");
                        EditorGUI.BeginChangeCheck();
                        _selectComponentDrawer.OnGUI(r1, targProp);
                        if (EditorGUI.EndChangeCheck())
                        {
                            variant.ComponentValue = targProp.objectReferenceValue as Component;
                        }
                    }
                    break;
                case VariantType.Object:
                    {
                        var obj = variant.ObjectValue;
                        if(ComponentUtil.IsAcceptableComponentType(_forcedObjectType))
                        {
                            if (obj is GameObject || obj is Component)
                            {
                                _selectComponentDrawer.AllowNonComponents = false;
                                _selectComponentDrawer.RestrictionType = _forcedObjectType;
                                _selectComponentDrawer.ShowXButton = true;
                                var targProp = property.FindPropertyRelative("_unityObjectReference");
                                EditorGUI.BeginChangeCheck();
                                _selectComponentDrawer.OnGUI(r1, targProp);
                                if (EditorGUI.EndChangeCheck())
                                {
                                    variant.ObjectValue = targProp.objectReferenceValue as Component;
                                }
                            }
                            else
                            {
                                EditorGUI.BeginChangeCheck();
                                obj = EditorGUI.ObjectField(r1, obj, typeof(UnityEngine.Object), true);
                                if(EditorGUI.EndChangeCheck())
                                {
                                    if(obj == null)
                                    {
                                        variant.ObjectValue = null;
                                    }
                                    else if(TypeUtil.IsType(obj.GetType(), _forcedObjectType))
                                    {
                                        variant.ObjectValue = obj;
                                    }
                                    else
                                    {
                                        var go = GameObjectUtil.GetGameObjectFromSource(obj);
                                        if (go != null)
                                            variant.ObjectValue = go.GetComponent(_forcedObjectType);
                                        else
                                            variant.ObjectValue = null;
                                    }
                                }
                            }
                        }
                        else
                        {
                            variant.ObjectValue = EditorGUI.ObjectField(r1, obj, _forcedObjectType, true);
                        }
                    }
                    break;
                case VariantType.LayerMask:
                    {
                        variant.LayerMaskValue = SPEditorGUI.LayerMaskField(r1, GUIContent.none, (int)variant.LayerMaskValue);
                    }
                    break;
                case VariantType.Rect:
                    {
                        variant.RectValue = EditorGUI.RectField(r1, variant.RectValue);
                    }
                    break;
            }
        }
 public EditorHelper(VariantReference obj)
 {
     _variant = obj;
 }
 public EditorHelper()
 {
     _variant = new VariantReference();
 }