1
0
mirror of https://github.com/Siccity/xNode.git synced 2025-12-20 01:06:01 +08:00

Added NodeHeaderAttribute

This commit is contained in:
Oli 2023-01-09 20:22:53 +00:00
parent d2b4b55872
commit 9ec2abb061
8 changed files with 32 additions and 115 deletions

View File

@ -1,71 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using XNode;
using XNodeEditor;
namespace XNodeEditor {
[CustomPropertyDrawer(typeof(NodeEnumAttribute))]
public class NodeEnumDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
EnumPopup(position, property, label);
EditorGUI.EndProperty();
}
public static void EnumPopup(Rect position, SerializedProperty property, GUIContent label) {
// Throw error on wrong type
if (property.propertyType != SerializedPropertyType.Enum) {
throw new ArgumentException("Parameter selected must be of type System.Enum");
}
// Add label
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
// Get current enum name
string enumName = "";
if (property.enumValueIndex >= 0 && property.enumValueIndex < property.enumDisplayNames.Length) enumName = property.enumDisplayNames[property.enumValueIndex];
#if UNITY_2017_1_OR_NEWER
// Display dropdown
if (EditorGUI.DropdownButton(position, new GUIContent(enumName), FocusType.Passive)) {
// Position is all wrong if we show the dropdown during the node draw phase.
// Instead, add it to onLateGUI to display it later.
NodeEditorWindow.current.onLateGUI += () => ShowContextMenuAtMouse(property);
}
#else
// Display dropdown
if (GUI.Button(position, new GUIContent(enumName), "MiniPopup")) {
// Position is all wrong if we show the dropdown during the node draw phase.
// Instead, add it to onLateGUI to display it later.
NodeEditorWindow.current.onLateGUI += () => ShowContextMenuAtMouse(property);
}
#endif
}
public static void ShowContextMenuAtMouse(SerializedProperty property) {
// Initialize menu
GenericMenu menu = new GenericMenu();
// Add all enum display names to menu
for (int i = 0; i < property.enumDisplayNames.Length; i++) {
int index = i;
menu.AddItem(new GUIContent(property.enumDisplayNames[i]), false, () => SetEnum(property, index));
}
// Display at cursor position
Rect r = new Rect(Event.current.mousePosition, new Vector2(0, 0));
menu.DropDown(r);
}
private static void SetEnum(SerializedProperty property, int index) {
property.enumValueIndex = index;
property.serializedObject.ApplyModifiedProperties();
property.serializedObject.Update();
}
}
}

View File

@ -1,13 +0,0 @@
fileFormatVersion: 2
guid: 83db81f92abadca439507e25d517cabe
timeCreated: 1541633798
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -25,8 +25,17 @@ namespace XNodeEditor {
protected internal static bool inNodeEditor = false;
#endif
public virtual void OnHeaderGUI() {
GUILayout.Label(target.name, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
public virtual void OnHeaderGUI()
{
var content = new GUIContent(target.name);
var type = target.GetType();
if (type.TryGetAttributeHeader(out GUIContent attrContent))
{
if (content.text != NodeEditorUtilities.NodeDefaultName(type))
attrContent.text = content.text;
content = attrContent;
}
GUILayout.Label(content, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
}
/// <summary> Draws standard field editors for all public fields </summary>

View File

@ -14,6 +14,7 @@ namespace XNodeEditor {
public static class NodeEditorReflection {
[NonSerialized] private static Dictionary<Type, Color> nodeTint;
[NonSerialized] private static Dictionary<Type, int> nodeWidth;
[NonSerialized] private static Dictionary<Type, GUIContent> nodeHeader;
/// <summary> All available node types </summary>
public static Type[] nodeTypes { get { return _nodeTypes != null ? _nodeTypes : _nodeTypes = GetNodeTypes(); } }
@ -47,6 +48,14 @@ namespace XNodeEditor {
return nodeWidth.TryGetValue(nodeType, out width);
}
/// <summary> Get custom node headers defined with [NodeHeader] </summary>
public static bool TryGetAttributeHeader(this Type nodeType, out GUIContent content)
{
if (nodeHeader == null)
CacheAttributes<GUIContent, XNode.Node.NodeHeaderAttribute>(ref nodeHeader, x => x.content);
return nodeHeader.TryGetValue(nodeType, out content);
}
private static void CacheAttributes<V, A>(ref Dictionary<Type, V> dict, Func<A, V> getter) where A : Attribute {
dict = new Dictionary<Type, V>();
for (int i = 0; i < nodeTypes.Length; i++) {

View File

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 5644dfc7eed151045af664a9d4fd1906
folderAsset: yes
timeCreated: 1541633926
licenseType: Free
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +0,0 @@
using UnityEngine;
/// <summary> Draw enums correctly within nodes. Without it, enums show up at the wrong positions. </summary>
/// <remarks> Enums with this attribute are not detected by EditorGui.ChangeCheck due to waiting before executing </remarks>
public class NodeEnumAttribute : PropertyAttribute { }

View File

@ -1,13 +0,0 @@
fileFormatVersion: 2
guid: 10a8338f6c985854697b35459181af0a
timeCreated: 1541633942
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace XNode {
@ -387,6 +388,16 @@ namespace XNode {
this.width = width;
}
}
/// <summary> Specify header GUIContent for this node type </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class NodeHeaderAttribute : Attribute
{
public GUIContent content;
public NodeHeaderAttribute(string name) => content = new GUIContent(name);
public NodeHeaderAttribute(string name, string iconPath) => content = new GUIContent(EditorGUIUtility.IconContent(iconPath)) {text = name};
}
#endregion
[Serializable] private class NodePortDictionary : Dictionary<string, NodePort>, ISerializationCallbackReceiver {
@ -406,7 +417,7 @@ namespace XNode {
public void OnAfterDeserialize() {
this.Clear();
#if UNITY_2021_3_OR_NEWER
#if UNITY_2021_3_OR_NEWER
this.EnsureCapacity(keys.Count);
#endif