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); } } }
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))); } }