Refactor #1671
This commit is contained in:
@@ -7,11 +7,12 @@ using Real = System.Single;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using FlaxEditor.CustomEditors.Editors;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEditor.Surface.Elements;
|
||||
using FlaxEditor.Surface.Undo;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Utilities;
|
||||
@@ -24,6 +25,101 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
[HideInEditor]
|
||||
public static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// A special type of node that adds the functionality to convert nodes to parameters.
|
||||
/// </summary>
|
||||
internal class ConvertToParameterNode : SurfaceNode
|
||||
{
|
||||
private readonly ScriptType _type;
|
||||
private readonly Func<object[], object> _convertFunction;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConvertToParameterNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch, ScriptType type, Func<object[], object> convertFunction = null)
|
||||
: base(id, context, nodeArch, groupArch)
|
||||
{
|
||||
_type = type;
|
||||
_convertFunction = convertFunction;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnShowSecondaryContextMenu(FlaxEditor.GUI.ContextMenu.ContextMenu menu, Float2 location)
|
||||
{
|
||||
base.OnShowSecondaryContextMenu(menu, location);
|
||||
|
||||
menu.AddSeparator();
|
||||
menu.AddButton("Convert to Parameter", OnConvertToParameter);
|
||||
}
|
||||
|
||||
private void OnConvertToParameter()
|
||||
{
|
||||
if (Surface.Owner is not IVisjectSurfaceWindow window)
|
||||
throw new Exception("Surface owner is not a Visject Surface Window");
|
||||
|
||||
Asset asset = Surface.Owner.SurfaceAsset;
|
||||
if (asset == null || !asset.IsLoaded)
|
||||
{
|
||||
Editor.LogError("Asset is null or not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add parameter to editor
|
||||
var paramIndex = Surface.Parameters.Count;
|
||||
var initValue = _convertFunction == null ? Values[0] : _convertFunction.Invoke(Values);
|
||||
var paramAction = new AddRemoveParamAction
|
||||
{
|
||||
Window = window,
|
||||
IsAdd = true,
|
||||
Name = Utilities.Utils.IncrementNameNumber("New parameter", OnParameterRenameValidate),
|
||||
Type = _type,
|
||||
Index = paramIndex,
|
||||
InitValue = initValue,
|
||||
};
|
||||
paramAction.Do();
|
||||
|
||||
// Spawn Get Parameter Node based on the added parameter
|
||||
Guid parameterGuid = Surface.Parameters[paramIndex].ID;
|
||||
bool undoEnabled = Surface.Undo.Enabled;
|
||||
Surface.Undo.Enabled = false;
|
||||
NodeArchetype arch = Surface.GetParameterGetterNodeArchetype(out var groupId);
|
||||
SurfaceNode node = Surface.Context.SpawnNode(groupId, arch.TypeID, Location, new object[] { parameterGuid });
|
||||
Surface.Undo.Enabled = undoEnabled;
|
||||
if (node is not Parameters.SurfaceNodeParamsGet getNode)
|
||||
throw new Exception("Node is not a ParamsGet node!");
|
||||
|
||||
// Recreate connections of constant node
|
||||
// Constant nodes and parameter nodes should have the same ports, so we can just iterate through the connections
|
||||
var boxes = GetBoxes();
|
||||
for (int i = 0; i < boxes.Count; i++)
|
||||
{
|
||||
Box box = boxes[i];
|
||||
if (!box.HasAnyConnection)
|
||||
continue;
|
||||
if (!getNode.TryGetBox(box.ID, out Box paramBox))
|
||||
continue;
|
||||
|
||||
// Iterating backwards, because the CreateConnection method deletes entries from the box connections when target box IsSingle is set to true
|
||||
for (int k = box.Connections.Count - 1; k >= 0; k--)
|
||||
{
|
||||
Box connectedBox = box.Connections[k];
|
||||
paramBox.CreateConnection(connectedBox);
|
||||
}
|
||||
}
|
||||
|
||||
// Add undo actions and remove constant node
|
||||
var spawnNodeAction = new AddRemoveNodeAction(getNode, true);
|
||||
var removeConstantAction = new AddRemoveNodeAction(this, false);
|
||||
Surface.AddBatchedUndoAction(new MultiUndoAction(paramAction, spawnNodeAction, removeConstantAction));
|
||||
removeConstantAction.Do();
|
||||
}
|
||||
|
||||
private bool OnParameterRenameValidate(string value)
|
||||
{
|
||||
if (Surface.Owner is not IVisjectSurfaceWindow window)
|
||||
throw new Exception("Surface owner is not a Visject Surface Window");
|
||||
return !string.IsNullOrWhiteSpace(value) && window.VisjectSurface.Parameters.All(x => x.Name != value);
|
||||
}
|
||||
}
|
||||
|
||||
private class EnumNode : SurfaceNode
|
||||
{
|
||||
private EnumComboBox _picker;
|
||||
@@ -356,7 +452,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 1,
|
||||
Title = "Bool",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(bool))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(bool))),
|
||||
Description = "Constant boolean value",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(110, 20),
|
||||
@@ -389,7 +485,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 2,
|
||||
Title = "Integer",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(int))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(int))),
|
||||
Description = "Constant integer value",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(110, 20),
|
||||
@@ -417,7 +513,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 3,
|
||||
Title = "Float",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(float))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(float))),
|
||||
Description = "Constant floating point",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(110, 20),
|
||||
@@ -445,7 +541,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 4,
|
||||
Title = "Float2",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Float2))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Float2))),
|
||||
Description = "Constant Float2",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(130, 60),
|
||||
@@ -476,7 +572,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 5,
|
||||
Title = "Float3",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Float3))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Float3))),
|
||||
Description = "Constant Float3",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(130, 80),
|
||||
@@ -509,7 +605,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 6,
|
||||
Title = "Float4",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Float4))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Float4))),
|
||||
Description = "Constant Float4",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(130, 100),
|
||||
@@ -544,7 +640,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 7,
|
||||
Title = "Color",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Color))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Color))),
|
||||
Description = "RGBA color",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(70, 100),
|
||||
@@ -577,10 +673,8 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 8,
|
||||
Title = "Rotation",
|
||||
// TODO: Way too long and ugly - find a better way to add conversion
|
||||
Create = (id, context, arch, groupArch) =>
|
||||
new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Quaternion)),
|
||||
values => Quaternion.Euler((float)values[0], (float)values[1], (float)values[2])),
|
||||
new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Quaternion)), values => Quaternion.Euler((float)values[0], (float)values[1], (float)values[2])),
|
||||
Description = "Euler angle rotation",
|
||||
Flags = NodeFlags.AnimGraph | NodeFlags.VisualScriptGraph | NodeFlags.ParticleEmitterGraph,
|
||||
Size = new Float2(110, 60),
|
||||
@@ -605,7 +699,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 9,
|
||||
Title = "String",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(string))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(string))),
|
||||
Description = "Text",
|
||||
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
|
||||
Size = new Float2(200, 20),
|
||||
@@ -656,8 +750,8 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 12,
|
||||
Title = "Unsigned Integer",
|
||||
AlternativeTitles = new[] { "UInt" , "U Int" },
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(uint))),
|
||||
AlternativeTitles = new[] { "UInt", "U Int" },
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(uint))),
|
||||
Description = "Constant unsigned integer value",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(170, 20),
|
||||
@@ -697,7 +791,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 15,
|
||||
Title = "Double",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(double))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(double))),
|
||||
Description = "Constant floating point",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(110, 20),
|
||||
@@ -715,7 +809,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 16,
|
||||
Title = "Vector2",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Vector2))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Vector2))),
|
||||
Description = "Constant Vector2",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(130, 60),
|
||||
@@ -736,7 +830,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 17,
|
||||
Title = "Vector3",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Vector3))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Vector3))),
|
||||
Description = "Constant Vector3",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(130, 80),
|
||||
@@ -759,7 +853,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 18,
|
||||
Title = "Vector4",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Vector4))),
|
||||
Create = (id, context, arch, groupArch) => new ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Vector4))),
|
||||
Description = "Constant Vector4",
|
||||
Flags = NodeFlags.AllGraphs,
|
||||
Size = new Float2(130, 100),
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 1,
|
||||
Title = "Texture",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(Texture))),
|
||||
Create = (id, context, arch, groupArch) => new Constants.ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(Texture))),
|
||||
Description = "Two dimensional texture object",
|
||||
Flags = NodeFlags.MaterialGraph,
|
||||
Size = new Float2(140, 120),
|
||||
@@ -133,7 +133,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 3,
|
||||
Title = "Cube Texture",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(CubeTexture))),
|
||||
Create = (id, context, arch, groupArch) => new Constants.ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(CubeTexture))),
|
||||
Description = "Set of 6 textures arranged in a cube",
|
||||
Flags = NodeFlags.MaterialGraph,
|
||||
Size = new Float2(140, 120),
|
||||
@@ -157,7 +157,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
TypeID = 4,
|
||||
Title = "Normal Map",
|
||||
Create = (id, context, arch, groupArch) => new ConvertibleNode(id, context, arch, groupArch, new ScriptType(typeof(NormalMap))),
|
||||
Create = (id, context, arch, groupArch) => new Constants.ConvertToParameterNode(id, context, arch, groupArch, new ScriptType(typeof(NormalMap))),
|
||||
Description = "Two dimensional texture object sampled as a normal map",
|
||||
Flags = NodeFlags.MaterialGraph,
|
||||
Size = new Float2(140, 120),
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEditor.Surface.Elements;
|
||||
using FlaxEditor.Surface.Undo;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Surface
|
||||
{
|
||||
/// <summary>
|
||||
/// A special type of node that adds the functionality to convert nodes to parameters
|
||||
/// </summary>
|
||||
internal class ConvertibleNode : SurfaceNode
|
||||
{
|
||||
private readonly ScriptType _type;
|
||||
private readonly Func<object[], object> _convertFunction;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConvertibleNode(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch, ScriptType type, Func<object[], object> convertFunction = null)
|
||||
: base(id, context, nodeArch, groupArch)
|
||||
{
|
||||
_type = type;
|
||||
_convertFunction = convertFunction;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnShowSecondaryContextMenu(FlaxEditor.GUI.ContextMenu.ContextMenu menu, Float2 location)
|
||||
{
|
||||
base.OnShowSecondaryContextMenu(menu, location);
|
||||
|
||||
menu.AddSeparator();
|
||||
menu.AddButton("Convert to Parameter", OnConvertToParameter);
|
||||
}
|
||||
|
||||
private void OnConvertToParameter()
|
||||
{
|
||||
if (Surface.Owner is not IVisjectSurfaceWindow window)
|
||||
throw new Exception("Surface owner is not a Visject Surface Window");
|
||||
|
||||
Asset asset = Surface.Owner.SurfaceAsset;
|
||||
if (asset == null || !asset.IsLoaded)
|
||||
{
|
||||
Editor.LogError("Asset is null or not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add parameter to editor
|
||||
var paramIndex = Surface.Parameters.Count;
|
||||
object initValue = _convertFunction == null ? Values[0] : _convertFunction.Invoke(Values);
|
||||
var paramAction = new AddRemoveParamAction
|
||||
{
|
||||
Window = window,
|
||||
IsAdd = true,
|
||||
Name = Utilities.Utils.IncrementNameNumber("New parameter", x => OnParameterRenameValidate(x)),
|
||||
Type = _type,
|
||||
Index = paramIndex,
|
||||
InitValue = initValue,
|
||||
};
|
||||
paramAction.Do();
|
||||
|
||||
// Spawn Get Parameter Node based on the added parameter
|
||||
Guid parameterGuid = Surface.Parameters[paramIndex].ID;
|
||||
bool undoEnabled = Surface.Undo.Enabled;
|
||||
Surface.Undo.Enabled = false;
|
||||
NodeArchetype arch = Surface.GetParameterGetterNodeArchetype(out var groupId);
|
||||
SurfaceNode node = Surface.Context.SpawnNode(groupId, arch.TypeID, this.Location, new object[] { parameterGuid });
|
||||
Surface.Undo.Enabled = undoEnabled;
|
||||
|
||||
if (node is not Archetypes.Parameters.SurfaceNodeParamsGet getNode)
|
||||
throw new Exception("Node is not a ParamsGet node!");
|
||||
|
||||
// Recreate connections of constant node
|
||||
// Constant nodes and parameter nodes should have the same ports, so we can just iterate through the connections
|
||||
var boxes = GetBoxes();
|
||||
for (int i = 0; i < boxes.Count; i++)
|
||||
{
|
||||
Box box = boxes[i];
|
||||
if (!box.HasAnyConnection)
|
||||
continue;
|
||||
|
||||
if (!getNode.TryGetBox(box.ID, out Box paramBox))
|
||||
continue;
|
||||
|
||||
// Iterating backwards, because the CreateConnection method deletes entries from the box connections when target box IsSingle is set to true
|
||||
for (int k = box.Connections.Count - 1; k >= 0; k--)
|
||||
{
|
||||
Box connectedBox = box.Connections[k];
|
||||
paramBox.CreateConnection(connectedBox);
|
||||
}
|
||||
}
|
||||
|
||||
// Add undo actions and remove constant node
|
||||
var spawnNodeAction = new AddRemoveNodeAction(getNode, true);
|
||||
var removeConstantAction = new AddRemoveNodeAction(this, false);
|
||||
|
||||
Surface.AddBatchedUndoAction(new MultiUndoAction(paramAction, spawnNodeAction, removeConstantAction));
|
||||
removeConstantAction.Do();
|
||||
}
|
||||
|
||||
private bool OnParameterRenameValidate(string value)
|
||||
{
|
||||
if (Surface.Owner is not IVisjectSurfaceWindow window)
|
||||
throw new Exception("Surface owner is not a Visject Surface Window");
|
||||
return !string.IsNullOrWhiteSpace(value) && window.VisjectSurface.Parameters.All(x => x.Name != value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ namespace FlaxEditor.Surface
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="initValue">The initial value to use. Null to use automatic default value.</param>
|
||||
/// <returns>The created parameter.</returns>
|
||||
public static SurfaceParameter Create(ScriptType type, string name, object initValue = null)
|
||||
{
|
||||
|
||||
@@ -279,7 +279,7 @@ namespace FlaxEditor.Surface
|
||||
public ScriptType Type;
|
||||
|
||||
/// <summary>
|
||||
/// The value to initialize the parameter with. (Can be null)
|
||||
/// The value to initialize the parameter with. Can be null to use default one for the parameter type.
|
||||
/// </summary>
|
||||
public object InitValue;
|
||||
|
||||
@@ -1065,7 +1065,6 @@ namespace FlaxEditor.Surface
|
||||
public virtual void OnParamRemoveUndo()
|
||||
{
|
||||
_refreshPropertiesOnLoad = true;
|
||||
//_propertiesEditor.BuildLayoutOnUpdate();
|
||||
_propertiesEditor.BuildLayout();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user