public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            float space    = 5;
            float iconSize = EditorGUIUtility.singleLineHeight;

            GUI.enabled = !isLock;
            EditorGUI.PropertyField(position.ExtendRight(-iconSize - space), property, label);
            GUI.enabled = true;

            GUI.contentColor = isLock ? new Color(0.9F, 0.9F, 0.9F) : new Color(1F, 0.8F, 0.1F);
            bool isClick = GUI.Button(
                position.ExtendLeft(-(position.width - iconSize)).SetHeight(iconSize),
                new GUIContent(OnionDataEditor.GetIconTexture(isLock ? "Lock" : "Unlock")),
                new GUIStyle(EditorStyles.label)
            {
                padding = new RectOffset(2, 2, 2, 2)
            });

            GUI.contentColor = Color.white;

            if (isClick)
            {
                isLock = !isLock;
            }
        }
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            float h = EditorGUIUtility.singleLineHeight;

            var objectTypeSp = property.FindPropertyRelative("objectType");

            Rect r = position
                     .SetHeight(h);

            Type type = null;

            using (var ch = new EditorGUI.ChangeCheckScope())
            {
                string objectTypeStr = EditorGUI.DelayedTextField(r.ExtendLeft(-h - gap), objectTypeSp.stringValue);

                type = NodeExtensions.GetTypeByName(objectTypeStr);
                Texture texture = EditorGUIUtility.ObjectContent(null, type)?.image;
                texture = texture == null?OnionDataEditor.GetIconTexture("Dot") : texture;

                EditorGUI.LabelField(r.SetWidth(h), new GUIContent(texture));


                if (ch.changed)
                {
                    property.FindPropertyRelative("objectType").stringValue = objectTypeStr;

                    property.FindPropertyRelative("objectTypeFullName").stringValue = type?.FullName ?? "";

                    property.serializedObject.ApplyModifiedProperties();
                }
            }

            string objectType = objectTypeSp.stringValue;

            if (string.IsNullOrEmpty(objectType))
            {
                EditorGUI.LabelField(position.MoveDown(h + gap).SetHeight(h), $"Please input type.", EditorStyles.miniLabel);
                return;
            }

            type = NodeExtensions.GetTypeByName(objectTypeSp.stringValue);
            if (type != null)
            {
                EditorGUI.LabelField(position.MoveDown(h + gap).SetHeight(h), $"Type : {type.FullName}", EditorStyles.miniLabel);
                ObjectPropertyGUI(position.MoveDown(50), property, type);
                return;
            }

            EditorGUI.LabelField(position.MoveDown(h + gap).SetHeight(h), $"Nothing compare this type.", EditorStyles.miniLabel);
        }
        public override TreeNode Construct(TreeNode node, Object target)
        {
            if (AssetDatabase.IsMainAsset(target) && AssetDatabase.GetAssetPath(target).EndsWith(".json"))
            {
                var n = new JsonNodeConstructor().Construct(node, target);

                return(n);
            }


            Init(target);


            //node.OnInspectorGUI = OnInspectorGUI;
            node.OnInspectorVisualElementRoot = CreateInspectorRoot();

            node.NodeActions = new List <OnionAction>
            {
                new OnionAction(Save, "Save", OnionDataEditor.GetIconTexture("Save")),
            };

            return(node);
        }
        protected override void RowGUI(RowGUIArgs args)
        {
            TreeNode node = treeQuery[args.item.id];

            RowState state;

            if (node.IsNull)
            {
                state = RowState.Error;
            }
            else if (node.IsPseudo)
            {
                state = RowState.Pseudo;
            }
            else
            {
                state = RowState.Normal;
            }

            GUIStyle style   = GetStateGUIStyle(state, args.item);
            bool     hasIcon = node.icon != null;

            if (OnionDataEditor.Setting.isRowGUIActive)
            {
                DrawNodeRowGUI();
            }

            DrawIcon();

            DrawTitle();

            DrawRightSideInfo();

            DrawTagColor();

            //Line
            Rect lineRect = args.rowRect
                            .ExtendLeft(-GetContentIndent(args.item))
                            .ExtendUpToFit(1);

            EditorGUI.DrawRect(lineRect, new Color(0.5f, 0.5f, 0.5f, 0.05F));      //線


            void DrawNodeRowGUI()
            {
                const float leftSpace  = 200F;
                const float rightSpace = 40F;

                if (Event.current.type == EventType.Repaint &&
                    args.rowRect.width < leftSpace + rightSpace)
                {
                    return;
                }

                Rect rect = args.rowRect
                            .ExtendLeft(-leftSpace)
                            .ExtendRight(-rightSpace);

                //EditorGUI.DrawRect(rect, new Color(1, 1, 1, 0.3F)); //For Debug

                node.OnRowGUI?.Invoke(rect);
            }

            void DrawIcon()
            {
                const float padding = 1F;

                if (hasIcon)
                {
                    float iconHeight = args.rowRect.height - padding * 2;

                    Rect iconRect = new Rect(args.rowRect)
                                    .ExtendLeft(-GetContentIndent(args.item))
                                    .SetSize(iconHeight, iconHeight);


                    GUI.Label(iconRect, node.icon);
                }
            }

            void DrawTitle()
            {
                Rect labelRect = new Rect(args.rowRect)
                                 .ExtendLeft(-GetContentIndent(args.item))
                                 .ExtendLeft(-(hasIcon ? (args.rowRect.height + 4F) : 2F));

                GUI.Label(labelRect, node.displayName, style);
            }

            void DrawRightSideInfo()
            {
                bool isHideElementNodes = node.Flag.HasFlag(TreeNode.NodeFlag.HideElementNodes);

                if (treeQuery[args.item.id].ChildCount > 0 || isHideElementNodes)
                {
                    const float tagWidth  = 40F;
                    Rect        rightRect = new Rect(args.rowRect)
                                            .ExtendLeft(-args.rowRect.width)
                                            .ExtendLeft(tagWidth);

                    GUIStyle labelStyle = new GUIStyle(GUI.skin.label)
                    {
                        normal =
                        {
                            textColor = new Color(0.5F, 0.5F, 0.5F, 0.5F),
                        },
                        alignment = TextAnchor.MiddleCenter,
                        fontSize  = 10,
                        padding   = new RectOffset(0, 0, 0, 0),
                        border    = new RectOffset(16, 16, 16, 16),
                    };

                    if (isHideElementNodes)
                    {
                        var icon = OnionDataEditor.GetIconTexture("HideElement");
                        GUI.color = new Color(1, 1, 1, 0.5F);
                        GUI.Label(
                            rightRect.ExtendLeft(-rightRect.width + rightRect.height).MoveLeft(8),
                            new GUIContent(icon, "Hide Elements"));
                        GUI.color = Color.white;
                    }
                    else
                    {
                        string displayTag = treeQuery[args.item.id].ChildCount.ToString();
                        GUI.Label(rightRect.ExtendHorizontal(-5).ExtendVertical(-2), $"[ {displayTag} ]", labelStyle);
                    }
                }
            }

            void DrawTagColor()
            {
                if (node.tagColor.a > 0F)
                {
                    const float colorTagWidth = 3F;
                    Rect        colorTagRect  = new Rect(args.rowRect)
                                                .ExtendLeft(-args.rowRect.width)
                                                .ExtendLeft(colorTagWidth)
                                                .ExtendDown(-1);

                    EditorGUI.DrawRect(colorTagRect, node.tagColor);
                }
            }
        }
