diff --git a/TNode/Attribute/GraphUsageAttribute.cs b/TNode/Attribute/GraphUsageAttribute.cs index 50c9c08..fd17135 100644 --- a/TNode/Attribute/GraphUsageAttribute.cs +++ b/TNode/Attribute/GraphUsageAttribute.cs @@ -5,21 +5,21 @@ using Unity.VisualScripting; namespace TNode.Attribute{ /// - /// Use this attribute to claim the usage of a type of node on the derived NodeData class. + /// Use this attribute to claim the usage of a type derived IModel IModel /// it can be applied to the same node multiple times. /// /// [GraphUsage(DialogueGraph)] /// /// [AttributeUsage(AttributeTargets.Class)] - [BaseTypeRequired(typeof(NodeData))] + [BaseTypeRequired(typeof(IModel))] public class GraphUsageAttribute:System.Attribute{ public readonly Type GraphDataType; public string Category; public GraphUsageAttribute(Type t,string category = null){ //check if the type t is graph if(!typeof(GraphData).IsAssignableFrom(t)){ - throw new Exception("The type must be a graph"); + throw new Exception("The type used on Graph Usage must be a graph"); } GraphDataType = t; if (category != null){ @@ -27,4 +27,6 @@ namespace TNode.Attribute{ } } } + + } \ No newline at end of file diff --git a/TNode/Editor/BaseViews/DataGraphView.cs b/TNode/Editor/BaseViews/DataGraphView.cs index fc11fe7..408bfed 100644 --- a/TNode/Editor/BaseViews/DataGraphView.cs +++ b/TNode/Editor/BaseViews/DataGraphView.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using TNode.BaseViews; using TNode.Cache; using TNode.Editor.Inspector; @@ -152,7 +153,7 @@ namespace TNode.Editor.BaseViews{ //Rebuild the contextual menu this.RegisterCallback(evt => { - Vector2 editorPosition = Owner.position.position; + Vector2 editorPosition = Owner==null?Vector2.zero:Owner.position.position; //Remove all the previous menu items evt.menu.MenuItems().Clear(); evt.menu.AppendAction("Create Node", dma => { @@ -232,21 +233,51 @@ namespace TNode.Editor.BaseViews{ miniMap.SetPosition(rect); } - public void CreateBlackBoard(){ + public void CreateBlackboard(){ var 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(); - }; - + // 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(); + // }; + // //Set black board to left side of the view blackboard.SetPosition(new Rect(0,0,200,600)); - this.Add(blackboard); + 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); + } + } + }; + } public virtual void DestroyInspector(){ if(_nodeInspector!=null){ diff --git a/TNode/Editor/BaseViews/NodeView.cs b/TNode/Editor/BaseViews/NodeView.cs index b5aca22..15c6636 100644 --- a/TNode/Editor/BaseViews/NodeView.cs +++ b/TNode/Editor/BaseViews/NodeView.cs @@ -63,7 +63,6 @@ namespace TNode.Editor.BaseViews{ var propertyInfos = _data.GetType().GetProperties(); foreach (var propertyInfo in propertyInfos){ - Debug.Log(propertyInfos); var attribute = propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true); if (attribute.Length > 0){ Port port = InstantiatePort(Orientation.Horizontal, Direction.Output,Port.Capacity.Multi,propertyInfo.PropertyType); diff --git a/TNode/Editor/Cache/NodeEditorExtensions.cs b/TNode/Editor/Cache/NodeEditorExtensions.cs index 813d68a..6338d97 100644 --- a/TNode/Editor/Cache/NodeEditorExtensions.cs +++ b/TNode/Editor/Cache/NodeEditorExtensions.cs @@ -18,6 +18,7 @@ namespace TNode.Cache{ private static NodeEditorSingleton _instance; public readonly Dictionary FromGenericToSpecific = new Dictionary(); public readonly Dictionary> GraphDataUsage = new Dictionary>(); + public Dictionary GraphBlackboard = new(); public static NodeEditorSingleton Instance{ get{ return _instance ??= new NodeEditorSingleton(); } } @@ -45,14 +46,30 @@ namespace TNode.Cache{ private void SetGraphUsageAttribute(Type type){ foreach (var attribute in type.GetCustomAttributes(typeof(GraphUsageAttribute), true)){ var parent = type.BaseType; - if (typeof(NodeData).IsAssignableFrom(type.BaseType)){ + if (typeof(IModel).IsAssignableFrom(type.BaseType)){ //Check if GraphDataUsage dictionary has GraphDataType of attribute - if (attribute is GraphUsageAttribute attributeCasted){ - if (GraphDataUsage.ContainsKey(attributeCasted.GraphDataType)){ - GraphDataUsage[attributeCasted.GraphDataType].Add(type); + + if (typeof(NodeData).IsAssignableFrom(type)){ + if (attribute is GraphUsageAttribute attributeCasted){ + if (GraphDataUsage.ContainsKey(attributeCasted.GraphDataType)){ + GraphDataUsage[attributeCasted.GraphDataType].Add(type); + } + else{ + GraphDataUsage.Add(attributeCasted.GraphDataType, new List{type}); + } } - else{ - GraphDataUsage.Add(attributeCasted.GraphDataType, new List{type}); + } + + if (typeof(BlackboardData).IsAssignableFrom(type)){ + if (attribute is GraphUsageAttribute attributeCasted){ + if (GraphBlackboard.ContainsKey(attributeCasted.GraphDataType)){ + GraphBlackboard[attributeCasted.GraphDataType] = type; + + } + else{ + GraphBlackboard.Add(attributeCasted.GraphDataType, type); + } + } } } @@ -107,6 +124,12 @@ namespace TNode.Cache{ } return new List(); } + public static BlackboardData GetAppropriateBlackboardData(Type t){ + if (NodeEditorSingleton.Instance.GraphBlackboard.ContainsKey(t)){ + return (BlackboardData)Activator.CreateInstance(NodeEditorSingleton.Instance.GraphBlackboard[t]); + } + return null; + } public static object CreateNodeViewFromNodeType() where T:NodeData,new(){ //Check specific derived type exists or not. var type = typeof(NodeView); diff --git a/TNode/Editor/Inspector/NodeInspectorInNode.cs b/TNode/Editor/Inspector/NodeInspectorInNode.cs index 61a1b70..0268d98 100644 --- a/TNode/Editor/Inspector/NodeInspectorInNode.cs +++ b/TNode/Editor/Inspector/NodeInspectorInNode.cs @@ -17,7 +17,6 @@ namespace TNode.Editor.Inspector{ } private void UpdateData(){ - Debug.Log(_data); if (_data != null){ RefreshInspector(); } diff --git a/TNode/Editor/Model.meta b/TNode/Editor/Model.meta deleted file mode 100644 index 505afc9..0000000 --- a/TNode/Editor/Model.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: e3bc969c46434a308e20796dede95f3b -timeCreated: 1655969991 \ No newline at end of file diff --git a/TNode/Models/BlackDragNodeData.cs b/TNode/Models/BlackDragNodeData.cs index 6038a6f..19eb282 100644 --- a/TNode/Models/BlackDragNodeData.cs +++ b/TNode/Models/BlackDragNodeData.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using System.Runtime.InteropServices; +using Newtonsoft.Json; using TNode.Attribute.Ports; namespace TNode.Models{ @@ -7,6 +8,12 @@ namespace TNode.Models{ 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 5d60568..4b2c2e7 100644 --- a/TNode/Models/BlackboardData.cs +++ b/TNode/Models/BlackboardData.cs @@ -1,6 +1,8 @@ namespace TNode.Models{ - public class BlackboardData{ - + public class BlackboardData:IModel{ + public T GetValue(string key){ + return default(T); + } } } \ No newline at end of file diff --git a/TNode/Models/IModel.cs b/TNode/Models/IModel.cs new file mode 100644 index 0000000..0328c7d --- /dev/null +++ b/TNode/Models/IModel.cs @@ -0,0 +1,5 @@ +namespace TNode.Models{ + public interface IModel{ + + } +} \ No newline at end of file diff --git a/TNode/Models/IModel.cs.meta b/TNode/Models/IModel.cs.meta new file mode 100644 index 0000000..6656fdf --- /dev/null +++ b/TNode/Models/IModel.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7d60da1ee3e9447a9a2f764a6655536f +timeCreated: 1656953115 \ No newline at end of file diff --git a/TNode/Models/NodeData.cs b/TNode/Models/NodeData.cs index d9c6bf9..a9fc49b 100644 --- a/TNode/Models/NodeData.cs +++ b/TNode/Models/NodeData.cs @@ -11,7 +11,7 @@ namespace TNode.Models{ /// /// [Serializable] - public class NodeData{ + public class NodeData:IModel{ public NodeData() : base(){ //Object Registration diff --git a/TNode/RuntimeCache/RuntimeCache.cs b/TNode/RuntimeCache/RuntimeCache.cs index 4ec50ce..13e82e4 100644 --- a/TNode/RuntimeCache/RuntimeCache.cs +++ b/TNode/RuntimeCache/RuntimeCache.cs @@ -14,11 +14,11 @@ namespace TNode.RuntimeCache{ get{ return _instance ??= new RuntimeCache(); } } //delegate return a value from a nodedata - public delegate object GetValueDelegate(NodeData nodeData); + public delegate object GetValueDelegate(IModel nodeData); public readonly Dictionary> CachedDelegatesForGettingValue = new (); - + public void ExecuteOutput(T nodeData) where T:NodeData{ var type = typeof(T); if(!CachedDelegatesForGettingValue.ContainsKey(type)){ @@ -29,7 +29,7 @@ namespace TNode.RuntimeCache{ 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)){ @@ -44,9 +44,20 @@ namespace TNode.RuntimeCache{ //Cache already exists for this type } - - - + } + public void RegisterRuntimeBlackboard(Type type){ + if(!CachedDelegatesForGettingValue.ContainsKey(type)){ + CachedDelegatesForGettingValue.Add(type, new List()); + var properties = type.GetProperties(); + foreach(var property in properties){ + //if the property only has a setter ,skip + if(property.GetMethod == null){ + continue; + } + var getValueDelegate = GetValueDelegateForProperty(property); + CachedDelegatesForGettingValue[type].Add(getValueDelegate); + } + } } private GetValueDelegate GetValueDelegateForProperty(PropertyInfo property){