From 76e8b7031658d5637c9cbbff703d1189976c67f1 Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Mon, 9 Oct 2017 19:52:41 +0200 Subject: [PATCH 01/10] Initialization performance updates (wip) --- Resources.meta | 9 +++ Resources/NodeDataCache.asset | Bin 0 -> 4184 bytes Resources/NodeDataCache.asset.meta | 9 +++ Scripts/Editor/NodeEditor.cs | 4 +- Scripts/Editor/NodeEditorToolbar.cs | 2 +- Scripts/Node.cs | 47 ++---------- Scripts/NodeDataCache.cs | 113 ++++++++++++++++++++++++++++ Scripts/NodeDataCache.cs.meta | 12 +++ Scripts/NodePort.cs | 12 ++- 9 files changed, 159 insertions(+), 49 deletions(-) create mode 100644 Resources.meta create mode 100644 Resources/NodeDataCache.asset create mode 100644 Resources/NodeDataCache.asset.meta create mode 100644 Scripts/NodeDataCache.cs create mode 100644 Scripts/NodeDataCache.cs.meta diff --git a/Resources.meta b/Resources.meta new file mode 100644 index 0000000..f101f36 --- /dev/null +++ b/Resources.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 65ed9b337b7f0b74ab007799bb407a5e +folderAsset: yes +timeCreated: 1507567488 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Resources/NodeDataCache.asset b/Resources/NodeDataCache.asset new file mode 100644 index 0000000000000000000000000000000000000000..d1187300b7f1e4551ac517d2a4276b409a2423f4 GIT binary patch literal 4184 zcmeH~y=zlZ7{=d|n;Ny&Z>#-K2gQ%&;?+W-Xo!%cN=u0jrHj}|BS~pKNJ5B%awkC? zIuyatMHh($kvh0`=^xOwI15f)N{7bhIrrvrqPx?1;c(9Ro%cNFJax}NJj_vE14?J5OU*DF$eJn-f1s<)Mx-}pGu+V8x4)q3~)$L!wC#J$yp z>+csYA#DncTM|nANf93sUA@~USMtdb|0~wwVIFhI8Qb8;(8tgM9+Mqt3}eoG$KWn> zE@OT;TI@k9rp_UQn>vYzE17^!E7ai`_w`zTJx2^~>Ku)@k`Ji!33OQB zAT=P=^I-;@_u`#<^%rsOukhR#2hd4$|$G|taNJkY-r>YpX|eb(8he~vsw-mlN^iLIKO`sX9A zWE-{Iz?^knK+pJFerB`4wIXvEe*i#Dk2e4S literal 0 HcmV?d00001 diff --git a/Resources/NodeDataCache.asset.meta b/Resources/NodeDataCache.asset.meta new file mode 100644 index 0000000..cd7469f --- /dev/null +++ b/Resources/NodeDataCache.asset.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a6799b9b87b05a14f9053390f4500d7b +timeCreated: 1507567505 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs index 901feb5..1bde7d3 100644 --- a/Scripts/Editor/NodeEditor.cs +++ b/Scripts/Editor/NodeEditor.cs @@ -63,14 +63,14 @@ public class NodeEditor { /// Draw node port GUI using automatic layouting. Returns port handle position. protected Vector2 DrawNodePortGUI(NodePort port) { GUIStyle style = port.direction == NodePort.IO.Input ? NodeEditorResources.styles.inputPort : NodeEditorResources.styles.outputPort; - Rect rect = GUILayoutUtility.GetRect(new GUIContent(port.name.PrettifyCamelCase()), style); + Rect rect = GUILayoutUtility.GetRect(new GUIContent(port.fieldName.PrettifyCamelCase()), style); return DrawNodePortGUI(rect, port); } /// Draw node port GUI in rect. Returns port handle position. protected Vector2 DrawNodePortGUI(Rect rect, NodePort port) { GUIStyle style = port.direction == NodePort.IO.Input ? NodeEditorResources.styles.inputPort : NodeEditorResources.styles.outputPort; - GUI.Label(rect, new GUIContent(port.name.PrettifyCamelCase()), style); + GUI.Label(rect, new GUIContent(port.fieldName.PrettifyCamelCase()), style); Vector2 handlePoint = rect.center; diff --git a/Scripts/Editor/NodeEditorToolbar.cs b/Scripts/Editor/NodeEditorToolbar.cs index eb89b6f..8d7900b 100644 --- a/Scripts/Editor/NodeEditorToolbar.cs +++ b/Scripts/Editor/NodeEditorToolbar.cs @@ -19,7 +19,7 @@ public partial class NodeEditorWindow { if (IsHoveringNode) { GUILayout.Space(20); string hoverInfo = hoveredNode.GetType().ToString(); - if (IsHoveringPort) hoverInfo += " > " + hoveredPort.name; + if (IsHoveringPort) hoverInfo += " > " + hoveredPort.fieldName; GUILayout.Label(hoverInfo); } } diff --git a/Scripts/Node.cs b/Scripts/Node.cs index 49f62d0..ea0d485 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -20,12 +20,13 @@ public abstract class Node : ScriptableObject { public int OutputCount { get { return outputs.Count; } } protected Node() { - CachePorts(); //Cache the ports at creation time so we don't have to use reflection at runtime + + GetPorts(); //Cache the ports at creation time so we don't have to use reflection at runtime } protected void OnEnable() { VerifyConnections(); - CachePorts(); + GetPorts(); Init(); } @@ -117,45 +118,7 @@ public abstract class Node : ScriptableObject { } } - /// Use reflection to find all fields with or , and write to and - private void CachePorts() { - List inputPorts = new List(); - List outputPorts = new List(); - - System.Reflection.FieldInfo[] fieldInfo = GetType().GetFields(); - for (int i = 0; i < fieldInfo.Length; i++) { - - //Get InputAttribute and OutputAttribute - object[] attribs = fieldInfo[i].GetCustomAttributes(false); - InputAttribute inputAttrib = null; - OutputAttribute outputAttrib = null; - for (int k = 0; k < attribs.Length; k++) { - if (attribs[k] is InputAttribute) inputAttrib = attribs[k] as InputAttribute; - else if (attribs[k] is OutputAttribute) outputAttrib = attribs[k] as OutputAttribute; - } - - if (inputAttrib != null && outputAttrib != null) Debug.LogError("Field " + fieldInfo + " cannot be both input and output."); - else if (inputAttrib != null) inputPorts.Add(new NodePort(fieldInfo[i], this)); - else if (outputAttrib != null) outputPorts.Add(new NodePort(fieldInfo[i], this)); - } - - //Remove - for (int i = inputs.Count-1; i >= 0; i--) { - //If input nodeport does not exist, remove it - if (!inputPorts.Any(x => inputs[i].fieldName == x.fieldName)) inputs.RemoveAt(i); - } - for (int i = outputs.Count - 1; i >= 0; i--) { - //If output nodeport does not exist, remove it - if (!outputPorts.Any(x => outputs[i].fieldName == x.fieldName)) outputs.RemoveAt(i); - } - //Add - for (int i = 0; i < inputPorts.Count; i++) { - //If inputports contains a new port, add it - if (!inputs.Any(x => x.fieldName == inputPorts[i].fieldName)) inputs.Add(inputPorts[i]); - } - for (int i = 0; i < outputPorts.Count; i++) { - //If inputports contains a new port, add it - if (!outputs.Any(x => x.fieldName == outputPorts[i].fieldName)) outputs.Add(outputPorts[i]); - } + private void GetPorts() { + NodeDataCache.GetPorts(this, out inputs, out outputs); } } diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs new file mode 100644 index 0000000..8608d21 --- /dev/null +++ b/Scripts/NodeDataCache.cs @@ -0,0 +1,113 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System.Reflection; +using System.Linq; + +/// Precaches reflection data in editor so we won't have to do it runtime +public sealed class NodeDataCache : ScriptableObject { + public static NodeDataCache instance { get { return _instance; } } + private static NodeDataCache _instance; + + [SerializeField] + private PortDataCache portDataCache = new PortDataCache(); + + [RuntimeInitializeOnLoadMethod] + private static void InitializeInstance() { + Debug.Log("INIT"); + NodeDataCache[] ndc = Resources.FindObjectsOfTypeAll(); + if (ndc == null || ndc.Length == 0) { + Debug.LogWarning("No NodeDataCache found. Creating."); + _instance = ScriptableObject.CreateInstance(); + _instance.BuildCache(); + } + else if (ndc.Length > 1) { + Debug.LogWarning("Multiple NodeDataCaches found."); + } + _instance = ndc[0]; + } + + /// Return port data from cache + public static void GetPorts(Node node, out List inputs, out List outputs) { + if (_instance == null) InitializeInstance(); + + System.Type nodeType = node.GetType(); + inputs = new List(); + outputs = new List(); + if (!_instance.portDataCache.ContainsKey(nodeType)) return; + for (int i = 0; i < _instance.portDataCache[nodeType].Count; i++) { + if (_instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); + else outputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); + } + } + +#if UNITY_EDITOR + [UnityEditor.InitializeOnLoadMethod] +#endif + private static void Init() { + instance.BuildCache(); + } + + private void BuildCache() { + System.Type baseType = typeof(Node); + Assembly assembly = Assembly.GetAssembly(baseType); + System.Type[] nodeTypes = assembly.GetTypes().Where(t => + !t.IsAbstract && + baseType.IsAssignableFrom(t) + ).ToArray(); + portDataCache.Clear(); + + for (int i = 0; i < nodeTypes.Length; i++) { + CachePorts(nodeTypes[i]); + } + } + + private void CachePorts(System.Type nodeType) { + List inputPorts = new List(); + List outputPorts = new List(); + + System.Reflection.FieldInfo[] fieldInfo = nodeType.GetFields(); + for (int i = 0; i < fieldInfo.Length; i++) { + + //Get InputAttribute and OutputAttribute + object[] attribs = fieldInfo[i].GetCustomAttributes(false); + Node.InputAttribute inputAttrib = attribs.FirstOrDefault(x => x is Node.InputAttribute) as Node.InputAttribute; + Node.OutputAttribute outputAttrib = attribs.FirstOrDefault(x => x is Node.OutputAttribute) as Node.OutputAttribute; + + if (inputAttrib == null && outputAttrib == null) continue; + + if (inputAttrib != null && outputAttrib != null) Debug.LogError("Field " + fieldInfo + " cannot be both input and output."); + else { + if (!portDataCache.ContainsKey(nodeType)) portDataCache.Add(nodeType, new List()); + portDataCache[nodeType].Add(new NodePort(fieldInfo[i])); + } + } + } + + [System.Serializable] + private class PortDataCache : Dictionary>, ISerializationCallbackReceiver { + [SerializeField] private List keys = new List(); + [SerializeField] private List> values = new List>(); + + // save the dictionary to lists + public void OnBeforeSerialize() { + keys.Clear(); + values.Clear(); + foreach (var pair in this) { + keys.Add(pair.Key); + values.Add(pair.Value); + } + } + + // load dictionary from lists + public void OnAfterDeserialize() { + this.Clear(); + + if (keys.Count != values.Count) + throw new System.Exception(string.Format("there are {0} keys and {1} values after deserialization. Make sure that both key and value types are serializable.")); + + for (int i = 0; i < keys.Count; i++) + this.Add(keys[i], values[i]); + } + } +} diff --git a/Scripts/NodeDataCache.cs.meta b/Scripts/NodeDataCache.cs.meta new file mode 100644 index 0000000..34482f2 --- /dev/null +++ b/Scripts/NodeDataCache.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 64ea6af1e195d024d8df0ead1921e517 +timeCreated: 1507566823 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index dfef17c..54e55d9 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -19,7 +19,6 @@ public class NodePort { public bool IsOutput { get { return direction == IO.Output; } } public Node node { get; private set; } - [SerializeField] public string name; public bool enabled { get { return _enabled; } set { _enabled = value; } } public string fieldName { get { return _fieldName; } } @@ -30,11 +29,9 @@ public class NodePort { [SerializeField] private bool _enabled = true; [SerializeField] private IO _direction; - public NodePort(FieldInfo fieldInfo, Node node) { + public NodePort(FieldInfo fieldInfo) { _fieldName = fieldInfo.Name; - name = _fieldName; type = fieldInfo.FieldType; - this.node = node; var attribs = fieldInfo.GetCustomAttributes(false); for (int i = 0; i < attribs.Length; i++) { @@ -43,6 +40,13 @@ public class NodePort { } } + public NodePort(NodePort nodePort, Node node) { + _fieldName = nodePort._fieldName; + type = nodePort.type; + this.node = node; + _direction = nodePort.direction; + } + /// Checks all connections for invalid references, and removes them. public void VerifyConnections() { for (int i = 0; i < connections.Count; i++) { From d52ecf193125ce4414765d450c7e5dfa14536e20 Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Tue, 10 Oct 2017 00:30:24 +0200 Subject: [PATCH 02/10] Fixed compile errors. Still doesn't initialize correctly, nor saves connections --- Example/ExampleNodeGraph.asset | Bin 5896 -> 1414 bytes Resources/NodeDataCache.asset | Bin 4184 -> 378 bytes Scripts/Node.cs | 9 +-------- Scripts/NodeDataCache.cs | 30 +++++++++++++++++++----------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Example/ExampleNodeGraph.asset b/Example/ExampleNodeGraph.asset index 16e79ec98ced5388a7423c64462f39ff59a7313d..b15bf9c1269b8a3dae42a82000de438cbb4e8f23 100644 GIT binary patch literal 1414 zcmds%-*1~R5Xay1SGW(|Q-b^pgL&)LEQ_>sl~z@%rl~UVk$572jOm(9{oi-M!_qX< zracxUgni#T&iA?F{O)4)k+6tO&TlRj+M3tRKx>dt2qLU#9`@^7#XADo5vrP;I@p~LpIhr;C7#zPfGNk)Dau7u?! zN}dih%PN4cO!?BjFgy5@@4Pa32{t2a2sO7Z)c!>lpV!_s;UF?&@on!QjS^a? zTmfH8nM;}Ef*S#rDkT+Dd`iN;fsBYT<15T4BlAbIYf8APEiAlgwg(x!D^1%jEgsqx z4tz$?R-vx#i#7XQ0jy|}q+G;!V+L5?{sYeiT*q1qs<@y`iuCCi$&vl_!QmWe4BW6H zHa1Z*PGf3g&KbvgD6UV!S()%RARZgG=Rrsd-kH+<0DB9*b#;{yJ{TS|G82MEEM?=y z9yb_GBgT|YTPY}ld$&P5+<3vRQ;UK`i0YPx{a@Z~ES>nqD;7LKT{_f?5*`CV8G{o+MyIA$iQwlgKY!+mvR1YswC= ns=NE~Z*XcB{|!B(G~y!FBj*9V;F0379-HBR$v^ZN_K<%8Mgy8a literal 5896 zcmeI0U2IfE6vxkPw_QGzRxK1o5n3$ZM_~&H0xetmL4neiY8nzlVCi1mZMM6c?Y6cU zV11CJ@qt7^WICdk*nZ$;aULIygeY9qKhr(jYiEYbEja-{cft<+o=F=p*um0f_cBs z&U-gF#X>~9{?AfObML$*F1Mrw^S%!|jDIP4Mvb=uh$odCYc5uhyinPnhkNMHz2r&@ zWjn_9K-s^~<=Xy=to<_bOoo0M_Ggm^$xZuQPu!}w*M7OnEx8I`mY`2R=i*A4YX5$X z|7QOI53fd>{xin&T<$aC`5?G{UY~g5`B0X3bfi=3o5Im_BGojQw&Q)#M7&OVcQr?2 z_U1-3Izs6P8u3Kf?h`e7Q5)KIdgEB~Y5U->nenry>h{k)aN(UR&n}N%x65w+ITrXS zyrE_FmEor`(WUHU`HjQH$Zwo~vvCR#w;MP>xN*4YJsU?(ViP<8=7UadoC3v{W%=aB z(HsYb8b7&lG{?cNI5!T3>s5#ACMY*7HxBkUsCgjFce!~W@F1t~pr9RYSlU@Ym?8J6 z1Fa2R@`WxhG7g*yaDAW^8wXk?xzb|eKwIQ;pKuTEfztjXxaxUL`&BMC?Jp*WSW>L) zIR0}Tv>m_1(cA~+L9`S~vGDpD#|Y;I_o!l;dk><=T<%wKIEX&|d>mJ8f0_{ouCtEA zbR!Nt40Rl)8*$+JYp&xwj6Urz$2C_Rm>0R?TtlwZjPnYY`_v2ZNVdNcSH4-fzKp{g z==z|m$RSQ%y^A*ed6FS< z6^?RVT1oV$)eIq=d?~xHKbDqWlrql@C2d{06v&a*y0YU-d{x`Oe(z}gnwd8{Yk%2s z`9^xnm%sn`!o;D|A2USfp7rBR1dfz^&2JvX|5WqmOBdu$kojXCeU;h0MehBr zw8-V=D<)sMRtHXP$ThBFK zs9Za~yLnEPp1)$&w{PDV+28z9(aws6_1&*%I-Gc`wB*dH`q5*l@7A_=zNo31<4!;5 zAI0luDf&%=q26T7X2G{96-q`phR;NCo|SDU7Hr>+IP=k#^Zcw&x1qS>{WawyW8bX1 z{+UQigI4Vu{}|2Ify!5ob^ItoTQ8d6Rb-CieAiA%aK^Pt{v^6%ar|Y79e?>dxiQ+8 mjD?1}RIZ@kweRzd>reQ`9KU&=*DuG86EClyxyIpkC4T|So1(b@ diff --git a/Resources/NodeDataCache.asset b/Resources/NodeDataCache.asset index d1187300b7f1e4551ac517d2a4276b409a2423f4..dbef4f74edacf1f52e1b76229623be5638bcba0d 100644 GIT binary patch literal 378 zcmZ`#O;5ux488YPc!zQ7rlu`{PFzO5}j7=l*nmenlO$S6TxIMIirlFaN}Eau3%%dd7uM+ zE7MsK05qSw{EG_rq$EAoShWJ8e!RC-V!lU9+Fd9Deo9qSw)B+W0VmUrtj78pUt>f6 zX;&Kanxp{MuUbjvjJ#-K2gQ%&;?+W-Xo!%cN=u0jrHj}|BS~pKNJ5B%awkC? zIuyatMHh($kvh0`=^xOwI15f)N{7bhIrrvrqPx?1;c(9Ro%cNFJax}NJj_vE14?J5OU*DF$eJn-f1s<)Mx-}pGu+V8x4)q3~)$L!wC#J$yp z>+csYA#DncTM|nANf93sUA@~USMtdb|0~wwVIFhI8Qb8;(8tgM9+Mqt3}eoG$KWn> zE@OT;TI@k9rp_UQn>vYzE17^!E7ai`_w`zTJx2^~>Ku)@k`Ji!33OQB zAT=P=^I-;@_u`#<^%rsOukhR#2hd4$|$G|taNJkY-r>YpX|eb(8he~vsw-mlN^iLIKO`sX9A zWE-{Iz?^knK+pJFerB`4wIXvEe*i#Dk2e4S diff --git a/Scripts/Node.cs b/Scripts/Node.cs index ea0d485..2f5dbf0 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -19,18 +19,11 @@ public abstract class Node : ScriptableObject { public int InputCount { get { return inputs.Count; } } public int OutputCount { get { return outputs.Count; } } - protected Node() { - - GetPorts(); //Cache the ports at creation time so we don't have to use reflection at runtime - } - protected void OnEnable() { - VerifyConnections(); GetPorts(); Init(); } - /// Checks all connections for invalid references, and removes them. public void VerifyConnections() { for (int i = 0; i < InputCount; i++) { @@ -119,6 +112,6 @@ public abstract class Node : ScriptableObject { } private void GetPorts() { - NodeDataCache.GetPorts(this, out inputs, out outputs); + NodeDataCache.GetPorts(this, ref inputs, ref outputs); } } diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index 8608d21..d5e0e7e 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -6,35 +6,43 @@ using System.Linq; /// Precaches reflection data in editor so we won't have to do it runtime public sealed class NodeDataCache : ScriptableObject { - public static NodeDataCache instance { get { return _instance; } } + public static NodeDataCache instance { get { + if (!_instance) + _instance = GetInstance(); + return _instance; + } } private static NodeDataCache _instance; - [SerializeField] + [SerializeField] private PortDataCache portDataCache = new PortDataCache(); - [RuntimeInitializeOnLoadMethod] - private static void InitializeInstance() { - Debug.Log("INIT"); + private static NodeDataCache GetInstance() { NodeDataCache[] ndc = Resources.FindObjectsOfTypeAll(); if (ndc == null || ndc.Length == 0) { Debug.LogWarning("No NodeDataCache found. Creating."); - _instance = ScriptableObject.CreateInstance(); - _instance.BuildCache(); + NodeDataCache n = ScriptableObject.CreateInstance(); + n.BuildCache(); + return n; } else if (ndc.Length > 1) { Debug.LogWarning("Multiple NodeDataCaches found."); } - _instance = ndc[0]; + return ndc[0]; } + private void OnEnable() { + _instance = this; + } + + /// Return port data from cache - public static void GetPorts(Node node, out List inputs, out List outputs) { - if (_instance == null) InitializeInstance(); + public static void GetPorts(Node node, ref List inputs, ref List outputs) { + //if (_instance == null) Resources.FindObjectsOfTypeAll()[0]; System.Type nodeType = node.GetType(); inputs = new List(); outputs = new List(); - if (!_instance.portDataCache.ContainsKey(nodeType)) return; + if (!instance.portDataCache.ContainsKey(nodeType)) return; for (int i = 0; i < _instance.portDataCache[nodeType].Count; i++) { if (_instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); else outputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); From 984364f08f946c8e04377b503fe0b1959e17731e Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Tue, 10 Oct 2017 23:53:27 +0200 Subject: [PATCH 03/10] Still haven't found a solution to initializing a static scriptableObject instance --- Example/ExampleNodeGraph.asset | 34 +++++-------------------- Scripts/NodeDataCache.cs | 45 +++++++++++----------------------- 2 files changed, 20 insertions(+), 59 deletions(-) diff --git a/Example/ExampleNodeGraph.asset b/Example/ExampleNodeGraph.asset index b15bf9c..c624f53 100644 --- a/Example/ExampleNodeGraph.asset +++ b/Example/ExampleNodeGraph.asset @@ -11,10 +11,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a6399826e2c44b447b32a3ed06646162, type: 3} m_Name: ExampleNodeGraph m_EditorClassIdentifier: - nodes: - - {fileID: 114778235353399140} - - {fileID: 114295993062301438} ---- !u!114 &114295993062301438 + nodes: [] +--- !u!114 &114063446055957998 MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} @@ -27,33 +25,13 @@ MonoBehaviour: m_EditorClassIdentifier: rect: serializedVersion: 2 - x: -330.1812 - y: -108.116974 + x: 0 + y: 0 width: 200 height: 200 inputs: [] outputs: [] - a: 2.01 - b: 0.01 + a: 0 + b: 0 result: 0 mathType: 0 ---- !u!114 &114778235353399140 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 98f6f901f0da53142b79277ea3f42518, type: 3} - m_Name: DisplayValue - m_EditorClassIdentifier: - rect: - serializedVersion: 2 - x: 100.23894 - y: -132.62592 - width: 200 - height: 200 - inputs: [] - outputs: [] - value: 0 diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index d5e0e7e..61aa3db 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -3,38 +3,20 @@ using System.Collections.Generic; using UnityEngine; using System.Reflection; using System.Linq; +using UnityEditor; /// Precaches reflection data in editor so we won't have to do it runtime public sealed class NodeDataCache : ScriptableObject { - public static NodeDataCache instance { get { - if (!_instance) - _instance = GetInstance(); - return _instance; - } } - private static NodeDataCache _instance; + public static NodeDataCache instance { + get { + if (_instance == null) _instance = Resources.FindObjectsOfTypeAll().FirstOrDefault(); + return _instance; + } + } + public static NodeDataCache _instance; [SerializeField] private PortDataCache portDataCache = new PortDataCache(); - - private static NodeDataCache GetInstance() { - NodeDataCache[] ndc = Resources.FindObjectsOfTypeAll(); - if (ndc == null || ndc.Length == 0) { - Debug.LogWarning("No NodeDataCache found. Creating."); - NodeDataCache n = ScriptableObject.CreateInstance(); - n.BuildCache(); - return n; - } - else if (ndc.Length > 1) { - Debug.LogWarning("Multiple NodeDataCaches found."); - } - return ndc[0]; - } - - private void OnEnable() { - _instance = this; - } - - /// Return port data from cache public static void GetPorts(Node node, ref List inputs, ref List outputs) { //if (_instance == null) Resources.FindObjectsOfTypeAll()[0]; @@ -43,16 +25,17 @@ public sealed class NodeDataCache : ScriptableObject { inputs = new List(); outputs = new List(); if (!instance.portDataCache.ContainsKey(nodeType)) return; - for (int i = 0; i < _instance.portDataCache[nodeType].Count; i++) { - if (_instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); - else outputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); + for (int i = 0; i < instance.portDataCache[nodeType].Count; i++) { + if (instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); + else outputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); } } - + #if UNITY_EDITOR - [UnityEditor.InitializeOnLoadMethod] + [UnityEditor.InitializeOnLoadMethod( )] #endif private static void Init() { + Debug.Log("Init"); instance.BuildCache(); } From 963eb84edb3f6bbbb5430afc8bc1c20be03a421e Mon Sep 17 00:00:00 2001 From: Thor Date: Wed, 11 Oct 2017 08:36:36 +0200 Subject: [PATCH 04/10] Possible solution found. NodeGraph now initializes NodeDataCache before creating any nodes. --- Resources/New Node Data Cache.asset | Bin 0 -> 4184 bytes ...et.meta => New Node Data Cache.asset.meta} | 6 ++-- Resources/NodeDataCache.asset | 14 ---------- Scripts/NodeDataCache.cs | 26 +++++++++++------- Scripts/NodeGraph.cs | 4 +-- 5 files changed, 21 insertions(+), 29 deletions(-) create mode 100644 Resources/New Node Data Cache.asset rename Resources/{NodeDataCache.asset.meta => New Node Data Cache.asset.meta} (61%) delete mode 100644 Resources/NodeDataCache.asset diff --git a/Resources/New Node Data Cache.asset b/Resources/New Node Data Cache.asset new file mode 100644 index 0000000000000000000000000000000000000000..98c7f5f59a4d35c557ef7fbc609f1d162e555f8d GIT binary patch literal 4184 zcmeH~PiqrF7{;H;*49>2wQ98pHmA~4AXF=&NYtdX6hge|K_%GLL~5gP@y~59?M=`x zAfAFCR`BEpXg@#?h0=re;Hh{JJa~%nd3HC;sCz|<(mTiR1@cg!xY86 zNdFwysGc$LsCl@>+{bL1pGKi63H7fKvdYeAiZYO@uTYC-L0?Lpng)4rL` zQT+2cQ3UkkE8_D4d#}HwbIh%`C(qx>-gwj5+kH27@0or;7tR6afOEh(;2dxcI0u{q l&H?9ubKrnGp!bnNeeaE=_h7|;nX5FH{G1+Kx%kDUy#I7mhHd}= literal 0 HcmV?d00001 diff --git a/Resources/NodeDataCache.asset.meta b/Resources/New Node Data Cache.asset.meta similarity index 61% rename from Resources/NodeDataCache.asset.meta rename to Resources/New Node Data Cache.asset.meta index cd7469f..830cf51 100644 --- a/Resources/NodeDataCache.asset.meta +++ b/Resources/New Node Data Cache.asset.meta @@ -1,7 +1,7 @@ fileFormatVersion: 2 -guid: a6799b9b87b05a14f9053390f4500d7b -timeCreated: 1507567505 -licenseType: Free +guid: a05ee176e92214f48a94c321dad1614d +timeCreated: 1507703437 +licenseType: Pro NativeFormatImporter: mainObjectFileID: 11400000 userData: diff --git a/Resources/NodeDataCache.asset b/Resources/NodeDataCache.asset deleted file mode 100644 index dbef4f7..0000000 --- a/Resources/NodeDataCache.asset +++ /dev/null @@ -1,14 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a6399826e2c44b447b32a3ed06646162, type: 3} - m_Name: NodeDataCache - m_EditorClassIdentifier: - nodes: [] diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index 61aa3db..aa02cd1 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -14,30 +14,36 @@ public sealed class NodeDataCache : ScriptableObject { } } public static NodeDataCache _instance; + public static bool Initialized { get { return _instance != null; } } [SerializeField] private PortDataCache portDataCache = new PortDataCache(); + /// Return port data from cache public static void GetPorts(Node node, ref List inputs, ref List outputs) { - //if (_instance == null) Resources.FindObjectsOfTypeAll()[0]; + if (!Initialized) Initialize(); System.Type nodeType = node.GetType(); inputs = new List(); outputs = new List(); - if (!instance.portDataCache.ContainsKey(nodeType)) return; - for (int i = 0; i < instance.portDataCache[nodeType].Count; i++) { - if (instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); - else outputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); + if (!_instance.portDataCache.ContainsKey(nodeType)) return; + for (int i = 0; i < _instance.portDataCache[nodeType].Count; i++) { + if (_instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); + else outputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); } } - + + public static void Initialize() { + _instance = Resources.LoadAll("").FirstOrDefault(); + } + #if UNITY_EDITOR - [UnityEditor.InitializeOnLoadMethod( )] -#endif - private static void Init() { - Debug.Log("Init"); + [UnityEditor.Callbacks.DidReloadScripts] + private static void Reload() { + Initialize(); instance.BuildCache(); } +#endif private void BuildCache() { System.Type baseType = typeof(Node); diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index 58baa23..878a6f0 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -1,5 +1,4 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using UnityEngine; using System; @@ -16,6 +15,7 @@ public abstract class NodeGraph : ScriptableObject, ISerializationCallbackReceiv } public virtual Node AddNode(Type type) { + if (!NodeDataCache.Initialized) NodeDataCache.Initialize(); Node node = ScriptableObject.CreateInstance(type) as Node; #if UNITY_EDITOR if (!Application.isPlaying) { From d608eaab9a5a24848dc6b26e88f7582c266e2811 Mon Sep 17 00:00:00 2001 From: Thor Date: Wed, 11 Oct 2017 09:03:20 +0200 Subject: [PATCH 05/10] NodeDataCache initialization now works correctly Still needs work on GetPorts, keep connections, disconnect invalid, etc. --- Example/ExampleNodeGraph.asset | Bin 856 -> 5424 bytes Example/ExampleNodeGraph.asset.meta | 6 ++-- Scripts/NodeDataCache.cs | 52 ++++++++++++---------------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/Example/ExampleNodeGraph.asset b/Example/ExampleNodeGraph.asset index c624f534de48bb18e310d624abb24f20ac39f9ae..2871ba7b5313da89a7d7aabe05d1ed1d8c8b822b 100644 GIT binary patch literal 5424 zcmeI0Uu+ab9LIm#UVE)5v=%CYApK(j!D^*NtWf(Ou(cFo2+=g<+HTv!>)qvgt*uGP znt-v1-QdGJ9|UX0Jgx2lQ8#KZ?eg2V^w_dBz@-KiuXZzlIk=62?@ zv)`Hh{dVRztw_<7$co2Aq)?>jJg!nxxwW#Yze@g|pP#p~0aBzQiG4ZeUZ1M^F1&yC zboJ<8GZTkLr~mk}{l>=dj;RCdj~`r%KD8(oO4t(T2@wYp^Jt<*Zpp{l;#|PJ5D@$6 z!e5aq;CJJig`#Bj z&Zw)yF&fl8b3XY29@M$Z=a!tnJiDO7`7NOaggigAf%Coi&ffe7G4Ai~xc7k5EO;b1 z|D}p)9vpX>&n?-7anC@9{x2YRRDY`q{$wFXz{RR3&sO@Y@eJp4FS#n&vKM_1p|D-# zbFII{)n88TIGm@Uzkn$Sj;YSvXnn+f{5JTsU0xfrTR{u?QXk;{sn;I9ZB6>hgt!qj{Cf7Z#4@ z*w~d07Y>c_s>5|B3KuLF4%RoQxgo6exw#>5Bd2krpbi%-b=DC&RGX&)W2JS;#+kI}veFsGx)!&FazwMjF z{b_Pl%(&P4+>ARy;_91zXk`C-YMFj$B3H$Xd$Z5YxVM1cEbgu3Fvk5PW^e}e5DM2l z?RFDo%I;0en2gIy(Z2Mc4BF9w!L%@Cb|zA3iN=#7X(UqAn-cLjIwRpquU|EDEVHik zN9|Z&M`XyB?m*R!M|xs*pLF*{IV4pQBWWc*8i|eAIzMO0r9ESRI&*#9WcN2Etm_V7q7EkpP#{kid^E!lX5`fGH8wxoMKF9U^NESSJf$wr-&Q8Vdh6#pikNr*S$=Gq28j!MYrJbF!zh{qyFFWwmn$TZ=2$L1Z%VLBX<_ znuZJSq<*X2v+os6OPBuo;nmXGkB16fT&9m0d zR3tgbK71#d_pYpazF_@!%o~qd-uv@UspjZ#G8P%%uZ~+v==nx*+P=ld*TmvImxFuy wOs40oy57N$r$^U$^WdlZEP}7(zMjO`N5ApLC-a`+{{`J|MKO=7=iHxv01o6p1ONa4 literal 856 zcmdr~!D<^Z5WVkLj1TF_4lAuB+q$K#;}~K$5ECdNlv!)+Rat8nt+tI@`tOl<2^gHv zdvuUAdNaeDr+4xFYIzInk|h`Gt2qqX0R-IX*4c2#%;l!q4|&R%PDZ2A5oJukr?{oZ zl`Jb)eWn6`*{bzA0oecemj9$pxUq(=OWZXY((d`r(-!kP^yEUHqT%n>mbCa9Q~sUg zELO{WvCh;M|* zg&5}<$Bay>lu%6ZA%sIs8nT}8Dl*bAd&YfT(yB5v_gEJv48D}uGz$}lwp&YHL&RLn zi@H2MooT8vAyg{mRE{HykEbr@luF{rwi3-)2|1Cek(@KmM5g%kO?8(T{->yqjyt*! zpdoLuw13DvkZ)||H1H01?u`g=c)k3#CKM5lHa=DsWOqfhMju;Ox1s+efT|5A5%vx8 T{_xbaWi0Dl9+|E?d!)$=0yzCE diff --git a/Example/ExampleNodeGraph.asset.meta b/Example/ExampleNodeGraph.asset.meta index 723ec56..04eb901 100644 --- a/Example/ExampleNodeGraph.asset.meta +++ b/Example/ExampleNodeGraph.asset.meta @@ -1,7 +1,7 @@ fileFormatVersion: 2 -guid: 5398d565241ec2d489f41c368ca6cf24 -timeCreated: 1507498811 -licenseType: Free +guid: b21c76861277d8445a55b4691205fd00 +timeCreated: 1507704049 +licenseType: Pro NativeFormatImporter: mainObjectFileID: 11400000 userData: diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index aa02cd1..681eaa2 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -7,52 +7,46 @@ using UnityEditor; /// Precaches reflection data in editor so we won't have to do it runtime public sealed class NodeDataCache : ScriptableObject { - public static NodeDataCache instance { - get { - if (_instance == null) _instance = Resources.FindObjectsOfTypeAll().FirstOrDefault(); - return _instance; + public static NodeDataCache instance { get; private set;} + public static bool Initialized { get { return instance != null; } } + + [SerializeField] private PortDataCache portDataCache; + +#if UNITY_EDITOR + [UnityEditor.Callbacks.DidReloadScripts] +#endif + public static void Initialize() { + if (!Initialized) { + instance = Resources.LoadAll("").FirstOrDefault(); +#if UNITY_EDITOR + instance.BuildCache(); +#endif } } - public static NodeDataCache _instance; - public static bool Initialized { get { return _instance != null; } } - - [SerializeField] - private PortDataCache portDataCache = new PortDataCache(); /// Return port data from cache public static void GetPorts(Node node, ref List inputs, ref List outputs) { - if (!Initialized) Initialize(); + Initialize(); System.Type nodeType = node.GetType(); inputs = new List(); outputs = new List(); - if (!_instance.portDataCache.ContainsKey(nodeType)) return; - for (int i = 0; i < _instance.portDataCache[nodeType].Count; i++) { - if (_instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); - else outputs.Add(new NodePort(_instance.portDataCache[nodeType][i], node)); - } - } - - public static void Initialize() { - _instance = Resources.LoadAll("").FirstOrDefault(); + if (!instance.portDataCache.ContainsKey(nodeType)) return; + for (int i = 0; i < instance.portDataCache[nodeType].Count; i++) { + if (instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); + else outputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); + } } #if UNITY_EDITOR - [UnityEditor.Callbacks.DidReloadScripts] - private static void Reload() { - Initialize(); - instance.BuildCache(); - } -#endif - private void BuildCache() { + portDataCache = new PortDataCache(); System.Type baseType = typeof(Node); Assembly assembly = Assembly.GetAssembly(baseType); System.Type[] nodeTypes = assembly.GetTypes().Where(t => !t.IsAbstract && baseType.IsAssignableFrom(t) ).ToArray(); - portDataCache.Clear(); for (int i = 0; i < nodeTypes.Length; i++) { CachePorts(nodeTypes[i]); @@ -60,9 +54,6 @@ public sealed class NodeDataCache : ScriptableObject { } private void CachePorts(System.Type nodeType) { - List inputPorts = new List(); - List outputPorts = new List(); - System.Reflection.FieldInfo[] fieldInfo = nodeType.GetFields(); for (int i = 0; i < fieldInfo.Length; i++) { @@ -80,6 +71,7 @@ public sealed class NodeDataCache : ScriptableObject { } } } +#endif [System.Serializable] private class PortDataCache : Dictionary>, ISerializationCallbackReceiver { From 8ce0d63903c16a0b4904c0473585f4973f120b2e Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Thu, 12 Oct 2017 00:18:40 +0200 Subject: [PATCH 06/10] NodeDataCache changed from ScriptableObject to static class. Nodes still don't load properly, but we're getting there. --- Example/ExampleNodeGraph.asset | Bin 5424 -> 1617 bytes Example/ExampleNodeGraph.asset.meta | 6 +- Resources.meta | 9 --- Resources/New Node Data Cache.asset | Bin 4184 -> 0 bytes Resources/New Node Data Cache.asset.meta | 9 --- Scripts/Editor/NodeEditorUtilities.cs | 1 + Scripts/Node.cs | 2 +- Scripts/NodeDataCache.cs | 75 +++++++++++++---------- Scripts/NodeGraph.cs | 1 - Scripts/NodePort.cs | 6 +- 10 files changed, 51 insertions(+), 58 deletions(-) delete mode 100644 Resources.meta delete mode 100644 Resources/New Node Data Cache.asset delete mode 100644 Resources/New Node Data Cache.asset.meta diff --git a/Example/ExampleNodeGraph.asset b/Example/ExampleNodeGraph.asset index 2871ba7b5313da89a7d7aabe05d1ed1d8c8b822b..f2238520e17d218064f6942207a10fa8c192f0bb 100644 GIT binary patch literal 1617 zcmds%%Wm5+5JmU?ipe5fSpi8=)MJ-6u4|x412hOw6oo;VBb$XR2^5vaE%NUrr4&)@ z6!AJ*=*1!DlK0GPn~{PKrEJ@Ua+}tL zMw5XXt6W^`4=Z>&0e7NQq=cj_O(+j(!hM400g*Ez;Yr8@VMHVk`B3el>zGq z?j2yECmLXvf#_d;X=OJqz}18Qzd^m;IL3x=T{WG3bbIL#DAmBs-J>3WRb5psu}jj2 zdDlH5&miRo-up}dqXiANU1@s-OQro*df8r6-Pv9QeE;FT`pmv8_bPfX#oNP&F(eT( zNsCCTSnw!`h>94a%vGFV>5KSWO8Z(pABRmq;{g}PO?o^ygJ=I7boK=>#%SdFQ5@~{ h2;XG(IC=tejFIoEa_Hsx@E9@=?^}0BH+^3ulfU5n*G2#U literal 5424 zcmeI0Uu+ab9LIm#UVE)5v=%CYApK(j!D^*NtWf(Ou(cFo2+=g<+HTv!>)qvgt*uGP znt-v1-QdGJ9|UX0Jgx2lQ8#KZ?eg2V^w_dBz@-KiuXZzlIk=62?@ zv)`Hh{dVRztw_<7$co2Aq)?>jJg!nxxwW#Yze@g|pP#p~0aBzQiG4ZeUZ1M^F1&yC zboJ<8GZTkLr~mk}{l>=dj;RCdj~`r%KD8(oO4t(T2@wYp^Jt<*Zpp{l;#|PJ5D@$6 z!e5aq;CJJig`#Bj z&Zw)yF&fl8b3XY29@M$Z=a!tnJiDO7`7NOaggigAf%Coi&ffe7G4Ai~xc7k5EO;b1 z|D}p)9vpX>&n?-7anC@9{x2YRRDY`q{$wFXz{RR3&sO@Y@eJp4FS#n&vKM_1p|D-# zbFII{)n88TIGm@Uzkn$Sj;YSvXnn+f{5JTsU0xfrTR{u?QXk;{sn;I9ZB6>hgt!qj{Cf7Z#4@ z*w~d07Y>c_s>5|B3KuLF4%RoQxgo6exw#>5Bd2krpbi%-b=DC&RGX&)W2JS;#+kI}veFsGx)!&FazwMjF z{b_Pl%(&P4+>ARy;_91zXk`C-YMFj$B3H$Xd$Z5YxVM1cEbgu3Fvk5PW^e}e5DM2l z?RFDo%I;0en2gIy(Z2Mc4BF9w!L%@Cb|zA3iN=#7X(UqAn-cLjIwRpquU|EDEVHik zN9|Z&M`XyB?m*R!M|xs*pLF*{IV4pQBWWc*8i|eAIzMO0r9ESRI&*#9WcN2Etm_V7q7EkpP#{kid^E!lX5`fGH8wxoMKF9U^NESSJf$wr-&Q8Vdh6#pikNr*S$=Gq28j!MYrJbF!zh{qyFFWwmn$TZ=2$L1Z%VLBX<_ znuZJSq<*X2v+os6OPBuo;nmXGkB16fT&9m0d zR3tgbK71#d_pYpazF_@!%o~qd-uv@UspjZ#G8P%%uZ~+v==nx*+P=ld*TmvImxFuy wOs40oy57N$r$^U$^WdlZEP}7(zMjO`N5ApLC-a`+{{`J|MKO=7=iHxv01o6p1ONa4 diff --git a/Example/ExampleNodeGraph.asset.meta b/Example/ExampleNodeGraph.asset.meta index 04eb901..51a01a0 100644 --- a/Example/ExampleNodeGraph.asset.meta +++ b/Example/ExampleNodeGraph.asset.meta @@ -1,7 +1,7 @@ fileFormatVersion: 2 -guid: b21c76861277d8445a55b4691205fd00 -timeCreated: 1507704049 -licenseType: Pro +guid: 2c7ed5ea36166484a8bcecda71ad8cc8 +timeCreated: 1507760054 +licenseType: Free NativeFormatImporter: mainObjectFileID: 11400000 userData: diff --git a/Resources.meta b/Resources.meta deleted file mode 100644 index f101f36..0000000 --- a/Resources.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 65ed9b337b7f0b74ab007799bb407a5e -folderAsset: yes -timeCreated: 1507567488 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Resources/New Node Data Cache.asset b/Resources/New Node Data Cache.asset deleted file mode 100644 index 98c7f5f59a4d35c557ef7fbc609f1d162e555f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4184 zcmeH~PiqrF7{;H;*49>2wQ98pHmA~4AXF=&NYtdX6hge|K_%GLL~5gP@y~59?M=`x zAfAFCR`BEpXg@#?h0=re;Hh{JJa~%nd3HC;sCz|<(mTiR1@cg!xY86 zNdFwysGc$LsCl@>+{bL1pGKi63H7fKvdYeAiZYO@uTYC-L0?Lpng)4rL` zQT+2cQ3UkkE8_D4d#}HwbIh%`C(qx>-gwj5+kH27@0or;7tR6afOEh(;2dxcI0u{q l&H?9ubKrnGp!bnNeeaE=_h7|;nX5FH{G1+Kx%kDUy#I7mhHd}= diff --git a/Resources/New Node Data Cache.asset.meta b/Resources/New Node Data Cache.asset.meta deleted file mode 100644 index 830cf51..0000000 --- a/Resources/New Node Data Cache.asset.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: a05ee176e92214f48a94c321dad1614d -timeCreated: 1507703437 -licenseType: Pro -NativeFormatImporter: - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Scripts/Editor/NodeEditorUtilities.cs b/Scripts/Editor/NodeEditorUtilities.cs index 9d683bd..78ee295 100644 --- a/Scripts/Editor/NodeEditorUtilities.cs +++ b/Scripts/Editor/NodeEditorUtilities.cs @@ -41,6 +41,7 @@ public static class NodeEditorUtilities { /// Return color based on type public static Color GetTypeColor(Type type) { + if (type == null) return Color.gray; UnityEngine.Random.InitState(type.Name.GetHashCode()); return new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value); } diff --git a/Scripts/Node.cs b/Scripts/Node.cs index 2f5dbf0..7759d6e 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -112,6 +112,6 @@ public abstract class Node : ScriptableObject { } private void GetPorts() { - NodeDataCache.GetPorts(this, ref inputs, ref outputs); + NodeDataCache.UpdatePorts(this, inputs, outputs); } } diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs index 681eaa2..f14fb9f 100644 --- a/Scripts/NodeDataCache.cs +++ b/Scripts/NodeDataCache.cs @@ -6,40 +6,54 @@ using System.Linq; using UnityEditor; /// Precaches reflection data in editor so we won't have to do it runtime -public sealed class NodeDataCache : ScriptableObject { - public static NodeDataCache instance { get; private set;} - public static bool Initialized { get { return instance != null; } } +public static class NodeDataCache { + private static PortDataCache portDataCache; + private static bool Initialized { get { return portDataCache != null; } } - [SerializeField] private PortDataCache portDataCache; + /// Checks for invalid and removes them. + /// Checks for missing ports and adds them. + /// Checks for invalid connections and removes them. + public static void UpdatePorts(Node node, List inputs, List outputs) { + if (!Initialized) BuildCache(); -#if UNITY_EDITOR - [UnityEditor.Callbacks.DidReloadScripts] -#endif - public static void Initialize() { - if (!Initialized) { - instance = Resources.LoadAll("").FirstOrDefault(); -#if UNITY_EDITOR - instance.BuildCache(); -#endif + List inputPorts = new List(); + List outputPorts = new List(); + + System.Type nodeType = node.GetType(); + inputPorts = new List(); + outputPorts = new List(); + if (!portDataCache.ContainsKey(nodeType)) return; + for (int i = 0; i < portDataCache[nodeType].Count; i++) { + if (portDataCache[nodeType][i].direction == NodePort.IO.Input) inputPorts.Add(new NodePort(portDataCache[nodeType][i], node)); + else outputPorts.Add(new NodePort(portDataCache[nodeType][i], node)); + } + + for (int i = inputs.Count-1; i >= 0; i--) { + int index = inputPorts.FindIndex(x => inputs[i].fieldName == x.fieldName); + //If input nodeport does not exist, remove it + if (index == -1) inputs.RemoveAt(i); + //If input nodeport does exist, update it + else inputs[i].type = inputPorts[index].type; + } + for (int i = outputs.Count - 1; i >= 0; i--) { + int index = outputPorts.FindIndex(x => outputs[i].fieldName == x.fieldName); + //If output nodeport does not exist, remove it + if (index == -1) outputs.RemoveAt(i); + //If output nodeport does exist, update it + else outputs[i].type = outputPorts[index].type; + } + //Add + for (int i = 0; i < inputPorts.Count; i++) { + //If inputports contains a new port, add it + if (!inputs.Any(x => x.fieldName == inputPorts[i].fieldName)) inputs.Add(inputPorts[i]); + } + for (int i = 0; i < outputPorts.Count; i++) { + //If inputports contains a new port, add it + if (!outputs.Any(x => x.fieldName == outputPorts[i].fieldName)) outputs.Add(outputPorts[i]); } } - /// Return port data from cache - public static void GetPorts(Node node, ref List inputs, ref List outputs) { - Initialize(); - - System.Type nodeType = node.GetType(); - inputs = new List(); - outputs = new List(); - if (!instance.portDataCache.ContainsKey(nodeType)) return; - for (int i = 0; i < instance.portDataCache[nodeType].Count; i++) { - if (instance.portDataCache[nodeType][i].direction == NodePort.IO.Input) inputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); - else outputs.Add(new NodePort(instance.portDataCache[nodeType][i], node)); - } - } - -#if UNITY_EDITOR - private void BuildCache() { + private static void BuildCache() { portDataCache = new PortDataCache(); System.Type baseType = typeof(Node); Assembly assembly = Assembly.GetAssembly(baseType); @@ -53,7 +67,7 @@ public sealed class NodeDataCache : ScriptableObject { } } - private void CachePorts(System.Type nodeType) { + private static void CachePorts(System.Type nodeType) { System.Reflection.FieldInfo[] fieldInfo = nodeType.GetFields(); for (int i = 0; i < fieldInfo.Length; i++) { @@ -71,7 +85,6 @@ public sealed class NodeDataCache : ScriptableObject { } } } -#endif [System.Serializable] private class PortDataCache : Dictionary>, ISerializationCallbackReceiver { diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index 878a6f0..7c00faf 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -15,7 +15,6 @@ public abstract class NodeGraph : ScriptableObject, ISerializationCallbackReceiv } public virtual Node AddNode(Type type) { - if (!NodeDataCache.Initialized) NodeDataCache.Initialize(); Node node = ScriptableObject.CreateInstance(type) as Node; #if UNITY_EDITOR if (!Application.isPlaying) { diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index 54e55d9..ad51779 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -19,14 +19,12 @@ public class NodePort { public bool IsOutput { get { return direction == IO.Output; } } public Node node { get; private set; } - public bool enabled { get { return _enabled; } set { _enabled = value; } } public string fieldName { get { return _fieldName; } } - [SerializeField] private List connections = new List(); [SerializeField] private string _fieldName; [SerializeField] public Type type; - [SerializeField] private bool _enabled = true; + [SerializeField] private List connections = new List(); [SerializeField] private IO _direction; public NodePort(FieldInfo fieldInfo) { @@ -59,7 +57,7 @@ public class NodePort { } } - public object GetValue() { + public object GetValue() { return node.GetValue(this); } From 3dae0910dc77fcbdade7bd321cbb05e2d1e6227c Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Fri, 13 Oct 2017 00:08:33 +0200 Subject: [PATCH 07/10] Serialization now works correctly. Removal of nodes still broken --- Example/ExampleNodeGraph.asset | 69 ---------------------- Example/ExampleNodeGraph.asset.meta | 9 --- Example/Nodes/Editor/DisplayValueEditor.cs | 1 - Scripts/Node.cs | 6 +- Scripts/NodeGraph.cs | 10 ++-- Scripts/NodePort.cs | 10 ++-- 6 files changed, 13 insertions(+), 92 deletions(-) delete mode 100644 Example/ExampleNodeGraph.asset delete mode 100644 Example/ExampleNodeGraph.asset.meta diff --git a/Example/ExampleNodeGraph.asset b/Example/ExampleNodeGraph.asset deleted file mode 100644 index f223852..0000000 --- a/Example/ExampleNodeGraph.asset +++ /dev/null @@ -1,69 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a6399826e2c44b447b32a3ed06646162, type: 3} - m_Name: ExampleNodeGraph - m_EditorClassIdentifier: - nodes: - - {fileID: 114169009298143184} - - {fileID: 114520184832602068} ---- !u!114 &114169009298143184 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 98f6f901f0da53142b79277ea3f42518, type: 3} - m_Name: DisplayValue - m_EditorClassIdentifier: - rect: - serializedVersion: 2 - x: 130 - y: 6 - width: 200 - height: 200 - inputs: - - _fieldName: value - connections: - - node: {fileID: 114520184832602068} - fieldName: result - _direction: 0 - outputs: [] - value: 0 ---- !u!114 &114520184832602068 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 22e05e2a1f5ad7645850d52212143629, type: 3} - m_Name: Math - m_EditorClassIdentifier: - rect: - serializedVersion: 2 - x: -176 - y: 96 - width: 200 - height: 200 - inputs: [] - outputs: - - _fieldName: result - connections: - - node: {fileID: 114169009298143184} - fieldName: value - _direction: 1 - a: 0 - b: 0 - result: 0 - mathType: 0 diff --git a/Example/ExampleNodeGraph.asset.meta b/Example/ExampleNodeGraph.asset.meta deleted file mode 100644 index 51a01a0..0000000 --- a/Example/ExampleNodeGraph.asset.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 2c7ed5ea36166484a8bcecda71ad8cc8 -timeCreated: 1507760054 -licenseType: Free -NativeFormatImporter: - mainObjectFileID: 11400000 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Example/Nodes/Editor/DisplayValueEditor.cs b/Example/Nodes/Editor/DisplayValueEditor.cs index b0f4643..34276a8 100644 --- a/Example/Nodes/Editor/DisplayValueEditor.cs +++ b/Example/Nodes/Editor/DisplayValueEditor.cs @@ -20,7 +20,6 @@ public class DisplayValueEditor : NodeEditor { NodePort connection = port.GetConnection(i); if (connection == null) continue; - object obj = connection.GetValue(); if (obj == null) continue; diff --git a/Scripts/Node.cs b/Scripts/Node.cs index 7759d6e..60db807 100644 --- a/Scripts/Node.cs +++ b/Scripts/Node.cs @@ -41,21 +41,19 @@ public abstract class Node : ScriptableObject { else return GetInputByFieldName(fieldName); } - /// Returns output port which matches fieldName + /// Returns output port which matches fieldName. Returns null if none found. public NodePort GetOutputByFieldName(string fieldName) { for (int i = 0; i < OutputCount; i++) { if (outputs[i].fieldName == fieldName) return outputs[i]; } - Debug.LogWarning("No outputs with fieldName '" + fieldName+"'"); return null; } - /// Returns input port which matches fieldName + /// Returns input port which matches. Returns null if none found. public NodePort GetInputByFieldName(string fieldName) { for (int i = 0; i < InputCount; i++) { if (inputs[i].fieldName == fieldName) return inputs[i]; } - Debug.LogWarning("No inputs with fieldName '" + fieldName+"'"); return null; } diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index 7c00faf..4c1d798 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -49,17 +49,17 @@ public abstract class NodeGraph : ScriptableObject, ISerializationCallbackReceiv } public void OnAfterDeserialize() { - for (int i = 0; i < nodes.Count; i++) { + /*for (int i = 0; i < nodes.Count; i++) { nodes[i].graph = this; - } - VerifyConnections(); + }*/ + //VerifyConnections(); } - /// Checks all connections for invalid references, and removes them. + /*/// Checks all connections for invalid references, and removes them. public void VerifyConnections() { for (int i = 0; i < nodes.Count; i++) { nodes[i].VerifyConnections(); } - } + }*/ } diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index ad51779..f36be55 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -18,10 +18,10 @@ public class NodePort { public bool IsInput { get { return direction == IO.Input; } } public bool IsOutput { get { return direction == IO.Output; } } - public Node node { get; private set; } public string fieldName { get { return _fieldName; } } + [SerializeField] public Node node; [SerializeField] private string _fieldName; [SerializeField] public Type type; [SerializeField] private List connections = new List(); @@ -57,7 +57,7 @@ public class NodePort { } } - public object GetValue() { + public object GetValue() { return node.GetValue(this); } @@ -77,7 +77,8 @@ public class NodePort { } public NodePort GetConnection(int i) { - return connections[i].Port; + NodePort port = connections[i].node.GetPortByFieldName(connections[i].fieldName); + return port; } public bool IsConnectedTo(NodePort port) { @@ -108,8 +109,8 @@ public class NodePort { [Serializable] public class PortConnection { - [SerializeField] public Node node; [SerializeField] public string fieldName; + [SerializeField] public Node node; public NodePort Port { get { return port != null ? port : port = GetPort(); } } [NonSerialized] private NodePort port; @@ -120,6 +121,7 @@ public class NodePort { } private NodePort GetPort() { + for (int i = 0; i < node.OutputCount; i++) { if (node.outputs[i].fieldName == fieldName) return node.outputs[i]; } From 899e5ae979c2bebda2f7a666dd8c6b3881ea4c5f Mon Sep 17 00:00:00 2001 From: Thor Date: Fri, 13 Oct 2017 10:37:34 +0200 Subject: [PATCH 08/10] Fixed Clear all connections bug --- Scripts/NodePort.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index f36be55..808fabd 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -102,8 +102,8 @@ public class NodePort { } public void ClearConnections() { - for (int i = 0; i < connections.Count; i++) { - Disconnect(connections[i].Port); + while(connections.Count > 0) { + Disconnect(connections[0].Port); } } From bc5c060dee59c9fba6a0f80f6b789bffa620746f Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Fri, 13 Oct 2017 20:28:40 +0200 Subject: [PATCH 09/10] Improved broken connection cleanup. Example updates --- Example/ExampleNodeGraph.asset | Bin 0 -> 8728 bytes Example/ExampleNodeGraph.asset.meta | 9 +++++++ Example/Nodes/BaseNode.cs | 15 ------------ Example/Nodes/ConstantValue.cs | 13 +++++++++++ ...BaseNode.cs.meta => ConstantValue.cs.meta} | 4 ++-- Example/Nodes/DisplayValue.cs | 3 ++- Example/Nodes/Editor/DisplayValueEditor.cs | 17 ++------------ Example/Nodes/ExampleNodeBase.cs | 22 ++++++++++++++++++ Example/Nodes/ExampleNodeBase.cs.meta | 12 ++++++++++ Example/Nodes/MathNode.cs | 13 +++++------ Scripts/Editor/NodeEditorGUI.cs | 2 ++ Scripts/NodePort.cs | 9 +++++++ 12 files changed, 79 insertions(+), 40 deletions(-) create mode 100644 Example/ExampleNodeGraph.asset create mode 100644 Example/ExampleNodeGraph.asset.meta delete mode 100644 Example/Nodes/BaseNode.cs create mode 100644 Example/Nodes/ConstantValue.cs rename Example/Nodes/{BaseNode.cs.meta => ConstantValue.cs.meta} (76%) create mode 100644 Example/Nodes/ExampleNodeBase.cs create mode 100644 Example/Nodes/ExampleNodeBase.cs.meta diff --git a/Example/ExampleNodeGraph.asset b/Example/ExampleNodeGraph.asset new file mode 100644 index 0000000000000000000000000000000000000000..8e72bce34b6042278f4d4335cd95155fc108d7ba GIT binary patch literal 8728 zcmeHMYiv|S6h61zvb^LiQb2@)JOnFCL9jyErB9&HLWC#=%eGzUl6H5q-In%8$;AXC z5+PQ=DnBUChz5*EsIMprMvXuGBZ*N{L8C^aKhTH-AN71QcW!6aO>F%|;+|yo&U|;~ zn=@z5nVCCFH1R#6oN+`nl4#;(e$u?TzJ?hUYTR9b6vhyi+`nWsrT*;mOkK>pTNAT<7t+ zxJC1sr`h2_9|7^s)Mt=}>pX*9+@em_b0hOWzaijYB4vk_jAL9Fv(mqg`~AV`_ZG$> z7F$Huf0)1|uJ=3K#Vso1eqUrB*nb3YThzCFY)>TMJm+NjfoBT-3ET$yi~=rFCavMR zTREXT+QlV*p2I%|xNSpEga20Ge&8lQ=98NWT<5>d#VxwTy3FJ<^n`yxlKHbG{15)| z8lKB}=norDaB+`e&xwr7@p?$N=j{$&S(%70F0KtHqVeLEL@3f2jz$Wop{gWYA6j0- znaW_Ijx&*HZK#n%?P;qyUmyd=qJ8BBW1gMqnZD-A$^C&vL$0;$dm`_TEknNue15i| zeQardId}BD(^)!jFd6B<`7eQ!!FIdK3kU)SL9Yc49p)gon=u4`N&+#?poDlUV68b2j}ma%Z%iTZx<3@{eP>A*!AU@VL? zT-*cQsg)D>F%PNuXSuk^e;05T^a~zkhuHva;9jBsPA-Cfj*Aa8^v66){RbKPV=I(}{7c+x*m*AaSuEaWyIBLZ5yLNJ{ei}UInTxA0=t*X9!`0jAj(gk<2>}A56}i~ z`pE(pH~r*Z;4I000)Lb|rk^YV&XVjW_X$kmx}W5`xalYNgTxl~4LdJJeLrw>9+vhF;!*BgQ`_kms+ozn1J@xp~gFD}@;31vk1XHKC zeL3x&eC|u1m(6AG-_FbFZC}O^mU(@dnd-zAjt}@AN^kq-a-QDy<^4f=+n3+{H|w^q zjswRyo^c$&=Q2d$CpZs$6+jl?IIf=JJaBwEKyLoyLk(3^Jk;1!pP&Z5Q+S{?<{Tz6 z>EO`Qv+};rekeP4&&fkuic5EVHgoWXJ=yJFt-HQ9HsR%^82k&I(uWCkS(m;;NZ%o( z?-0^=2!4vFRr`{u~i<8387vo_{T3DmSp)H}oT zW5>F|%R1jbKW5vLuT)7?(DeNWc7ouk^uzsmaZ9ivRv*H}QE5CFt3w_9c?eN4$spqHtrZKG?cmTsjG&QOk&qTp%hdL{jaP9$8#R z`j8we#^M||MQeRb0_f+D>JO8k^u(O6;D&MZ>Nr z>uqWPIHGh=@AWaJ;#Ia$?G#Uco~o_x-@}-IZx9<3!AN4VHbc}o{vuJ>wE_B3?Uf%T zk6pg^`%$+)qIh9vH6JPc#?C7wn)7b5-zY!T^#P}DQ|P1nHp=}KrDvb)cX>41@4Txk z`cmyx?CJVq?08>|iY&@6bWG{*@c2c=e*CEZGr5hjGsfcjJ#A-wZ@4-`Cy3rJ^aGEs dJL;%0ArH~pr1E?9UZ0~>ylQTh?vh>V@Hfa(MTGzW literal 0 HcmV?d00001 diff --git a/Example/ExampleNodeGraph.asset.meta b/Example/ExampleNodeGraph.asset.meta new file mode 100644 index 0000000..6ec3d2f --- /dev/null +++ b/Example/ExampleNodeGraph.asset.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e8c47bc953732464a9bf3a76273d99ef +timeCreated: 1507916591 +licenseType: Free +NativeFormatImporter: + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Example/Nodes/BaseNode.cs b/Example/Nodes/BaseNode.cs deleted file mode 100644 index 26d4a8d..0000000 --- a/Example/Nodes/BaseNode.cs +++ /dev/null @@ -1,15 +0,0 @@ -using UnityEngine; - -[System.Serializable] -public class BaseNode : Node { - - [Input] public string input; - [Output] public string output; - public bool concat; - [TextArea] - public string SomeString; - [Header("New stuff")] - public Color col; - public AnimationCurve anim; - public Vector3 vec; -} diff --git a/Example/Nodes/ConstantValue.cs b/Example/Nodes/ConstantValue.cs new file mode 100644 index 0000000..b0b99ce --- /dev/null +++ b/Example/Nodes/ConstantValue.cs @@ -0,0 +1,13 @@ +[System.Serializable] +public class ConstantValue : ExampleNodeBase { + public float a; + [Output] public float value; + + protected override void Init() { + name = "Constant Value"; + } + + public override object GetValue(NodePort port) { + return a; + } +} diff --git a/Example/Nodes/BaseNode.cs.meta b/Example/Nodes/ConstantValue.cs.meta similarity index 76% rename from Example/Nodes/BaseNode.cs.meta rename to Example/Nodes/ConstantValue.cs.meta index e525d86..e836841 100644 --- a/Example/Nodes/BaseNode.cs.meta +++ b/Example/Nodes/ConstantValue.cs.meta @@ -1,6 +1,6 @@ fileFormatVersion: 2 -guid: 23665941e8cd89a48b1272ac5fd6510c -timeCreated: 1505462705 +guid: 707240ce8955a0240a7c0c4177d83bf5 +timeCreated: 1505937586 licenseType: Free MonoImporter: serializedVersion: 2 diff --git a/Example/Nodes/DisplayValue.cs b/Example/Nodes/DisplayValue.cs index 01a2b0f..d19dd21 100644 --- a/Example/Nodes/DisplayValue.cs +++ b/Example/Nodes/DisplayValue.cs @@ -1,5 +1,6 @@ using UnityEngine; -public class DisplayValue : Node { +public class DisplayValue : ExampleNodeBase { [Input] public float value; + } diff --git a/Example/Nodes/Editor/DisplayValueEditor.cs b/Example/Nodes/Editor/DisplayValueEditor.cs index 34276a8..0530c18 100644 --- a/Example/Nodes/Editor/DisplayValueEditor.cs +++ b/Example/Nodes/Editor/DisplayValueEditor.cs @@ -12,20 +12,7 @@ public class DisplayValueEditor : NodeEditor { } public float GetResult() { - float result = 0f; - NodePort port = target.GetInputByFieldName("value"); - if (port == null) return result; - int connectionCount = port.ConnectionCount; - for (int i = 0; i < connectionCount; i++) { - - NodePort connection = port.GetConnection(i); - if (connection == null) continue; - object obj = connection.GetValue(); - if (obj == null) continue; - - if (connection.type == typeof(int)) result += (int)obj; - else if (connection.type == typeof(float)) result += (float)obj; - } - return result; + ExampleNodeBase t = target as ExampleNodeBase; + return t.GetInputFloat("value"); } } diff --git a/Example/Nodes/ExampleNodeBase.cs b/Example/Nodes/ExampleNodeBase.cs new file mode 100644 index 0000000..c47cff0 --- /dev/null +++ b/Example/Nodes/ExampleNodeBase.cs @@ -0,0 +1,22 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class ExampleNodeBase : Node { + + public float GetInputFloat(string fieldName) { + float result = 0f; + NodePort port = GetInputByFieldName(fieldName); + if (port == null) return result; + int connectionCount = port.ConnectionCount; + for (int i = 0; i < connectionCount; i++) { + NodePort connection = port.GetConnection(i); + if (connection == null) continue; + object obj = connection.GetValue(); + if (obj == null) continue; + if (connection.type == typeof(int)) result += (int)obj; + else if (connection.type == typeof(float)) result += (float)obj; + } + return result; + } +} diff --git a/Example/Nodes/ExampleNodeBase.cs.meta b/Example/Nodes/ExampleNodeBase.cs.meta new file mode 100644 index 0000000..1cc1c43 --- /dev/null +++ b/Example/Nodes/ExampleNodeBase.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 923bada49e668fd4a98b04fcb49999d7 +timeCreated: 1507917099 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Example/Nodes/MathNode.cs b/Example/Nodes/MathNode.cs index 32aa322..475698d 100644 --- a/Example/Nodes/MathNode.cs +++ b/Example/Nodes/MathNode.cs @@ -1,9 +1,9 @@ using UnityEngine; [System.Serializable] -public class MathNode : Node { - public float a; - public float b; +public class MathNode : ExampleNodeBase { + [Input] public float c; + [Input] public float b; [Output] public float result; public enum MathType { Add, Subtract, Multiply, Divide} public MathType mathType = MathType.Add; @@ -13,6 +13,9 @@ public class MathNode : Node { } public override object GetValue(NodePort port) { + float a = GetInputFloat("c"); + float b = GetInputFloat("b"); + switch(port.fieldName) { case "result": switch(mathType) { @@ -25,8 +28,4 @@ public class MathNode : Node { } return 0f; } - - public override void OnCreateConnection(NodePort from, NodePort to) { - - } } diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index cf0c44e..d04f747 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -128,7 +128,9 @@ public partial class NodeEditorWindow { if (!portConnectionPoints.ContainsKey(output)) continue; Vector2 from = _portConnectionPoints[output].center; for (int k = 0; k < output.ConnectionCount; k++) { + NodePort input = output.GetConnection(k); + if (input == null) return; //If a script has been updated and the port doesn't exist, it is removed and null is returned. If this happens, return. Vector2 to = _portConnectionPoints[input].center; DrawConnection(from, to, NodeEditorUtilities.GetTypeColor(output.type)); } diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs index 808fabd..1980935 100644 --- a/Scripts/NodePort.cs +++ b/Scripts/NodePort.cs @@ -77,7 +77,16 @@ public class NodePort { } public NodePort GetConnection(int i) { + //If the connection is broken for some reason, remove it. + if (connections[i].node == null || string.IsNullOrEmpty(connections[i].fieldName)) { + connections.RemoveAt(i); + return null; + } NodePort port = connections[i].node.GetPortByFieldName(connections[i].fieldName); + if (port == null) { + connections.RemoveAt(i); + return null; + } return port; } From 2bccb2ca3a1e70f0e4256e68c171dd0276545e92 Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Fri, 13 Oct 2017 20:38:00 +0200 Subject: [PATCH 10/10] Removed toolbar. It might return later, but at this point there's no use for it. --- Scripts/Editor/NodeEditorGUI.cs | 1 - Scripts/Editor/NodeEditorToolbar.cs | 55 ------------------------ Scripts/Editor/NodeEditorToolbar.cs.meta | 12 ------ 3 files changed, 68 deletions(-) delete mode 100644 Scripts/Editor/NodeEditorToolbar.cs delete mode 100644 Scripts/Editor/NodeEditorToolbar.cs.meta diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index d04f747..4a7e617 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -15,7 +15,6 @@ public partial class NodeEditorWindow { DrawConnections(); DrawDraggedConnection(); DrawNodes(); - DrawToolbar(); GUI.matrix = m; } diff --git a/Scripts/Editor/NodeEditorToolbar.cs b/Scripts/Editor/NodeEditorToolbar.cs deleted file mode 100644 index 8d7900b..0000000 --- a/Scripts/Editor/NodeEditorToolbar.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; - -public partial class NodeEditorWindow { - - public void DrawToolbar() { - EditorGUILayout.BeginHorizontal("Toolbar"); - - if (DropdownButton("File", 50)) FileContextMenu(); - if (DropdownButton("Edit", 50)) EditContextMenu(); - if (DropdownButton("View", 50)) { } - if (DropdownButton("Settings", 70)) { } - if (DropdownButton("Tools", 50)) ToolsContextMenu(); - - //Draw hover info - if (Event.current.type == EventType.Layout || Event.current.type == EventType.Repaint) { - if (IsHoveringNode) { - GUILayout.Space(20); - string hoverInfo = hoveredNode.GetType().ToString(); - if (IsHoveringPort) hoverInfo += " > " + hoveredPort.fieldName; - GUILayout.Label(hoverInfo); - } - } - - // Make the toolbar extend all throughout the window extension. - GUILayout.FlexibleSpace(); - - EditorGUILayout.EndHorizontal(); - } - - public void FileContextMenu() { - GenericMenu contextMenu = new GenericMenu(); - - contextMenu.AddItem(new GUIContent("Save"), false, Save); - contextMenu.AddItem(new GUIContent("Save As"), false, SaveAs); - - contextMenu.DropDown(new Rect(5f, 17f, 0f, 0f)); - } - - public void EditContextMenu() { - GenericMenu contextMenu = new GenericMenu(); - contextMenu.AddItem(new GUIContent("Clear"), false, () => graph.Clear()); - - contextMenu.DropDown(new Rect(5f, 17f, 0f, 0f)); - } - - public void ToolsContextMenu() { - GenericMenu contextMenu = new GenericMenu(); - contextMenu.AddItem(new GUIContent("Debug Custom Node Editors"), false, () => CacheCustomNodeEditors()); - - contextMenu.DropDown(new Rect(5f, 17f, 0f, 0f)); - } -} diff --git a/Scripts/Editor/NodeEditorToolbar.cs.meta b/Scripts/Editor/NodeEditorToolbar.cs.meta deleted file mode 100644 index cc85b52..0000000 --- a/Scripts/Editor/NodeEditorToolbar.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: fa774a466fc664148b43879d282ea071 -timeCreated: 1505932458 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: