A solution can be to comment the assignation to fields “this.translation” and “this.zoomFactor “in constructor of the class GraphSerializationData ?
Thank you for your reply.
The solution resolve in part the problem. When the exception is not verified the data of valueinput are restore correctly but the connections are lost.
This video reproduce of issue:
Thank you for your input and confirmation that this is needed. I have added this to the roadmap. It’s a bit harder to implement than I thought perfomance wise, cinsidering the current implementation, but it will happen Thank you.
I would not like to ask a question with a too complex answer but I would like to know the reasons why it could lead to a deterioration in performance.
I ask this question because I’m modifying your framework quite intensively for my use case and I wouldn’t want it to make any mistakes that I shouldn’t be making
I too share the need to have a private git repository so I can fork and be able to contribute and synchronize any new updates to my fork.
Excellent also the idea of being able to trace new requests for features and any issue
I think that you have a conflict. So both plugins have a class Colors. Maybe the plugin Corgi Engine doesn’t have a namespace to Colors class. For fix this you can add a namespace.
Thank you for you advices.
I do your flownode class a partial class and it’s works and more easy extended flownode. So I will gladly when you make it partial officially for the next version 🙂
Furthermore for my use case I have followed your advice for extend my nodo with a custom method OnSceneGUI
1 2 3 4 5 6 7 8 |
public class MyNode: FlowControlNode { public ObservableValueInput<GameObject> subject; ... virtual public void OnSceneGUI () { } ... } |
To do this when the node is selected I add to the reference subject gameobject a support class “ActionsceneGUI”
1 2 3 4 5 6 7 8 9 |
protected override void OnNodePicked () { if(subject.value!=null){ ActionSceneGUI actionGUI = subject.value.GetComponent<ActionSceneGUI> (); if (actionGUI == null) subject.value.AddComponent<ActionSceneGUI> (); } } |
So to ActionSceneGUI I associate a class ActionGUIEditor that extends Editor and invokes the OnsceneGUI method based on the selected node
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[CustomEditor (typeof (ActionSceneGUI))] public class ActionSceneGUIEditor : Editor { void OnSceneGUI () { var t = target as ActionSceneGUI; if (NodeCanvas.Editor.GraphEditorUtility.activeNode != null) { if (NodeCanvas.Editor.GraphEditorUtility.activeNode is MyNode) { var node = NodeCanvas.Editor.GraphEditorUtility.activeNode as MyNode; if (t.gameObject == node.subject.value) { node.OnSceneGUI (); } } } } } |
This avoids me writing a lot of code around. Thanks for you advice 🙂 . I was wondering if you have any more optimal solutions or if it may be enough so
Regarding the advice I asked you about how I could listen to the change in the value of an ValueInput, I extended the ValueInput class this way:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using FlowCanvas; using NodeCanvas.Editor; using NodeCanvas.Framework; using ParadoxNotion.Design; using UnityEditor; using UnityEngine; namespace MyProject.FlowCanvas { public class ObservableValueInput<T> : global::FlowCanvas.ValueInput<T> { public ObservableValueInput() { } public ObservableValueInput(FlowNode parent, string name, string ID) : base(parent, name, ID) { } public event System.Action<T, T> onValueChanged; public override object serializedValue { get { return base.serializedValue; } set { System.Object oldvalue = base.serializedValue; base.serializedValue = value; if (oldvalue != value) { if (onValueChanged != null) { onValueChanged((T)oldvalue, (T)value); } } } } } } |
I also had to extend the FlowControlNode class by adding the AddObservableValueInput method. The problem that to do this I had to modify the class changing the access level of the QualifyPortNameAndID method and the inputPorts variable from private to protected. How can I achieve the same result without modifying your framework? I do not want to have to report my changes to your framework every time when there is a new update
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
using FlowCanvas; using NodeCanvas.Editor; using NodeCanvas.Framework; using ParadoxNotion.Design; using UnityEditor; using UnityEngine; namespace MyProject.FlowCanvas { /// <summary> /// To be able to extend the class correctly, you have changed the visibility levels to the parent class of the source framework: /// inputPorts da private a protected /// QualitiPortNameAndId da private a protected /// /// /// /// </summary> abstract public class FlowControlNode :FlowCanvas.Nodes.FlowControlNode { /// <summary> /// Consente di poter aggiungere al nodo una input port di tipo ObservableValueInput /// in cui ci si può mettere in ascolto quando i suo valore cambia /// </summary> /// <param name="name">porta</param> /// <param name="ID"></param> /// <typeparam name="T"></typeparam> /// <returns></returns> public ObservableValueInput<T> AddObservableValueInput<T>(string name, string ID = "") { QualifyPortNameAndID(ref name, ref ID, inputPorts); return (ObservableValueInput<T>)(inputPorts[ID] = new ObservableValueInput<T>(this, name, ID)); } protected override void OnNodePicked() { GraphEditorUtility.onActiveElementChanged += onActiveElementChanged; } protected abstract void OnNodeUnPicked(); void onActiveElementChanged(IGraphElement node) { if (node != this) { OnNodeUnPicked(); GraphEditorUtility.onActiveElementChanged -= onActiveElementChanged; } } } } |
Thanks, It’s works!
I want that user can editing some variables of node through the tools of support.
So, I have created a node custom “TweenPosition” for create an animation of an object in a determinate position (To). You can look my example here:
If you can look at my code I would like to know if it is the correct way to achieve this goal.Basically what I do that when the node is selected I then transfer the reference of the “to” field of the node to an internal my class that serves to manage the waypoint on the scene.
This class is my custom flownode
Tweenposition.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
using NodeCanvas.Editor; using NodeCanvas.Framework; using ParadoxNotion.Design; using UnityEditor; using UnityEngine; namespace FlowCanvas.Nodes { [Name("Tween Position")] [Category("ActionSwipeStory")] [Description("crea effetto transizione")] public class TweenPosition : FlowControlNode { ValueInput<GameObject> obj; ValueInput<Vector3> to; protected override void RegisterPorts() { obj = AddValueInput<GameObject>("object"); to = AddValueInput<Vector3>("to"); var t = AddValueInput<float>("time"); var start = AddFlowOutput("startEvent"); var end = AddFlowOutput("finishEvent"); AddFlowInput("In", (f) => { Debug.Log("Tween position"); start.Call(f); LeanTween.move(obj.value, to.value, t.value).setOnComplete(() => { end.Call(f); }); }); } protected override void OnNodePicked() { if (obj.value != null) { ConfigurationPlaceholder(); GraphEditorUtility.onActiveElementChanged += onActiveElementChanged; } } void ConfigurationPlaceholder() { Debug.Log("ConfigurationPlaceholder"); if (obj.value != null) { TweenPositionMonoB action = obj.value.GetComponent<TweenPositionMonoB>(); if (action == null) { action = obj.value.AddComponent<TweenPositionMonoB>(); } action.to = to; Selection.activeGameObject = obj.value; } } void OnNodeUnPicked() { Selection.activeGameObject = null; } void onActiveElementChanged(IGraphElement node) { if (node != this) { OnNodeUnPicked(); GraphEditorUtility.onActiveElementChanged -= onActiveElementChanged; } } protected override void OnNodeGUI() { base.OnNodeGUI(); } protected override void OnNodeReleased() { Debug.Log("Nodo rilasciato"); } } } |
This class is useful to create the placeholder waypoint on the object on which the node works
TweenPositionEditor.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; [CustomEditor(typeof(TweenPositionMonoB))] public class TweenPositionEditor : Editor { void OnSceneGUI() { var t = target as TweenPositionMonoB; if (t.to != null) { t.to.serializedValue = Handles.FreeMoveHandle(t.to.value, Quaternion.identity, 0.7f, Vector2.zero, Handles.CylinderHandleCap); Handles.DrawLine(t.transform.localPosition, t.to.value); } } } |
This class does the through to share the variable position of the node “Tweenposition.cs” with the class “TweenPositionEditor.cs “that manage the waypoint drawn the handles on the Scenaview
TweenPositionMonoB.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
using System.Collections; using System.Collections.Generic; using FlowCanvas; using UnityEngine; public class TweenPositionMonoB : MonoBehaviour { public ValueInput<Vector3> to; // Use this for initialization void Start() { } } |
If I may I would ask you another advice. I would like to know when the Serializevalue changes value. I thought I’d extend the class Valueinput<T> and overwrite the serializedvalue set method to launch an event when its value changes from the previous.