public void DrawSmart(
            Rect position, SerializedProperty valProp, SerializedProperty refProp,
            Vector2 min, Vector2 max, bool showCreateBtn, SmartDataRefBase.RefType?rt = null
            )
        {
            Rect fieldPos = new Rect(position.x, position.y, position.width - (18 + SPACING), position.height);

            // In LOCAL mode, trigger dispatch if value changed from editor
            EditorGUI.BeginChangeCheck();
            EditorGUI.PropertyField(fieldPos, valProp, GUIContent.none);
            if (rt.HasValue && rt.Value == SmartDataRefBase.RefType.LOCAL && Application.isPlaying && EditorGUI.EndChangeCheck())
            {
                var o = refProp.GetObject();
                var d = o.GetType().GetMethod("Dispatch", BindingFlags.Instance | BindingFlags.Public);
                if (d != null)
                {
                    d.Invoke(o, null);
                }
            }

            if (showCreateBtn && !Application.isPlaying)
            {
                Rect createBtnPos = new Rect();
                createBtnPos.xMin   = fieldPos.max.x + SPACING;              // - SmartEditorUtils.indent;
                createBtnPos.xMax   = max.x;
                createBtnPos.yMin   = fieldPos.yMin;
                createBtnPos.height = fieldPos.height;
                Color gbc = GUI.backgroundColor;
                GUI.backgroundColor = Color.green;
                if (GUI.Button(createBtnPos, _gcCreateBtn, EditorStyles.miniButton))
                {
                    var s = ScriptableObject.CreateInstance(valProp.GetFieldType().FullName);
                    s.name = ObjectNames.NicifyVariableName(_baseProperty.name).Replace(" ", "");
                    valProp.objectReferenceValue = s;
                    AssetDatabase.CreateAsset(s, string.Format("{0}/{1}.asset", ProjectPanelPathUtil.GetProjectPath(), s.name));
                    EditorGUIUtility.PingObject(s);
                }
                GUI.backgroundColor = gbc;
            }
        }
        public sealed override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            ProjectPanelPathUtil.Init();

            bool metadataGenerated = false;

            _baseProperty = property;
            var ownerProp = property.FindPropertyRelative("_owner");
            var owner     = property.serializedObject.targetObject;
            int id        = 0;

            if (owner is Component)
            {
                // Owner is a Component - find GameObject
                var og = (owner as Component).gameObject;
                if (ownerProp.objectReferenceValue != og)
                {
                    ownerProp.objectReferenceValue = og;
                    metadataGenerated = true;
                }
                id = og.GetInstanceID();
            }
            else
            {
                // Owner is an Object - use directly
                if (ownerProp.objectReferenceValue != owner)
                {
                    ownerProp.objectReferenceValue = owner;
                    metadataGenerated = true;
                }
                id = owner.GetInstanceID();
            }

            var ownerName = property.FindPropertyRelative("_ownerName");

            if (ownerName.stringValue != owner.name)
            {
                ownerName.stringValue = owner.name;
                metadataGenerated     = true;
            }

            var    pathProp = property.FindPropertyRelative("_propertyPath");
            string pp       = pathProp.stringValue;

            if (pp != property.propertyPath)
            {
                pathProp.stringValue = property.propertyPath;
                metadataGenerated    = true;
            }
            if (metadataGenerated)
            {
                property.serializedObject.ApplyModifiedProperties();
            }

            EditorGUI.BeginChangeCheck();
            EditorGUI.BeginProperty(position, label, property);
            Vector2 min = position.min;
            Vector2 max = position.max;

            position.height = BasePropertyHeight(property, label);
            DrawGUI(position, property, label, min, max);
            EditorGUI.EndProperty();
            if (EditorGUI.EndChangeCheck())
            {
                property.serializedObject.ApplyModifiedProperties();
            }
        }