NodeCanvas Forums › Support › IterateDictionary
I write this thread just to share my IterateDictionary implementation.
Enjoy 😉
[EDIT]
OnNodeInspectorGUI has to be change.
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
using System.Collections; using NodeCanvas.Framework; using NodeCanvas.Framework.Internal; using ParadoxNotion.Design; using ParadoxNotion; using NodeCanvas.BehaviourTrees; using NodeCanvas; using UnityEngine; namespace NodeCanvas.BehaviourTrees{ [Name("IterateDictionary")] [Category("Decorators")] [Description("Iterate any type of dictionary and execute the child node for each key, value in the dictionary. Keeps iterating until the Termination Condition is met or the whole dictionary is iterated, in which case the last interation's child status is returned.")] [Icon("List")] public class IterateDictionary : BTDecorator{ public enum TerminationConditions { None, FirstSuccess, FirstFailure } [RequiredField] [BlackboardOnly] [Tooltip("The list to iterate")] public BBParameter<IDictionary> targetDictionary; [BlackboardOnly] [Name("Current Element")] [Tooltip("Store the current element")] public BBObjectParameter current; [BlackboardOnly] [Name("Current Key")] [Tooltip("Store the current key")] public BBObjectParameter key; [BlackboardOnly] [Name("Current Index")] [Tooltip("Store the current index")] public BBParameter<int> storeIndex; [Tooltip("The maximum count of iterations. Leave at -1 to iterate the whole list")] public BBParameter<int> maxIteration = -1; [Tooltip("The condition when to terminate the iteration and return status")] public TerminationConditions terminationCondition = TerminationConditions.None; [Tooltip("Should the iteration start from the begining after a node reset?")] public bool resetIndex = true; private int currentIndex; private IDictionary dictionary{ get {return targetDictionary != null? targetDictionary.value : null;} } protected override Status OnExecute(Component agent, IBlackboard blackboard){ if (decoratedConnection == null){ return Status.Optional; } if (dictionary == null || dictionary.Count == 0){ return Status.Failure; } var iter = dictionary.GetEnumerator(); // https://docs.microsoft.com/fr-fr/dotnet/api/system.collections.ienumerable.getenumerator?view=netframework-4.7.2 for(var i = 0; i < currentIndex && i < dictionary.Count && iter.MoveNext(); i++) {} for(var i = currentIndex; i < dictionary.Count && iter.MoveNext(); i++){ key.value = iter.Key; current.value = iter.Value; storeIndex.value = i; status = decoratedConnection.Execute(agent, blackboard); if (status == Status.Success && terminationCondition == TerminationConditions.FirstSuccess){ return Status.Success; } if (status == Status.Failure && terminationCondition == TerminationConditions.FirstFailure){ return Status.Failure; } if (status == Status.Running){ currentIndex = i; return Status.Running; } if (currentIndex == dictionary.Count-1 || currentIndex == maxIteration.value-1){ if (resetIndex){ currentIndex = 0; } return status; } decoratedConnection.Reset(); currentIndex ++; } return Status.Running; } protected override void OnReset(){ if (resetIndex){ currentIndex = 0; } } //////////////////////////////////////// ///////////GUI AND EDITOR STUFF///////// //////////////////////////////////////// #if UNITY_EDITOR protected override void OnNodeGUI(){ var leftLabelStyle = new GUIStyle(GUI.skin.GetStyle("label")); leftLabelStyle.richText = true; leftLabelStyle.alignment = TextAnchor.UpperLeft; GUILayout.Label("For Each \t" + current + "\nIn \t" + targetDictionary, leftLabelStyle); if (terminationCondition != TerminationConditions.None) GUILayout.Label("Break on " + terminationCondition.ToString()); if (UnityEngine.Application.isPlaying) GUILayout.Label("Index: " + currentIndex.ToString() + " / " + (dictionary != null && dictionary.Count != 0? (dictionary.Count -1).ToString() : "?") ); } protected override void OnNodeInspectorGUI(){ DrawDefaultInspector(); if (GUI.changed){ var argType = targetDictionary.refType != null? targetDictionary.refType.GetEnumerableElementType() : null; if (current.varType != argType){ current.SetType(argType); } } } #endif } } |
Thanks for sharing 🙂
There is a special Forums section; “Custom Nodes & Tasks” you can use in the future by the way if you want 😉
Join us on Discord: https://discord.gg/97q2Rjh