Merge pull request #24 from taoria/working-in-process

Working in process
main
taoria 3 years ago committed by GitHub
commit be3408a10a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      TNodeCore/Attribute/GraphUsageAttribute.cs
  2. 2
      TNodeCore/DataWrapper.cs
  3. 16
      TNodeCore/Models/BlackboardDragNodeData.cs
  4. 9
      TNodeCore/Runtime/RuntimeGraph.cs
  5. 2
      TNodeCore/Runtime/RuntimeNode.cs
  6. 3
      TNodeCore/RuntimeCache/RuntimeCache.cs
  7. 16
      TNodeGraphViewImpl/Editor/Cache/NodeEditorExtensions.cs
  8. 4
      TNodeGraphViewImpl/Editor/GraphBlackboard/BlackboardField.cs
  9. 2
      TNodeGraphViewImpl/Editor/GraphBlackboard/DefaultGraphBlackboardView.cs
  10. 34
      TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs
  11. 27
      TNodeGraphViewImpl/Editor/NodeViews/DragNodeView.cs
  12. 3
      TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs
  13. 30
      TNodeGraphViewImpl/Editor/Search/NodeSearchWindowProvider.cs

@ -16,15 +16,14 @@ namespace TNodeCore.Attribute{
public class GraphUsageAttribute:System.Attribute{ public class GraphUsageAttribute:System.Attribute{
public readonly Type GraphDataType; public readonly Type GraphDataType;
public string Category; public string Category;
public GraphUsageAttribute(Type t,string category = null){ public GraphUsageAttribute(Type t,string category = "default"){
//check if the type t is graph //check if the type t is graph
if(!typeof(GraphData).IsAssignableFrom(t)){ if(!typeof(GraphData).IsAssignableFrom(t)){
throw new Exception("The type used on Graph Usage must be a graph"); throw new Exception("The type used on Graph Usage must be a graph");
} }
GraphDataType = t; GraphDataType = t;
if (category != null){
Category = category; Category = category;
}
} }
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEditor;
using UnityEngine; using UnityEngine;
namespace TNodeCore{ namespace TNodeCore{
@ -34,6 +35,7 @@ namespace TNodeCore{
var fieldInfo = data.GetType().GetField(path); var fieldInfo = data.GetType().GetField(path);
return fieldInfo.GetValue(data); return fieldInfo.GetValue(data);
} }
public virtual TData GetData(){ public virtual TData GetData(){
return data; return data;
} }

@ -7,17 +7,25 @@ using UnityEngine;
namespace TNodeCore.Models{ namespace TNodeCore.Models{
[Serializable] [Serializable]
[InternalModel] [InternalModel]
public class BlackboardDragNodeData:NodeData{ public class BlackboardDragNodeData:RuntimeNodeData{
public string blackDragData; public string blackDragData;
[SerializeReference]
public BlackboardData blackboardData;
/// <summary>
/// it's very hacky way to get blackboard data ,even when the value is null,type info is not null!
/// </summary>
/// TODO : The type handling in a safer way in the future
[Output("",PortNameHandling.MemberType,TypeHandling.Implemented)] [Output("",PortNameHandling.MemberType,TypeHandling.Implemented)]
public object Value => blackboardData.GetValue(blackDragData); public object Value => BlackboardData.GetValue(blackDragData);
public BlackboardDragNodeData(){ public BlackboardDragNodeData(){
} }
} }
[Serializable]
public class RuntimeNodeData:NodeData{
public BlackboardData BlackboardData{ get; set; }
}
} }

@ -16,6 +16,9 @@ namespace TNodeCore.Runtime{
[NonSerialized] [NonSerialized]
public readonly List<RuntimeNode> TopologicalOrder = new List<RuntimeNode>(); public readonly List<RuntimeNode> TopologicalOrder = new List<RuntimeNode>();
public readonly List<RuntimeNode> EntryNodes = new List<RuntimeNode>(); public readonly List<RuntimeNode> EntryNodes = new List<RuntimeNode>();
/// <summary>
/// elements are read only ,do not modify them
/// </summary>
public readonly Dictionary<string, RuntimeNode> RuntimeNodes; public readonly Dictionary<string, RuntimeNode> RuntimeNodes;
public void DependencyTraversal(RuntimeNode runtimeNode){ public void DependencyTraversal(RuntimeNode runtimeNode){
var links = runtimeNode.InputLink; var links = runtimeNode.InputLink;
@ -125,6 +128,12 @@ namespace TNodeCore.Runtime{
RuntimeNodes[inNode.id].InputLink.Add(linkData); RuntimeNodes[inNode.id].InputLink.Add(linkData);
} }
public List<RuntimeNode> GetRuntimeNodesOfType<T>(){
return RuntimeNodes.Values.Where(x => x.NodeType == typeof(T)).ToList();
}
public List<RuntimeNode> GetRuntimeNodesOfType(Type type){
return RuntimeNodes.Values.Where(x => x.NodeType == type).ToList();
}
private void ModifyOrCreateOutNode(NodeLink linkData){ private void ModifyOrCreateOutNode(NodeLink linkData){
var outNodeId = linkData.outPort.nodeDataId; var outNodeId = linkData.outPort.nodeDataId;
var outNode = graphData.NodeDictionary[outNodeId]; var outNode = graphData.NodeDictionary[outNodeId];

@ -15,7 +15,7 @@ namespace TNodeCore.Runtime{
public List<NodeLink> OutputLink = new List<NodeLink>(); public List<NodeLink> OutputLink = new List<NodeLink>();
//Cache node data type for fast access //Cache node data type for fast access
private readonly Type _type; private readonly Type _type;
public Type NodeType => _type;
public void SetInput(string portName,object value){ public void SetInput(string portName,object value){
_portAccessors[portName].SetValue(this.NodeData,value); _portAccessors[portName].SetValue(this.NodeData,value);

@ -80,10 +80,7 @@ namespace TNodeCore.RuntimeCache{
} }
} }
} }
} }
private void AddTypeToCache(Type type,System.Attribute attribute){ private void AddTypeToCache(Type type,System.Attribute attribute){
//Check if the type is a blackboard data type //Check if the type is a blackboard data type
if(typeof(BlackboardData).IsAssignableFrom(type)){ if(typeof(BlackboardData).IsAssignableFrom(type)){

@ -18,8 +18,7 @@ namespace TNodeGraphViewImpl.Editor.Cache{
/// Internal singleton class for caching TNode reflection Data. /// Internal singleton class for caching TNode reflection Data.
/// </summary> /// </summary>
internal class NodeEditorTypeDictionary:Dictionary<Type, Type>{ internal class NodeEditorTypeDictionary:Dictionary<Type, Type>{
private class NodeEditorTypeDictionaryComparer : IEqualityComparer<Type> private class NodeEditorTypeDictionaryComparer : IEqualityComparer<Type>{
{
public bool Equals(Type x, Type y){ public bool Equals(Type x, Type y){
return x?.ToString() == y?.ToString(); return x?.ToString() == y?.ToString();
} }
@ -28,11 +27,9 @@ namespace TNodeGraphViewImpl.Editor.Cache{
return obj.ToString().GetHashCode(); return obj.ToString().GetHashCode();
} }
} }
public NodeEditorTypeDictionary():base(new NodeEditorTypeDictionaryComparer()){ public NodeEditorTypeDictionary():base(new NodeEditorTypeDictionaryComparer()){
} }
} }
internal class NodeEditorSingleton{ internal class NodeEditorSingleton{
@ -132,6 +129,10 @@ namespace TNodeGraphViewImpl.Editor.Cache{
var instance = (T)Activator.CreateInstance(implementedType); var instance = (T)Activator.CreateInstance(implementedType);
return instance; return instance;
} }
public static string GetTypeCategory(Type type){
var category = type.GetCustomAttribute<GraphUsageAttribute>();
return category?.Category ?? "";
}
/// <summary> /// <summary>
/// by given a generic type t,return the implementation instance of the generic type /// by given a generic type t,return the implementation instance of the generic type
@ -190,6 +191,13 @@ namespace TNodeGraphViewImpl.Editor.Cache{
} }
return new List<Type>(); return new List<Type>();
} }
public static List<string> GetGraphCategories(Type t){
var list = NodeEditorSingleton.Instance.GraphDataUsage[t];
//Merge same category
var res = list.Select(x=>x.GetCustomAttribute<GraphUsageAttribute>().Category).Distinct().ToList();
return res;
}
public static BlackboardData GetAppropriateBlackboardData(Type t){ public static BlackboardData GetAppropriateBlackboardData(Type t){
if (NodeEditorSingleton.Instance.GraphBlackboard.ContainsKey(t)){ if (NodeEditorSingleton.Instance.GraphBlackboard.ContainsKey(t)){
return (BlackboardData)Activator.CreateInstance(NodeEditorSingleton.Instance.GraphBlackboard[t]); return (BlackboardData)Activator.CreateInstance(NodeEditorSingleton.Instance.GraphBlackboard[t]);

@ -1,9 +1,9 @@
using UnityEditor.Experimental.GraphView; using UnityEditor.Experimental.GraphView;
namespace TNodeGraphViewImpl.Editor.GraphBlackboard{ namespace TNodeGraphViewImpl.Editor.GraphBlackboard{
public class BlackboardPropertyField:BlackboardField{ public class BlackboardField:UnityEditor.Experimental.GraphView.BlackboardField{
public BlackboardProperty.BlackboardProperty BlackboardProperty; public BlackboardProperty.BlackboardProperty BlackboardProperty;
public BlackboardPropertyField(BlackboardProperty.BlackboardProperty blackboardProperty):base(null,blackboardProperty.PropertyName,null){ public BlackboardField(BlackboardProperty.BlackboardProperty blackboardProperty):base(null,blackboardProperty.PropertyName,null){
BlackboardProperty = blackboardProperty; BlackboardProperty = blackboardProperty;
} }

@ -30,7 +30,7 @@ namespace TNodeGraphViewImpl.Editor.GraphBlackboard{
//skip if the field is a list or Ilist //skip if the field is a list or Ilist
if (!typeof(IList).IsAssignableFrom(field.FieldType)){ if (!typeof(IList).IsAssignableFrom(field.FieldType)){
VisualElement visualElement = new VisualElement(); VisualElement visualElement = new VisualElement();
var propertyField = new BlackboardPropertyField(new BlackboardProperty.BlackboardProperty(field.Name,field.FieldType)); var propertyField = new BlackboardField(new BlackboardProperty.BlackboardProperty(field.Name,field.FieldType));
var foldoutData = new Foldout{ var foldoutData = new Foldout{
text = field.Name text = field.Name
}; };

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using TNode.Editor.Inspector; using TNode.Editor.Inspector;
using TNode.Editor.Search; using TNode.Editor.Search;
using TNodeCore.Editor.Blackboard; using TNodeCore.Editor.Blackboard;
@ -12,13 +13,12 @@ using TNodeCore.Runtime;
using TNodeGraphViewImpl.Editor.Cache; using TNodeGraphViewImpl.Editor.Cache;
using TNodeGraphViewImpl.Editor.GraphBlackboard; using TNodeGraphViewImpl.Editor.GraphBlackboard;
using TNodeGraphViewImpl.Editor.NodeViews; using TNodeGraphViewImpl.Editor.NodeViews;
using TNodeGraphViewImpl.Editor.Search;
using UnityEditor; using UnityEditor;
using UnityEditor.Experimental.GraphView; using UnityEditor.Experimental.GraphView;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
using BlackboardField = TNodeGraphViewImpl.Editor.GraphBlackboard.BlackboardField;
using Edge = UnityEditor.Experimental.GraphView.Edge; using Edge = UnityEditor.Experimental.GraphView.Edge;
namespace TNodeGraphViewImpl.Editor.NodeGraphView{ namespace TNodeGraphViewImpl.Editor.NodeGraphView{
@ -216,12 +216,12 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{
private void OnDragPerform(DragPerformEvent evt){ private void OnDragPerform(DragPerformEvent evt){
if (DragAndDrop.GetGenericData("DragSelection") is List<ISelectable>{Count: > 0} data){ if (DragAndDrop.GetGenericData("DragSelection") is List<ISelectable>{Count: > 0} data){
var blackboardFields = data.OfType<BlackboardPropertyField >(); var blackboardFields = data.OfType<BlackboardField >();
foreach (var selectable in blackboardFields){ foreach (var selectable in blackboardFields){
if(selectable is { } field) { if(selectable is { } field) {
//Make a constructor of BlackboardDragNodeData<field.PropertyType > by reflection //Make a constructor of BlackboardDragNodeData<field.PropertyType > by reflection
var dragNodeData = NodeCreator.InstantiateNodeData<BlackboardDragNodeData>(); var dragNodeData = NodeCreator.InstantiateNodeData<BlackboardDragNodeData>();
dragNodeData.blackboardData = GetBlackboardData(); dragNodeData.BlackboardData = GetBlackboardData();
dragNodeData.blackDragData = field.BlackboardProperty.PropertyName; dragNodeData.blackDragData = field.BlackboardProperty.PropertyName;
AddTNode(dragNodeData,new Rect(evt.mousePosition,new Vector2(200,200))); AddTNode(dragNodeData,new Rect(evt.mousePosition,new Vector2(200,200)));
} }
@ -231,17 +231,11 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{
} }
private void OnDragUpdated(DragUpdatedEvent evt){ private void OnDragUpdated(DragUpdatedEvent evt){
//check if the drag data is BlackboardField //check if the drag data is BlackboardField
if (DragAndDrop.GetGenericData("DragSelection") is List<ISelectable>{Count: > 0} data){ if (DragAndDrop.GetGenericData("DragSelection") is List<ISelectable>{Count: > 0} data){
DragAndDrop.visualMode = DragAndDropVisualMode.Move; DragAndDrop.visualMode = DragAndDropVisualMode.Move;
} }
} }
#endregion #endregion
@ -263,7 +257,9 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{
//Get the node type //Get the node type
var nodeType = dataNode.GetType(); var nodeType = dataNode.GetType();
//Get the derived type of NodeAttribute View from the node type //Get the derived type of NodeAttribute View from the node type
if (dataNode is RuntimeNodeData runtimeNodeData){
runtimeNodeData.BlackboardData = GetBlackboardData();
}
var nodePos = Owner.graphEditorData.graphElementsData. var nodePos = Owner.graphEditorData.graphElementsData.
FirstOrDefault(x => x.guid == dataNode.id)?.pos??new Rect(0,0,200,200); FirstOrDefault(x => x.guid == dataNode.id)?.pos??new Rect(0,0,200,200);
@ -403,10 +399,20 @@ namespace TNodeGraphViewImpl.Editor.NodeGraphView{
_data.blackboardData = NodeEditorExtensions.GetAppropriateBlackboardData(_data.GetType()); _data.blackboardData = NodeEditorExtensions.GetAppropriateBlackboardData(_data.GetType());
} }
} }
//TODO:Handling implicit conversion when two port types are different but compatible
private static bool HasImplicitConversion(Type baseType, Type targetType)
{
return baseType.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(mi => mi.Name == "op_Implicit" && mi.ReturnType == targetType)
.Any(mi => {
ParameterInfo pi = mi.GetParameters().FirstOrDefault();
return pi != null && pi.ParameterType == baseType;
});
}
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter){
return ports.Where(x => startPort!=x && (x.portType == startPort.portType || x.portType.IsAssignableFrom(startPort.portType))).ToList();
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter){
return ports.Where(x => x.portType == startPort.portType || x.portType.IsAssignableFrom(startPort.portType)).ToList();
} }
public virtual void OnGraphViewCreate(){ public virtual void OnGraphViewCreate(){

@ -1,6 +1,13 @@
using TNodeCore.Attribute; using TNodeCore.Attribute;
using TNodeCore.Editor.Serialization;
using TNodeCore.Models; using TNodeCore.Models;
using TNodeGraphViewImpl.Editor.NodeViews; using TNodeGraphViewImpl.Editor.NodeViews;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEditor.Graphs;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace TNode.Editor.NodeViews{ namespace TNode.Editor.NodeViews{
[ViewComponent] [ViewComponent]
@ -8,6 +15,26 @@ namespace TNode.Editor.NodeViews{
public DragBaseNodeView() : base(){ public DragBaseNodeView() : base(){
this.titleContainer.visible = false; this.titleContainer.visible = false;
this.titleContainer.RemoveFromHierarchy(); this.titleContainer.RemoveFromHierarchy();
this.OnDataChanged += OnDataChangedHandler;
}
private void OnDataChangedHandler(BlackboardDragNodeData obj){
var port = this.Q<Port>();
var label = port.Q<Label>();
var blackboard = obj.BlackboardData;
BlackboardDataWrapper blackboardWrapper = (BlackboardDataWrapper)blackboard;
var serializedData = new SerializedObject(blackboardWrapper);
var serializedProperty = serializedData.FindProperty("data").FindPropertyRelative(obj.blackDragData);
PropertyField field = new PropertyField(serializedProperty,"");
field.Bind(serializedData);
label.parent.parent.style.flexDirection = FlexDirection.RowReverse;
label.parent.parent.Add(field);
label.parent.parent.style.alignItems = Align.Center;
label.parent.parent.style.justifyContent = Justify.Center;
label.parent.parent.style.paddingTop = 0;
label.parent.parent.style.paddingBottom = 0;
label.RemoveFromHierarchy();
} }
} }
} }

@ -59,10 +59,7 @@ namespace TNodeGraphViewImpl.Editor.NodeViews{
this.title = _data.nodeName; this.title = _data.nodeName;
if (_nodeInspectorInNode != null){ if (_nodeInspectorInNode != null){
_nodeInspectorInNode.Data = obj; _nodeInspectorInNode.Data = obj;
} }
BuildInputAndOutputPort(); BuildInputAndOutputPort();
this.expanded = true; this.expanded = true;
this.RefreshExpandedState(); this.RefreshExpandedState();

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using TNodeCore.Editor.NodeGraphView; using TNodeCore.Editor.NodeGraphView;
using TNodeCore.Editor.Tools.NodeCreator; using TNodeCore.Editor.Tools.NodeCreator;
using TNodeCore.Models; using TNodeCore.Models;
@ -9,7 +10,7 @@ using UnityEditor.Experimental.GraphView;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
namespace TNode.Editor.Search{ namespace TNodeGraphViewImpl.Editor.Search{
public class NodeSearchWindowProvider:ScriptableObject,ISearchWindowProvider{ public class NodeSearchWindowProvider:ScriptableObject,ISearchWindowProvider{
private Type _graphType; private Type _graphType;
private GraphView _graphView; private GraphView _graphView;
@ -21,20 +22,26 @@ namespace TNode.Editor.Search{
} }
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context){ public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context){
var nodeDataTypes = NodeEditorExtensions.GetGraphDataUsage(_graphType); var nodeDataTypes = NodeEditorExtensions.GetGraphDataUsage(_graphType);
var categories = NodeEditorExtensions.GetGraphCategories(_graphType);
var list = new List<SearchTreeEntry>{ var list = new List<SearchTreeEntry>{
new SearchTreeGroupEntry(new GUIContent("Add New Node"), 0),
}; };
//TODO a node icon shall be given by some way var root = new SearchTreeGroupEntry(new GUIContent("Create"),0);
list.Add(root);
Texture2D icon = new Texture2D(2,2); Texture2D icon = new Texture2D(2,2);
foreach (var nodeDataType in nodeDataTypes){ foreach (var category in categories){
Debug.Log(nodeDataType.Name); var categoryEntry = new SearchTreeGroupEntry(new GUIContent(category),1);
list.Add(categoryEntry);
nodeDataTypes.Where(x => NodeEditorExtensions.GetTypeCategory(x).Equals(category)).ToList().ForEach(x => {
list.Add(new SearchTreeEntry(new GUIContent($" {nodeDataType.Name} ",icon)){ var nodeDataType = x;
level = 1, var nodeDataTypeEntry = new SearchTreeEntry(new GUIContent($" {nodeDataType.Name} ",icon)){
userData = nodeDataType, level = 2,
userData = nodeDataType
};
list.Add(nodeDataTypeEntry);
}); });
} }
return list; return list;
} }
@ -55,8 +62,5 @@ namespace TNode.Editor.Search{
} }
return false; return false;
} }
public NodeSearchWindowProvider(){
}
} }
} }
Loading…
Cancel
Save