mirror of
https://github.com/Siccity/xNode.git
synced 2026-02-09 16:48:43 +08:00
Add [RequireNode] attribute to graphs (#254)
This commit is contained in:
parent
c298b5ee53
commit
d9d90f0f7b
@ -67,7 +67,7 @@ namespace XNodeEditor {
|
|||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
|
||||||
#if ODIN_INSPECTOR
|
#if ODIN_INSPECTOR
|
||||||
// Call repaint so that the graph window elements respond properly to layout changes coming from Odin
|
// Call repaint so that the graph window elements respond properly to layout changes coming from Odin
|
||||||
if (GUIHelper.RepaintRequested) {
|
if (GUIHelper.RepaintRequested) {
|
||||||
GUIHelper.ClearRepaintRequest();
|
GUIHelper.ClearRepaintRequest();
|
||||||
window.Repaint();
|
window.Repaint();
|
||||||
@ -106,17 +106,22 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary>
|
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary>
|
||||||
public virtual void AddContextMenuItems(GenericMenu menu) {
|
public virtual void AddContextMenuItems(GenericMenu menu) {
|
||||||
|
bool canRemove = true;
|
||||||
// Actions if only one node is selected
|
// Actions if only one node is selected
|
||||||
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
||||||
XNode.Node node = Selection.activeObject as XNode.Node;
|
XNode.Node node = Selection.activeObject as XNode.Node;
|
||||||
menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node));
|
menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node));
|
||||||
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode);
|
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode);
|
||||||
|
|
||||||
|
canRemove = NodeGraphEditor.GetEditor(node.graph, NodeEditorWindow.current).CanRemove(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add actions to any number of selected nodes
|
// Add actions to any number of selected nodes
|
||||||
menu.AddItem(new GUIContent("Copy"), false, NodeEditorWindow.current.CopySelectedNodes);
|
menu.AddItem(new GUIContent("Copy"), false, NodeEditorWindow.current.CopySelectedNodes);
|
||||||
menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes);
|
menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes);
|
||||||
menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
|
|
||||||
|
if (canRemove) menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
|
||||||
|
else menu.AddItem(new GUIContent("Remove"), false, null);
|
||||||
|
|
||||||
// Custom sctions if only one node is selected
|
// Custom sctions if only one node is selected
|
||||||
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
||||||
@ -132,11 +137,10 @@ namespace XNodeEditor {
|
|||||||
OnRename();
|
OnRename();
|
||||||
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
|
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Called after this node's name has changed. </summary>
|
/// <summary> Called after this node's name has changed. </summary>
|
||||||
public virtual void OnRename() { }
|
public virtual void OnRename() { }
|
||||||
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class CustomNodeEditorAttribute : Attribute,
|
public class CustomNodeEditorAttribute : Attribute,
|
||||||
XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node>.INodeEditorAttrib {
|
XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node>.INodeEditorAttrib {
|
||||||
@ -152,4 +156,4 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,8 +187,25 @@ namespace XNodeEditor {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Return false for nodes that can't be removed </summary>
|
||||||
|
public virtual bool CanRemove(XNode.Node node) {
|
||||||
|
// Check graph attributes to see if this node is required
|
||||||
|
Type graphType = target.GetType();
|
||||||
|
XNode.NodeGraph.RequireNodeAttribute[] attribs = Array.ConvertAll(
|
||||||
|
graphType.GetCustomAttributes(typeof(XNode.NodeGraph.RequireNodeAttribute), true), x => x as XNode.NodeGraph.RequireNodeAttribute);
|
||||||
|
if (attribs.Any(x => x.Requires(node.GetType()))) {
|
||||||
|
if (target.nodes.Count(x => x.GetType() == node.GetType()) <= 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Safely remove a node and all its connections. </summary>
|
/// <summary> Safely remove a node and all its connections. </summary>
|
||||||
public virtual void RemoveNode(XNode.Node node) {
|
public virtual void RemoveNode(XNode.Node node) {
|
||||||
|
if (!CanRemove(node)) return;
|
||||||
|
|
||||||
|
// Remove the node
|
||||||
Undo.RecordObject(node, "Delete Node");
|
Undo.RecordObject(node, "Delete Node");
|
||||||
Undo.RecordObject(target, "Delete Node");
|
Undo.RecordObject(target, "Delete Node");
|
||||||
foreach (var port in node.Ports)
|
foreach (var port in node.Ports)
|
||||||
|
|||||||
45
Scripts/Editor/NodeGraphImporter.cs
Normal file
45
Scripts/Editor/NodeGraphImporter.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Experimental.AssetImporters;
|
||||||
|
using UnityEngine;
|
||||||
|
using XNode;
|
||||||
|
|
||||||
|
namespace XNodeEditor {
|
||||||
|
/// <summary> Deals with modified assets </summary>
|
||||||
|
class NodeGraphImporter : AssetPostprocessor {
|
||||||
|
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) {
|
||||||
|
foreach (string path in importedAssets) {
|
||||||
|
// Skip processing anything without the .asset extension
|
||||||
|
if (Path.GetExtension(path) != ".asset") continue;
|
||||||
|
|
||||||
|
// Get the object that is requested for deletion
|
||||||
|
NodeGraph graph = AssetDatabase.LoadAssetAtPath<NodeGraph>(path);
|
||||||
|
if (graph == null) continue;
|
||||||
|
|
||||||
|
// Get attributes
|
||||||
|
Type graphType = graph.GetType();
|
||||||
|
NodeGraph.RequireNodeAttribute[] attribs = Array.ConvertAll(
|
||||||
|
graphType.GetCustomAttributes(typeof(NodeGraph.RequireNodeAttribute), true), x => x as NodeGraph.RequireNodeAttribute);
|
||||||
|
|
||||||
|
Vector2 position = Vector2.zero;
|
||||||
|
foreach (NodeGraph.RequireNodeAttribute attrib in attribs) {
|
||||||
|
if (attrib.type0 != null) AddRequired(graph, attrib.type0, ref position);
|
||||||
|
if (attrib.type1 != null) AddRequired(graph, attrib.type1, ref position);
|
||||||
|
if (attrib.type2 != null) AddRequired(graph, attrib.type2, ref position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddRequired(NodeGraph graph, Type type, ref Vector2 position) {
|
||||||
|
if (!graph.nodes.Any(x => x.GetType() == type)) {
|
||||||
|
XNode.Node node = graph.AddNode(type);
|
||||||
|
node.position = position;
|
||||||
|
position.x += 200;
|
||||||
|
if (node.name == null || node.name.Trim() == "") node.name = NodeEditorUtilities.NodeDefaultName(type);
|
||||||
|
if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(graph))) AssetDatabase.AddObjectToAsset(node, graph);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Scripts/Editor/NodeGraphImporter.cs.meta
Normal file
11
Scripts/Editor/NodeGraphImporter.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7a816f2790bf3da48a2d6d0035ebc9a0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -81,5 +81,44 @@ namespace XNode {
|
|||||||
// Remove all nodes prior to graph destruction
|
// Remove all nodes prior to graph destruction
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Attributes
|
||||||
|
/// <summary> Automatically ensures the existance of a certain node type, and prevents it from being deleted. </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||||
|
public class RequireNodeAttribute : Attribute {
|
||||||
|
public Type type0;
|
||||||
|
public Type type1;
|
||||||
|
public Type type2;
|
||||||
|
|
||||||
|
/// <summary> Automatically ensures the existance of a certain node type, and prevents it from being deleted </summary>
|
||||||
|
public RequireNodeAttribute(Type type) {
|
||||||
|
this.type0 = type;
|
||||||
|
this.type1 = null;
|
||||||
|
this.type2 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Automatically ensures the existance of a certain node type, and prevents it from being deleted </summary>
|
||||||
|
public RequireNodeAttribute(Type type, Type type2) {
|
||||||
|
this.type0 = type;
|
||||||
|
this.type1 = type2;
|
||||||
|
this.type2 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Automatically ensures the existance of a certain node type, and prevents it from being deleted </summary>
|
||||||
|
public RequireNodeAttribute(Type type, Type type2, Type type3) {
|
||||||
|
this.type0 = type;
|
||||||
|
this.type1 = type2;
|
||||||
|
this.type2 = type3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Requires(Type type) {
|
||||||
|
if (type == null) return false;
|
||||||
|
if (type == type0) return true;
|
||||||
|
else if (type == type1) return true;
|
||||||
|
else if (type == type2) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user