diff --git a/Source/Editor/Surface/Archetypes/Collections.cs b/Source/Editor/Surface/Archetypes/Collections.cs
new file mode 100644
index 000000000..9ce2d811b
--- /dev/null
+++ b/Source/Editor/Surface/Archetypes/Collections.cs
@@ -0,0 +1,264 @@
+// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
+
+using FlaxEngine;
+using FlaxEditor.Scripting;
+using FlaxEditor.Surface.Elements;
+
+namespace FlaxEditor.Surface.Archetypes
+{
+ ///
+ /// Contains archetypes for nodes from the Collections group.
+ ///
+ [HideInEditor]
+ public static class Collections
+ {
+ internal static ScriptType GetArrayItemType(Box box, ScriptType type)
+ {
+ if (type == ScriptType.Null)
+ return box.DefaultType;
+ return box.DefaultType != null ? new ScriptType(type.GetElementType()) : type;
+ }
+
+ ///
+ /// The nodes for that group.
+ ///
+ public static NodeArchetype[] Nodes =
+ {
+ new NodeArchetype
+ {
+ TypeID = 1,
+ Title = "Array Length",
+ Description = "Gets the length of the arary (amount of the items).",
+ AlternativeTitles = new[] { "Count" },
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 20),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, typeof(int), 1)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 2,
+ Title = "Array Contains",
+ Description = "Returns the true if arrayt contains a given item, otherwise false.",
+ AlternativeTitles = new[] { "Contains" },
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 40),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Item", true, typeof(object), 1),
+ NodeElementArchetype.Factory.Output(0, string.Empty, typeof(bool), 2)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 3,
+ Title = "Array Index Of",
+ Description = "Returns the zero-based index of the item found in the array or -1 if nothing found.",
+ AlternativeTitles = new[] { "IndexOf", "Find" },
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 40),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1, 2 },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Item", true, typeof(object), 1),
+ NodeElementArchetype.Factory.Output(0, string.Empty, typeof(int), 2)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 4,
+ Title = "Array Last Index Of",
+ Description = "Returns the zero-based index of the item found in the array or -1 if nothing found (searches from back to front).",
+ AlternativeTitles = new[] { "LastIndexOf", "FindLast" },
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 40),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1, 2 },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Item", true, typeof(object), 1),
+ NodeElementArchetype.Factory.Output(0, string.Empty, typeof(int), 2)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 5,
+ Title = "Array Clear",
+ Description = "Clears array.",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 20),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1 },
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 1)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 6,
+ Title = "Array Remove",
+ Description = "Removes the given item from the array.",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 40),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1, 2 },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Item", true, typeof(object), 1),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 2)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 7,
+ Title = "Array Remove At",
+ Description = "Removes an item at the given index from the array.",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(170, 40),
+ DefaultValues = new object[] { 0 },
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 2 },
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Index", true, typeof(int), 1, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 2)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 8,
+ Title = "Array Add",
+ Description = "Adds the item to the array (to the end).",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 40),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1, 2 },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Item", true, typeof(object), 1),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 2)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 9,
+ Title = "Array Insert",
+ Description = "Inserts the item to the array at the given index.",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 60),
+ DefaultValues = new object[] { 0 },
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1, 3 },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Item", true, typeof(object), 1),
+ NodeElementArchetype.Factory.Input(2, "Index", true, typeof(int), 2, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 3)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 10,
+ Title = "Array Get",
+ Description = "Gets the item from the array (at the given zero-based index).",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 40),
+ DefaultValues = new object[] { 0 },
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 2 },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Index", true, typeof(int), 1, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, typeof(object), 2)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 11,
+ Title = "Array Set",
+ Description = "Sets the item in the array (at the given zero-based index).",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 60),
+ DefaultValues = new object[] { 0 },
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 2, 3 },
+ DependentBoxFilter = GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Input(1, "Index", true, typeof(int), 1, 0),
+ NodeElementArchetype.Factory.Input(2, "Item", true, typeof(object), 2),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 3)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 12,
+ Title = "Array Sort",
+ Description = "Sorts the items in the array (ascending).",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 20),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1 },
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 1)
+ }
+ },
+ new NodeArchetype
+ {
+ TypeID = 13,
+ Title = "Array Reverse",
+ Description = "Reverses the order of the items in the array.",
+ Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
+ Size = new Vector2(150, 20),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 0 },
+ DependentBoxes = new int[] { 1 },
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, "Array", true, null, 0),
+ NodeElementArchetype.Factory.Output(0, string.Empty, null, 1)
+ }
+ },
+ // first 100 IDs reserved for arrays
+ };
+ }
+}
diff --git a/Source/Editor/Surface/Archetypes/Flow.cs b/Source/Editor/Surface/Archetypes/Flow.cs
index d7fc5dcc2..3e79bfe23 100644
--- a/Source/Editor/Surface/Archetypes/Flow.cs
+++ b/Source/Editor/Surface/Archetypes/Flow.cs
@@ -308,6 +308,28 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Output(0, string.Empty, typeof(void), 2, true),
}
},
+ new NodeArchetype
+ {
+ TypeID = 7,
+ Title = "Array For Each",
+ AlternativeTitles = new[] { "foreach" },
+ Description = "Iterates over the array items.",
+ Flags = NodeFlags.VisualScriptGraph,
+ Size = new Vector2(160, 80),
+ ConnectionsHints = ConnectionsHint.Array,
+ IndependentBoxes = new int[] { 1 },
+ DependentBoxes = new int[] { 4, },
+ DependentBoxFilter = Collections.GetArrayItemType,
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Input(0, string.Empty, false, typeof(void), 0),
+ NodeElementArchetype.Factory.Input(1, "Array", false, null, 1),
+ NodeElementArchetype.Factory.Input(2, "Break", false, typeof(void), 2),
+ NodeElementArchetype.Factory.Output(0, "Loop", typeof(void), 3, true),
+ NodeElementArchetype.Factory.Output(1, "Item", typeof(object), 4),
+ NodeElementArchetype.Factory.Output(2, "Done", typeof(void), 5, true),
+ }
+ },
};
}
}
diff --git a/Source/Editor/Surface/Elements/Box.cs b/Source/Editor/Surface/Elements/Box.cs
index 271ff0c28..7ee0aaf07 100644
--- a/Source/Editor/Surface/Elements/Box.cs
+++ b/Source/Editor/Surface/Elements/Box.cs
@@ -200,6 +200,8 @@ namespace FlaxEditor.Surface.Elements
return "Vector";
if ((hint & ConnectionsHint.Scalar) == ConnectionsHint.Scalar)
return "Scalar";
+ if ((hint & ConnectionsHint.Array) == ConnectionsHint.Array)
+ return "Array";
return null;
}
@@ -236,6 +238,11 @@ namespace FlaxEditor.Surface.Elements
// Can
return true;
}
+ if ((connectionsHints & ConnectionsHint.Array) == ConnectionsHint.Array && type.IsArray)
+ {
+ // Can
+ return true;
+ }
if ((connectionsHints & ConnectionsHint.Vector) == ConnectionsHint.Vector)
{
var t = type.Type;
diff --git a/Source/Editor/Surface/NodeArchetype.cs b/Source/Editor/Surface/NodeArchetype.cs
index b2a859cc5..7b74128ef 100644
--- a/Source/Editor/Surface/NodeArchetype.cs
+++ b/Source/Editor/Surface/NodeArchetype.cs
@@ -52,6 +52,11 @@ namespace FlaxEditor.Surface
///
Enum = 16,
+ ///
+ /// Allow any array types connections.
+ ///
+ Array = 32,
+
///
/// Allow any scalar or vector numeric value types connections (bool, int, float, vector2, color..).
///
@@ -60,7 +65,7 @@ namespace FlaxEditor.Surface
///
/// All flags.
///
- All = Scalar | Vector | Enum | Anything | Value,
+ All = Scalar | Vector | Enum | Anything | Value | Array,
}
///
@@ -152,6 +157,11 @@ namespace FlaxEditor.Surface
///
public int[] DependentBoxes;
+ ///
+ /// Custom function to convert type for dependant box (optional).
+ ///
+ public Func DependentBoxFilter;
+
///
/// Array with default elements descriptions.
///
diff --git a/Source/Editor/Surface/NodeFactory.cs b/Source/Editor/Surface/NodeFactory.cs
index 2888010f9..96d381669 100644
--- a/Source/Editor/Surface/NodeFactory.cs
+++ b/Source/Editor/Surface/NodeFactory.cs
@@ -168,6 +168,13 @@ namespace FlaxEditor.Surface
Color = new Color(237, 136, 64),
Archetypes = Archetypes.Flow.Nodes
},
+ new GroupArchetype
+ {
+ GroupID = 18,
+ Name = "Collections",
+ Color = new Color(110, 180, 81),
+ Archetypes = Archetypes.Collections.Nodes
+ },
};
///
diff --git a/Source/Editor/Surface/SurfaceNode.cs b/Source/Editor/Surface/SurfaceNode.cs
index d52a845c4..a3e1e6ddf 100644
--- a/Source/Editor/Surface/SurfaceNode.cs
+++ b/Source/Editor/Surface/SurfaceNode.cs
@@ -476,7 +476,7 @@ namespace FlaxEditor.Surface
var b = GetBox(Archetype.DependentBoxes[i]);
if (b != null)
{
- b.CurrentType = type;
+ b.CurrentType = Archetype.DependentBoxFilter != null ? Archetype.DependentBoxFilter(b, type) : type;
}
}
diff --git a/Source/Editor/Surface/SurfaceStyle.cs b/Source/Editor/Surface/SurfaceStyle.cs
index 198fd7c67..f14aa8de4 100644
--- a/Source/Editor/Surface/SurfaceStyle.cs
+++ b/Source/Editor/Surface/SurfaceStyle.cs
@@ -156,6 +156,8 @@ namespace FlaxEditor.Surface
type = TypeUtils.GetType(typeName.Substring(0, typeName.Length - 1));
GetConnectionColor(type, hint, out color);
}
+ else if (type.IsArray)
+ GetConnectionColor(new ScriptType(type.GetElementType()), hint, out color);
else if (type.Type == typeof(void))
color = Colors.Impulse;
else if (type.Type == typeof(bool))
diff --git a/Source/Engine/Content/Assets/VisualScript.cpp b/Source/Engine/Content/Assets/VisualScript.cpp
index 3cd379d79..47b815e66 100644
--- a/Source/Engine/Content/Assets/VisualScript.cpp
+++ b/Source/Engine/Content/Assets/VisualScript.cpp
@@ -1112,6 +1112,76 @@ void VisualScriptExecutor::ProcessGroupFlow(Box* boxBase, Node* node, Value& val
eatBox(node, boxBase->FirstConnection());
}
break;
+ }
+ // Array For Each
+ case 7:
+ {
+ const auto scope = ThreadStacks.Get().Stack->Scope;
+ int32 iteratorIndex = 0;
+ for (; iteratorIndex < scope->ReturnedValues.Count(); iteratorIndex++)
+ {
+ const auto& e = scope->ReturnedValues[iteratorIndex];
+ if (e.NodeId == node->ID && e.BoxId == 0)
+ break;
+ }
+ int32 arrayIndex = 0;
+ for (; iteratorIndex < scope->ReturnedValues.Count(); arrayIndex++)
+ {
+ const auto& e = scope->ReturnedValues[arrayIndex];
+ if (e.NodeId == node->ID && e.BoxId == 1)
+ break;
+ }
+ switch (boxBase->ID)
+ {
+ // Loop
+ case 0:
+ {
+ if (iteratorIndex == scope->ReturnedValues.Count())
+ {
+ if (arrayIndex == scope->ReturnedValues.Count())
+ arrayIndex++;
+ scope->ReturnedValues.AddOne();
+ }
+ if (arrayIndex == scope->ReturnedValues.Count())
+ scope->ReturnedValues.AddOne();
+ auto& iteratorValue = scope->ReturnedValues[iteratorIndex];
+ iteratorValue.NodeId = node->ID;
+ iteratorValue.BoxId = 0;
+ iteratorValue.Value = 0;
+ auto& arrayValue = scope->ReturnedValues[arrayIndex];
+ arrayValue.NodeId = node->ID;
+ arrayValue.BoxId = 1;
+ arrayValue.Value = tryGetValue(node->GetBox(1), Value::Null);
+ if (arrayValue.Value.Type.Type != VariantType::Array)
+ {
+ OnError(node, boxBase, String::Format(TEXT("Input value {0} is not an array."), arrayValue.Value));
+ return;
+ }
+ const int32 count = arrayValue.Value.AsArray().Count();
+ for (; iteratorValue.Value.AsInt < count; iteratorValue.Value.AsInt++)
+ {
+ boxBase = node->GetBox(3);
+ if (boxBase->HasConnection())
+ eatBox(node, boxBase->FirstConnection());
+ }
+ boxBase = node->GetBox(5);
+ if (boxBase->HasConnection())
+ eatBox(node, boxBase->FirstConnection());
+ break;
+ }
+ // Break
+ case 2:
+ // Reset loop iterator
+ if (iteratorIndex != scope->ReturnedValues.Count())
+ scope->ReturnedValues[iteratorIndex].Value.AsInt = MAX_int32 - 1;
+ break;
+ // Item
+ case 4:
+ if (iteratorIndex != scope->ReturnedValues.Count() && arrayIndex != scope->ReturnedValues.Count())
+ value = scope->ReturnedValues[arrayIndex].Value.AsArray()[(int32)scope->ReturnedValues[iteratorIndex].Value];
+ break;
+ }
+ break;
}
}
}
diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp
index 1c0c79176..63a262d11 100644
--- a/Source/Engine/Visject/VisjectGraph.cpp
+++ b/Source/Engine/Visject/VisjectGraph.cpp
@@ -3,6 +3,7 @@
#include "VisjectGraph.h"
#include "GraphUtilities.h"
#include "Engine/Core/Random.h"
+#include "Engine/Core/Collections/Sorting.h"
#include "Engine/Core/Math/Vector4.h"
#include "Engine/Core/Math/Transform.h"
#include "Engine/Engine/GameplayGlobals.h"
@@ -16,6 +17,7 @@
#include "Engine/Utilities/StringConverter.h"
#define RAND Random::Rand()
+#define ENSURE(condition, errorMsg) if (!(condition)) { OnError(node, box, errorMsg); return; }
VisjectExecutor::VisjectExecutor()
{
@@ -32,6 +34,7 @@ VisjectExecutor::VisjectExecutor()
_perGroupProcessCall[11] = &VisjectExecutor::ProcessGroupBitwise;
_perGroupProcessCall[12] = &VisjectExecutor::ProcessGroupComparisons;
_perGroupProcessCall[14] = &VisjectExecutor::ProcessGroupParticles;
+ _perGroupProcessCall[18] = &VisjectExecutor::ProcessGroupCollections;
}
VisjectExecutor::~VisjectExecutor()
@@ -1218,6 +1221,109 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value)
}
}
+void VisjectExecutor::ProcessGroupCollections(Box* box, Node* node, Value& value)
+{
+ if (node->TypeID < 100)
+ {
+ // Array
+ Variant v = tryGetValue(node->GetBox(0), Value::Null);
+ ENSURE(v.Type.Type == VariantType::Array, String::Format(TEXT("Input value {0} is not an array."), v));
+ auto& array = v.AsArray();
+ Box* b;
+ switch (node->TypeID)
+ {
+ // Count
+ case 1:
+ value = array.Count();
+ break;
+ // Contains
+ case 2:
+ value = array.Contains(tryGetValue(node->GetBox(1), Value::Null));
+ break;
+ // Find
+ case 3:
+ b = node->GetBox(1);
+ ENSURE(b->HasConnection(), TEXT("Missing value to find."));
+ value = array.Find(eatBox(b->GetParent(), b->FirstConnection()));
+ break;
+ // Find Last
+ case 4:
+ b = node->GetBox(1);
+ ENSURE(b->HasConnection(), TEXT("Missing value to find."));
+ value = array.FindLast(eatBox(b->GetParent(), b->FirstConnection()));
+ break;
+ // Clear
+ case 5:
+ array.Clear();
+ value = MoveTemp(v);
+ break;
+ // Remove
+ case 6:
+ b = node->GetBox(1);
+ ENSURE(b->HasConnection(), TEXT("Missing value to remove."));
+ array.Remove(eatBox(b->GetParent(), b->FirstConnection()));
+ value = MoveTemp(v);
+ break;
+ // Remove At
+ case 7:
+ {
+ const int32 index = (int32)tryGetValue(node->GetBox(1), 0, Value::Null);
+ ENSURE(index >= 0 && index < array.Count(), String::Format(TEXT("Array index {0} is out of range [0;{1}]."), index, array.Count() - 1));
+ array.RemoveAt(index);
+ value = MoveTemp(v);
+ break;
+ }
+ // Add
+ case 8:
+ b = node->GetBox(1);
+ ENSURE(b->HasConnection(), TEXT("Missing value to add."));
+ array.Add(eatBox(b->GetParent(), b->FirstConnection()));
+ value = MoveTemp(v);
+ break;
+ // Insert
+ case 9:
+ {
+ b = node->GetBox(1);
+ ENSURE(b->HasConnection(), TEXT("Missing value to add."));
+ const int32 index = (int32)tryGetValue(node->GetBox(2), 0, Value::Null);
+ ENSURE(index >= 0 && index <= array.Count(), String::Format(TEXT("Array index {0} is out of range [0;{1}]."), index, array.Count()));
+ array.Insert(index, eatBox(b->GetParent(), b->FirstConnection()));
+ value = MoveTemp(v);
+ break;
+ }
+ // Get
+ case 10:
+ {
+ const int32 index = (int32)tryGetValue(node->GetBox(1), 0, Value::Null);
+ ENSURE(index >= 0 && index < array.Count(), String::Format(TEXT("Array index {0} is out of range [0;{1}]."), index, array.Count() - 1));
+ value = MoveTemp(array[index]);
+ break;
+ }
+ // Set
+ case 11:
+ {
+ b = node->GetBox(2);
+ ENSURE(b->HasConnection(), TEXT("Missing value to set."));
+ const int32 index = (int32)tryGetValue(node->GetBox(1), 0, Value::Null);
+ ENSURE(index >= 0 && index < array.Count(), String::Format(TEXT("Array index {0} is out of range [0;{1}]."), index, array.Count() - 1));
+ array[index] = MoveTemp(eatBox(b->GetParent(), b->FirstConnection()));
+ value = MoveTemp(v);
+ break;
+ }
+ // Sort
+ case 12:
+ Sorting::QuickSort(array.Get(), array.Count());
+ value = MoveTemp(v);
+ break;
+ // Reverse
+ case 13:
+ array.Reverse();
+ value = MoveTemp(v);
+ break;
+ }
+ }
+}
+
VisjectExecutor::Value VisjectExecutor::tryGetValue(Box* box, int32 defaultValueBoxIndex, const Value& defaultValue)
{
const auto parentNode = box->GetParent();
diff --git a/Source/Engine/Visject/VisjectGraph.h b/Source/Engine/Visject/VisjectGraph.h
index 4ffd97db7..4cbe47b2e 100644
--- a/Source/Engine/Visject/VisjectGraph.h
+++ b/Source/Engine/Visject/VisjectGraph.h
@@ -226,7 +226,7 @@ public:
protected:
- ProcessBoxHandler _perGroupProcessCall[18];
+ ProcessBoxHandler _perGroupProcessCall[19];
public:
@@ -256,6 +256,7 @@ public:
void ProcessGroupBitwise(Box* box, Node* node, Value& value);
void ProcessGroupComparisons(Box* box, Node* node, Value& value);
void ProcessGroupParticles(Box* box, Node* node, Value& value);
+ void ProcessGroupCollections(Box* box, Node* node, Value& value);
protected: