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

Working in process
main
taoria 3 years ago committed by GitHub
commit f3b2268cd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      README.md
  2. 2
      TNode/TNodeCore/Editor/EditorPersistence/GraphEditorData.cs
  3. 9
      TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs
  4. 2
      TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs
  5. 6
      TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs
  6. 3
      TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs.meta
  7. 5
      TNode/TNodeCore/Runtime/Attributes/ModelColor.cs
  8. 3
      TNode/TNodeCore/Runtime/Attributes/ModelColor.cs.meta
  9. 3
      TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs
  10. 8
      TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs
  11. 8
      TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs
  12. 8
      TNode/TNodeCore/Runtime/Models/BlackboardData.cs
  13. 7
      TNode/TNodeCore/Runtime/Models/IModel.cs
  14. 19
      TNode/TNodeCore/Runtime/Models/Model.cs
  15. 0
      TNode/TNodeCore/Runtime/Models/Model.cs.meta
  16. 7
      TNode/TNodeCore/Runtime/Models/NodeData.cs
  17. 21
      TNode/TNodeCore/Runtime/NodeLogger.cs
  18. 3
      TNode/TNodeCore/Runtime/NodeLogger.cs.meta
  19. 14
      TNode/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs
  20. 2
      TNode/TNodeGraphViewImpl/Editor/Cache/NodeEditorExtensions.cs
  21. 4
      TNode/TNodeGraphViewImpl/Editor/GraphBlackboard/DefaultGraphBlackboardView.cs
  22. 2
      TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs
  23. 149
      TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs
  24. 53
      TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs
  25. 3
      TNode/TNodeGtfImpl/Editor.meta

@ -1,10 +1,10 @@
# T-Node
Node graph creation tool based on unity experimental graphview and if possible latter,GTF.
the main goal of the repo is to make graph creation easier and more intuitive.
Note **it's not usable and productive on current stage** and need a better
development .
and it's mainly for my own use now.
The tool separate its graph editor implementation and the graph creation logic.
@ -12,25 +12,24 @@ The tool separate its graph editor implementation and the graph creation logic.
currently under development
# Main Features
# Some Features
* Create graph script by the creator tool
* Create graph script a the creator tool
* Node creation based on specified type of graph
* Easy port creation via attribute
* Runtime graph
* Blackboard for runtime graph as exposed parameters
* Runtime graph execution
* An easy test mode (Runtime graph only)
* Scene object nodes hold scene objects
# Some To-dos
* Caching runtime state for faster execution
* Undo redo support
* Function as port
* Better blackboard support
* Circular dependency support for some situations such as FSM
* Edge colors customization
# Usage
No ,It's better not to use TNode at current stage until it's stable.
Not yet documented
### Convention

