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

Working in process
main
taoria 3 years ago committed by GitHub
commit d30c2ecab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      Sample/Editor/HelloGraphView.cs
  2. 0
      Sample/HelloGraph.cs
  3. 0
      Sample/HelloGraph.cs.meta
  4. 10
      Sample/HelloNode.cs
  5. 3
      Sample/HelloNode.cs.meta
  6. 337
      Scenes/SampleScene.unity
  7. 12
      TNode/Attribute/AssetMenuCreateAsGraphEditor.cs
  8. 3
      TNode/Attribute/AssetMenuCreateAsGraphEditor.cs.meta
  9. 26
      TNode/Attribute/GraphUsageAttribute.cs
  10. 3
      TNode/Attribute/GraphUsageAttribute.cs.meta
  11. 39
      TNode/Editor/BaseViews/DataGraphView.cs
  12. 3
      TNode/Editor/BaseViews/SimpleGraphSubWindow.cs
  13. 94
      TNode/Editor/Cache/NodeEditorExtensions.cs
  14. 8
      TNode/Editor/DefaultNodeView.cs
  15. 3
      TNode/Editor/DefaultNodeView.cs.meta
  16. 7
      TNode/Editor/GraphEditor.cs
  17. 2
      TNode/Editor/Inspector/DefaultInspectorItemFactory.cs
  18. 10
      TNode/Editor/Inspector/NodeInspector.cs
  19. 0
      TNode/Editor/Resources/NodeInspector.uxml
  20. 0
      TNode/Editor/Resources/NodeInspector.uxml.meta
  21. 55
      TNode/Editor/SearchWindowProvider.cs
  22. 3
      TNode/TNodeSample.meta
  23. 8
      TNode/TNodeSample/GraphViewTest.cs
  24. 3
      TNode/TNodeSample/GraphViewTest.cs.meta
  25. 15
      TNode/TNodeSample/NodeDataTest.cs
  26. 3
      TNode/TNodeSample/NodeDataTest.cs.meta

@ -1,9 +1,13 @@
using TNode.Attribute;
using TNode.Editor.BaseViews;
using TNode.Editor.Inspector;
using UnityEngine;
namespace Sample.Editor{
[NodeComponent]
public class HelloGraphView : DataGraphView<HelloGraph>{
public override void OnGraphViewCreate(){
CreateInspector();
}
}
}

@ -0,0 +1,10 @@
using Sample.Editor;
using TNode.Attribute;
using TNode.Models;
namespace Sample{
[GraphUsage(typeof(HelloGraph))]
public class HelloNode:NodeData{
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 928bb3292c464ae0b811455e9f4e8667
timeCreated: 1656391464

@ -123,6 +123,107 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &507038906
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 507038910}
- component: {fileID: 507038909}
- component: {fileID: 507038908}
- component: {fileID: 507038907}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &507038907
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 507038906}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 4294967295
--- !u!114 &507038908
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 507038906}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 0
--- !u!223 &507038909
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 507038906}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_AdditionalShaderChannelsFlag: 0
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!224 &507038910
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 507038906}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!1 &519420028
GameObject:
m_ObjectHideFlags: 0
@ -202,7 +303,243 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &691266389
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 691266390}
- component: {fileID: 691266391}
m_Layer: 0
m_Name: Circle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &691266390
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 691266389}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.79506373, y: 0.7908081, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1608359614}
m_RootOrder: -1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!331 &691266391
SpriteMask:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 691266389}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10758, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Sprite: {fileID: -2413806693520163455, guid: a86470a33a6bf42c4b3595704624658b, type: 3}
m_MaskAlphaCutoff: 0.2
m_FrontSortingLayerID: 0
m_BackSortingLayerID: 0
m_FrontSortingLayer: 0
m_BackSortingLayer: 0
m_FrontSortingOrder: 0
m_BackSortingOrder: 0
m_IsCustomRangeActive: 0
m_SpriteSortPoint: 0
--- !u!1 &1608359612
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1608359614}
- component: {fileID: 1608359613}
m_Layer: 0
m_Name: Circle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!212 &1608359613
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1608359612}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Sprite: {fileID: -2413806693520163455, guid: a86470a33a6bf42c4b3595704624658b, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 2
m_SpriteSortPoint: 0
--- !u!4 &1608359614
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1608359612}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 16.183, y: 14.154, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 691266390}
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1701140682
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1701140685}
- component: {fileID: 1701140684}
- component: {fileID: 1701140683}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1701140683
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1701140682}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &1701140684
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1701140682}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &1701140685
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1701140682}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