示例#5
0
        public override TreeNode Construct(TreeNode node, UnityEngine.Object target)
        {
            InitStyles();

            node.ClearChildren();

            JsonNode root = new JsonNode()
            {
                displayName = "root",
                description = "Object",
            };

            node.AddSingleChild(root);

            var saveAction = new OnionAction(() =>
            {
                string jsonText = JsonBridge.GetJsonText(root);
                Save(jsonText);
            }, "Save", OnionDataEditor.GetIconTexture("Save"));

            node.NodeActions = new List <OnionAction> {
                saveAction
            };

            JsonBridge.BuildNode(root, target, Bind);

            return(node);

            //

            void Bind(JsonNode jsonNode)
            {
                jsonNode.description = jsonNode.JsonType.ToString();

                //Object
                if (jsonNode.JsonType == JsonNode.JsonNodeType.Object)
                {
                    jsonNode.OnInspectorGUI = () => DrawCollectionGUI(jsonNode, false);
                    jsonNode.NodeActions    = new List <OnionAction>
                    {
                        saveAction,
                        GetRemoveNodeAction(jsonNode),
                        new OnionAction(() =>
                        {
                            CommonTypeNameInputWindow.Open(
                                "Add Property",
                                JsonNode.JsonNodeType.Object,
                                "",
                                (propertyType, propertyName) =>
                            {
                                if (string.IsNullOrEmpty(propertyName) == false)
                                {
                                    AddNewObjectProperty(jsonNode, propertyName, (JsonNode.JsonNodeType)propertyType);
                                }
                            });
                        },
                                        "Add Property",
                                        OnionDataEditor.GetIconTexture("Add")),
                    };

                    return;
                }

                //Array
                if (jsonNode.JsonType == JsonNode.JsonNodeType.Array)
                {
                    jsonNode.OnInspectorGUI = () => DrawCollectionGUI(jsonNode, true);
                    jsonNode.NodeActions    = new List <OnionAction>
                    {
                        saveAction,
                        GetRemoveNodeAction(jsonNode),
                        new OnionAction(() =>
                        {
                            if (jsonNode.ChildCount == 0)
                            {
                                CommonTypeNameInputWindow.Open(
                                    "Add Item",
                                    JsonNode.JsonNodeType.Object,
                                    jsonType =>
                                {
                                    AddNewArrayItem(jsonNode, (JsonNode.JsonNodeType)jsonType);
                                });
                            }
                            else
                            {
                                JsonNode.JsonNodeType arrayItemType = (jsonNode.GetChildren().First() as JsonNode).JsonType;
                                AddNewArrayItem(jsonNode, arrayItemType);
                            }
                        },
                                        "Add Item",
                                        OnionDataEditor.GetIconTexture("Add")),
                    };

                    return;
                }

                //Field
                jsonNode.OnInspectorGUI = () => DrawFieldGUI(jsonNode);
                jsonNode.OnRowGUI       = (rect) =>
                {
                    float h = EditorGUIUtility.singleLineHeight;
                    rect = rect.MoveDown((rect.height - h) / 2 - 1).SetHeight(h);

                    jsonNode.DrawFieldGUI(rect);
                };
                jsonNode.NodeActions = new List <OnionAction>
                {
                    saveAction,
                    GetRemoveNodeAction(jsonNode),
                };
            }

            OnionAction GetRemoveNodeAction(JsonNode targetNode)
            {
                return(new OnionAction(() =>
                {
                    JsonNode parent = (targetNode.Parent as JsonNode);
                    if (parent != null)
                    {
                        parent.Remove(targetNode);
                        parent.UpdateItemIndexDisplayName();
                        OnionDataEditorWindow.UpdateTreeView();
                        OnionDataEditorWindow.SetSelectionAt(parent);
                    }
                },
                                       "Remove",
                                       OnionDataEditor.GetIconTexture("Trash")));
            }

            void AddNewArrayItem(JsonNode arrayNode, JsonNode.JsonNodeType jsonNodeType)
            {
                var newArrayNode = new JsonNode()
                {
                    JsonType = jsonNodeType,
                };

                Bind(newArrayNode);
                arrayNode.AddItem(newArrayNode);
                arrayNode.UpdateItemIndexDisplayName();
                OnionDataEditorWindow.UpdateTreeView();
            }

            void AddNewObjectProperty(JsonNode objectNode, string propertyName, JsonNode.JsonNodeType jsonNodeType)
            {
                var newObjectNode = new JsonNode()
                {
                    JsonType = jsonNodeType,
                };

                Bind(newObjectNode);
                objectNode.AddProperty(propertyName, newObjectNode);
                objectNode.UpdatePropertyDisplayName();
                OnionDataEditorWindow.UpdateTreeView();
            }

            //

            void DrawCollectionGUI(JsonNode jsonNode, bool isArray)
            {
                string lb = isArray ? "[" : "{";
                string rb = isArray ? "]" : "}";

                using (new GUILayout.HorizontalScope())
                {
                    jsonNode.isExpend = GUILayout.Toggle(jsonNode.isExpend,
                                                         new GUIContent($"{jsonNode.displayName}"),
                                                         objectOrArrayTitle,
                                                         GUILayout.Height(EditorGUIUtility.singleLineHeight));

                    GUI.color = new Color(1, 1, 1, 0.7F);

                    GUILayout.Label(
                        $"  {lb}",
                        objectOrArrayTitleChip,
                        GUILayout.Height(EditorGUIUtility.singleLineHeight));

                    if (jsonNode.isExpend == false)
                    {
                        GUILayout.Space(7);

                        GUILayout.Label($"{jsonNode.ChildCount}", new GUIStyle(EditorStyles.helpBox)
                        {
                            stretchWidth = false
                        });

                        GUILayout.Space(7);

                        GUILayout.Label(
                            $"{rb}",
                            objectOrArrayTitleChip,
                            GUILayout.Height(EditorGUIUtility.singleLineHeight));
                    }

                    GUI.color = Color.white;
                }

                if (jsonNode.isExpend)
                {
                    using (new GUILayout.VerticalScope(objectOrArrayConatiner))
                    {
                        using (new GUILayout.HorizontalScope())
                        {
                            GUILayout.Space(5);
                            GUI.color = new Color(1, 1, 1, 0.1F);
                            GUILayout.Label(
                                "",
                                new GUIStyle()
                            {
                                normal        = { background = OnionDataEditor.GetIconTexture("Gray") },
                                stretchHeight = true,
                            },
                                GUILayout.Width(1));
                            GUI.color = Color.white;
                            GUILayout.Space(10);

                            using (new GUILayout.VerticalScope())
                            {
                                if (jsonNode.ChildCount > 0)
                                {
                                    foreach (var nodeCh in jsonNode.GetChildren())
                                    {
                                        nodeCh.OnInspectorGUI?.Invoke();
                                    }
                                }

                                else
                                {
                                    using (new GUILayout.HorizontalScope())
                                    {
                                        GUILayout.Space(14);
                                        GUI.color = new Color(1, 1, 1, 0.5F);
                                        GUILayout.Label(
                                            isArray ? "Array is empty" : "Object is empty",
                                            new GUIStyle(EditorStyles.helpBox)
                                        {
                                            stretchWidth = false
                                        });
                                        GUI.color = Color.white;
                                    }
                                }
                            }
                        }
                    }

                    if (true)
                    {
                        using (new GUILayout.HorizontalScope())
                        {
                            GUI.color = new Color(1, 1, 1, 0.7F);
                            GUILayout.Space(5);
                            GUILayout.Label(
                                $"{rb}",
                                objectOrArrayTitleChip,
                                GUILayout.Height(EditorGUIUtility.singleLineHeight));
                            GUI.color = Color.white;
                        }
                    }
                }
            }

            void DrawFieldGUI(JsonNode jsonNode)
            {
                using (new GUILayout.HorizontalScope())
                {
                    using (new GUILayout.HorizontalScope(GUILayout.Width(200)))
                    {
                        GUI.color = new Color(1, 1, 1, 0.5F);
                        GUILayout.Label(OnionDataEditor.GetIconTexture("Dash"),
                                        new GUIStyle(EditorStyles.label)
                        {
                            margin = new RectOffset(0, 0, 4, 1)
                        },
                                        GUILayout.Width(14), GUILayout.Height(14));
                        GUI.color = Color.white;

                        GUILayout.Label(
                            new GUIContent(jsonNode.displayName),
                            new GUIStyle(EditorStyles.label)
                        {
                            margin = new RectOffset(0, 0, 1, 1)
                        },
                            GUILayout.Height(EditorGUIUtility.singleLineHeight));

                        GUILayout.FlexibleSpace();
                    }

                    Rect rect = GUILayoutUtility.GetRect(new GUIContent(), new GUIStyle()
                    {
                        stretchWidth = true, stretchHeight = true
                    });

                    float h = EditorGUIUtility.singleLineHeight;
                    rect = rect.MoveDown((rect.height - h) / 2 - 1).SetHeight(h);

                    jsonNode.DrawFieldGUI(rect);
                }
            }

            //

            void InitStyles()
            {
                objectOrArrayConatiner = new GUIStyle
                {
                    padding = new RectOffset(0, 0, 0, 0),
                };

                objectOrArrayTitle = new GUIStyle(EditorStyles.foldoutHeader)
                {
                    margin       = new RectOffset(0, 0, 4, 4),
                    stretchWidth = false,
                    fontStyle    = FontStyle.Normal,
                };

                objectOrArrayTitleChip = new GUIStyle(EditorStyles.label)
                {
                    stretchWidth = false,
                    fontSize     = 12,
                    padding      = new RectOffset(0, 0, 0, 0),
                    margin       = new RectOffset(0, 0, 2, 2),
                };
            }

            void Save(string jsonText)
            {
                string assetPath = AssetDatabase.GetAssetPath(target).Substring("Asset/".Length);

                string projectPath = Application.dataPath;

                string path = $"{projectPath}{assetPath}";

                try
                {
                    File.WriteAllText(path, jsonText, Encoding.UTF8);
                    EditorUtility.SetDirty(target);
                    AssetDatabase.Refresh();

                    //Debug.Log(resultJsonText);
                    Debug.Log("Save success");
                }
                catch (Exception e)
                {
                    Debug.LogError(e.Message);
                }
            }
        }
        void ObjectPropertyGUI(Rect position, SerializedProperty property, Type type)
        {
            if (type.FullName != objectTypeCache)
            {
                memberInfosCache = type.GetMembers(flag);
                objectTypeCache  = type.FullName;
            }

            float h = EditorGUIUtility.singleLineHeight;

            List <(DefineType defineType, MemberInfo memberInfo, Type memberType)> members = new List <(DefineType, MemberInfo, Type)>();

            foreach (var m in memberInfosCache)
            {
                Type propType = null;
                if (m.MemberType == MemberTypes.Property)
                {
                    PropertyInfo propertyInfo = (PropertyInfo)m;

                    //if is indexer, skip.
                    if (propertyInfo.GetIndexParameters().Length > 0)
                    {
                        continue;
                    }

                    propType = propertyInfo.PropertyType;
                }
                else if (m.MemberType == MemberTypes.Field)
                {
                    propType = ((FieldInfo)m).FieldType;
                }
                else
                {
                    continue;
                }

                if (IsTitleType(propType))
                {
                    members.Add((DefineType.Title, m, propType));
                }

                if (IsDescriptionType(propType))
                {
                    members.Add((DefineType.Description, m, propType));
                }

                if (IsIconType(propType))
                {
                    members.Add((DefineType.Icon, m, propType));
                }

                if (IsColorTagType(propType))
                {
                    members.Add((DefineType.TagColor, m, propType));
                }

                if (IsElementType(propType))
                {
                    members.Add((DefineType.Element, m, propType));
                }
            }

            //

            const float titleWidth = 150F;
            int         index      = 0;

            foreach (DefineType defineType in Enum.GetValues(typeof(DefineType)).Cast <DefineType>())
            {
                var rLeft = position
                            .MoveDown(index * (h + gap))
                            .SetWidth(titleWidth)
                            .SetHeight(h);

                Texture icon = OnionDataEditor.GetIconTexture($"Node_{defineType}");
                EditorGUI.LabelField(rLeft, new GUIContent($"{defineType}", icon), EditorStyles.boldLabel);

                var rRight = position
                             .MoveDown(index * (h + gap))
                             .ExtendLeft(-titleWidth)
                             .SetHeight(h);
                RegHeight(rRight);

                var list = members.Where(n => n.defineType == defineType).Select(n => n.memberInfo.Name).ToList();

                if (list.Count > 0)
                {
                    list.Insert(0, defaultString);

                    if (defineType == DefineType.Element)
                    {
                        MuiltpleEnumPop(rRight, defineType, list);
                    }
                    else
                    {
                        EnumPop(rRight, defineType, list);
                    }
                }
                else
                {
                    GUI.color = new Color(1, 1, 1, 0.25F);
                    EditorGUI.LabelField(rRight, $"Only default.", EditorStyles.miniLabel);
                    GUI.color = Color.white;
                }

                index++;
            }

            void EnumPop(Rect r, DefineType defineType, List <string> contentList)
            {
                var sp = GetSpByDefineType(defineType);

                EditorGUI.BeginChangeCheck();
                int originIndex = contentList.IndexOf(sp.stringValue);

                originIndex = Mathf.Max(originIndex, 0);

                int selectIndex = EditorGUI.Popup(r, originIndex, contentList.ToArray());

                if (EditorGUI.EndChangeCheck())
                {
                    if (selectIndex != 0)
                    {
                        sp.stringValue = contentList[selectIndex];
                    }
                    else
                    {
                        sp.stringValue = "";
                    }
                    sp.serializedObject.ApplyModifiedProperties();
                }
            }

            void MuiltpleEnumPop(Rect r, DefineType defineType, List <string> contentList)
            {
                var sp = GetSpByDefineType(defineType);

                HashSet <string> elList = new HashSet <string>();

                for (int i = 0; i < sp.arraySize; i++)
                {
                    elList.Add(sp.GetArrayElementAtIndex(i).stringValue);
                }

                string displayName = elList.Count == 0 ? defaultString : string.Join(", ", elList);

                if (GUI.Button(r, displayName, EditorStyles.popup))
                {
                    GenericMenu menu = new GenericMenu();
                    for (int i = 0; i < contentList.Count; i++)
                    {
                        int  iCache = i;
                        bool isOn   = elList.Contains(contentList[i]);
                        menu.AddItem(
                            new GUIContent(contentList[i]),
                            iCache == 0 ? elList.Count == 0 : isOn,
                            () =>
                        {
                            if (iCache == 0)
                            {
                                //Default
                                elList.Clear();
                                sp.ClearArray();
                            }
                            else
                            {
                                if (isOn)
                                {
                                    elList.Remove(contentList[iCache]);
                                }
                                else
                                {
                                    elList.Add(contentList[iCache]);
                                }
                                sp.ClearArray();

                                foreach (var elString in elList)
                                {
                                    sp.InsertArrayElementAtIndex(sp.arraySize);
                                    sp.GetArrayElementAtIndex(sp.arraySize - 1).stringValue = elString;
                                }
                            }

                            sp.serializedObject.ApplyModifiedProperties();
                        });
                    }

                    menu.DropDown(r.MoveDown(h).SetSize(0, 0));
                }
            }

            SerializedProperty GetSpByDefineType(DefineType defineType)
            {
                switch (defineType)
                {
                case DefineType.Title:
                    return(property.FindPropertyRelative("titlePropertyName"));

                case DefineType.Description:
                    return(property.FindPropertyRelative("descriptionPropertyName"));

                case DefineType.Icon:
                    return(property.FindPropertyRelative("iconPropertyName"));

                case DefineType.TagColor:
                    return(property.FindPropertyRelative("tagColorPorpertyName"));

                case DefineType.Element:
                    return(property.FindPropertyRelative("elementPropertyNames"));

                default:
                    throw new Exception($"Can not find compare serialized property by {defineType}");
                }
            }

            bool IsTitleType(Type t) => IsType <string>(t);

            bool IsDescriptionType(Type t) => IsType <string>(t);

            bool IsIconType(Type t) => IsType <Texture>(t) || IsType <Sprite>(t);

            bool IsColorTagType(Type t) => IsType <Color>(t);

            bool IsElementType(Type t)
            {
                return
                    (IsType <UnityEngine.Object>(t) ||
                     (t.IsSubclassOf(typeof(IEnumerable <>)) && IsType <UnityEngine.Object>(t.GenericTypeArguments[0])) ||
                     (t.IsArray && IsType <UnityEngine.Object>(t.GetElementType())));
            }

            bool IsType <T>(Type t)
            {
                return(t == typeof(T) || t.IsSubclassOf(typeof(T)));
            }
        }