diff --git a/TNode/Attribute/Ports/BatchInputAttribute.cs b/TNode/Attribute/Ports/BatchInputAttribute.cs
new file mode 100644
index 0000000..4786d55
--- /dev/null
+++ b/TNode/Attribute/Ports/BatchInputAttribute.cs
@@ -0,0 +1,5 @@
+namespace TNode.Attribute.Ports{
+ public class BatchInputAttribute{
+
+ }
+}
\ No newline at end of file
diff --git a/TNode/Attribute/Ports/BatchInputAttribute.cs.meta b/TNode/Attribute/Ports/BatchInputAttribute.cs.meta
new file mode 100644
index 0000000..2847ec0
--- /dev/null
+++ b/TNode/Attribute/Ports/BatchInputAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8745aaf35940443693af378c8214060e
+timeCreated: 1657190813
\ No newline at end of file
diff --git a/TNode/Attribute/Ports/BatchOutputAttribute.cs b/TNode/Attribute/Ports/BatchOutputAttribute.cs
new file mode 100644
index 0000000..71a20c3
--- /dev/null
+++ b/TNode/Attribute/Ports/BatchOutputAttribute.cs
@@ -0,0 +1,13 @@
+using System;
+using UnityEditor.Experimental.GraphView;
+
+namespace TNode.Attribute.Ports{
+ ///
+ /// Batch out port attribute could specify a batch out port,allowing large scale calculation.
+ ///
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
+ public class BatchOutputAttribute:PortAttribute{
+ public BatchOutputAttribute(string name="") : base(name){
+ }
+ }
+}
\ No newline at end of file
diff --git a/TNode/Attribute/Ports/BatchOutputAttribute.cs.meta b/TNode/Attribute/Ports/BatchOutputAttribute.cs.meta
new file mode 100644
index 0000000..e5a345e
--- /dev/null
+++ b/TNode/Attribute/Ports/BatchOutputAttribute.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 0a6ca9cc801d4db3b73ee59cf0aef38e
+timeCreated: 1657190648
\ No newline at end of file
diff --git a/TNode/Attribute/Ports/InputAttribute.cs b/TNode/Attribute/Ports/InputAttribute.cs
index 0ac3ed1..dd4b855 100644
--- a/TNode/Attribute/Ports/InputAttribute.cs
+++ b/TNode/Attribute/Ports/InputAttribute.cs
@@ -7,11 +7,7 @@ namespace TNode.Attribute{
[MeansImplicitUse]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class InputAttribute : PortAttribute{
- public InputAttribute(string portName, Type nodeLinkType, Port.Capacity capacity, string portAccepted = "*") : base(portName, nodeLinkType, capacity, portAccepted){
- }
- public InputAttribute(Type nodeLinkType, Port.Capacity capacity, string portAccepted="*") : base(nodeLinkType, capacity, portAccepted){
- }
- public InputAttribute(string portName="*",string portAccepted = "*") :base(portName, typeof(NodeLink),Port.Capacity.Multi,portAccepted){
+ public InputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto) : base(name, nameHandling){
}
}
}
\ No newline at end of file
diff --git a/TNode/Attribute/Ports/OutputAttribute.cs b/TNode/Attribute/Ports/OutputAttribute.cs
index 675d731..a0c3908 100644
--- a/TNode/Attribute/Ports/OutputAttribute.cs
+++ b/TNode/Attribute/Ports/OutputAttribute.cs
@@ -1,5 +1,6 @@
namespace TNode.Attribute.Ports{
- public class OutputAttribute:System.Attribute{
-
+ public class OutputAttribute:PortAttribute{
+ public OutputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto) : base(name, nameHandling){
+ }
}
}
\ No newline at end of file
diff --git a/TNode/Attribute/Ports/PortAttribute.cs b/TNode/Attribute/Ports/PortAttribute.cs
index 1b983eb..24feda5 100644
--- a/TNode/Attribute/Ports/PortAttribute.cs
+++ b/TNode/Attribute/Ports/PortAttribute.cs
@@ -3,26 +3,24 @@ using JetBrains.Annotations;
using UnityEditor.Experimental.GraphView;
namespace TNode.Attribute{
+
+ public enum PortNameHandling{
+ Auto,
+ MemberName,
+ Manual,
+ Format,
+ MemberType
+
+ }
[MeansImplicitUse]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
-
public class PortAttribute:System.Attribute{
- public string PortName;
- public string PortAccepted;
- public Type NodeLinkType;
- public Port.Capacity Capacity;
-
- public PortAttribute(string portName, Type nodeLinkType, Port.Capacity capacity,string portAccepted="*"){
- PortName = portName;
- PortAccepted = portAccepted;
- NodeLinkType = nodeLinkType;
- Capacity = capacity;
- }
- //Auto generate port name via variable use this attribute
- public PortAttribute(Type nodeLinkType, Port.Capacity capacity, string portAccepted = "*"){
- PortAccepted = portAccepted;
- NodeLinkType = nodeLinkType;
- Capacity = capacity;
+ public readonly string Name;
+ public readonly PortNameHandling NameHandling;
+
+ public PortAttribute(string name,PortNameHandling nameHandling=PortNameHandling.Auto){
+ this.Name = name;
+ this.NameHandling = nameHandling;
}
}
}
\ No newline at end of file
diff --git a/TNode/Attribute/ShowInNodeViewAttribute.cs b/TNode/Attribute/ShowInNodeViewAttribute.cs
index f2ffde9..d516534 100644
--- a/TNode/Attribute/ShowInNodeViewAttribute.cs
+++ b/TNode/Attribute/ShowInNodeViewAttribute.cs
@@ -2,6 +2,7 @@
namespace TNode.Attribute{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
+
public class ShowInNodeViewAttribute:System.Attribute{
}
diff --git a/TNode/Editor/BaseViews/DataGraphView.cs b/TNode/Editor/BaseViews/DataGraphView.cs
index 408bfed..dac2122 100644
--- a/TNode/Editor/BaseViews/DataGraphView.cs
+++ b/TNode/Editor/BaseViews/DataGraphView.cs
@@ -4,8 +4,10 @@ using System.Linq;
using System.Reflection;
using TNode.BaseViews;
using TNode.Cache;
+using TNode.Editor.GraphBlackboard;
using TNode.Editor.Inspector;
using TNode.Editor.Model;
+using TNode.Editor.Tools.NodeCreator;
using TNode.Models;
using Unity.VisualScripting;
using UnityEditor;
@@ -109,6 +111,11 @@ namespace TNode.Editor.BaseViews{
}
*/
public abstract class DataGraphView:GraphView,IDataGraphView where T:GraphData{
+ #region variables and properties
+
+
+
+
private T _data;
private bool _isInspectorOn;
@@ -116,7 +123,9 @@ namespace TNode.Editor.BaseViews{
private NodeInspector _nodeInspector;
public GraphEditor Owner;
private Dictionary _nodeDict = new();
+ private Blackboard _blackboard;
+
public T Data{
get{ return _data; }
set{
@@ -128,11 +137,17 @@ namespace TNode.Editor.BaseViews{
}
}
public event DataChangedEventHandler OnDataChanged;
+ #endregion
+ #region event declarations
public delegate void DataChangedEventHandler(object sender, DataChangedEventArgs e);
+
+ #endregion
//A Constructor for the DataGraphView ,never to override it
+
+
+ #region construct default behaviour
public DataGraphView(){
-
styleSheets.Add(Resources.Load("GraphViewBackground"));
var grid = new GridBackground();
Insert(0,grid);
@@ -141,6 +156,7 @@ namespace TNode.Editor.BaseViews{
this.AddManipulator(new SelectionDragger());
this.AddManipulator(new RectangleSelector());
SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale);
+ RegisterDragEvent();
OnInit();
}
private void ConstructDefaultBehaviour(){
@@ -149,10 +165,7 @@ namespace TNode.Editor.BaseViews{
}
public void ConstructViewContextualMenu(){
-
- //Rebuild the contextual menu
-
- this.RegisterCallback(evt => {
+ RegisterCallback(evt => {
Vector2 editorPosition = Owner==null?Vector2.zero:Owner.position.position;
//Remove all the previous menu items
evt.menu.MenuItems().Clear();
@@ -163,15 +176,57 @@ namespace TNode.Editor.BaseViews{
searchWindow.Setup(typeof(T),this,Owner);
SearchWindow.Open(searchWindowContext, searchWindow);
});
-
});
-
}
private void OnInit(){
ConstructDefaultBehaviour();
OnGraphViewCreate();
}
+ public void RegisterDragEvent(){
+ RegisterCallback(OnDragUpdated);
+ RegisterCallback(OnDragPerform);
+ }
+
+ #endregion
+
+ #region event callbakc
+
+ private void OnDragPerform(DragPerformEvent evt){
+
+ if (DragAndDrop.GetGenericData("DragSelection") is List{Count: > 0} data){
+ var blackboardFields = data.OfType();
+ foreach (var selectable in blackboardFields){
+ if(selectable is { } field) {
+ //Make a constructor of BlackboardDragNodeData by reflection
+ var specifiedType =
+ typeof(BlackboardDragNodeData<>).MakeGenericType(field.BlackboardProperty.PropertyType);
+ //Create a new instance of specified type
+ var dragNodeData = NodeCreator.InstantiateNodeData(specifiedType);
+ this.AddTNode(dragNodeData,new Rect(evt.mousePosition,new Vector2(200,200)));
+ }
+ }
+
+ }
+ }
+
+ private void OnDragUpdated(DragUpdatedEvent evt){
+ Debug.Log(evt);
+
+ //check if the drag data is BlackboardField
+
+ if (DragAndDrop.GetGenericData("DragSelection") is List{Count: > 0} data){
+ DragAndDrop.visualMode = DragAndDropVisualMode.Move;
+
+ }
+
+
+ }
+
+ #endregion
+
+
+
public void ResetGraphView(){
//Clear all nodes
foreach (var node in nodes){
@@ -206,8 +261,7 @@ namespace TNode.Editor.BaseViews{
input = inputNodeView.inputContainer.Q(edge.inPort.portName),
output = outputNodeView.outputContainer.Q(edge.outPort.portName)
};
- Debug.Log(edge.inPort.portName);
- Debug.Log(edge.outPort.portName);
+
newEdge.input?.Connect(newEdge);
newEdge.output?.Connect(newEdge);
AddElement(newEdge);
@@ -219,7 +273,7 @@ namespace TNode.Editor.BaseViews{
-
+
public virtual void CreateInspector(){
NodeInspector nodeInspector = new NodeInspector();
this.Add(nodeInspector);
@@ -227,58 +281,48 @@ namespace TNode.Editor.BaseViews{
_isInspectorOn = true;
}
- public void CreateMiniMap(Rect rect){
+ public virtual void CreateMiniMap(Rect rect){
var miniMap = new MiniMap();
this.Add(miniMap);
miniMap.SetPosition(rect);
}
- public void CreateBlackboard(){
- var blackboard = new Blackboard();
+ public virtual void CreateBlackboard(){
+ _blackboard = new Blackboard();
//Blackboard add "Add Node" button
// blackboard.Add(new BlackboardSection(){
// title = "Hello World",
// });
// blackboard.addItemRequested = (item) => {
// //Create a sub window for the blackboard to show the selection
- // var subWindow = ScriptableObject.CreateInstance();
+ // var subWindow = ScriptableObject.CreateNodeComponentFromGenericType();
// };
//
//Set black board to left side of the view
- blackboard.SetPosition(new Rect(0,0,200,600));
- Add(blackboard);
+ _blackboard.SetPosition(new Rect(0,0,200,600));
+ Add(_blackboard);
//Check the type of the blackboard
- OnDataChanged+= (sender, e) => {
-
- if (_data.blackboardData==null||_data.blackboardData.GetType()==typeof(BlackboardData)){
- _data.blackboardData = NodeEditorExtensions.GetAppropriateBlackboardData(_data.GetType());
-
- if(_data.blackboardData==null) return;
-
- }
- Debug.Log(_data.blackboardData);
- //Iterate field of the blackboard and add a button for each field
- foreach (var field in _data.blackboardData.GetType()
- .GetFields(BindingFlags.Public|BindingFlags.NonPublic | BindingFlags.Instance)){
- Debug.Log(field);
- //if the field is MonoBehaviour,add a property field for blackboard
- if(typeof(UnityEngine.Object).IsAssignableFrom(field.FieldType)){
- var propertyField = new BlackboardField(null,field.Name,null){
-
- };
- blackboard.Add(propertyField);
- }
- if(typeof(string).IsAssignableFrom(field.FieldType)){
- var propertyField = new BlackboardField(null,field.Name,null){
-
- };
- blackboard.Add(propertyField);
- }
- }
- };
+ OnDataChanged+= (sender, e) => { BlackboardUpdate(); };
+
+ }
+ private void BlackboardUpdate(){
+ if (_data.blackboardData == null || _data.blackboardData.GetType() == typeof(BlackboardData)){
+ _data.blackboardData = NodeEditorExtensions.GetAppropriateBlackboardData(_data.GetType());
+
+ if (_data.blackboardData == null) return;
+ }
+
+ //Iterate field of the blackboard and add a button for each field
+ foreach (var field in _data.blackboardData.GetType()
+ .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)){
+ //if the field is MonoBehaviour,add a property field for blackboard
+ var propertyField = new BlackboardPropertyField(new BlackboardProperty(field.Name,field.FieldType));
+ _blackboard.Add(propertyField);
+ }
}
+
public virtual void DestroyInspector(){
if(_nodeInspector!=null){
this.Remove(_nodeInspector);
@@ -329,11 +373,10 @@ namespace TNode.Editor.BaseViews{
}
}
private void SaveEdge(){
+ var links = new List();
foreach (var edge in edges){
var inputNode = edge.input.node as INodeView;
var outputNode = edge.output.node as INodeView;
- var links = new List();
- Debug.Log($"Edge{inputNode},{outputNode}");
if (inputNode != null && outputNode != null){
var inputNodeData = inputNode.GetNodeData();
var outputNodeData = outputNode.GetNodeData();
@@ -347,17 +390,16 @@ namespace TNode.Editor.BaseViews{
});
links.Add(newNodeLink);
}
-
- _data.nodeLinks = links;
}
+
+ _data.nodeLinks = links;
}
private void SaveGraphData(){
_data.NodeDictionary.Clear();
-
+ _data.nodeLinks.Clear();
SaveNode();
SaveEdge();
-
EditorUtility.SetDirty(_data);
}
@@ -377,13 +419,16 @@ namespace TNode.Editor.BaseViews{
OnGraphViewDestroy();
}
+ public bool IsDroppable(){
+ return true;
+ }
+
public void AddTNode(NodeData nodeData, Rect rect){
if (NodeEditorExtensions.CreateNodeViewFromNodeType(nodeData.GetType()) is Node nodeView){
nodeView.SetPosition(rect);
AddElement(nodeView);
//Add a select callback to the nodeView
nodeView.RegisterCallback(evt => {
- Debug.Log("NodeView Selected");
if (evt.clickCount == 1){
if (_isInspectorOn){
_nodeInspector.Data = nodeData;
@@ -391,7 +436,6 @@ namespace TNode.Editor.BaseViews{
}
}
});
-
if(nodeView is INodeView nodeViewInterface){
nodeViewInterface.SetNodeData(nodeData);
}
@@ -403,30 +447,27 @@ namespace TNode.Editor.BaseViews{
menu.AddItem(new GUIContent("Delete"), false, () => {
RemoveElement(nodeView);
if (nodeView is INodeView tNodeView){
- var nodeData1 = tNodeView.GetNodeData();
- _data.NodeDictionary.Remove(nodeData1.id);
- _nodeDict.Remove(nodeData1.id);
- //Break all edges connected to this node
- foreach (var edge in edges){
- if (edge.input.node == nodeView || edge.output.node == nodeView){
- RemoveElement(edge);
- }
- }
- Owner.graphEditorData.graphElementsData.RemoveAll(x => x.guid == nodeData1.id);
+ RemoveTNode(tNodeView.GetNodeData());
}
});
menu.ShowAsContext();
});
-
-
-
-
}
}
public void RemoveTNode(NodeData nodeData){
- throw new NotImplementedException();
+
+ _data.NodeDictionary.Remove(nodeData.id);
+ var nodeView = _nodeDict[nodeData.id];
+ _nodeDict.Remove(nodeData.id);
+ //Break all edges connected to this node
+ foreach (var edge in edges){
+ if (edge.input.node == nodeView || edge.output.node == nodeView){
+ RemoveElement(edge);
+ }
+ }
+ Owner.graphEditorData.graphElementsData.RemoveAll(x => x.guid == nodeData.id);
}
}
diff --git a/TNode/Editor/BaseViews/NodeView.cs b/TNode/Editor/BaseViews/NodeView.cs
deleted file mode 100644
index 15c6636..0000000
--- a/TNode/Editor/BaseViews/NodeView.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-using System;
-using TNode.Attribute;
-using TNode.Attribute.Ports;
-using TNode.Editor.Inspector;
-using TNode.Models;
-using UnityEditor;
-using UnityEditor.Experimental.GraphView;
-using UnityEditor.UIElements;
-using UnityEngine;
-
-namespace TNode.Editor.BaseViews{
-
- //A NodeAttribute monitor some type of node in the graph
-
- public abstract class NodeView : Node,INodeView where T:NodeData,new(){
- protected T _data;
- private readonly NodeInspectorInNode _nodeInspectorInNode;
-
- public T Data{
- get => _data;
- set{
- if(_data!=null)
- ((NodeDataWrapper)_data).OnValueChanged -= OnDataValueChanged;
- _data = value;
- OnDataChanged?.Invoke(value);
- if(_data!=null)
- ((NodeDataWrapper)_data).OnValueChanged += OnDataValueChanged;
-
- }
- }
-
- private void OnDataValueChanged(NodeDataWrapper obj){
- Refresh();
- }
-
- public sealed override string title{
- get => base.title;
- set => base.title = value;
- }
- public event System.Action OnDataChanged;
-
- protected NodeView(){
- OnDataChanged+=OnDataChangedHandler;
- _nodeInspectorInNode = new NodeInspectorInNode(){
- name = "nodeInspectorInNode"
- };
- this.extensionContainer.Add(_nodeInspectorInNode);
- }
- private void OnDataChangedHandler(T obj){
- this.title = _data.nodeName;
- if (_nodeInspectorInNode != null){
- _nodeInspectorInNode.Data = obj;
-
-
- }
-
- BuildInputAndOutputPort();
- this.expanded = true;
- this.RefreshExpandedState();
- }
-
- private void BuildInputAndOutputPort(){
- var propertyInfos = _data.GetType().GetProperties();
-
- foreach (var propertyInfo in propertyInfos){
- var attribute = propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true);
- if (attribute.Length > 0){
- Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,Port.Capacity.Multi,propertyInfo.PropertyType);
- this.outputContainer.Add(port);
- port.portName = propertyInfo.Name;
- port.name = propertyInfo.Name;
- }
- }
- foreach (var propertyInfo in propertyInfos){
- Debug.Log(propertyInfos);
- var attribute = propertyInfo.GetCustomAttributes(typeof(InputAttribute),true);
- if (attribute.Length > 0){
- Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,Port.Capacity.Multi,propertyInfo.PropertyType);
- this.inputContainer.Add(port);
- port.portName = propertyInfo.Name;
- port.name = propertyInfo.Name;
- }
- }
- }
-
- public void SetNodeData(NodeData nodeData){
- Data = (T)nodeData;
-
- }
-
- public NodeData GetNodeData(){
- return _data;
- }
-
- public void OnDataModified(){
- Refresh();
- }
-
- public void Refresh(){
- title = _data.nodeName;
- }
- }
-
- public interface INodeView{
- public void SetNodeData(NodeData nodeData);
- public NodeData GetNodeData();
-
- public void OnDataModified();
-
- }
-}
\ No newline at end of file
diff --git a/TNode/Editor/Cache/NodeEditorExtensions.cs b/TNode/Editor/Cache/NodeEditorExtensions.cs
index 6338d97..d21c96c 100644
--- a/TNode/Editor/Cache/NodeEditorExtensions.cs
+++ b/TNode/Editor/Cache/NodeEditorExtensions.cs
@@ -9,14 +9,37 @@ using TNode.Editor.Inspector;
using TNode.Models;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
+using UnityEngine.TestTools.Utils;
namespace TNode.Cache{
///
/// Internal singleton class for caching TNode reflection Data.
///
+ internal class NodeEditorTypeDictionary:Dictionary{
+ //Custom camparator for sorting the dictionary by key.
+
+
+
+ private class NodeEditorTypeDictionaryComparer : IEqualityComparer
+ {
+ public bool Equals(Type x, Type y){
+ return x?.ToString() == y?.ToString();
+ }
+
+ public int GetHashCode(Type obj){
+ return obj.ToString().GetHashCode();
+ }
+ }
+
+ public NodeEditorTypeDictionary():base(new NodeEditorTypeDictionaryComparer()){
+
+ }
+
+ }
+
internal class NodeEditorSingleton{
private static NodeEditorSingleton _instance;
- public readonly Dictionary FromGenericToSpecific = new Dictionary();
+ public readonly Dictionary FromGenericToSpecific = new NodeEditorTypeDictionary();
public readonly Dictionary> GraphDataUsage = new Dictionary>();
public Dictionary GraphBlackboard = new();
public static NodeEditorSingleton Instance{
@@ -75,15 +98,22 @@ namespace TNode.Cache{
}
}
}
- private readonly Type[] _acceptedTypesForGenericToSpecific = new Type[]{typeof(NodeView<>),typeof(DataGraphView<>),typeof(InspectorItem<>)};
+ private readonly Type[] _acceptedTypesForGenericToSpecific = new Type[]{typeof(NodeView<>),typeof(DataGraphView<>),typeof(InspectorItem<>),typeof(NodeView<>)};
private void SetNodeComponentAttribute(Type type){
foreach (var attribute in type.GetCustomAttributes(typeof(NodeComponentAttribute), false)){
//fetch this type 's parent class
var parent = type.BaseType;
- //Check if this type is a generic type and is a generic type of NodeView or DataGraphView
- if (parent is{IsGenericType: true} && _acceptedTypesForGenericToSpecific.Contains(parent.GetGenericTypeDefinition())){
+ //Check if this type is a generic type and is a generic type of NodeView or DataGraphView,
+ //Two level generic definition is now supported by TNode
+ //Deeper nested generic definition is not supported by TNode
+ if (parent is{IsGenericType: true} &&
+ (_acceptedTypesForGenericToSpecific.Contains(parent.GetGenericTypeDefinition()) ||
+ (parent.GetGenericTypeDefinition().IsGenericType && _acceptedTypesForGenericToSpecific.Contains(parent.GetGenericTypeDefinition().GetGenericTypeDefinition()))
+ )
+ ){
//Get the generic type of this type
//Add this type to the dictionary
+ Debug.Log($"type {type} is a registered as node component for {parent}");
FromGenericToSpecific.Add(parent, type);
}
//TODO Note that a node component only applied to a specific type of editor,so ,same GraphView could behave differently in different editor.it's a todo feature.
@@ -92,32 +122,32 @@ namespace TNode.Cache{
}
//Outer wrapper for the singleton class
public static class NodeEditorExtensions{
- public static T CreateInstance(){
+ public static T CreateNodeComponentFromGenericType(){
var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[typeof(T)];
var instance = (T)Activator.CreateInstance(implementedType);
return instance;
}
- public static object CreateInstance(Type t){
+ public static object CreateNodeComponentFromGenericType(Type t){
if (NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(t)){
var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[t];
var instance = Activator.CreateInstance(implementedType);
return instance;
}
- else{
- Debug.Log($"No given type found {t}");
- //check if t is a generic type node view
- if (t is{IsGenericType: true} && t.GetGenericTypeDefinition() == typeof(NodeView<>)){
- var instance = Activator.CreateInstance(typeof(NodeView));
- return instance;
- }
-
- return null;
+ //check if t is a generic type node view
+ if (t is{IsGenericType: true} && t.GetGenericTypeDefinition() == typeof(NodeView<>)){
+ var instance = Activator.CreateInstance(typeof(NodeView));
+ return instance;
}
+ return null;
}
- public static bool HasSpecificType() where T : class{
+ public static bool HasSpecificTypeComponent() where T : class{
return NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(typeof(T));
}
+ public static bool HasSpecificTypeComponent(Type t) {
+
+ return NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(t);
+ }
public static List GetGraphDataUsage(Type t){
if (NodeEditorSingleton.Instance.GraphDataUsage.ContainsKey(t)){
return NodeEditorSingleton.Instance.GraphDataUsage[t];
@@ -145,13 +175,46 @@ namespace TNode.Cache{
}
public static object CreateNodeViewFromNodeType(Type t){
//Check the generic type of NodeView by t
+
+ if (t.IsGenericType){
+ Debug.Log($"A generic type {t} is detected");
+ //AKA if BlackboardDragNodeData is pulled
+ //Get BlackboardDragNodeData as generic type
+
+
+ var genericTypeDefinition = t.GetGenericTypeDefinition();
+
+ //What you want is a NodeView> to be created
+ var genericViewType = typeof(NodeView<>).MakeGenericType(genericTypeDefinition);
+ Debug.Log($"The generic view type is {genericViewType}");
+
+ //search for the specific type of genericViewType in the dictionary
+ if (NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(genericViewType)){
+
+ var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[genericViewType];
+ //The implementedType is still a generic type ,so we make it a specific type by using MakeGenericType
+ Debug.Log($"{implementedType}");
+ //Get argument type of t
+ var argumentType = t.GetGenericArguments()[0];
+ var instance = Activator.CreateInstance(implementedType.MakeGenericType(argumentType));
+
+ return instance;
+
+ }
+ else{
+ return new DefaultNodeView();
+ }
+
+ }
var type = typeof(NodeView<>).MakeGenericType(t);
if (NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(type)){
+
var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[type];
var instance = Activator.CreateInstance(implementedType);
return instance;
}
else{
+
return new DefaultNodeView();
}
diff --git a/TNode/Editor/GraphBlackboard/BlackboardField.cs b/TNode/Editor/GraphBlackboard/BlackboardField.cs
new file mode 100644
index 0000000..87f5d9d
--- /dev/null
+++ b/TNode/Editor/GraphBlackboard/BlackboardField.cs
@@ -0,0 +1,12 @@
+using UnityEditor.Experimental.GraphView;
+
+namespace TNode.Editor.GraphBlackboard{
+ public class BlackboardPropertyField:BlackboardField{
+ public BlackboardProperty BlackboardProperty;
+ public BlackboardPropertyField(BlackboardProperty blackboardProperty):base(null,blackboardProperty.PropertyName,null){
+ BlackboardProperty = blackboardProperty;
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/TNode/Editor/GraphBlackboard/BlackboardField.cs.meta b/TNode/Editor/GraphBlackboard/BlackboardField.cs.meta
new file mode 100644
index 0000000..e30c407
--- /dev/null
+++ b/TNode/Editor/GraphBlackboard/BlackboardField.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5603912d8c2b4d71878f76a7eb5915a7
+timeCreated: 1657033185
\ No newline at end of file
diff --git a/TNode/Editor/GraphBlackboard/BlackboardProperty.meta b/TNode/Editor/GraphBlackboard/BlackboardProperty.meta
new file mode 100644
index 0000000..85b9875
--- /dev/null
+++ b/TNode/Editor/GraphBlackboard/BlackboardProperty.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 35fceca3e7c849279ed5bee0a5ee3225
+timeCreated: 1657041797
\ No newline at end of file
diff --git a/TNode/Editor/GraphBlackboard/BlackboardProperty/BlackboardProperty.cs b/TNode/Editor/GraphBlackboard/BlackboardProperty/BlackboardProperty.cs
new file mode 100644
index 0000000..d7dff1a
--- /dev/null
+++ b/TNode/Editor/GraphBlackboard/BlackboardProperty/BlackboardProperty.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace TNode.Editor.GraphBlackboard{
+ public class BlackboardProperty{
+ public string PropertyName;
+ public Type PropertyType;
+ // public RuntimeCache.RuntimeCache.GetValueDelegate GetValue;
+ // public RuntimeCache.RuntimeCache.SetValueDelegate SetValue;
+ public BlackboardProperty(string propertyName, Type propertyType){
+ PropertyName = propertyName;
+ PropertyType = propertyType;
+ }
+ }
+}
\ No newline at end of file
diff --git a/TNode/Editor/GraphBlackboard/BlackboardProperty/BlackboardProperty.cs.meta b/TNode/Editor/GraphBlackboard/BlackboardProperty/BlackboardProperty.cs.meta
new file mode 100644
index 0000000..c0b848a
--- /dev/null
+++ b/TNode/Editor/GraphBlackboard/BlackboardProperty/BlackboardProperty.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: b022203e15244da5bcfbf7932e7dd30c
+timeCreated: 1657034160
\ No newline at end of file
diff --git a/TNode/Editor/GraphEditor.cs b/TNode/Editor/GraphEditor.cs
index 7619b74..e045f39 100644
--- a/TNode/Editor/GraphEditor.cs
+++ b/TNode/Editor/GraphEditor.cs
@@ -36,7 +36,7 @@ namespace TNode.Editor{
}
private void BuildGraphView(){
- _graphView = NodeEditorExtensions.CreateInstance>();
+ _graphView = NodeEditorExtensions.CreateNodeComponentFromGenericType>();
rootVisualElement.Add(_graphView);
_graphView.StretchToParentSize();
}
diff --git a/TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs b/TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs
new file mode 100644
index 0000000..148f9d7
--- /dev/null
+++ b/TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs
@@ -0,0 +1,20 @@
+using System;
+using TNode.Attribute;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace TNode.Editor.Inspector.InspectorImplementation{
+ [NodeComponent]
+ public class EnumFieldItem:InspectorItem{
+ public EnumFieldItem() : base(){
+ var field = new EnumField();
+ Debug.Log("An Enum Field is created");
+ CreateBindable(field);
+ OnDataChanged += () => {
+
+ field.Init(Value);
+ Debug.Log(Value.GetType());
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs.meta b/TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs.meta
new file mode 100644
index 0000000..1a83a95
--- /dev/null
+++ b/TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6eb83a1255d545e5998c7b3efd1b0d69
+timeCreated: 1657193097
\ No newline at end of file
diff --git a/TNode/Editor/Inspector/InspectorItem.cs b/TNode/Editor/Inspector/InspectorItem.cs
index 829ac4b..8802bb5 100644
--- a/TNode/Editor/Inspector/InspectorItem.cs
+++ b/TNode/Editor/Inspector/InspectorItem.cs
@@ -6,8 +6,8 @@ using UnityEngine.UIElements;
namespace TNode.Editor.Inspector{
public abstract class InspectorItem:VisualElement,INodeDataBinding {
- private NodeData _bindingNodeData;
- private string _bindingFieldName;
+ protected NodeData _bindingNodeData;
+ protected string _bindingFieldName;
protected BaseField Bindable;
protected event System.Action OnDataChanged;
@@ -38,15 +38,19 @@ namespace TNode.Editor.Inspector{
}
private T GetValue(){
-
+
var fieldInfo = _bindingNodeData.GetType().GetField(BindingPath, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
- //check field type
- if (fieldInfo != null && fieldInfo.FieldType == typeof(T)){
+ if (fieldInfo == null){
+ throw new Exception("Null field info");
+ }
+ if (fieldInfo.FieldType == typeof(T)){
return (T)fieldInfo.GetValue(BindingNodeData);
}
- else{
- Debug.LogError("Wrong Type for current node data");
+
+ if (fieldInfo.FieldType.IsEnum){
+ return (T)fieldInfo.GetValue(BindingNodeData);
}
+ Debug.LogError("Wrong Type for current node data");
return default;
}
@@ -75,7 +79,7 @@ namespace TNode.Editor.Inspector{
Bindable.UnregisterValueChangedCallback(OnInspectorItemValueChanged);
}
Bindable = bindable;
- this.Add(Bindable);
+ Add(Bindable);
Bindable?.RegisterValueChangedCallback(OnInspectorItemValueChanged);
}
private void OnDataChangedHandler(){
diff --git a/TNode/Editor/Inspector/InspectorItemFactory.cs b/TNode/Editor/Inspector/InspectorItemFactory.cs
index be99391..9e5f9a7 100644
--- a/TNode/Editor/Inspector/InspectorItemFactory.cs
+++ b/TNode/Editor/Inspector/InspectorItemFactory.cs
@@ -11,9 +11,30 @@ namespace TNode.Editor.Inspector{
public InspectorItem Create(){
//Check type of GraphDataType
- var hasSpecificType = NodeEditorExtensions.HasSpecificType>();
+ var hasSpecificType = NodeEditorExtensions.HasSpecificTypeComponent>();
+
if (hasSpecificType){
- return NodeEditorExtensions.CreateInstance>();
+ return NodeEditorExtensions.CreateNodeComponentFromGenericType>();
+ }
+
+ if (typeof(T).IsEnum){
+
+ return NodeEditorExtensions.CreateNodeComponentFromGenericType(typeof(InspectorItem)) as InspectorItem;
+ }
+ return null;
+ }
+
+ public INodeDataBindingBase Create(Type t){
+ var genericType = typeof(InspectorItem<>).MakeGenericType(t);
+ var hasSpecificType = NodeEditorExtensions.HasSpecificTypeComponent(genericType);
+
+ if (hasSpecificType){
+ return NodeEditorExtensions.CreateNodeComponentFromGenericType(genericType) as INodeDataBindingBase;
+ }
+
+ if (t.IsEnum){
+
+ return NodeEditorExtensions.CreateNodeComponentFromGenericType(typeof(InspectorItem)) as INodeDataBindingBase;
}
return null;
}
diff --git a/TNode/Editor/Inspector/NodeInspectorInNode.cs b/TNode/Editor/Inspector/NodeInspectorInNode.cs
index 0268d98..e89603e 100644
--- a/TNode/Editor/Inspector/NodeInspectorInNode.cs
+++ b/TNode/Editor/Inspector/NodeInspectorInNode.cs
@@ -33,16 +33,21 @@ namespace TNode.Editor.Inspector{
if(!showInNodeViewAttribute)
continue;
//Invoke generic function Create<> of default inspector item factory to create an inspector item of appropriate type by reflection
- MethodInfo methodInfo = inspectorItemFactory.GetType().GetMethod("Create", BindingFlags.Instance | BindingFlags.Public);
- if (methodInfo != null){
- var genericMethod = methodInfo.MakeGenericMethod(type);
- var createdItem = genericMethod.Invoke(inspectorItemFactory,null) as VisualElement;
- Add(createdItem);
- if (createdItem is INodeDataBindingBase castedItem){
- castedItem.BindingNodeData = _data;
- castedItem.BindingPath = bindingPath;
- }
+ var createdItem = inspectorItemFactory.Create(type);
+ if (createdItem is { } castedItem){
+ castedItem.BindingNodeData = _data;
+ castedItem.BindingPath = bindingPath;
}
+ Add((VisualElement)createdItem);
+ // MethodInfo methodInfo = inspectorItemFactory.GetType().GetMethod("Create", BindingFlags.Instance | BindingFlags.Public);
+ // if (methodInfo != null){
+ // var genericMethod = methodInfo.MakeGenericMethod(type);
+ // Debug.Log(genericMethod);
+ // var createdItem = genericMethod.Invoke(inspectorItemFactory,null) as VisualElement;
+ // Add(createdItem);
+ // Debug.Log(createdItem?.GetType());
+ //
+ // }
}
}
}
diff --git a/TNode/Editor/Inspector/TinyInspectorItem.cs b/TNode/Editor/Inspector/TinyInspectorItem.cs
deleted file mode 100644
index 89186c9..0000000
--- a/TNode/Editor/Inspector/TinyInspectorItem.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using TNode.Models;
-using UnityEngine.UIElements;
-
-namespace TNode.Editor.Inspector{
- ///
- /// Tiny Inspector item is a simple inspector item inside a node view ,it monitor node data
- ///
- ///
- public class TinyInspectorItem:VisualElement,INodeDataBinding{
- public string BindingPath{ get; set; }
- public NodeData BindingNodeData{ get; set; }
- }
-}
\ No newline at end of file
diff --git a/TNode/Editor/Inspector/TinyInspectorItem.cs.meta b/TNode/Editor/Inspector/TinyInspectorItem.cs.meta
deleted file mode 100644
index 5944c38..0000000
--- a/TNode/Editor/Inspector/TinyInspectorItem.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: 7eeddeb28a5a475c85c85ceae3198778
-timeCreated: 1656142058
\ No newline at end of file
diff --git a/TNode/Editor/Manipulators.meta b/TNode/Editor/Manipulators.meta
new file mode 100644
index 0000000..f9c9614
--- /dev/null
+++ b/TNode/Editor/Manipulators.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 400542f3cec140e2b55e2bcf637b2d9b
+timeCreated: 1657009018
\ No newline at end of file
diff --git a/TNode/Editor/NodeViews.meta b/TNode/Editor/NodeViews.meta
new file mode 100644
index 0000000..8da3bd3
--- /dev/null
+++ b/TNode/Editor/NodeViews.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: ea202e63fe8e4d3b9b7759488419dde7
+timeCreated: 1657197080
\ No newline at end of file
diff --git a/TNode/Editor/DefaultNodeView.cs b/TNode/Editor/NodeViews/DefaultNodeView.cs
similarity index 100%
rename from TNode/Editor/DefaultNodeView.cs
rename to TNode/Editor/NodeViews/DefaultNodeView.cs
diff --git a/TNode/Editor/DefaultNodeView.cs.meta b/TNode/Editor/NodeViews/DefaultNodeView.cs.meta
similarity index 100%
rename from TNode/Editor/DefaultNodeView.cs.meta
rename to TNode/Editor/NodeViews/DefaultNodeView.cs.meta
diff --git a/TNode/Editor/NodeViews/DragNodeView.cs b/TNode/Editor/NodeViews/DragNodeView.cs
new file mode 100644
index 0000000..8ce31c7
--- /dev/null
+++ b/TNode/Editor/NodeViews/DragNodeView.cs
@@ -0,0 +1,15 @@
+using TNode.Attribute;
+using TNode.Editor.BaseViews;
+using TNode.Models;
+
+namespace TNode.Editor.NodeViews{
+ [NodeComponent]
+ public class DragNodeView:NodeView>{
+ public DragNodeView() : base(){
+ //Make capsule like style
+
+ this.titleContainer.visible = false;
+ this.titleContainer.RemoveFromHierarchy();
+ }
+ }
+}
\ No newline at end of file
diff --git a/TNode/Editor/NodeViews/DragNodeView.cs.meta b/TNode/Editor/NodeViews/DragNodeView.cs.meta
new file mode 100644
index 0000000..97c8950
--- /dev/null
+++ b/TNode/Editor/NodeViews/DragNodeView.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 899b964a5f674c2fbf1db20cf40ff5e7
+timeCreated: 1657197096
\ No newline at end of file
diff --git a/TNode/Editor/NodeViews/NodeView.cs b/TNode/Editor/NodeViews/NodeView.cs
new file mode 100644
index 0000000..0079cb6
--- /dev/null
+++ b/TNode/Editor/NodeViews/NodeView.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using TNode.Attribute;
+using TNode.Attribute.Ports;
+using TNode.Editor.Inspector;
+using TNode.Models;
+using UnityEditor;
+using UnityEditor.Experimental.GraphView;
+using UnityEditor.UIElements;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace TNode.Editor.BaseViews{
+
+ //A NodeAttribute monitor some type of node in the graph
+
+ public abstract class NodeView : Node,INodeView where T:NodeData,new(){
+ protected T _data;
+ private readonly NodeInspectorInNode _nodeInspectorInNode;
+
+ public T Data{
+ get => _data;
+ set{
+ if(_data!=null)
+ ((NodeDataWrapper)_data).OnValueChanged -= OnDataValueChanged;
+ _data = value;
+ OnDataChanged?.Invoke(value);
+ if(_data!=null)
+ ((NodeDataWrapper)_data).OnValueChanged += OnDataValueChanged;
+
+ }
+ }
+
+ private void OnDataValueChanged(NodeDataWrapper obj){
+ Refresh();
+ }
+
+ public sealed override string title{
+ get => base.title;
+ set => base.title = value;
+ }
+ public event System.Action OnDataChanged;
+
+ protected NodeView(){
+ OnDataChanged+=OnDataChangedHandler;
+
+ _nodeInspectorInNode = new NodeInspectorInNode(){
+ name = "nodeInspectorInNode"
+ };
+ this.extensionContainer.Add(_nodeInspectorInNode);
+
+ BuildDoubleClickRename();
+ }
+ private void OnDataChangedHandler(T obj){
+ this.title = _data.nodeName;
+ if (_nodeInspectorInNode != null){
+ _nodeInspectorInNode.Data = obj;
+
+
+ }
+
+ BuildInputAndOutputPort();
+ this.expanded = true;
+ this.RefreshExpandedState();
+ }
+
+ protected virtual string BuildPortName(PortAttribute portAttribute,PropertyInfo propertyInfo,params object[] args){
+ switch (portAttribute.NameHandling){
+ case PortNameHandling.Auto:
+ return portAttribute.Name.Trim(' ').Length>0?portAttribute.Name:propertyInfo.Name;
+ break;
+ case PortNameHandling.Manual:
+ return portAttribute.Name;
+ break;
+ case PortNameHandling.MemberName:
+ return propertyInfo.Name;
+ case PortNameHandling.Format:
+ return String.Format(propertyInfo.Name, args);
+ case PortNameHandling.MemberType:
+ return propertyInfo.PropertyType.Name;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ ///
+ /// of course you can override this method to build your own port builder
+ ///
+ protected virtual void BuildInputAndOutputPort(){
+ var propertyInfos = _data.GetType().GetProperties();
+
+ foreach (var propertyInfo in propertyInfos){
+ if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){
+ Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,Port.Capacity.Multi,propertyInfo.PropertyType);
+ this.outputContainer.Add(port);
+ var portName = BuildPortName(attribute,propertyInfo);
+ port.portName = portName;
+ port.name = portName;
+ }
+ }
+ foreach (var propertyInfo in propertyInfos){
+ if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){
+ Port port = InstantiatePort(Orientation.Horizontal, Direction.Input,Port.Capacity.Single,propertyInfo.PropertyType);
+ this.inputContainer.Add(port);
+ var portName = BuildPortName(attribute,propertyInfo);
+ port.portName = portName;
+ port.name = portName;
+ }
+ }
+ }
+
+ public void StartARenameTitleTextField(){
+ var textField = new TextField{
+ value = title,
+ style ={
+ //Make the text filed overlap the title container
+ position = Position.Absolute,
+ left = 0,
+ top = 0,
+ width = titleContainer.layout.width,
+ height = titleContainer.layout.height
+ }
+ };
+ textField.StretchToParentSize();
+ textField.RegisterValueChangedCallback(evt2 => {
+ title = evt2.newValue;
+ });
+ textField.RegisterCallback(evt2 => {
+ title = textField.text;
+ ((NodeDataWrapper)_data).SetValue("nodeName",textField.text);
+ textField.RemoveFromHierarchy();
+ });
+ //if enter is pressed ,set the title and remove the text field
+ textField.RegisterCallback(evt2 => {
+ if (evt2.keyCode == KeyCode.Return){
+ title = textField.text;
+ ((NodeDataWrapper)_data).SetValue("nodeName",textField.text);
+ textField.RemoveFromHierarchy();
+ }
+ });
+
+ titleContainer.Add(textField);
+ textField.Focus();
+ }
+ private void BuildDoubleClickRename(){
+ //when double click titleContainer ,create a textfield to rename the node
+ titleContainer.RegisterCallback(evt => {
+ if (evt.clickCount == 2){
+ StartARenameTitleTextField();
+ }
+ });
+ }
+
+ public void SetNodeData(NodeData nodeData){
+ Data = (T)nodeData;
+
+ }
+
+ public NodeData GetNodeData(){
+ return _data;
+ }
+
+ public void OnDataModified(){
+ Refresh();
+ }
+
+ public void Refresh(){
+ title = _data.nodeName;
+ }
+ }
+
+ public interface INodeView{
+ public void SetNodeData(NodeData nodeData);
+ public NodeData GetNodeData();
+
+ public void OnDataModified();
+
+ }
+}
\ No newline at end of file
diff --git a/TNode/Editor/BaseViews/NodeView.cs.meta b/TNode/Editor/NodeViews/NodeView.cs.meta
similarity index 100%
rename from TNode/Editor/BaseViews/NodeView.cs.meta
rename to TNode/Editor/NodeViews/NodeView.cs.meta
diff --git a/TNode/Editor/Search/BlackboardSearchWindowProvider.cs b/TNode/Editor/Search/BlackboardSearchWindowProvider.cs
index 53dfcbb..e0f5ed4 100644
--- a/TNode/Editor/Search/BlackboardSearchWindowProvider.cs
+++ b/TNode/Editor/Search/BlackboardSearchWindowProvider.cs
@@ -1,5 +1,16 @@
-namespace TNode.Editor{
- public class BlackboardSearchWindowProvider{
-
+using System.Collections.Generic;
+using UnityEditor.Experimental.GraphView;
+
+namespace TNode.Editor{
+ public class BlackboardSearchWindowProvider:ISearchWindowProvider{
+
+ public List CreateSearchTree(SearchWindowContext context){
+ throw new System.NotImplementedException();
+ }
+
+ public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context){
+ throw new System.NotImplementedException();
+ }
}
+
}
\ No newline at end of file
diff --git a/TNode/Editor/Search/NodeSearchWindowProvider.cs b/TNode/Editor/Search/NodeSearchWindowProvider.cs
index 58a3c1d..e694f4a 100644
--- a/TNode/Editor/Search/NodeSearchWindowProvider.cs
+++ b/TNode/Editor/Search/NodeSearchWindowProvider.cs
@@ -48,8 +48,8 @@ namespace TNode.Editor{
//Check if type is derived from NodeData
if (typeof(NodeData).IsAssignableFrom(type)){
//Make an instance of the type
- if (NodeHelper.InstantiateNodeData(type) is { } nodeData){
- nodeData.nodeName = "New Node";
+ if (NodeCreator.InstantiateNodeData(type) is { } nodeData){
+ nodeData.nodeName = $"New {type.Name}";
((IDataGraphView) _graphView).AddTNode(nodeData, new Rect(localPos.x, localPos.y, 100, 100));
}
}
diff --git a/TNode/Editor/Tools/NodeCreator/NodeHelper.cs b/TNode/Editor/Tools/NodeCreator/NodeCreator.cs
similarity index 94%
rename from TNode/Editor/Tools/NodeCreator/NodeHelper.cs
rename to TNode/Editor/Tools/NodeCreator/NodeCreator.cs
index adf3b15..416e8a1 100644
--- a/TNode/Editor/Tools/NodeCreator/NodeHelper.cs
+++ b/TNode/Editor/Tools/NodeCreator/NodeCreator.cs
@@ -2,7 +2,7 @@
using TNode.Models;
namespace TNode.Editor.Tools.NodeCreator{
- public static class NodeHelper{
+ public static class NodeCreator{
///
/// always use this to create a new node.
diff --git a/TNode/Editor/Tools/NodeCreator/NodeHelper.cs.meta b/TNode/Editor/Tools/NodeCreator/NodeCreator.cs.meta
similarity index 100%
rename from TNode/Editor/Tools/NodeCreator/NodeHelper.cs.meta
rename to TNode/Editor/Tools/NodeCreator/NodeCreator.cs.meta
diff --git a/TNode/JsonSerialize/JsonSerializeTool.cs b/TNode/JsonSerialize/JsonSerializeTool.cs
index e886ccf..58888ba 100644
--- a/TNode/JsonSerialize/JsonSerializeTool.cs
+++ b/TNode/JsonSerialize/JsonSerializeTool.cs
@@ -21,7 +21,9 @@ namespace TNode.JsonSerialize{
DateFormatString = "yyyy-MM-dd HH:mm:ss",
Converters = new List { new Vector3Converter() },
TypeNameHandling = TypeNameHandling.Auto,
- ContractResolver = new WritablePropertiesOnlyResolver()
+ ContractResolver = new WritablePropertiesOnlyResolver(),
+ Formatting = Formatting.Indented
+
};
diff --git a/TNode/Models/BlackDragNodeData.cs b/TNode/Models/BlackDragNodeData.cs
deleted file mode 100644
index 19eb282..0000000
--- a/TNode/Models/BlackDragNodeData.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Runtime.InteropServices;
-using Newtonsoft.Json;
-using TNode.Attribute.Ports;
-
-namespace TNode.Models{
- public class BlackDragNodeData:NodeData{
- [JsonIgnore]
- private string _blackDragData;
- [JsonIgnore]
- private BlackboardData _blackboardData;
-
- [Output] public T value => _blackboardData.GetValue(_blackDragData);
- public BlackDragNodeData(string blackDragData,BlackboardData blackboardData){
- _blackDragData = blackDragData;
- _blackboardData = blackboardData;
- }
-
- }
-}
\ No newline at end of file
diff --git a/TNode/Models/BlackboardData.cs b/TNode/Models/BlackboardData.cs
index 4b2c2e7..fc0b66a 100644
--- a/TNode/Models/BlackboardData.cs
+++ b/TNode/Models/BlackboardData.cs
@@ -1,8 +1,6 @@
namespace TNode.Models{
public class BlackboardData:IModel{
- public T GetValue(string key){
- return default(T);
- }
+
}
}
\ No newline at end of file
diff --git a/TNode/Models/BlackboardDragNodeData.cs b/TNode/Models/BlackboardDragNodeData.cs
new file mode 100644
index 0000000..dc587ad
--- /dev/null
+++ b/TNode/Models/BlackboardDragNodeData.cs
@@ -0,0 +1,21 @@
+using System.Runtime.InteropServices;
+using Newtonsoft.Json;
+using TNode.Attribute;
+using TNode.Attribute.Ports;
+using TNode.RuntimeCache;
+
+namespace TNode.Models{
+ public class BlackboardDragNodeData:NodeData{
+ private string _blackDragData;
+ [JsonIgnore]
+ private BlackboardData _blackboardData;
+
+ [Output("",PortNameHandling.MemberType)]
+ public T Value => _blackboardData.GetValue(_blackDragData);
+
+ public BlackboardDragNodeData(){
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/TNode/Models/BlackDragNodeData.cs.meta b/TNode/Models/BlackboardDragNodeData.cs.meta
similarity index 100%
rename from TNode/Models/BlackDragNodeData.cs.meta
rename to TNode/Models/BlackboardDragNodeData.cs.meta
diff --git a/TNode/Models/GraphData.cs b/TNode/Models/GraphData.cs
index 2d4d323..3937714 100644
--- a/TNode/Models/GraphData.cs
+++ b/TNode/Models/GraphData.cs
@@ -33,7 +33,6 @@ namespace TNode.Models{
var deserializedBlackboard = JsonConvert.DeserializeObject(jsonBlackboard,JsonSerializeTool.JsonSerializerSettings);
blackboardData = deserializedBlackboard;
- Debug.Log("hi");
}
}
}
\ No newline at end of file
diff --git a/TNode/Runtime/Runtimeblackboard.cs b/TNode/Runtime/Runtimeblackboard.cs
new file mode 100644
index 0000000..1a91406
--- /dev/null
+++ b/TNode/Runtime/Runtimeblackboard.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using TNode.Models;
+
+namespace TNode.Runtime{
+ public class RuntimeBlackboard where T:BlackboardData{
+
+ public T Data { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/TNode/Runtime/Runtimeblackboard.cs.meta b/TNode/Runtime/Runtimeblackboard.cs.meta
new file mode 100644
index 0000000..02868cd
--- /dev/null
+++ b/TNode/Runtime/Runtimeblackboard.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 6b69b2dedba24e35bf04bc9112da6b12
+timeCreated: 1656958407
\ No newline at end of file
diff --git a/TNode/RuntimeCache/RuntimeCache.cs b/TNode/RuntimeCache/RuntimeCache.cs
index 13e82e4..4310a3e 100644
--- a/TNode/RuntimeCache/RuntimeCache.cs
+++ b/TNode/RuntimeCache/RuntimeCache.cs
@@ -15,39 +15,15 @@ namespace TNode.RuntimeCache{
}
//delegate return a value from a nodedata
public delegate object GetValueDelegate(IModel nodeData);
+ public delegate object SetValueDelegate(IModel nodeData,object value);
- public readonly Dictionary> CachedDelegatesForGettingValue =
+ public readonly Dictionary> CachedDelegatesForGettingValue =
new ();
- public void ExecuteOutput(T nodeData) where T:NodeData{
- var type = typeof(T);
- if(!CachedDelegatesForGettingValue.ContainsKey(type)){
- return;
- }
- var delegates = CachedDelegatesForGettingValue[type];
- foreach(var delegateInstance in delegates){
- var value = delegateInstance(nodeData);
- }
- }
private static readonly string[] ExcludedAssemblies = new string[]{"Microsoft", "UnityEngine","UnityEditor","mscorlib","System"};
- public void RegisterRuntimeNode() where T:NodeData{
- var type = typeof(T);
- if(!CachedDelegatesForGettingValue.ContainsKey(type)){
- CachedDelegatesForGettingValue.Add(type, new List());
- var properties = type.GetProperties();
- foreach(var property in properties){
- var getValueDelegate = GetValueDelegateForProperty(property);
- CachedDelegatesForGettingValue[type].Add(getValueDelegate);
- }
- }
- else{
- //Cache already exists for this type
-
- }
- }
public void RegisterRuntimeBlackboard(Type type){
if(!CachedDelegatesForGettingValue.ContainsKey(type)){
- CachedDelegatesForGettingValue.Add(type, new List());
+ CachedDelegatesForGettingValue.Add(type, new Dictionary());
var properties = type.GetProperties();
foreach(var property in properties){
//if the property only has a setter ,skip
@@ -55,14 +31,46 @@ namespace TNode.RuntimeCache{
continue;
}
var getValueDelegate = GetValueDelegateForProperty(property);
- CachedDelegatesForGettingValue[type].Add(getValueDelegate);
+ CachedDelegatesForGettingValue[type].Add(property.Name,getValueDelegate);
+ }
+ //register the fields
+ var fields = type.GetFields();
+ foreach(var field in fields){
+ var getValueDelegate = GetValueDelegateForField(field);
+ CachedDelegatesForGettingValue[type].Add(field.Name,getValueDelegate);
}
}
}
+ private GetValueDelegate GetValueDelegateForField(FieldInfo field){
+ return field.GetValue;
+ }
+
+
private GetValueDelegate GetValueDelegateForProperty(PropertyInfo property){
var getValueDelegate = (GetValueDelegate)Delegate.CreateDelegate(typeof(GetValueDelegate), property.GetGetMethod());
return getValueDelegate;
}
+
+
+
+ }
+ public static class RuntimeExtension{
+
+ //todo latter on i will try some way caching reflection more efficiently
+ public static T GetValue(this BlackboardData blackboardData,string path){
+ var method = RuntimeCache.Instance.CachedDelegatesForGettingValue[blackboardData.GetType()][path];
+ return (T) method.Invoke(blackboardData);
+ }
+
+ public static object GetValue(this BlackboardData blackboardData, string path){
+ var method = RuntimeCache.Instance.CachedDelegatesForGettingValue[blackboardData.GetType()][path];
+ return method.Invoke(blackboardData);
+ }
+ public static RuntimeCache.GetValueDelegate GetValueDelegate(this BlackboardData blackboardData,string path){
+ var method = RuntimeCache.Instance.CachedDelegatesForGettingValue[blackboardData.GetType()][path];
+ return method;
+ }
+
}
}
\ No newline at end of file