feat: Add an new property drawer for graph

main
taoria 3 years ago
parent 1e16ddda5c
commit ba8b9ccac9
  1. 5
      TNode/Attribute/Ports/BatchInputAttribute.cs
  2. 3
      TNode/Attribute/Ports/BatchInputAttribute.cs.meta
  3. 12
      TNode/Attribute/Ports/BatchOutputAttribute.cs
  4. 3
      TNode/Attribute/Ports/BatchOutputAttribute.cs.meta
  5. 7
      TNode/Attribute/Ports/InputAttribute.cs
  6. 16
      TNode/Attribute/Ports/PortAttribute.cs
  7. 1
      TNode/Attribute/ShowInNodeViewAttribute.cs
  8. 8
      TNode/Editor/BaseViews/DataGraphView.cs
  9. 1
      TNode/Editor/BaseViews/NodeView.cs
  10. 16
      TNode/Editor/Cache/NodeEditorExtensions.cs
  11. 2
      TNode/Editor/GraphEditor.cs
  12. 20
      TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs
  13. 3
      TNode/Editor/Inspector/InspectorImplementation/EnumFieldItem.cs.meta
  14. 19
      TNode/Editor/Inspector/InspectorItem.cs
  15. 25
      TNode/Editor/Inspector/InspectorItemFactory.cs
  16. 19
      TNode/Editor/Inspector/NodeInspectorInNode.cs
  17. 13
      TNode/Editor/Inspector/TinyInspectorItem.cs
  18. 3
      TNode/Editor/Inspector/TinyInspectorItem.cs.meta
  19. 15
      TNode/Editor/Search/BlackboardSearchWindowProvider.cs
  20. 1
      TNode/Models/GraphData.cs

@ -0,0 +1,5 @@
namespace TNode.Attribute.Ports{
public class BatchInputAttribute{
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8745aaf35940443693af378c8214060e
timeCreated: 1657190813

@ -0,0 +1,12 @@
using System;
using UnityEditor.Experimental.GraphView;
namespace TNode.Attribute.Ports{
/// <summary>
/// Batch out port attribute could specify a batch out port,allowing large scale calculation.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class BatchOutputAttribute:PortAttribute{
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0a6ca9cc801d4db3b73ee59cf0aef38e
timeCreated: 1657190648

@ -7,11 +7,6 @@ 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){
}
}
}

@ -7,22 +7,6 @@ namespace TNode.Attribute{
[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;
}
}
}

