Add Switch On Enum node

This commit is contained in:
Wojciech Figat
2020-12-14 12:39:55 +01:00
parent 058ccf24b7
commit 1b818499b7
2 changed files with 164 additions and 0 deletions

View File

@@ -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<byte>();
if (valueBox.HasAnyConnection)
{
var valueType = valueBox.CurrentType;
if (valueType.IsEnum)
{
// Get enum entries
var entries = new List<EnumComboBox.Entry>();
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();
}
}
/// <summary>
/// The nodes for that group.
/// </summary>
@@ -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<byte>() },
ConnectionsHints = ConnectionsHint.Enum,
Elements = new[]
{
NodeElementArchetype.Factory.Input(0, "Value", true, null, 0),
NodeElementArchetype.Factory.Output(0, string.Empty, null, 1),
}
},
};
}
}

View File

@@ -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;
}
}
}