Add Arrays to Visual Scripting
This commit is contained in:
264
Source/Editor/Surface/Archetypes/Collections.cs
Normal file
264
Source/Editor/Surface/Archetypes/Collections.cs
Normal file
@@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains archetypes for nodes from the Collections group.
|
||||||
|
/// </summary>
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The nodes for that group.
|
||||||
|
/// </summary>
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -308,6 +308,28 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
NodeElementArchetype.Factory.Output(0, string.Empty, typeof(void), 2, true),
|
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),
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,6 +200,8 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
return "Vector";
|
return "Vector";
|
||||||
if ((hint & ConnectionsHint.Scalar) == ConnectionsHint.Scalar)
|
if ((hint & ConnectionsHint.Scalar) == ConnectionsHint.Scalar)
|
||||||
return "Scalar";
|
return "Scalar";
|
||||||
|
if ((hint & ConnectionsHint.Array) == ConnectionsHint.Array)
|
||||||
|
return "Array";
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +238,11 @@ namespace FlaxEditor.Surface.Elements
|
|||||||
// Can
|
// Can
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if ((connectionsHints & ConnectionsHint.Array) == ConnectionsHint.Array && type.IsArray)
|
||||||
|
{
|
||||||
|
// Can
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if ((connectionsHints & ConnectionsHint.Vector) == ConnectionsHint.Vector)
|
if ((connectionsHints & ConnectionsHint.Vector) == ConnectionsHint.Vector)
|
||||||
{
|
{
|
||||||
var t = type.Type;
|
var t = type.Type;
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ namespace FlaxEditor.Surface
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Enum = 16,
|
Enum = 16,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allow any array types connections.
|
||||||
|
/// </summary>
|
||||||
|
Array = 32,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allow any scalar or vector numeric value types connections (bool, int, float, vector2, color..).
|
/// Allow any scalar or vector numeric value types connections (bool, int, float, vector2, color..).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -60,7 +65,7 @@ namespace FlaxEditor.Surface
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// All flags.
|
/// All flags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
All = Scalar | Vector | Enum | Anything | Value,
|
All = Scalar | Vector | Enum | Anything | Value | Array,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -152,6 +157,11 @@ namespace FlaxEditor.Surface
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int[] DependentBoxes;
|
public int[] DependentBoxes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom function to convert type for dependant box (optional).
|
||||||
|
/// </summary>
|
||||||
|
public Func<Elements.Box, ScriptType, ScriptType> DependentBoxFilter;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Array with default elements descriptions.
|
/// Array with default elements descriptions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -168,6 +168,13 @@ namespace FlaxEditor.Surface
|
|||||||
Color = new Color(237, 136, 64),
|
Color = new Color(237, 136, 64),
|
||||||
Archetypes = Archetypes.Flow.Nodes
|
Archetypes = Archetypes.Flow.Nodes
|
||||||
},
|
},
|
||||||
|
new GroupArchetype
|
||||||
|
{
|
||||||
|
GroupID = 18,
|
||||||
|
Name = "Collections",
|
||||||
|
Color = new Color(110, 180, 81),
|
||||||
|
Archetypes = Archetypes.Collections.Nodes
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ namespace FlaxEditor.Surface
|
|||||||
var b = GetBox(Archetype.DependentBoxes[i]);
|
var b = GetBox(Archetype.DependentBoxes[i]);
|
||||||
if (b != null)
|
if (b != null)
|
||||||
{
|
{
|
||||||
b.CurrentType = type;
|
b.CurrentType = Archetype.DependentBoxFilter != null ? Archetype.DependentBoxFilter(b, type) : type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,8 @@ namespace FlaxEditor.Surface
|
|||||||
type = TypeUtils.GetType(typeName.Substring(0, typeName.Length - 1));
|
type = TypeUtils.GetType(typeName.Substring(0, typeName.Length - 1));
|
||||||
GetConnectionColor(type, hint, out color);
|
GetConnectionColor(type, hint, out color);
|
||||||
}
|
}
|
||||||
|
else if (type.IsArray)
|
||||||
|
GetConnectionColor(new ScriptType(type.GetElementType()), hint, out color);
|
||||||
else if (type.Type == typeof(void))
|
else if (type.Type == typeof(void))
|
||||||
color = Colors.Impulse;
|
color = Colors.Impulse;
|
||||||
else if (type.Type == typeof(bool))
|
else if (type.Type == typeof(bool))
|
||||||
|
|||||||
@@ -1112,6 +1112,76 @@ void VisualScriptExecutor::ProcessGroupFlow(Box* boxBase, Node* node, Value& val
|
|||||||
eatBox(node, boxBase->FirstConnection());
|
eatBox(node, boxBase->FirstConnection());
|
||||||
}
|
}
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "VisjectGraph.h"
|
#include "VisjectGraph.h"
|
||||||
#include "GraphUtilities.h"
|
#include "GraphUtilities.h"
|
||||||
#include "Engine/Core/Random.h"
|
#include "Engine/Core/Random.h"
|
||||||
|
#include "Engine/Core/Collections/Sorting.h"
|
||||||
#include "Engine/Core/Math/Vector4.h"
|
#include "Engine/Core/Math/Vector4.h"
|
||||||
#include "Engine/Core/Math/Transform.h"
|
#include "Engine/Core/Math/Transform.h"
|
||||||
#include "Engine/Engine/GameplayGlobals.h"
|
#include "Engine/Engine/GameplayGlobals.h"
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
#include "Engine/Utilities/StringConverter.h"
|
#include "Engine/Utilities/StringConverter.h"
|
||||||
|
|
||||||
#define RAND Random::Rand()
|
#define RAND Random::Rand()
|
||||||
|
#define ENSURE(condition, errorMsg) if (!(condition)) { OnError(node, box, errorMsg); return; }
|
||||||
|
|
||||||
VisjectExecutor::VisjectExecutor()
|
VisjectExecutor::VisjectExecutor()
|
||||||
{
|
{
|
||||||
@@ -32,6 +34,7 @@ VisjectExecutor::VisjectExecutor()
|
|||||||
_perGroupProcessCall[11] = &VisjectExecutor::ProcessGroupBitwise;
|
_perGroupProcessCall[11] = &VisjectExecutor::ProcessGroupBitwise;
|
||||||
_perGroupProcessCall[12] = &VisjectExecutor::ProcessGroupComparisons;
|
_perGroupProcessCall[12] = &VisjectExecutor::ProcessGroupComparisons;
|
||||||
_perGroupProcessCall[14] = &VisjectExecutor::ProcessGroupParticles;
|
_perGroupProcessCall[14] = &VisjectExecutor::ProcessGroupParticles;
|
||||||
|
_perGroupProcessCall[18] = &VisjectExecutor::ProcessGroupCollections;
|
||||||
}
|
}
|
||||||
|
|
||||||
VisjectExecutor::~VisjectExecutor()
|
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<Node>(), 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<Node>(), 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<Node>(), 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<Node>(), 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<Node>(), 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<Node>(), 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)
|
VisjectExecutor::Value VisjectExecutor::tryGetValue(Box* box, int32 defaultValueBoxIndex, const Value& defaultValue)
|
||||||
{
|
{
|
||||||
const auto parentNode = box->GetParent<Node>();
|
const auto parentNode = box->GetParent<Node>();
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
ProcessBoxHandler _perGroupProcessCall[18];
|
ProcessBoxHandler _perGroupProcessCall[19];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -256,6 +256,7 @@ public:
|
|||||||
void ProcessGroupBitwise(Box* box, Node* node, Value& value);
|
void ProcessGroupBitwise(Box* box, Node* node, Value& value);
|
||||||
void ProcessGroupComparisons(Box* box, Node* node, Value& value);
|
void ProcessGroupComparisons(Box* box, Node* node, Value& value);
|
||||||
void ProcessGroupParticles(Box* box, Node* node, Value& value);
|
void ProcessGroupParticles(Box* box, Node* node, Value& value);
|
||||||
|
void ProcessGroupCollections(Box* box, Node* node, Value& value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user