@ -2,6 +2,7 @@
namespace TNode.Attribute{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
public class ShowInNodeViewAttribute:System.Attribute{
}

@ -261,8 +261,7 @@ namespace TNode.Editor.BaseViews{
input = inputNodeView.inputContainer.Q<Port>(edge.inPort.portName),
output = outputNodeView.outputContainer.Q<Port>(edge.outPort.portName)
};
Debug.Log(edge.inPort.portName);
Debug.Log(edge.outPort.portName);
newEdge.input?.Connect(newEdge);
newEdge.output?.Connect(newEdge);
AddElement(newEdge);
@ -296,7 +295,7 @@ namespace TNode.Editor.BaseViews{
// });
// blackboard.addItemRequested = (item) => {
// //Create a sub window for the blackboard to show the selection
// var subWindow = ScriptableObject.CreateInstance<NodeSearchWindowProvider>();
// var subWindow = ScriptableObject.CreateNodeComponentFromGenericType<NodeSearchWindowProvider>();
// };
//
//Set black board to left side of the view
@ -315,11 +314,9 @@ namespace TNode.Editor.BaseViews{
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
var propertyField = new BlackboardPropertyField(new BlackboardProperty(field.Name,field.FieldType));
_blackboard.Add(propertyField);
@ -432,7 +429,6 @@ namespace TNode.Editor.BaseViews{
AddElement(nodeView);
//Add a select callback to the nodeView
nodeView.RegisterCallback<MouseDownEvent>(evt => {
Debug.Log("NodeView Selected");
if (evt.clickCount == 1){
if (_isInspectorOn){
_nodeInspector.Data = nodeData;

@ -76,7 +76,6 @@ namespace TNode.Editor.BaseViews{
}
}
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);

@ -92,32 +92,33 @@ namespace TNode.Cache{
}
//Outer wrapper for the singleton class
public static class NodeEditorExtensions{
public static T CreateInstance<T>(){
public static T CreateNodeComponentFromGenericType<T>(){
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<NodeData>));
return instance;
}
return null;
}
}
public static bool HasSpecificType<T>() where T : class{
public static bool HasSpecificTypeComponent<T>() 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<Type> GetGraphDataUsage(Type t){
if (NodeEditorSingleton.Instance.GraphDataUsage.ContainsKey(t)){
return NodeEditorSingleton.Instance.GraphDataUsage[t];
@ -145,9 +146,6 @@ namespace TNode.Cache{
}
public static object CreateNodeViewFromNodeType(Type t){
//Check the generic type of NodeView by t
Debug.Log(t);
Debug.Log(t.ToString());
Debug.Log(typeof(NodeData).IsAssignableFrom(t));
var type = typeof(NodeView<>).MakeGenericType(t);
if (NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(type)){
var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[type];

@ -36,7 +36,7 @@ namespace TNode.Editor{
}
private void BuildGraphView(){
_graphView = NodeEditorExtensions.CreateInstance<DataGraphView<T>>();
_graphView = NodeEditorExtensions.CreateNodeComponentFromGenericType<DataGraphView<T>>();
rootVisualElement.Add(_graphView);
_graphView.StretchToParentSize();
}

@ -0,0 +1,20 @@
using System;
using TNode.Attribute;
using UnityEngine;
using UnityEngine.UIElements;
namespace TNode.Editor.Inspector.InspectorImplementation{
[NodeComponent]
public class EnumFieldItem:InspectorItem<Enum>{
public EnumFieldItem() : base(){
var field = new EnumField();
Debug.Log("An Enum Field is created");
CreateBindable(field);
OnDataChanged += () => {
field.Init(Value);
Debug.Log(Value.GetType());
};
}
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6eb83a1255d545e5998c7b3efd1b0d69
timeCreated: 1657193097

@ -6,8 +6,8 @@ using UnityEngine.UIElements;
namespace TNode.Editor.Inspector{
public abstract class InspectorItem<T>:VisualElement,INodeDataBinding<T> {
private NodeData _bindingNodeData;
private string _bindingFieldName;
protected NodeData _bindingNodeData;
protected string _bindingFieldName;
protected BaseField<T> Bindable;
protected event System.Action OnDataChanged;
@ -40,13 +40,17 @@ 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(){
@ -84,6 +88,7 @@ namespace TNode.Editor.Inspector{
Bindable.value = Value;
Bindable.label = BindingPath;
}
Debug.Log(Value.GetType());
}
private void OnNodeDataValueChanged(NodeDataWrapper wrapper){

@ -11,9 +11,30 @@ namespace TNode.Editor.Inspector{
public InspectorItem<T> Create<T>(){
//Check type of GraphDataType
var hasSpecificType = NodeEditorExtensions.HasSpecificType<InspectorItem<T>>();
var hasSpecificType = NodeEditorExtensions.HasSpecificTypeComponent<InspectorItem<T>>();
if (hasSpecificType){
return NodeEditorExtensions.CreateInstance<InspectorItem<T>>();
return NodeEditorExtensions.CreateNodeComponentFromGenericType<InspectorItem<T>>();
}
if (typeof(T).IsEnum){
return NodeEditorExtensions.CreateNodeComponentFromGenericType(typeof(InspectorItem<Enum>)) as InspectorItem<T>;
}
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<Enum>)) as INodeDataBindingBase;
}
return null;
}

@ -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){
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());
//
// }
}
}
}

@ -1,13 +0,0 @@
using TNode.Models;
using UnityEngine.UIElements;
namespace TNode.Editor.Inspector{
/// <summary>
/// Tiny Inspector item is a simple inspector item inside a node view ,it monitor node data
///
/// </summary>
public class TinyInspectorItem<T>:VisualElement,INodeDataBinding<T>{
public string BindingPath{ get; set; }
public NodeData BindingNodeData{ get; set; }
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 7eeddeb28a5a475c85c85ceae3198778
timeCreated: 1656142058

@ -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<SearchTreeEntry> CreateSearchTree(SearchWindowContext context){
throw new System.NotImplementedException();
}
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context){
throw new System.NotImplementedException();
}
}
}

@ -33,7 +33,6 @@ namespace TNode.Models{
var deserializedBlackboard = JsonConvert.DeserializeObject<BlackboardData>(jsonBlackboard,JsonSerializeTool.JsonSerializerSettings);
blackboardData = deserializedBlackboard;
Debug.Log("hi");
}
}
}
Loading…
Cancel
Save