@ -3,6 +3,7 @@ using System.Collections.Generic;
using TNodeCore.Editor.NodeGraphView;
using TNodeCore.Runtime.Models;
using UnityEngine;
using UnityEngine.Serialization;
namespace TNodeCore.Editor.EditorPersistence{
@ -14,6 +15,7 @@ namespace TNodeCore.Editor.EditorPersistence{
public GraphImplType graphImplType = GraphImplType.GraphViewImpl;
public static Func<Type,IBaseDataGraphView> GraphViewImplCreator;
public static Func<Type,IBaseDataGraphView> GtfImplCreator;
[FormerlySerializedAs("testMode")] public bool autoUpdate;
public IDataGraphView<T> GetGraphView<T> () where T:GraphData{
switch (graphImplType){

@ -14,7 +14,7 @@ namespace TNodeCore.Editor.NodeGraphView{
public void RemoveLink(NodeLink nodeLink);
public bool TestMode{ get; set; }
public bool AutoUpdate{ get; set; }
public void CreateBlackboard();
public GraphData GetGraphData();
public BlackboardData GetBlackboardData();
@ -30,9 +30,12 @@ namespace TNodeCore.Editor.NodeGraphView{
public void SetGraphData(GraphData graph);
void NotifyRuntimeUpdate();
public Action AfterRuntimeGraphUpdate{ get; set; }
public Action AfterGraphResolved{ get; set; }
void AfterEditorLoadGraphView();
//todo remove it later ,keep it now
void NotifyRuntimeUpdate();
}
}

@ -4,7 +4,7 @@ using TNodeCore.Runtime.Models;
namespace TNodeCore.Runtime.Attributes{
/// <summary>
/// Use this attribute to claim the usage of a type derived IModel IModel
/// Use this attribute to claim the usage of a type derived Model Model
/// it can be applied to the same node multiple times.
/// <example>
/// [GraphUsage(DialogueGraph)]

@ -0,0 +1,6 @@
namespace TNodeCore.Runtime.Attributes{
public class HideInBlackboard:System.Attribute{
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 731893f9f7824b939cee169d61092ad3
timeCreated: 1659517588

@ -0,0 +1,5 @@
namespace TNodeCore.Runtime.Attributes{
public class ModelColor{
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cdec5767969f4e11bbcfb245693796f9
timeCreated: 1659521617

@ -1,5 +1,6 @@
using System;
using JetBrains.Annotations;
using UnityEngine;
namespace TNodeCore.Runtime.Attributes.Ports{
[MeansImplicitUse]
@ -7,5 +8,7 @@ namespace TNodeCore.Runtime.Attributes.Ports{
public class InputAttribute : PortAttribute{
public InputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto,TypeHandling typeHandling=TypeHandling.Declared) : base(name, nameHandling,typeHandling){
}
public InputAttribute(Color color):base(color){
}
}
}

@ -1,8 +1,14 @@
namespace TNodeCore.Runtime.Attributes.Ports{
using UnityEngine;
namespace TNodeCore.Runtime.Attributes.Ports{
public class OutputAttribute:PortAttribute{
public OutputAttribute(string name="", PortNameHandling nameHandling = PortNameHandling.Auto,TypeHandling typeHandling = TypeHandling.Declared) : base(name, nameHandling,typeHandling){
}
public OutputAttribute(Color color):base(color){
}
}
}

@ -1,6 +1,8 @@
using System;
using UnityEngine;
using JetBrains.Annotations;
namespace TNodeCore.Runtime.Attributes.Ports{
public enum PortNameHandling{
@ -23,6 +25,7 @@ namespace TNodeCore.Runtime.Attributes.Ports{
public readonly PortNameHandling NameHandling;
public Type HandledType;
public bool Multiple = true;
public Color PortColor = Color.black;
public TypeHandling TypeHandling{ get; set; }
public PortAttribute(string name,PortNameHandling nameHandling=PortNameHandling.Auto,TypeHandling typeHandling=TypeHandling.Declared){
this.Name = name;
@ -30,6 +33,11 @@ namespace TNodeCore.Runtime.Attributes.Ports{
this.TypeHandling = typeHandling;
}
public PortAttribute(Color color):this("",PortNameHandling.Auto,TypeHandling.Declared){
PortColor = color;
}
}
}

@ -1,4 +1,5 @@
using System;
using UnityEngine;
namespace TNodeCore.Runtime.Models{
/// <summary>
@ -6,10 +7,9 @@ namespace TNodeCore.Runtime.Models{
/// </summary>
[Serializable]
public class BlackboardData:IModel,ICloneable{
public object Clone(){
return this.MemberwiseClone();
}
public class BlackboardData:Model,ICloneable{
}

@ -1,7 +0,0 @@
using System;
namespace TNodeCore.Runtime.Models{
public interface IModel:ICloneable{
}
}

@ -0,0 +1,19 @@
using System;
using TNodeCore.Runtime.Attributes;
using UnityEngine;
using UnityEngine.Serialization;
namespace TNodeCore.Runtime.Models{
[Serializable]
public abstract class Model:ICloneable{
#if UNITY_EDITOR
[HideInBlackboard]
public Rect positionInView;
#endif
public object Clone(){
var memberwiseClone = this.MemberwiseClone();
return memberwiseClone;
}
}
}

@ -12,7 +12,7 @@ namespace TNodeCore.Runtime.Models{
///
/// </summary>
[Serializable]
public class NodeData:IModel{
public class NodeData:Model{
public NodeData() : base(){
//Object Registration
@ -37,8 +37,7 @@ namespace TNodeCore.Runtime.Models{
}
#endif
public object Clone(){
return this.MemberwiseClone();
}
}
}

@ -0,0 +1,21 @@
using System.Collections.Generic;
using TNodeCore.Runtime.Models;
using UnityEngine;
namespace TNodeCore.Runtime{
public static class NodeLogger{
public static Dictionary<string, INodeLoggerImpl> Loggers = new ();
public static void Log(this NodeData t,string message){
if (!Loggers.ContainsKey(t.id)) return;
var nodeLoggerImpl = Loggers[t.id];
nodeLoggerImpl.Log(message);
Debug.Log(message);
}
}
public interface INodeLoggerImpl{
public void Log(string message);
}
}

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 48be07a2cf064167b15d378ac41757c4
timeCreated: 1659592209

@ -64,8 +64,8 @@ namespace TNodeCore.Runtime.RuntimeCache{
get{ return _instance ??= new RuntimeCache(); }
}
//delegate return a value from a nodedata
public delegate object GetValueDelegate(IModel nodeData);
public delegate void SetValueDelegate(IModel nodeData,object value);
public delegate object GetValueDelegate(Model nodeData);
public delegate void SetValueDelegate(Model nodeData,object value);
@ -258,11 +258,11 @@ namespace TNodeCore.Runtime.RuntimeCache{
public static class RuntimeExtension{
//todo latter on i will try some way caching reflection more efficiently
public static T GetValue<T>(this IModel data,string path,Type type=null){
public static T GetValue<T>(this Model data,string path,Type type=null){
var method = RuntimeCache.Instance.CachedDelegatesForGettingValue[type??data.GetType()][path];
return (T) method.Invoke(data);
}
public static object GetValue(this IModel data, string path,Type type=null){
public static object GetValue(this Model data, string path,Type type=null){
if(!RuntimeCache.Instance.CachedDelegatesForGettingValue.ContainsKey(type??data.GetType())){
return null;
}
@ -270,7 +270,7 @@ namespace TNodeCore.Runtime.RuntimeCache{
var method = dic.ContainsKey(path) ? dic[path] : null;
return method?.Invoke(data);
}
public static object GetListValue(this IModel data,string path,int index,Type type=null){
public static object GetListValue(this Model data,string path,int index,Type type=null){
if(!RuntimeCache.Instance.CachedDelegatesForGettingValue.ContainsKey(type??data.GetType())){
return null;
}
@ -286,11 +286,11 @@ namespace TNodeCore.Runtime.RuntimeCache{
return list[index];
}
public static void SetValue<T>(this IModel data,string path,T value,Type type=null){
public static void SetValue<T>(this Model data,string path,T value,Type type=null){
var method = RuntimeCache.Instance.CachedDelegatesForSettingValue[type??data.GetType()][path];
method.Invoke(data,value);
}
public static void SetValue(this IModel data,string path,object value,Type type=null){
public static void SetValue(this Model data,string path,object value,Type type=null){
var method = RuntimeCache.Instance.CachedDelegatesForSettingValue[type??data.GetType()][path];
method.Invoke(data,value);
}

@ -89,7 +89,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.Cache{
private void SetGraphUsageAttribute(Type type){
foreach (var attribute in type.GetCustomAttributes(typeof(GraphUsageAttribute), true)){
var parent = type.BaseType;
if (typeof(IModel).IsAssignableFrom(type.BaseType)){
if (typeof(Model).IsAssignableFrom(type.BaseType)){
//Check if GraphDataUsage dictionary has GraphDataType of attribute
if (typeof(NodeData).IsAssignableFrom(type)){

@ -6,6 +6,7 @@ using TNodeCore.Editor.NodeGraphView;
using TNodeCore.Editor.Serialization;
using TNodeCore.Runtime.Attributes;
using TNodeCore.Runtime.Models;
using Unity.VisualScripting;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEditor.UIElements;
@ -22,8 +23,8 @@ namespace TNode.TNodeGraphViewImpl.Editor.GraphBlackboard{
}
protected override void UpdateBlackboard(BlackboardData data){
Clear();
if (data == null) return;
this.Clear();
var serializedObject = new SerializedObject((BlackboardDataWrapper)data);
var currentGraphView = graphView as IBaseDataGraphView;
var isRuntimeGraph = currentGraphView?.IsRuntimeGraph ?? false;
@ -33,6 +34,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.GraphBlackboard{
Add(blackboardGlobalSection);
foreach (var field in data.GetType()
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)){
if(field.HasAttribute(typeof(HideInBlackboard))) continue;
//if the field is MonoBehaviour,add a property field for blackboard
//skip if the field is a list or Ilist
if (!typeof(IList).IsAssignableFrom(field.FieldType)&&!field.FieldType.IsArray){

@ -67,7 +67,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.Inspector{
Add(drawer);
}
var globalTest = GetFirstAncestorOfType<IBaseDataGraphView>()?.TestMode;
var globalTest = GetFirstAncestorOfType<IBaseDataGraphView>()?.AutoUpdate;
if(globalTest??false){
CreateTestButton();
}

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using TNode.TNodeGraphViewImpl.Editor.Cache;
using TNode.TNodeGraphViewImpl.Editor.GraphBlackboard;
using TNode.TNodeGraphViewImpl.Editor.Inspector;
@ -16,6 +17,7 @@ using TNodeCore.Editor.Tools.NodeCreator;
using TNodeCore.Runtime.Components;
using TNodeCore.Runtime.Models;
using TNodeCore.Runtime.RuntimeCache;
using Unity.VisualScripting;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
@ -25,16 +27,18 @@ using Edge = UnityEditor.Experimental.GraphView.Edge;
namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
public class BaseDataGraphView<T>:GraphView,IDataGraphView<T> where T:GraphData{
#region const
public const float RefreshRate = 1f;
#endregion
#region variables and properties
private T _data;
private RuntimeGraph _runtimeGraph;
private bool _isInspectorOn;
private NodeSearchWindowProvider _nodeSearchWindowProvider;
private NodeInspector _nodeInspector;
private Dictionary<string,Node> _nodeDict = new();
private IBlackboardView _blackboard;
private bool _runtimeGraphUpdate;
private bool _loaded;
public T Data{
get{ return _data; }
set{
@ -98,15 +102,14 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
var res = DragAndDrop.objectReferences;
foreach (var obj in res){
if (obj is T graphData){
Data = graphData;
IsRuntimeGraph = false;
Data = graphData;
}
else{
if (obj is GameObject gameObject){
if (gameObject.GetComponent<RuntimeGraph>() != null){
if (gameObject.GetComponent<RuntimeGraph>().graphData != null){
_runtimeGraph = gameObject.GetComponent<RuntimeGraph>();
IsRuntimeGraph = true;
BuildRuntimeGraphBehaviour();
@ -114,7 +117,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
if(Data==null){
Debug.LogError($"Dragged a wrong graph data to editor,expected {typeof(T)} but got {gameObject.GetComponent<RuntimeGraph>().graphData.GetType()}");
}
}
}
}
@ -147,25 +149,36 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
}
private void BuildRuntimeGraphBehaviour(){
EditorApplication.update+= UpdateRuntimeGraphBehaviour;
//EditorApplication.update+= UpdateRuntimeGraphBehaviour;
UpdateRuntimeGraphBehaviourInTime();
}
private void UpdateRuntimeGraphBehaviour(){
private async void UpdateRuntimeGraphBehaviourInTime(){
while (_loaded){
await Task.Delay(TimeSpan.FromSeconds(RefreshRate));
if(_runtimeGraph != null){
if (_runtimeGraphUpdate){
_runtimeGraphUpdate = false;
if (AutoUpdate){
_runtimeGraph.ResolveDependency();
AfterRuntimeGraphUpdate?.Invoke();
AfterGraphResolved?.Invoke();
}
}
else{
EditorApplication.update -= UpdateRuntimeGraphBehaviour;
}
}
// private void UpdateRuntimeGraphBehaviour(){
// if(_runtimeGraph != null){
// if (_runtimeGraphUpdate){
// _runtimeGraphUpdate = false;
// _runtimeGraph.ResolveDependency();
//
// AfterGraphResolved?.Invoke();
// }
// }
// else{
// EditorApplication.update -= UpdateRuntimeGraphBehaviour;
// }
// }
private void CheckDataAfterInit(){
if(Data == null){
@ -201,6 +214,18 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
OnGraphViewCreate();
BuildUndo();
_loaded = true;
SetDetachedFromPanel();
}
private void SetDetachedFromPanel(){
this.RegisterCallback<DetachFromPanelEvent>(evt => {
_loaded = false;
});
}
private void BuildUndo(){
@ -227,22 +252,32 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
//Add a toggle button to toggle test mode
var testModeToggle = new Toggle{
var autoUpdateToggle = new Toggle{
name = "TestModeToggle",
label = "Test Mode",
value = false
value = AutoUpdate
};
testModeToggle.RegisterValueChangedCallback(evt => {
autoUpdateToggle.RegisterValueChangedCallback(evt => {
if (evt.newValue){
TestMode = true;
AutoUpdate = true;
}
else{
TestMode = false;
AutoUpdate = false;
}
});
visualElement.Add(testModeToggle);
visualElement.Add(autoUpdateToggle);
var runButton = new Button{
name = "RunButton",
text = "Run Once"
};
runButton.RegisterCallback<ClickEvent>(evt => {
if (IsRuntimeGraph){
_runtimeGraph.ResolveDependency();
AfterGraphResolved?.Invoke();
}
});
visualElement.Add(runButton);
}
public void RegisterDragEvent(){
@ -341,8 +376,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
}
private void AddPersistentNode(NodeData dataNode){
var nodePos = Owner.graphEditorData.graphElementsData.FirstOrDefault(x => x.guid == dataNode.id)?.pos ??
new Rect(0, 0, 200, 200);
var nodePos = dataNode.positionInView;
AddTNode(dataNode, nodePos);
}
//OnDataChanged event
@ -391,21 +425,21 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
}
public void SaveEditorData(GraphEditorData graphEditorData){
graphEditorData.graphElementsData?.Clear();
//iterator nodes
if (graphEditorData.graphElementsData == null){
graphEditorData.graphElementsData = new List<GraphElementEditorData>();
}
foreach (var node in this.nodes){
var nodeEditorData = new GraphElementEditorData{
pos = node.GetPosition(),
};
if (node is IBaseNodeView nodeView){
nodeEditorData.guid = nodeView.GetNodeData().id;
}
graphEditorData.graphElementsData.Add(nodeEditorData);
EditorUtility.SetDirty(graphEditorData);
}
// graphEditorData.graphElementsData?.Clear();
// //iterator nodes
// if (graphEditorData.graphElementsData == null){
// graphEditorData.graphElementsData = new List<GraphElementEditorData>();
// }
// foreach (var node in this.nodes){
// var nodeEditorData = new GraphElementEditorData{
// pos = node.GetPosition(),
// };
// if (node is IBaseNodeView nodeView){
// nodeEditorData.guid = nodeView.GetNodeData().id;
// }
// graphEditorData.graphElementsData.Add(nodeEditorData);
// EditorUtility.SetDirty(graphEditorData);
// }
}
public void SaveWithEditorData(GraphEditorData graphEditorData){
@ -499,8 +533,15 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
#region implement interfaces
public void AddTNode(NodeData nodeData, Rect rect){
if (NodeEditorExtensions.CreateNodeViewFromNodeType(nodeData.GetType()) is Node nodeView){
nodeView.SetPosition(rect);
//convert rect at graph space
var resPos = this.viewTransform.matrix.inverse.MultiplyPoint3x4(rect.position);
rect.position = resPos;
if(nodeView is IBaseNodeView nodeViewInterface){
nodeViewInterface.SetNodeData(nodeData);
}
AddElement(nodeView);
((IBaseNodeView)nodeView).InitializePosition(rect);
//Add a select callback to the nodeView
nodeView.RegisterCallback<MouseDownEvent>(evt => {
if (evt.clickCount == 1){
@ -510,14 +551,17 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
}
}
});
if(nodeView is IBaseNodeView nodeViewInterface){
nodeViewInterface.SetNodeData(nodeData);
}
if(_nodeDict.ContainsKey(nodeData.id)==false)
_nodeDict.Add(nodeData.id, nodeView);
if (_data.NodeDictionary.ContainsKey(nodeData.id) == false){
Undo.RegisterCompleteObjectUndo(_data,"Node Creation");
_data.NodeDictionary.Add(nodeData.id,nodeData);
}
//register an callback ,when right click context menu
nodeView.RegisterCallback<ContextClickEvent>(evt => {
var menu = new GenericMenu();
@ -529,6 +573,8 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
});
menu.ShowAsContext();
});
}
}
@ -557,12 +603,21 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
_data.NodeLinks.Remove(nodeLink);
}
public bool TestMode{ get; set; }
public bool AutoUpdate{
get=>Owner.graphEditorData.autoUpdate; set=>Owner.graphEditorData.autoUpdate = value;
}
public override EventPropagation DeleteSelection(){
Undo.RegisterCompleteObjectUndo(_data,"Delete Selection");
var res = base.DeleteSelection();
SaveGraphData();
ResetGraphView();
return res;
}
public void CreateBlackboard(){
_blackboard = NodeEditorExtensions.CreateBlackboardWithGraphData(typeof(T));
_blackboard.Setup(this,Owner);
Debug.Log(Owner);
var castedBlackboard = _blackboard as Blackboard;
Add(castedBlackboard);
Rect blackboardPos = new Rect(0,0,300,700);
@ -594,11 +649,9 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
public void NotifyRuntimeUpdate(){
_runtimeGraphUpdate = true;
}
public Action AfterRuntimeGraphUpdate{ get; set; }
public Action AfterGraphResolved{ get; set; }
#endregion
}

@ -18,6 +18,27 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
public abstract class BaseNodeView<T> : Node,INodeView<T> where T:NodeData,new(){
protected T _data;
private readonly NodeInspectorInNode _nodeInspectorInNode;
private NodeViewLogger _viewLogger;
private class NodeViewLogger:INodeLoggerImpl{
public BaseNodeView<T> NodeView { get; set; }
public void Log(string message){
var loggerAreaParent = NodeView.extensionContainer;
if (loggerAreaParent == null){
return;
}
var loggerArea = loggerAreaParent.Q<TextField>("loggerArea");
if(loggerArea == null){
loggerArea = new TextField();
loggerArea.name = "loggerArea";
loggerArea.AddToClassList("loggerArea");
loggerAreaParent.Add(loggerArea);
}
loggerArea.multiline = true;
loggerArea.value = message;
}
}
public IBaseDataGraphView BaseDataGraphView{
get{
@ -31,18 +52,22 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
if(_data!=null)
((NodeDataWrapper)_data).OnValueChanged -= OnDataValueChanged;
_data = value;
OnDataChanged?.Invoke(value);
if(_data!=null)
((NodeDataWrapper)_data).OnValueChanged += OnDataValueChanged;
}
}
private void OnDataValueChanged(DataWrapper<NodeDataWrapper, NodeData> obj){
Refresh();
if (BaseDataGraphView == null) return;
if (BaseDataGraphView.IsRuntimeGraph){
BaseDataGraphView.NotifyRuntimeUpdate();
}
}
public sealed override string title{
get => base.title;
@ -65,6 +90,13 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
if (_nodeInspectorInNode != null){
_nodeInspectorInNode.Data = obj;
}
_viewLogger ??= new NodeViewLogger{NodeView = this};
if (NodeLogger.Loggers.ContainsKey(obj.id)){
NodeLogger.Loggers[obj.id] = _viewLogger;
}
else{
NodeLogger.Loggers.Add(obj.id,_viewLogger);
}
BuildInputAndOutputPort();
this.expanded = true;
this.RefreshExpandedState();
@ -106,7 +138,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
foreach (var propertyInfo in propertyInfos){
if (propertyInfo.GetCustomAttributes(typeof(OutputAttribute),true).FirstOrDefault() is OutputAttribute attribute){
Port port = new CustomPort(Orientation.Horizontal, Direction.Output,
attribute.Multiple ? Port.Capacity.Multi : Port.Capacity.Single,
BuildPortType(attribute, propertyInfo));
@ -115,16 +146,18 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
var portName = ObjectNames.NicifyVariableName(BuildPortName(attribute,propertyInfo));
port.portName = portName;
port.name = propertyInfo.Name;
}
}
foreach (var propertyInfo in propertyInfos){
if(propertyInfo.GetCustomAttributes(typeof(InputAttribute),true).FirstOrDefault() is InputAttribute attribute){
Port port = new CustomPort(Orientation.Horizontal, Direction.Input,attribute.Multiple?Port.Capacity.Multi:Port.Capacity.Single,BuildPortType(attribute,propertyInfo));
this.inputContainer.Add(port);
var portName = BuildPortName(attribute,propertyInfo);
port.portName = portName;
port.name = propertyInfo.Name;
}
}
}
@ -184,6 +217,18 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
Refresh();
}
public override void SetPosition(Rect newPos){
var graphView = (GraphView)BaseDataGraphView;
//Cast newPos s position to global space
var globalPos = graphView.contentViewContainer.LocalToWorld(newPos.position);
_data.positionInView.position = globalPos;
base.SetPosition(newPos);
}
public void InitializePosition(Rect pos){
base.SetPosition(pos);
}
public void Refresh(){
title = _data.nodeName;
}
@ -195,6 +240,8 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
public void OnDataModified();
IBaseDataGraphView BaseDataGraphView{ get; }
public void InitializePosition(Rect pos);
}
public interface INodeView<T>:IBaseNodeView where T:NodeData,new(){

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