@ -1,12 +0,0 @@
using System;
using JetBrains.Annotations;
using UnityEngine;
namespace TNode.Attribute{
[MeansImplicitUse]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[BaseTypeRequired(typeof(ScriptableObject))]
public class AssetMenuCreateAsGraphEditorAttribute:System.Attribute{
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 536eae3bd21b49609d88e3bd24b4d7d0
timeCreated: 1656038984

@ -0,0 +1,26 @@
using System;
using JetBrains.Annotations;
using TNode.Models;
using Unity.VisualScripting;
namespace TNode.Attribute{
/// <summary>
/// Use this attribute to claim the usage of a type of node on the derived NodeData class.
/// it can be applied to the same node multiple times.
/// <example>
/// [GraphUsage(DialogueGraph)]
/// </example>
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
[BaseTypeRequired(typeof(NodeData))]
public class GraphUsageAttribute:System.Attribute{
public Type GraphDataType;
public GraphUsageAttribute(Type t){
//check if the type t is graph
if(!typeof(GraphData).IsAssignableFrom(t)){
throw new Exception("The type must be a graph");
}
GraphDataType = t;
}
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 25593dbfe27b42809a2a38eae3458521
timeCreated: 1656389642

@ -2,6 +2,7 @@
using System.Collections.Generic;
using TNode.BaseViews;
using TNode.Cache;
using TNode.Editor.Inspector;
using TNode.Models;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
@ -102,9 +103,11 @@ namespace TNode.Editor.BaseViews{
}
}
*/
public abstract class DataGraphView<T>:GraphView where T:GraphData{
public abstract class DataGraphView<T>:GraphView,IDataGraphView where T:GraphData{
private T _data;
private SearchWindowProvider _searchWindowProvider;
private bool _isInspectorOn;
private NodeInspector _nodeInspector;
public T Data{
get{ return _data; }
set{
@ -173,6 +176,14 @@ namespace TNode.Editor.BaseViews{
OnGraphViewCreate();
}
public virtual void CreateInspector(){
NodeInspector nodeInspector = new NodeInspector();
nodeInspector.SetPosition(new Rect(200,200,200,600));
this.Add(nodeInspector);
_nodeInspector = nodeInspector;
_isInspectorOn = true;
}
public virtual void OnGraphViewCreate(){
@ -184,14 +195,28 @@ namespace TNode.Editor.BaseViews{
~DataGraphView(){
OnGraphViewDestroy();
}
//rewrite function of the derived class in the comment on the top of this script file in this class
// public abstract override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter);
//
// public void AddNode(NodeData nodeData){
//
// }
public void AddTNode(NodeData nodeData, Rect rect){
if (NodeEditorExtensions.CreateNodeViewFromNodeType(nodeData.GetType()) is GraphElement nodeView){
nodeView.SetPosition(rect);
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;
}
}
});
}
}
}
public interface IDataGraphView{
public void AddTNode(NodeData nodeData, Rect rect);
}
public class DataChangedEventArgs<T>{

@ -7,6 +7,7 @@ namespace TNode.BaseViews{
private readonly Dragger _dragger = new Dragger();
protected void ConstructWindowBasicSetting(){
RegisterCallback<WheelEvent>(evt => { evt.StopPropagation(); });
focusable = false;
capabilities |= Capabilities.Movable | Capabilities.Resizable;
@ -19,6 +20,7 @@ namespace TNode.BaseViews{
}
public SimpleGraphSubWindow(string defaultUxml=null){
style.position = new StyleEnum<Position>(Position.Absolute);
ConstructWindowBasicSetting();
if (defaultUxml != null){
var uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(defaultUxml);
@ -26,6 +28,7 @@ namespace TNode.BaseViews{
}
}
public SimpleGraphSubWindow(VisualTreeAsset visualTreeAsset){
style.position = new StyleEnum<Position>(Position.Absolute);
ConstructWindowBasicSetting();
BuildWindow(visualTreeAsset);
}

@ -1,38 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TNode.Attribute;
using TNode.BaseViews;
using TNode.Editor;
using TNode.Editor.BaseViews;
using TNode.Models;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
namespace TNode.Cache{
/// <summary>
/// Internal singleton class for caching TNode reflection Data.
/// </summary>
internal class NodeEditorSingleton{
private static NodeEditorSingleton _instance;
public readonly Dictionary<Type,Type> FromGenericToSpecific = new Dictionary<Type, Type>();
public readonly Dictionary<Type, List<Type>> GraphDataUsage = new Dictionary<Type, List<Type>>();
public static NodeEditorSingleton Instance{
get{ return _instance ??= new NodeEditorSingleton(); }
}
private static readonly string[] ExcludedAssemblies = new string[]{"Microsoft", "UnityEngine","UnityEditor","mscorlib","System"};
private NodeEditorSingleton(){
foreach(var assembly in AppDomain.CurrentDomain.GetAssemblies()){
//exclude unity ,system ,and microsoft types
var assemblies = AppDomain.
CurrentDomain.GetAssemblies()
.Where(x=>ExcludedAssemblies.All(y=>!x.GetName().Name.Split(".")[0].Equals(y)));
foreach(var assembly in assemblies){
foreach(var type in assembly.GetTypes()){
if(type.IsClass && !type.IsAbstract){
foreach(var attribute in type.GetCustomAttributes(typeof(NodeComponentAttribute), false)){
//Register Node View And Graph View via its parent class
SetNodeComponentAttribute(type);
//Register Node Data by GraphUsageAttribute.
SetGraphUsageAttribute(type);
}
}
}
}
private void SetGraphUsageAttribute(Type type){
foreach (var attribute in type.GetCustomAttributes(typeof(GraphUsageAttribute), true)){
var parent = type.BaseType;
if (typeof(NodeData).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);
}
else{
GraphDataUsage.Add(attributeCasted.GraphDataType, new List<Type>{type});
}
}
}
}
}
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} && (parent.GetGenericTypeDefinition() == typeof(NodeView<>) || parent.GetGenericTypeDefinition() == typeof(DataGraphView<>))){
if (parent is{IsGenericType: true} && (parent.GetGenericTypeDefinition() == typeof(NodeView<>) ||
parent.GetGenericTypeDefinition() == typeof(DataGraphView<>))){
//Get the generic type of this type
//Add this type to the dictionary
Debug.Log($"Find a component named {type} and its parent is {parent}" );
Debug.Log($"Find a component named {type} and its parent is {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.
}
}
}
//Outer wrapper for the singleton class
public static class NodeEditorExtensions{
public static T CreateInstance<T>(){
Debug.Log($"Create A instance of {typeof(T)}");
@ -47,8 +89,40 @@ namespace TNode.Cache{
return instance;
}
public static bool HasSpecificType<T>() where T : class{
var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[typeof(T)] as T;
return (T)implementedType!=null;
return NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(typeof(T));
}
public static List<Type> GetGraphDataUsage(Type t){
if (NodeEditorSingleton.Instance.GraphDataUsage.ContainsKey(t)){
return NodeEditorSingleton.Instance.GraphDataUsage[t];
}
return new List<Type>();
}
public static object CreateNodeViewFromNodeType<T>() where T:NodeData,new(){
//Check specific derived type exists or not.
var type = typeof(NodeView<T>);
if (NodeEditorSingleton.Instance.FromGenericToSpecific.ContainsKey(type)){
var implementedType = NodeEditorSingleton.Instance.FromGenericToSpecific[type];
var instance = (NodeView<T>)Activator.CreateInstance(implementedType);
return instance;
}
else{
return new DefaultNodeView();
}
}
public static object CreateNodeViewFromNodeType(Type t){
//Check the generic type of NodeView by t
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();
}
}
}
}

@ -0,0 +1,8 @@
using TNode.BaseViews;
using TNode.Models;
namespace TNode.Editor{
public class DefaultNodeView:NodeView<NodeData>{
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 30bf0ad9c92f4bebae1a838bafd71c06
timeCreated: 1656401737

@ -52,7 +52,10 @@ namespace TNode.Editor{
evt.menu.AppendAction("Create Node", dma => {
var dmaPos = dma.eventInfo.mousePosition+editorPosition;
SearchWindowContext searchWindowContext = new SearchWindowContext(dmaPos,200,200);
SearchWindow.Open(searchWindowContext, ScriptableObject.CreateInstance<SearchWindowProvider>());
var searchWindow = CreateInstance<SearchWindowProvider>();
searchWindow.Setup(typeof(T),_graphView,this);
Debug.Log(searchWindow);
SearchWindow.Open(searchWindowContext, searchWindow);
});
});
}
@ -78,7 +81,7 @@ namespace TNode.Editor{
{
string path = EditorUtility.SaveFilePanel("Save Graph", "", "", "asset");
if (path.Length != 0){
//Create a new asset file with type of T
//Create a new asset file with type of GraphDataType
T asset = ScriptableObject.CreateInstance<T>();
AssetDatabase.CreateAsset(asset, path);
}

@ -8,7 +8,7 @@ namespace TNode.Editor.Inspector{
public class DefaultInspectorItemFactory{
public InspectorItem<T> Create<T>(){
//Check type of T
//Check type of GraphDataType
var hasSpecificType = NodeEditorExtensions.HasSpecificType<InspectorItem<T>>();
if (hasSpecificType){
return NodeEditorExtensions.CreateInstance<InspectorItem<T>>();

@ -13,24 +13,30 @@ namespace TNode.Editor.Inspector{
set{
_data = value;
UpdateData();
}
}
private void UpdateData(){
Debug.Log(_data);
if (_data != null){
RefreshInspector();
}
}
public NodeInspector(){
style.position = new StyleEnum<Position>(Position.Absolute);
var visualTreeAsset = Resources.Load<VisualTreeAsset>("NodeInspector");
Debug.Log(visualTreeAsset);
ConstructWindowBasicSetting();
BuildWindow(visualTreeAsset);
}
private void RefreshInspector(){
//iterate field of data and get name of every fields,create a new inspector item of appropriate type and add it to the inspector for each field
foreach (var field in GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)){
this.Q("InspectorBody").Clear();
foreach (var field in _data.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)){
var bindingPath = field.Name;
var type = field.FieldType;
DefaultInspectorItemFactory defaultInspectorItemFactory = new DefaultInspectorItemFactory();
//Invoke generic function Create<> of default inspector item factory to create an inspector item of appropriate type by reflection
@ -38,7 +44,7 @@ namespace TNode.Editor.Inspector{
if (methodInfo != null){
var genericMethod = methodInfo.MakeGenericMethod(type);
var createdInspector = genericMethod.Invoke(defaultInspectorItemFactory,null) as VisualElement;
Add(createdInspector);
this.Q("InspectorBody").Add(createdInspector);
if (createdInspector is INodeDataBindingBase castedInspector){
castedInspector.BindingNodeData = _data;
castedInspector.BindingPath = bindingPath;

@ -1,18 +1,63 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Drawing;
using TNode.BaseViews;
using TNode.Cache;
using TNode.Editor.BaseViews;
using TNode.Models;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;
namespace TNode.Editor{
public class SearchWindowProvider:ScriptableObject,ISearchWindowProvider{
private Type _graphType;
private GraphView _graphView;
private EditorWindow _editor;
public void Setup(Type graph,GraphView graphView,EditorWindow editor){
_graphType = graph;
_graphView = graphView;
_editor = editor;
}
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context){
var list = new List<SearchTreeEntry>();
list.Add(new SearchTreeGroupEntry(new GUIContent("Add New Node"), 0));
list.Add(new SearchTreeGroupEntry(new GUIContent("Add Placemat"), 0));
var nodeDataTypes = NodeEditorExtensions.GetGraphDataUsage(_graphType);
var list = new List<SearchTreeEntry>{
new SearchTreeGroupEntry(new GUIContent("Add New Node"), 0),
};
//TODO a node icon shall be given by some way
Texture2D icon = new Texture2D(2,2);
foreach (var nodeDataType in nodeDataTypes){
Debug.Log(nodeDataType.Name);
list.Add(new SearchTreeEntry(new GUIContent($" {nodeDataType.Name} ",icon)){
level = 1,
userData = nodeDataType,
});
}
return list;
}
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context){
var userData = SearchTreeEntry.userData;
var relativePos = context.screenMousePosition - _editor.position.position;
var localPos = _graphView.WorldToLocal(relativePos);
if (userData is Type type){
//Check if type is derived from NodeData
if (typeof(NodeData).IsAssignableFrom(type)){
//Make an instance of the type
var nodeData = (NodeData) Activator.CreateInstance(type);
nodeData.nodeName = "New Node";
((IDataGraphView)_graphView).AddTNode(nodeData,new Rect(localPos.x,localPos.y,100,100));
}
return true;
}
return false;
}
public SearchWindowProvider(){
}
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: ab3bb3578bf34dafad6ff9fb71f040e1
timeCreated: 1655794910

@ -1,8 +0,0 @@
using Dialogue;
using TNode.Attribute;
namespace TNode.TNodeSample{
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: a7d4101454c84539b936140f3b54a3a6
timeCreated: 1655794926

@ -1,15 +0,0 @@
using Dialogue;
using TNode.Attribute;
using TNode.Models;
using UnityEditor.Experimental.GraphView;
namespace TNode.TNodeSample{
public class NodeDataTest:NodeData{
[InputPort(typeof(NodeLink),Port.Capacity.Multi)]
private float _floatInput;
public NodeDataTest(string name):base(){
}
}
}

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 2d66df6e04694c51818042134869583f
timeCreated: 1655794954
Loading…
Cancel
Save