fix:Node create at correct position

main
taoria 3 years ago
parent c88caec24d
commit 8d6792ae58
  1. 15
      README.md
  2. 2
      TNode/TNodeCore/Runtime/Attributes/GraphUsageAttribute.cs
  3. 8
      TNode/TNodeCore/Runtime/Models/BlackboardData.cs
  4. 7
      TNode/TNodeCore/Runtime/Models/IModel.cs
  5. 17
      TNode/TNodeCore/Runtime/Models/Model.cs
  6. 0
      TNode/TNodeCore/Runtime/Models/Model.cs.meta
  7. 7
      TNode/TNodeCore/Runtime/Models/NodeData.cs
  8. 14
      TNode/TNodeCore/Runtime/RuntimeCache/RuntimeCache.cs
  9. 2
      TNode/TNodeGraphViewImpl/Editor/Cache/NodeEditorExtensions.cs
  10. 64
      TNode/TNodeGraphViewImpl/Editor/NodeGraphView/DataGraphView.cs
  11. 14
      TNode/TNodeGraphViewImpl/Editor/NodeViews/NodeView.cs
  12. 3
      TNode/TNodeGtfImpl/Editor.meta

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

@ -4,7 +4,7 @@ using TNodeCore.Runtime.Models;
namespace TNodeCore.Runtime.Attributes{ namespace TNodeCore.Runtime.Attributes{
/// <summary> /// <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. /// it can be applied to the same node multiple times.
/// <example> /// <example>
/// [GraphUsage(DialogueGraph)] /// [GraphUsage(DialogueGraph)]

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

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

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

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

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

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

@ -98,15 +98,14 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
var res = DragAndDrop.objectReferences; var res = DragAndDrop.objectReferences;
foreach (var obj in res){ foreach (var obj in res){
if (obj is T graphData){ if (obj is T graphData){
Data = graphData;
IsRuntimeGraph = false; IsRuntimeGraph = false;
Data = graphData;
} }
else{ else{
if (obj is GameObject gameObject){ if (obj is GameObject gameObject){
if (gameObject.GetComponent<RuntimeGraph>() != null){ if (gameObject.GetComponent<RuntimeGraph>() != null){
if (gameObject.GetComponent<RuntimeGraph>().graphData != null){ if (gameObject.GetComponent<RuntimeGraph>().graphData != null){
_runtimeGraph = gameObject.GetComponent<RuntimeGraph>(); _runtimeGraph = gameObject.GetComponent<RuntimeGraph>();
IsRuntimeGraph = true; IsRuntimeGraph = true;
BuildRuntimeGraphBehaviour(); BuildRuntimeGraphBehaviour();
@ -114,7 +113,6 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
if(Data==null){ if(Data==null){
Debug.LogError($"Dragged a wrong graph data to editor,expected {typeof(T)} but got {gameObject.GetComponent<RuntimeGraph>().graphData.GetType()}"); Debug.LogError($"Dragged a wrong graph data to editor,expected {typeof(T)} but got {gameObject.GetComponent<RuntimeGraph>().graphData.GetType()}");
} }
} }
} }
} }
@ -341,8 +339,7 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
} }
private void AddPersistentNode(NodeData dataNode){ private void AddPersistentNode(NodeData dataNode){
var nodePos = Owner.graphEditorData.graphElementsData.FirstOrDefault(x => x.guid == dataNode.id)?.pos ?? var nodePos = dataNode.positionInView;
new Rect(0, 0, 200, 200);
AddTNode(dataNode, nodePos); AddTNode(dataNode, nodePos);
} }
//OnDataChanged event //OnDataChanged event
@ -391,21 +388,21 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
} }
public void SaveEditorData(GraphEditorData graphEditorData){ public void SaveEditorData(GraphEditorData graphEditorData){
graphEditorData.graphElementsData?.Clear(); // graphEditorData.graphElementsData?.Clear();
//iterator nodes // //iterator nodes
if (graphEditorData.graphElementsData == null){ // if (graphEditorData.graphElementsData == null){
graphEditorData.graphElementsData = new List<GraphElementEditorData>(); // graphEditorData.graphElementsData = new List<GraphElementEditorData>();
} // }
foreach (var node in this.nodes){ // foreach (var node in this.nodes){
var nodeEditorData = new GraphElementEditorData{ // var nodeEditorData = new GraphElementEditorData{
pos = node.GetPosition(), // pos = node.GetPosition(),
}; // };
if (node is IBaseNodeView nodeView){ // if (node is IBaseNodeView nodeView){
nodeEditorData.guid = nodeView.GetNodeData().id; // nodeEditorData.guid = nodeView.GetNodeData().id;
} // }
graphEditorData.graphElementsData.Add(nodeEditorData); // graphEditorData.graphElementsData.Add(nodeEditorData);
EditorUtility.SetDirty(graphEditorData); // EditorUtility.SetDirty(graphEditorData);
} // }
} }
public void SaveWithEditorData(GraphEditorData graphEditorData){ public void SaveWithEditorData(GraphEditorData graphEditorData){
@ -499,8 +496,15 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
#region implement interfaces #region implement interfaces
public void AddTNode(NodeData nodeData, Rect rect){ public void AddTNode(NodeData nodeData, Rect rect){
if (NodeEditorExtensions.CreateNodeViewFromNodeType(nodeData.GetType()) is Node nodeView){ 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); AddElement(nodeView);
((IBaseNodeView)nodeView).InitializePosition(rect);
//Add a select callback to the nodeView //Add a select callback to the nodeView
nodeView.RegisterCallback<MouseDownEvent>(evt => { nodeView.RegisterCallback<MouseDownEvent>(evt => {
if (evt.clickCount == 1){ if (evt.clickCount == 1){
@ -510,14 +514,17 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
} }
} }
}); });
if(nodeView is IBaseNodeView nodeViewInterface){
nodeViewInterface.SetNodeData(nodeData);
}
_nodeDict.Add(nodeData.id, nodeView); if(_nodeDict.ContainsKey(nodeData.id)==false)
_nodeDict.Add(nodeData.id, nodeView);
if (_data.NodeDictionary.ContainsKey(nodeData.id) == false){ if (_data.NodeDictionary.ContainsKey(nodeData.id) == false){
Undo.RegisterCompleteObjectUndo(_data,"Node Creation"); Undo.RegisterCompleteObjectUndo(_data,"Node Creation");
_data.NodeDictionary.Add(nodeData.id,nodeData); _data.NodeDictionary.Add(nodeData.id,nodeData);
} }
//register an callback ,when right click context menu //register an callback ,when right click context menu
nodeView.RegisterCallback<ContextClickEvent>(evt => { nodeView.RegisterCallback<ContextClickEvent>(evt => {
var menu = new GenericMenu(); var menu = new GenericMenu();
@ -559,6 +566,13 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeGraphView{
public bool TestMode{ get; set; } public bool TestMode{ get; set; }
public override EventPropagation DeleteSelection(){
Undo.RegisterCompleteObjectUndo(_data,"Delete Selection");
var res = base.DeleteSelection();
ResetGraphView();
return res;
}
public void CreateBlackboard(){ public void CreateBlackboard(){
_blackboard = NodeEditorExtensions.CreateBlackboardWithGraphData(typeof(T)); _blackboard = NodeEditorExtensions.CreateBlackboardWithGraphData(typeof(T));
_blackboard.Setup(this,Owner); _blackboard.Setup(this,Owner);

@ -184,6 +184,18 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
Refresh(); 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(){ public void Refresh(){
title = _data.nodeName; title = _data.nodeName;
} }
@ -195,6 +207,8 @@ namespace TNode.TNodeGraphViewImpl.Editor.NodeViews{
public void OnDataModified(); public void OnDataModified();
IBaseDataGraphView BaseDataGraphView{ get; } IBaseDataGraphView BaseDataGraphView{ get; }
public void InitializePosition(Rect pos);
} }
public interface INodeView<T>:IBaseNodeView where T:NodeData,new(){ public interface INodeView<T>:IBaseNodeView where T:NodeData,new(){

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