diff --git a/Source/Editor/Surface/Archetypes/Comparisons.cs b/Source/Editor/Surface/Archetypes/Comparisons.cs index 0dbd4bdba..0744c45ff 100644 --- a/Source/Editor/Surface/Archetypes/Comparisons.cs +++ b/Source/Editor/Surface/Archetypes/Comparisons.cs @@ -1,5 +1,9 @@ // Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. +using System.Collections.Generic; +using FlaxEditor.GUI; +using FlaxEditor.Scripting; +using FlaxEditor.Surface.Elements; using FlaxEngine; namespace FlaxEditor.Surface.Archetypes @@ -39,6 +43,128 @@ namespace FlaxEditor.Surface.Archetypes }; } + private class SwitchOnEnumNode : SurfaceNode + { + public SwitchOnEnumNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch) + : base(id, context, nodeArch, groupArch) + { + } + + public override void OnLoaded() + { + base.OnLoaded(); + + // Restore saved input boxes layout + if (Values[0] is byte[] data) + { + for (int i = 0; i < data.Length / 4; i++) + AddBox(false, i + 2, i + 1, string.Empty, new ScriptType(), true); + } + } + + public override void OnSurfaceLoaded() + { + base.OnSurfaceLoaded(); + + UpdateBoxes(); + GetBox(0).CurrentTypeChanged += box => UpdateBoxes(); + } + + public override void ConnectionTick(Box box) + { + base.ConnectionTick(box); + + UpdateBoxes(); + } + + private unsafe void UpdateBoxes() + { + var valueBox = (InputBox)GetBox(0); + const int firstBox = 2; + const int maxBoxes = 40; + bool isInvalid = false; + var data = Utils.GetEmptyArray(); + + if (valueBox.HasAnyConnection) + { + var valueType = valueBox.CurrentType; + if (valueType.IsEnum) + { + // Get enum entries + var entries = new List(); + EnumComboBox.BuildEntriesDefault(valueType.Type, entries); + + // Setup switch value inputs + int id = firstBox; + ScriptType type = new ScriptType(); + for (; id < maxBoxes; id++) + { + var box = GetBox(id); + if (box == null) + break; + if (box.HasAnyConnection) + { + type = box.Connections[0].CurrentType; + break; + } + } + id = firstBox; + for (; id < entries.Count + firstBox; id++) + { + var e = entries[id - firstBox]; + var box = AddBox(false, id, id - 1, e.Name, type, true); + if (!string.IsNullOrEmpty(e.Tooltip)) + box.TooltipText = e.Tooltip; + } + for (; id < maxBoxes; id++) + { + var box = GetBox(id); + if (box == null) + break; + RemoveElement(box); + } + + // Setup output + var outputBox = (OutputBox)GetBox(1); + outputBox.CurrentType = type; + + // Build data about enum entries values for the runtime + if (Values[0] is byte[] dataPrev && dataPrev.Length == entries.Count * 4) + data = dataPrev; + else + data = new byte[entries.Count * 4]; + fixed (byte* dataPtr = data) + { + int* dataValues = (int*)dataPtr; + for (int i = 0; i < entries.Count; i++) + dataValues[i] = entries[i].Value; + } + } + else + { + // Not an enum + isInvalid = true; + } + } + + if (isInvalid) + { + // Remove input values boxes if switch value is unused + for (int id = firstBox; id < maxBoxes; id++) + { + var box = GetBox(id); + if (box == null) + break; + RemoveElement(box); + } + } + + Values[0] = data; + + ResizeAuto(); + } + } + /// /// The nodes for that group. /// @@ -81,6 +207,22 @@ namespace FlaxEditor.Surface.Archetypes NodeElementArchetype.Factory.Output(0, string.Empty, null, 3) } }, + new NodeArchetype + { + TypeID = 8, + Title = "Switch On Enum", + Create = (id, context, arch, groupArch) => new SwitchOnEnumNode(id, context, arch, groupArch), + Description = "Returns one of the input values based on the enum value", + Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph, + Size = new Vector2(160, 60), + DefaultValues = new object[] { Utils.GetEmptyArray() }, + ConnectionsHints = ConnectionsHint.Enum, + Elements = new[] + { + NodeElementArchetype.Factory.Input(0, "Value", true, null, 0), + NodeElementArchetype.Factory.Output(0, string.Empty, null, 1), + } + }, }; } } diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp index 0a719e179..9edc7a2a3 100644 --- a/Source/Engine/Visject/VisjectGraph.cpp +++ b/Source/Engine/Visject/VisjectGraph.cpp @@ -860,6 +860,28 @@ void VisjectExecutor::ProcessGroupComparisons(Box* box, Node* node, Value& value else value = tryGetValue(node->GetBox(1), 0, Value::Zero); break; + } + // Switch On Enum + case 8: + { + const Value v = tryGetValue(node->GetBox(0), Value::Null); + if (v.Type.Type == VariantType::Enum && node->Values.Count() == 1 && node->Values[0].Type.Type == VariantType::Blob) + { + int32* dataValues = (int32*)node->Values[0].AsBlob.Data; + int32 dataValuesCount = node->Values[0].AsBlob.Length / 4; + int32 vAsInt = (int32)v; + for (int32 i = 0; i < dataValuesCount; i++) + { + if (dataValues[i] == vAsInt) + { + value = tryGetValue(node->GetBox(i + 2), Value::Null); + break; + } + } + } + else + value = Value::Null; + break; } } }