diff --git a/TNode/TNodeCore/Editor/EditorPersistence/GraphEditorData.cs b/TNode/TNodeCore/Editor/EditorPersistence/GraphEditorData.cs index 7d85841..10414d7 100644 --- a/TNode/TNodeCore/Editor/EditorPersistence/GraphEditorData.cs +++ b/TNode/TNodeCore/Editor/EditorPersistence/GraphEditorData.cs @@ -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,7 +15,8 @@ namespace TNodeCore.Editor.EditorPersistence{ public GraphImplType graphImplType = GraphImplType.GraphViewImpl; public static Func GraphViewImplCreator; public static Func GtfImplCreator; - + [FormerlySerializedAs("testMode")] public bool autoUpdate; + public IDataGraphView GetGraphView () where T:GraphData{ switch (graphImplType){ case GraphImplType.GraphViewImpl:{ diff --git a/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs b/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs index d907b4b..ee45cfc 100644 --- a/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs +++ b/TNode/TNodeCore/Editor/NodeGraphView/IBaseDataGraphView.cs @@ -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(); + } } \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs b/TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs new file mode 100644 index 0000000..b7268ce --- /dev/null +++ b/TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs @@ -0,0 +1,6 @@ +namespace TNodeCore.Runtime.Attributes{ + + public class HideInBlackboard:System.Attribute{ + + } +} \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs.meta b/TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs.meta new file mode 100644 index 0000000..5daa766 --- /dev/null +++ b/TNode/TNodeCore/Runtime/Attributes/HideInBlackboard.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 731893f9f7824b939cee169d61092ad3 +timeCreated: 1659517588 \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attributes/ModelColor.cs b/TNode/TNodeCore/Runtime/Attributes/ModelColor.cs new file mode 100644 index 0000000..ae7106c --- /dev/null +++ b/TNode/TNodeCore/Runtime/Attributes/ModelColor.cs @@ -0,0 +1,5 @@ +namespace TNodeCore.Runtime.Attributes{ + public class ModelColor{ + + } +} \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attributes/ModelColor.cs.meta b/TNode/TNodeCore/Runtime/Attributes/ModelColor.cs.meta new file mode 100644 index 0000000..e0cce46 --- /dev/null +++ b/TNode/TNodeCore/Runtime/Attributes/ModelColor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cdec5767969f4e11bbcfb245693796f9 +timeCreated: 1659521617 \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs index 6b8ba37..676f6db 100644 --- a/TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs +++ b/TNode/TNodeCore/Runtime/Attributes/Ports/InputAttribute.cs @@ -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){ + } } } \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs index b11340d..47eb6c9 100644 --- a/TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs +++ b/TNode/TNodeCore/Runtime/Attributes/Ports/OutputAttribute.cs @@ -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){ + } + + } } \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs b/TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs index b27710e..9146a79 100644 --- a/TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs +++ b/TNode/TNodeCore/Runtime/Attributes/Ports/PortAttribute.cs @@ -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; + } + } } \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/Models/Model.cs b/TNode/TNodeCore/Runtime/Models/Model.cs index 06b99dc..6571aa0 100644 --- a/TNode/TNodeCore/Runtime/Models/Model.cs +++ b/TNode/TNodeCore/Runtime/Models/Model.cs @@ -1,4 +1,5 @@ using System; +using TNodeCore.Runtime.Attributes; using UnityEngine; using UnityEngine.Serialization; @@ -6,6 +7,7 @@ namespace TNodeCore.Runtime.Models{ [Serializable] public abstract class Model:ICloneable{ #if UNITY_EDITOR + [HideInBlackboard] public Rect positionInView; #endif diff --git a/TNode/TNodeCore/Runtime/NodeLogger.cs b/TNode/TNodeCore/Runtime/NodeLogger.cs new file mode 100644 index 0000000..d967e62 --- /dev/null +++ b/TNode/TNodeCore/Runtime/NodeLogger.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using TNodeCore.Runtime.Models; +using UnityEngine; + +namespace TNodeCore.Runtime{ + public static class NodeLogger{ + public static Dictionary 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); + } +} \ No newline at end of file diff --git a/TNode/TNodeCore/Runtime/NodeLogger.cs.meta b/TNode/TNodeCore/Runtime/NodeLogger.cs.meta new file mode 100644 index 0000000..1d16c7b --- /dev/null +++ b/TNode/TNodeCore/Runtime/NodeLogger.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 48be07a2cf064167b15d378ac41757c4 +timeCreated: 1659592209 \ No newline at end of file diff --git a/TNode/TNodeGraphViewImpl/Editor/GraphBlackboard/DefaultGraphBlackboardView.cs b/TNode/TNodeGraphViewImpl/Editor/GraphBlackboard/DefaultGraphBlackboardView.cs index 36bd89c..ac89773 100644 --- a/TNode/TNodeGraphViewImpl/Editor/GraphBlackboard/DefaultGraphBlackboardView.cs +++ b/TNode/TNodeGraphViewImpl/Editor/GraphBlackboard/DefaultGraphBlackboardView.cs @@ -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){ diff --git a/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs b/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs index f54a4c6..66eb4f9 100644 --- a/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs +++ b/TNode/TNodeGraphViewImpl/Editor/Inspector/NodeInspectorInNode.cs @@ -67,7 +67,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.Inspector{ Add(drawer); } - var globalTest = GetFirstAncestorOfType()?.TestMode; + var globalTest = GetFirstAncestorOfType()?.AutoUpdate; if(globalTest??false){ CreateTestButton(); } diff --git a/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs b/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs index e6929fe..8a1459d 100644 --- a/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs +++ b/TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs @@ -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:GraphView,IDataGraphView 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 _nodeDict = new(); private IBlackboardView _blackboard; - private bool _runtimeGraphUpdate; + private bool _loaded; public T Data{ get{ return _data; } set{ @@ -145,25 +149,36 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ } private void BuildRuntimeGraphBehaviour(){ - EditorApplication.update+= UpdateRuntimeGraphBehaviour; + //EditorApplication.update+= UpdateRuntimeGraphBehaviour; + UpdateRuntimeGraphBehaviourInTime(); } - - private void UpdateRuntimeGraphBehaviour(){ - if(_runtimeGraph != null){ - if (_runtimeGraphUpdate){ - _runtimeGraphUpdate = false; - _runtimeGraph.ResolveDependency(); - - AfterRuntimeGraphUpdate?.Invoke(); + + private async void UpdateRuntimeGraphBehaviourInTime(){ + + while (_loaded){ + await Task.Delay(TimeSpan.FromSeconds(RefreshRate)); + if(_runtimeGraph != null){ + if (AutoUpdate){ + _runtimeGraph.ResolveDependency(); + 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){ @@ -199,6 +214,18 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ OnGraphViewCreate(); BuildUndo(); + + _loaded = true; + + SetDetachedFromPanel(); + + + } + + private void SetDetachedFromPanel(){ + this.RegisterCallback(evt => { + _loaded = false; + }); } private void BuildUndo(){ @@ -225,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(evt => { + if (IsRuntimeGraph){ + _runtimeGraph.ResolveDependency(); + AfterGraphResolved?.Invoke(); + } + }); + visualElement.Add(runButton); } public void RegisterDragEvent(){ @@ -536,6 +573,8 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ }); menu.ShowAsContext(); }); + + } } @@ -564,11 +603,14 @@ 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; } @@ -576,7 +618,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ 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); @@ -608,11 +649,9 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{ public void NotifyRuntimeUpdate(){ - _runtimeGraphUpdate = true; } - - - public Action AfterRuntimeGraphUpdate{ get; set; } + + public Action AfterGraphResolved{ get; set; } #endregion } diff --git a/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs b/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs index ca5ddfc..a94b9cf 100644 --- a/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs +++ b/TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs @@ -18,6 +18,27 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{ public abstract class BaseNodeView : Node,INodeView where T:NodeData,new(){ protected T _data; private readonly NodeInspectorInNode _nodeInspectorInNode; + private NodeViewLogger _viewLogger; + + private class NodeViewLogger:INodeLoggerImpl{ + public BaseNodeView NodeView { get; set; } + public void Log(string message){ + var loggerAreaParent = NodeView.extensionContainer; + if (loggerAreaParent == null){ + return; + } + var loggerArea = loggerAreaParent.Q("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 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; + } } }