diff --git a/Attributes/NodeAttribute.cs b/Attributes/NodeAttribute.cs
index 81e085d..6ef59c3 100644
--- a/Attributes/NodeAttribute.cs
+++ b/Attributes/NodeAttribute.cs
@@ -8,6 +8,11 @@ namespace NewGraph {
///
[AttributeUsage(AttributeTargets.Class)]
public class NodeAttribute : Attribute {
+ ///
+ /// Should an input port be created?
+ ///
+ public bool createInputPort = true;
+
///
/// Color of the node as a hex string, like #FFFFFFFF. Be aware: The last two characters are for alpha values!
///
@@ -42,7 +47,8 @@ public class NodeAttribute : Attribute {
/// A custom name for the input port.
/// The maximum amount of allowed connections to the input port of this node.
/// A custom name for the node.
- public NodeAttribute(string color = null, string categories = "", string inputPortName = null, Capacity inputPortCapacity = Capacity.Multiple, string nodeName = null) {
+ /// The maximum amount of allowed connections to the input port of this node.
+ public NodeAttribute(string color = null, string categories = "", string inputPortName = null, Capacity inputPortCapacity = Capacity.Multiple, string nodeName = null, bool createInputPort = true) {
if (color != null) {
ColorUtility.TryParseHtmlString(color, out this.color);
}
@@ -52,6 +58,7 @@ public NodeAttribute(string color = null, string categories = "", string inputPo
this.inputPortName = inputPortName;
this.inputPortCapacity = inputPortCapacity;
this.categories = categories;
+ this.createInputPort = createInputPort;
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1427895..31f225a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -169,4 +169,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.2.8] - 2023-03-15
### Fixed
-- Fixed possible ArgumentException caused by the new ContextMenu architecture
\ No newline at end of file
+- Fixed possible ArgumentException caused by the new ContextMenu architecture
+
+## [0.2.9] - 2023-03-16
+### Added
+- Added createInputPort to [Node] attribute. This allows to hide the input port for a node. [#6](https://github.com/Gentlymad-Studios/NewGraph/issues/6)
+- Added comments to ContextMenu, EdgeDropMenu so it is easier to understand & extend
\ No newline at end of file
diff --git a/Documentation~ b/Documentation~
index ed9da80..2821ff9 160000
--- a/Documentation~
+++ b/Documentation~
@@ -1 +1 @@
-Subproject commit ed9da80ba1a56f3e9c5a78e2d1761d43755617d5
+Subproject commit 2821ff9d93a468f9af96b8ad238d4e2f65329ff6
diff --git a/Editor/Attributes/CustomContextMenuAttribute.cs b/Editor/Attributes/CustomContextMenuAttribute.cs
index db7318b..ea4a724 100644
--- a/Editor/Attributes/CustomContextMenuAttribute.cs
+++ b/Editor/Attributes/CustomContextMenuAttribute.cs
@@ -1,6 +1,9 @@
using System;
namespace NewGraph {
+ ///
+ /// Attribute that can be attached to a class that inherits from ContextMenu to change & customize the main context menu.
+ ///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CustomContextMenuAttribute : Attribute {
diff --git a/Editor/Attributes/CustomEdgeDropMenuAttribute.cs b/Editor/Attributes/CustomEdgeDropMenuAttribute.cs
index 3527d17..a2d9c70 100644
--- a/Editor/Attributes/CustomEdgeDropMenuAttribute.cs
+++ b/Editor/Attributes/CustomEdgeDropMenuAttribute.cs
@@ -1,6 +1,9 @@
using System;
namespace NewGraph {
+ ///
+ /// Attribute that can be attached to a class that inherits from EdgeDropMenu to change & customize the edge drop context menu.
+ ///
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CustomEdgeDropMenuAttribute : Attribute {
diff --git a/Editor/Controllers/NodeController.cs b/Editor/Controllers/NodeController.cs
index ce359c2..23e4021 100644
--- a/Editor/Controllers/NodeController.cs
+++ b/Editor/Controllers/NodeController.cs
@@ -102,7 +102,9 @@ public void DoForEachPortListProperty(Action actio
}
public void DoForInputPortProperty(Action action) {
- action(propertyBag.inputPort, nodeDataProperty);
+ if (propertyBag.inputPort != null) {
+ action(propertyBag.inputPort, nodeDataProperty);
+ }
}
public void DoForNameProperty(Action action) {
diff --git a/Editor/Serialization/PropertyBag.cs b/Editor/Serialization/PropertyBag.cs
index 7ada957..fafdf0e 100644
--- a/Editor/Serialization/PropertyBag.cs
+++ b/Editor/Serialization/PropertyBag.cs
@@ -34,7 +34,9 @@ public class PropertyBag {
private PropertyBag(NodeAttribute nodeAttribute, Type nodeType, SerializedProperty nodeProperty) {
this.nodeType = nodeType;
- inputPort = new PortInfo(nodeProperty.propertyPath, nodeType, new PortBaseAttribute(nodeAttribute.inputPortName, nodeAttribute.inputPortCapacity, PortDirection.Input), Settings.defaultInputName);
+ if (nodeAttribute.createInputPort) {
+ inputPort = new PortInfo(nodeProperty.propertyPath, nodeType, new PortBaseAttribute(nodeAttribute.inputPortName, nodeAttribute.inputPortCapacity, PortDirection.Input), Settings.defaultInputName);
+ }
InitializeAttributebehaviors();
RetrieveAll(nodeProperty);
}
diff --git a/Editor/Views/ContextMenu.cs b/Editor/Views/ContextMenu.cs
index f25b1d7..dd0a232 100644
--- a/Editor/Views/ContextMenu.cs
+++ b/Editor/Views/ContextMenu.cs
@@ -6,44 +6,83 @@
using static NewGraph.GraphSettingsSingleton;
namespace NewGraph {
+ ///
+ /// Main ContextMenu that is being used when performing a right-click in the graph view.
+ /// This can be inherited by a custom class that has the [CustomContextMenu] attribute.
+ /// Beware: This class inherits from GraphSearchWindowProvider and therefore is a ScriptableObject by nature.
+ ///
public class ContextMenu : GraphSearchWindowProvider {
+ ///
+ /// static lookup table that gathers unique labels for node types.
+ ///
protected static Dictionary nodeTypeToCreationLabel = new Dictionary();
+ ///
+ /// the graph controller this context menu operates on.
+ ///
protected GraphController graphController;
+ ///
+ /// Initialize should be called after the object is created via CreateInstance
+ ///
+ /// The graph controller this context menu should operate on.
public void Initialize(GraphController graphController) {
this.graphController = graphController;
Initialize(this.graphController.graphView.shortcutHandler);
}
+ ///
+ /// Instantiate a custom or default context menu
+ ///
+ /// The graph controller this context menu should operate on.
+ /// The instance of the newly created context menu.
public static ContextMenu CreateContextMenu(GraphController graphController) {
+ // get all types that have the [CustomContextMenu] attribute
TypeCache.TypeCollection types = TypeCache.GetTypesWithAttribute();
ContextMenu menu;
foreach (Type type in types) {
+ // is the detected type actually inheriting from ContextMenu?
if (type.ImplementsOrInherits(typeof(ContextMenu))) {
+ // create an instance of the custom ContextMenu type!
menu = CreateInstance(type) as ContextMenu;
menu.Initialize(graphController);
return menu;
}
}
+ // no custom editor found or ineligible
menu = CreateInstance();
menu.Initialize(graphController);
return menu;
}
- public virtual bool DefaultEnableCheck() {
+ ///
+ /// Default check wether a menu entry should be enabled.
+ ///
+ /// Should the menu entry be enabled?
+ public virtual bool DefaultEnabledCheck() {
return graphController.graphView.GetSelectedNodeCount() > 0;
}
+ ///
+ /// Default check for node entries and wether they should be enabled.
+ ///
+ /// Should the node entry be enabled?
public virtual bool DefaultNodeEnabledCheck() {
return graphController.graphData != null;
}
+ ///
+ /// Header label
+ ///
+ ///
protected virtual string GetHeader() {
return Settings.searchWindowRootHeader;
}
+ ///
+ /// Creates/builds the context menu
+ ///
public virtual void BuildContextMenu() {
StartAddingMenuEntries(GetHeader());
AddNodeEntries();
@@ -51,10 +90,16 @@ public virtual void BuildContextMenu() {
AddCommands();
}
+ ///
+ /// Add all node entries.
+ ///
protected virtual void AddNodeEntries() {
AddNodeEntriesDefault();
}
+ ///
+ /// Default implementation to create all node entries.
+ ///
protected void AddNodeEntriesDefault() {
// get all types across all assemblies that implement our INode interface
TypeCache.TypeCollection nodeTypes = TypeCache.GetTypesWithAttribute();
@@ -89,19 +134,25 @@ protected void AddNodeEntriesDefault() {
}
}
+ ///
+ /// Add all command panel entries
+ ///
protected virtual void AddCommands() {
AddDefaultCommands();
}
+ ///
+ /// defualt implementation of all commands
+ ///
protected void AddDefaultCommands() {
AddSeparator(Settings.searchWindowCommandHeader);
AddShortcutEntry(Actions.Frame, SearchTreeEntry.AlwaysEnabled, graphController.FrameGraph);
AddShortcutEntry(Actions.Rename, () => graphController.graphView.GetSelectedNodeCount() == 1, graphController.OnRename);
- AddShortcutEntry(Actions.Cut, DefaultEnableCheck, graphController.OnCut);
- AddShortcutEntry(Actions.Copy, DefaultEnableCheck, graphController.OnCopy);
+ AddShortcutEntry(Actions.Cut, DefaultEnabledCheck, graphController.OnCut);
+ AddShortcutEntry(Actions.Copy, DefaultEnabledCheck, graphController.OnCopy);
AddShortcutEntry(Actions.Paste, () => graphController.copyPasteHandler.HasNodes(), graphController.OnPaste);
- AddShortcutEntry(Actions.Duplicate, DefaultEnableCheck, graphController.OnDuplicate);
- AddShortcutEntry(Actions.Delete, () => graphController.graphView.HasSelectedEdges() || DefaultEnableCheck(), graphController.OnDelete);
+ AddShortcutEntry(Actions.Duplicate, DefaultEnabledCheck, graphController.OnDuplicate);
+ AddShortcutEntry(Actions.Delete, () => graphController.graphView.HasSelectedEdges() || DefaultEnabledCheck(), graphController.OnDelete);
}
}
diff --git a/Editor/Views/EdgeDropMenu.cs b/Editor/Views/EdgeDropMenu.cs
index 832a29c..a565269 100644
--- a/Editor/Views/EdgeDropMenu.cs
+++ b/Editor/Views/EdgeDropMenu.cs
@@ -3,48 +3,80 @@
using UnityEditor;
namespace NewGraph {
+ ///
+ /// The EdgeDropMenu is being used after dropping an edge into empty space in the graph.
+ /// This can be inherited by a custom class that has the [CustomEdgeDropMenu] attribute.
+ /// Beware: This class inherits from GraphSearchWindowProvider and therefore is a ScriptableObject by nature.
+ ///
public class EdgeDropMenu : ContextMenu {
-
+ ///
+ /// the port this menu should operate on. This is required to be updated fromt he outside.
+ ///
public PortView port;
-
+
+ ///
+ /// Instantiate a custom or default edge drop menu
+ ///
+ /// The graph controller this edge drop menu should operate on.
+ /// The instance of the newly created edge drop menu.
public static EdgeDropMenu CreateEdgeDropMenu(GraphController graphController) {
+ // get all types that have the [CustomEgeDropMenu] attribute
TypeCache.TypeCollection types = TypeCache.GetTypesWithAttribute();
EdgeDropMenu menu;
foreach (Type type in types) {
+ // is the detected type actually inheriting from ContextMenu?
if (type.ImplementsOrInherits(typeof(EdgeDropMenu))) {
+ // create an instance of the custom ContextMenu type!
menu = CreateInstance(type) as EdgeDropMenu;
menu.Initialize(graphController);
return menu;
}
}
+ // no custom editor found or ineligible
menu = CreateInstance();
menu.Initialize(graphController);
return menu;
}
+ ///
+ /// Add all node entries.
+ ///
protected override void AddNodeEntries() {
PortView currentPort = port;
foreach (Type type in currentPort.connectableTypes) {
if (nodeTypeToCreationLabel.ContainsKey(type)) {
void CreateNodeAndConnect() {
NodeView nodeView = graphController.CreateNewNode(type, false);
- graphController.ConnectPorts(currentPort, nodeView.inputPort);
+ if (nodeView.inputPort != null) {
+ graphController.ConnectPorts(currentPort, nodeView.inputPort);
+ }
}
AddNodeEntry(nodeTypeToCreationLabel[type], (obj) => CreateNodeAndConnect());
}
}
}
+ ///
+ /// The edge drop menu node entries should always be enabled.
+ ///
+ ///
public override bool DefaultNodeEnabledCheck() {
return true;
}
- public override bool DefaultEnableCheck() {
+ ///
+ /// The edge drop menu entries should always be enabled.
+ ///
+ ///
+ public override bool DefaultEnabledCheck() {
return true;
}
+ ///
+ /// At least on default, the edge drop menu does not have a command panel.
+ ///
protected override void AddCommands() {}
}
}
diff --git a/package.json b/package.json
index a91aaba..940fb76 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "com.gentlymad.newgraph",
- "version": "0.2.8",
+ "version": "0.2.9",
"displayName": "NewGraph",
"description": "A general data oriented node graph solution. This is build upon the idea to visualize complex data structures as graph networks without having to modify already established data classes, except adding [Node], [Port] and [SerializeReference] attributes to call classes that should show in the Graph View.",
"unity": "2022.2",