Merge branch 'Chikinsupu-Visject-DescriptionPanel'
This commit is contained in:
@@ -316,7 +316,9 @@ namespace FlaxEditor.Modules.SourceCodeEditing
|
|||||||
var memberReader = xmlReader.ReadSubtree();
|
var memberReader = xmlReader.ReadSubtree();
|
||||||
if (memberReader.ReadToDescendant("summary"))
|
if (memberReader.ReadToDescendant("summary"))
|
||||||
{
|
{
|
||||||
result[rawName] = memberReader.ReadInnerXml().Replace('\n', ' ').Trim();
|
// Remove <see cref=""/> and replace them with the captured group (the content of the cref). Additionally, getting rid of prefixes
|
||||||
|
const string crefPattern = @"<see\s+cref=""(?:[A-Z]:FlaxEngine\.)?([^""]+)""\s*\/>";
|
||||||
|
result[rawName] = Regex.Replace(memberReader.ReadInnerXml(), crefPattern, "$1").Replace('\n', ' ').Trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -375,6 +375,13 @@ namespace FlaxEditor.Options
|
|||||||
[EditorDisplay("Visject"), EditorOrder(550)]
|
[EditorDisplay("Visject"), EditorOrder(550)]
|
||||||
public float ConnectionCurvature { get; set; } = 1.0f;
|
public float ConnectionCurvature { get; set; } = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the visject connection curvature.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(true)]
|
||||||
|
[EditorDisplay("Visject"), EditorOrder(550), Tooltip("Shows/hides the description panel in the visual scripting context menu.")]
|
||||||
|
public bool VisualScriptingDescriptionPanel { get; set; } = true;
|
||||||
|
|
||||||
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
|
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
|
||||||
private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont);
|
private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont);
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
{
|
{
|
||||||
Op1(1, "Bitwise NOT", "Negates the value using bitwise operation", new[] { "!", "~" }),
|
Op1(1, "Bitwise NOT", "Negates the value using bitwise operation", new[] { "!", "~" }),
|
||||||
Op2(2, "Bitwise AND", "Performs a bitwise conjunction on two values", new[] { "&" }),
|
Op2(2, "Bitwise AND", "Performs a bitwise conjunction on two values", new[] { "&" }),
|
||||||
Op2(3, "Bitwise OR", "", new[] { "|" }),
|
Op2(3, "Bitwise OR", "Performs a bitwise disjunction on two values", new[] { "|" }),
|
||||||
Op2(4, "Bitwise XOR", "", new[] { "^" }),
|
Op2(4, "Bitwise XOR", "Performs a bitwise exclusive disjunction on two values", new[] { "^" }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
public static NodeArchetype[] Nodes =
|
public static NodeArchetype[] Nodes =
|
||||||
{
|
{
|
||||||
Op1(1, "Boolean NOT", "Negates the boolean value", new[] { "!", "~" }),
|
Op1(1, "Boolean NOT", "Negates the boolean value", new[] { "!", "~" }),
|
||||||
Op2(2, "Boolean AND", "Performs a logical conjunction on two values", new[] { "&&" }),
|
Op2(2, "Boolean AND", "Performs a logical conjunction on two values. Returns true if both of its operands are true", new[] { "&&" }),
|
||||||
Op2(3, "Boolean OR", "Returns true if either (or both) of its operands is true", new[] { "||" }),
|
Op2(3, "Boolean OR", "Performs a logical disjunction on two values. Returns true if either (or both) of its operands is true", new[] { "||" }),
|
||||||
Op2(4, "Boolean XOR", "", new[] { "^" }),
|
Op2(4, "Boolean XOR", "Performs a logical exclusive disjunction on two values. Returns true if both of its operands are different", new[] { "^" }),
|
||||||
Op2(5, "Boolean NOR", ""),
|
Op2(5, "Boolean NOR", "Performs a logical disjunction on two values and negates it. Returns true if both of its operands are false"),
|
||||||
Op2(6, "Boolean NAND", ""),
|
Op2(6, "Boolean NAND", "Performs a logical conjunction on two values and negates it. Returns true if either (or both) of its operands are false"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,6 +182,13 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
|
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void GetInputOutputDescription(NodeArchetype nodeArch, out (string, ScriptType)[] inputs, out (string, ScriptType)[] outputs)
|
||||||
|
{
|
||||||
|
var type = new ScriptType(nodeArch.DefaultValues[0].GetType());
|
||||||
|
inputs = null;
|
||||||
|
outputs = [(type.Name, type)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ArrayNode : SurfaceNode
|
private class ArrayNode : SurfaceNode
|
||||||
@@ -321,6 +328,12 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
array.SetValue(value, box.ID - 1);
|
array.SetValue(value, box.ID - 1);
|
||||||
SetValue(0, array);
|
SetValue(0, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void GetInputOutputDescription(NodeArchetype nodeArch, out (string, ScriptType)[] inputs, out (string, ScriptType)[] outputs)
|
||||||
|
{
|
||||||
|
inputs = null;
|
||||||
|
outputs = [("", new ScriptType(typeof(Array)))];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DictionaryNode : SurfaceNode
|
private class DictionaryNode : SurfaceNode
|
||||||
@@ -449,6 +462,12 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
array.SetValue(value, box.ID - 1);
|
array.SetValue(value, box.ID - 1);
|
||||||
SetValue(0, array);
|
SetValue(0, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void GetInputOutputDescription(NodeArchetype nodeArch, out (string, ScriptType)[] inputs, out (string, ScriptType)[] outputs)
|
||||||
|
{
|
||||||
|
inputs = null;
|
||||||
|
outputs = [("", new ScriptType(typeof(System.Collections.Generic.Dictionary<int, string>)))];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -743,6 +762,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
Title = "Enum",
|
Title = "Enum",
|
||||||
Create = (id, context, arch, groupArch) => new EnumNode(id, context, arch, groupArch),
|
Create = (id, context, arch, groupArch) => new EnumNode(id, context, arch, groupArch),
|
||||||
Description = "Enum constant value.",
|
Description = "Enum constant value.",
|
||||||
|
GetInputOutputDescription = EnumNode.GetInputOutputDescription,
|
||||||
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
|
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
|
||||||
Size = new Float2(180, 20),
|
Size = new Float2(180, 20),
|
||||||
DefaultValues = new object[]
|
DefaultValues = new object[]
|
||||||
@@ -779,6 +799,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
Title = "Array",
|
Title = "Array",
|
||||||
Create = (id, context, arch, groupArch) => new ArrayNode(id, context, arch, groupArch),
|
Create = (id, context, arch, groupArch) => new ArrayNode(id, context, arch, groupArch),
|
||||||
Description = "Constant array value.",
|
Description = "Constant array value.",
|
||||||
|
GetInputOutputDescription = ArrayNode.GetInputOutputDescription,
|
||||||
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
|
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
|
||||||
Size = new Float2(150, 20),
|
Size = new Float2(150, 20),
|
||||||
DefaultValues = new object[] { new int[] { 0, 1, 2 } },
|
DefaultValues = new object[] { new int[] { 0, 1, 2 } },
|
||||||
@@ -790,6 +811,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
Title = "Dictionary",
|
Title = "Dictionary",
|
||||||
Create = (id, context, arch, groupArch) => new DictionaryNode(id, context, arch, groupArch),
|
Create = (id, context, arch, groupArch) => new DictionaryNode(id, context, arch, groupArch),
|
||||||
Description = "Creates an empty dictionary.",
|
Description = "Creates an empty dictionary.",
|
||||||
|
GetInputOutputDescription = DictionaryNode.GetInputOutputDescription,
|
||||||
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
|
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph,
|
||||||
Size = new Float2(150, 40),
|
Size = new Float2(150, 40),
|
||||||
DefaultValues = new object[] { typeof(int).FullName, typeof(string).FullName },
|
DefaultValues = new object[] { typeof(int).FullName, typeof(string).FullName },
|
||||||
|
|||||||
@@ -245,6 +245,29 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void GetInputOutputDescription(NodeArchetype nodeArch, out (string, ScriptType)[] inputs, out (string, ScriptType)[] outputs)
|
||||||
|
{
|
||||||
|
var typeName = (string)nodeArch.DefaultValues[0];
|
||||||
|
var type = TypeUtils.GetType(typeName);
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
var fields = type.GetMembers(BindingFlags.Public | BindingFlags.Instance).Where(x => x.IsField).ToArray();
|
||||||
|
var fieldsLength = fields.Length;
|
||||||
|
inputs = new (string, ScriptType)[fieldsLength];
|
||||||
|
for (var i = 0; i < fieldsLength; i++)
|
||||||
|
{
|
||||||
|
var field = fields[i];
|
||||||
|
inputs[i] = (field.Name, field.ValueType);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs = [(type.Name, type)];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs = null;
|
||||||
|
outputs = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class UnpackStructureNode : StructureNode
|
private sealed class UnpackStructureNode : StructureNode
|
||||||
@@ -283,6 +306,29 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void GetInputOutputDescription(NodeArchetype nodeArch, out (string, ScriptType)[] inputs, out (string, ScriptType)[] outputs)
|
||||||
|
{
|
||||||
|
var typeName = (string)nodeArch.DefaultValues[0];
|
||||||
|
var type = TypeUtils.GetType(typeName);
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
inputs = [(type.Name, type)];
|
||||||
|
|
||||||
|
var fields = type.GetMembers(BindingFlags.Public | BindingFlags.Instance).Where(x => x.IsField).ToArray();
|
||||||
|
var fieldsLength = fields.Length;
|
||||||
|
outputs = new (string, ScriptType)[fieldsLength];
|
||||||
|
for (var i = 0; i < fieldsLength; i++)
|
||||||
|
{
|
||||||
|
var field = fields[i];
|
||||||
|
outputs[i] = (field.Name, field.ValueType);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs = null;
|
||||||
|
outputs = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -411,6 +457,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
Create = (id, context, arch, groupArch) => new PackStructureNode(id, context, arch, groupArch),
|
Create = (id, context, arch, groupArch) => new PackStructureNode(id, context, arch, groupArch),
|
||||||
IsInputCompatible = PackStructureNode.IsInputCompatible,
|
IsInputCompatible = PackStructureNode.IsInputCompatible,
|
||||||
IsOutputCompatible = PackStructureNode.IsOutputCompatible,
|
IsOutputCompatible = PackStructureNode.IsOutputCompatible,
|
||||||
|
GetInputOutputDescription = PackStructureNode.GetInputOutputDescription,
|
||||||
Description = "Makes the structure data to from the components.",
|
Description = "Makes the structure data to from the components.",
|
||||||
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
|
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
|
||||||
Size = new Float2(180, 20),
|
Size = new Float2(180, 20),
|
||||||
@@ -523,6 +570,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
Create = (id, context, arch, groupArch) => new UnpackStructureNode(id, context, arch, groupArch),
|
Create = (id, context, arch, groupArch) => new UnpackStructureNode(id, context, arch, groupArch),
|
||||||
IsInputCompatible = UnpackStructureNode.IsInputCompatible,
|
IsInputCompatible = UnpackStructureNode.IsInputCompatible,
|
||||||
IsOutputCompatible = UnpackStructureNode.IsOutputCompatible,
|
IsOutputCompatible = UnpackStructureNode.IsOutputCompatible,
|
||||||
|
GetInputOutputDescription = UnpackStructureNode.GetInputOutputDescription,
|
||||||
Description = "Breaks the structure data to allow extracting components from it.",
|
Description = "Breaks the structure data to allow extracting components from it.",
|
||||||
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
|
Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI,
|
||||||
Size = new Float2(180, 20),
|
Size = new Float2(180, 20),
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
{
|
{
|
||||||
Name = module.Title,
|
Name = module.Title,
|
||||||
Tag = module.TypeID,
|
Tag = module.TypeID,
|
||||||
TooltipText = module.Description,
|
TooltipText = $"{(string.IsNullOrEmpty(module.Signature) ? module.Title : module.Signature)}\n{module.Description}",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cm.ItemClicked += item => AddModule((ushort)item.Tag);
|
cm.ItemClicked += item => AddModule((ushort)item.Tag);
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
using FlaxEditor.GUI.Input;
|
using FlaxEditor.GUI.Input;
|
||||||
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.GUI;
|
using FlaxEngine.GUI;
|
||||||
using FlaxEngine.Utilities;
|
using FlaxEngine.Utilities;
|
||||||
@@ -39,6 +41,9 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
/// <returns>TThe list of surface parameters or null if failed (readonly).</returns>
|
/// <returns>TThe list of surface parameters or null if failed (readonly).</returns>
|
||||||
public delegate List<SurfaceParameter> ParameterGetterDelegate();
|
public delegate List<SurfaceParameter> ParameterGetterDelegate();
|
||||||
|
|
||||||
|
private const float DefaultWidth = 300;
|
||||||
|
private const float DefaultHeight = 400;
|
||||||
|
|
||||||
private readonly List<VisjectCMGroup> _groups = new List<VisjectCMGroup>(16);
|
private readonly List<VisjectCMGroup> _groups = new List<VisjectCMGroup>(16);
|
||||||
private CheckBox _contextSensitiveToggle;
|
private CheckBox _contextSensitiveToggle;
|
||||||
private bool _contextSensitiveSearchEnabled = true;
|
private bool _contextSensitiveSearchEnabled = true;
|
||||||
@@ -52,10 +57,31 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
private NodeArchetype _parameterGetNodeArchetype;
|
private NodeArchetype _parameterGetNodeArchetype;
|
||||||
private NodeArchetype _parameterSetNodeArchetype;
|
private NodeArchetype _parameterSetNodeArchetype;
|
||||||
|
|
||||||
|
// Description panel elements
|
||||||
|
private readonly bool _useDescriptionPanel;
|
||||||
|
private bool _descriptionPanelVisible;
|
||||||
|
private readonly Panel _descriptionPanel;
|
||||||
|
private readonly Panel _descriptionPanelSeparator;
|
||||||
|
private readonly Image _descriptionDeclaringClassImage;
|
||||||
|
private readonly Label _descriptionSignatureLabel;
|
||||||
|
private readonly Label _descriptionLabel;
|
||||||
|
private readonly VerticalPanel _descriptionInputPanel;
|
||||||
|
private readonly VerticalPanel _descriptionOutputPanel;
|
||||||
|
private readonly SurfaceStyle _surfaceStyle;
|
||||||
|
private VisjectCMItem _selectedItem;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The selected item
|
/// The selected item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VisjectCMItem SelectedItem;
|
public VisjectCMItem SelectedItem
|
||||||
|
{
|
||||||
|
get => _selectedItem;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
_selectedItem = value;
|
||||||
|
_selectedItem?.OnSelect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event fired when any item in this popup menu gets clicked.
|
/// Event fired when any item in this popup menu gets clicked.
|
||||||
@@ -82,6 +108,11 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool CanSetParameters;
|
public bool CanSetParameters;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the surface should make use of a description panel drawn at the bottom of the context menu
|
||||||
|
/// </summary>
|
||||||
|
public bool UseDescriptionPanel;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The groups archetypes. Cannot be null.
|
/// The groups archetypes. Cannot be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -111,6 +142,11 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
/// The parameter setter node archetype to spawn when adding the parameter getter. Can be null.
|
/// The parameter setter node archetype to spawn when adding the parameter getter. Can be null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NodeArchetype ParameterSetNodeArchetype;
|
public NodeArchetype ParameterSetNodeArchetype;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The surface style to use to draw images in the description panel
|
||||||
|
/// </summary>
|
||||||
|
public SurfaceStyle Style;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -127,9 +163,11 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
_parameterGetNodeArchetype = info.ParameterGetNodeArchetype ?? Archetypes.Parameters.Nodes[0];
|
_parameterGetNodeArchetype = info.ParameterGetNodeArchetype ?? Archetypes.Parameters.Nodes[0];
|
||||||
if (info.CanSetParameters)
|
if (info.CanSetParameters)
|
||||||
_parameterSetNodeArchetype = info.ParameterSetNodeArchetype ?? Archetypes.Parameters.Nodes[3];
|
_parameterSetNodeArchetype = info.ParameterSetNodeArchetype ?? Archetypes.Parameters.Nodes[3];
|
||||||
|
_useDescriptionPanel = info.UseDescriptionPanel;
|
||||||
|
_surfaceStyle = info.Style;
|
||||||
|
|
||||||
// Context menu dimensions
|
// Context menu dimensions
|
||||||
Size = new Float2(300, 400);
|
Size = new Float2(_useDescriptionPanel ? DefaultWidth + 50f : DefaultWidth, DefaultHeight);
|
||||||
|
|
||||||
var headerPanel = new Panel(ScrollBars.None)
|
var headerPanel = new Panel(ScrollBars.None)
|
||||||
{
|
{
|
||||||
@@ -190,7 +228,6 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
Bounds = new Rectangle(0, _searchBox.Bottom + 1, Width, Height - _searchBox.Bottom - 2),
|
Bounds = new Rectangle(0, _searchBox.Bottom + 1, Width, Height - _searchBox.Bottom - 2),
|
||||||
Parent = this
|
Parent = this
|
||||||
};
|
};
|
||||||
|
|
||||||
_panel1 = panel1;
|
_panel1 = panel1;
|
||||||
|
|
||||||
// Create second panel (for groups arrangement)
|
// Create second panel (for groups arrangement)
|
||||||
@@ -202,6 +239,70 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
};
|
};
|
||||||
_groupsPanel = panel2;
|
_groupsPanel = panel2;
|
||||||
|
|
||||||
|
// Create description panel elements only when description panel is about to be used
|
||||||
|
if (_useDescriptionPanel)
|
||||||
|
{
|
||||||
|
_descriptionPanel = new Panel(ScrollBars.None)
|
||||||
|
{
|
||||||
|
Parent = this,
|
||||||
|
Bounds = new Rectangle(0, Height, Width, 0),
|
||||||
|
BackgroundColor = Style.Current.BackgroundNormal,
|
||||||
|
};
|
||||||
|
|
||||||
|
_descriptionDeclaringClassImage = new Image(8, 12, 20, 20)
|
||||||
|
{
|
||||||
|
Parent = _descriptionPanel,
|
||||||
|
Brush = new SpriteBrush(info.Style.Icons.BoxClose),
|
||||||
|
};
|
||||||
|
|
||||||
|
var descriptionFontReference = new FontReference(Style.Current.FontMedium.Asset, 9f);
|
||||||
|
_descriptionSignatureLabel = new Label(32, 8, Width - 40, 0)
|
||||||
|
{
|
||||||
|
Parent = _descriptionPanel,
|
||||||
|
HorizontalAlignment = TextAlignment.Near,
|
||||||
|
VerticalAlignment = TextAlignment.Near,
|
||||||
|
Wrapping = TextWrapping.WrapWords,
|
||||||
|
Font = descriptionFontReference,
|
||||||
|
Bold = true,
|
||||||
|
AutoHeight = true,
|
||||||
|
};
|
||||||
|
_descriptionSignatureLabel.SetAnchorPreset(AnchorPresets.TopLeft, true);
|
||||||
|
|
||||||
|
_descriptionLabel = new Label(32, 0, Width - 40, 0)
|
||||||
|
{
|
||||||
|
Parent = _descriptionPanel,
|
||||||
|
HorizontalAlignment = TextAlignment.Near,
|
||||||
|
VerticalAlignment = TextAlignment.Near,
|
||||||
|
Wrapping = TextWrapping.WrapWords,
|
||||||
|
Font = descriptionFontReference,
|
||||||
|
AutoHeight = true,
|
||||||
|
};
|
||||||
|
_descriptionLabel.SetAnchorPreset(AnchorPresets.TopLeft, true);
|
||||||
|
|
||||||
|
_descriptionPanelSeparator = new Panel(ScrollBars.None)
|
||||||
|
{
|
||||||
|
Parent = _descriptionPanel,
|
||||||
|
Bounds = new Rectangle(8, Height, Width - 16, 2),
|
||||||
|
BackgroundColor = Style.Current.BackgroundHighlighted,
|
||||||
|
};
|
||||||
|
|
||||||
|
_descriptionInputPanel = new VerticalPanel()
|
||||||
|
{
|
||||||
|
Parent = _descriptionPanel,
|
||||||
|
X = 8,
|
||||||
|
Width = Width * 0.5f - 16,
|
||||||
|
AutoSize = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
_descriptionOutputPanel = new VerticalPanel()
|
||||||
|
{
|
||||||
|
Parent = _descriptionPanel,
|
||||||
|
X = Width * 0.5f + 8,
|
||||||
|
Width = Width * 0.5f - 16,
|
||||||
|
AutoSize = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Init groups
|
// Init groups
|
||||||
var nodes = new List<NodeArchetype>();
|
var nodes = new List<NodeArchetype>();
|
||||||
foreach (var groupArchetype in info.Groups)
|
foreach (var groupArchetype in info.Groups)
|
||||||
@@ -693,9 +794,189 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
{
|
{
|
||||||
Focus(null);
|
Focus(null);
|
||||||
|
|
||||||
|
if (_useDescriptionPanel)
|
||||||
|
HideDescriptionPanel();
|
||||||
|
|
||||||
base.Hide();
|
base.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the description panel and shows information about the set archetype
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="archetype">The node archetype</param>
|
||||||
|
public void SetDescriptionPanelArchetype(NodeArchetype archetype)
|
||||||
|
{
|
||||||
|
if (!_useDescriptionPanel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (archetype == null || !Editor.Instance.Options.Options.Interface.VisualScriptingDescriptionPanel)
|
||||||
|
{
|
||||||
|
HideDescriptionPanel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Profiler.BeginEvent("VisjectCM.SetDescriptionPanelArchetype");
|
||||||
|
|
||||||
|
_descriptionInputPanel.RemoveChildren();
|
||||||
|
_descriptionOutputPanel.RemoveChildren();
|
||||||
|
|
||||||
|
// Fetch description and information from the memberInfo - mainly from nodes that got fetched asynchronously by the visual scripting editor
|
||||||
|
ScriptType declaringType;
|
||||||
|
if (archetype.Tag is ScriptMemberInfo memberInfo)
|
||||||
|
{
|
||||||
|
var name = memberInfo.Name;
|
||||||
|
if (memberInfo.IsMethod && memberInfo.Name.StartsWith("get_") || memberInfo.Name.StartsWith("set_"))
|
||||||
|
{
|
||||||
|
name = memberInfo.Name.Substring(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
declaringType = memberInfo.DeclaringType;
|
||||||
|
_descriptionSignatureLabel.Text = memberInfo.DeclaringType + "." + name;
|
||||||
|
|
||||||
|
// We have to add the Instance information manually for members that aren't static
|
||||||
|
if (!memberInfo.IsStatic)
|
||||||
|
AddInputOutputElement(archetype, declaringType, false, $"Instance ({memberInfo.DeclaringType.Name})");
|
||||||
|
|
||||||
|
// We also have to manually add the Return information as well.
|
||||||
|
if (memberInfo.ValueType != ScriptType.Null && memberInfo.ValueType != ScriptType.Void)
|
||||||
|
{
|
||||||
|
// When a field has a setter we don't want it to show the input as a return output.
|
||||||
|
if (memberInfo.IsField && archetype.Title.StartsWith("Set "))
|
||||||
|
AddInputOutputElement(archetype, memberInfo.ValueType, false, $"({memberInfo.ValueType.Name})");
|
||||||
|
else
|
||||||
|
AddInputOutputElement(archetype, memberInfo.ValueType, true, $"Return ({memberInfo.ValueType.Name})");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < memberInfo.ParametersCount; i++)
|
||||||
|
{
|
||||||
|
var param = memberInfo.GetParameters()[i];
|
||||||
|
AddInputOutputElement(archetype, param.Type, param.IsOut, $"{param.Name} ({param.Type.Name})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Try to fetch as many informations as possible from the predefined hardcoded nodes
|
||||||
|
_descriptionSignatureLabel.Text = string.IsNullOrEmpty(archetype.Signature) ? archetype.Title : archetype.Signature;
|
||||||
|
declaringType = archetype.DefaultType;
|
||||||
|
|
||||||
|
// Some nodes are more delicate. Like Arrays or Dictionaries. In this case we let them fetch the inputs/outputs for us.
|
||||||
|
// Otherwise, it is not possible to show a proper return type on some nodes.
|
||||||
|
if (archetype.GetInputOutputDescription != null)
|
||||||
|
{
|
||||||
|
archetype.GetInputOutputDescription.Invoke(archetype, out var inputs, out var outputs);
|
||||||
|
|
||||||
|
foreach (var input in inputs ?? [])
|
||||||
|
{
|
||||||
|
AddInputOutputElement(archetype, input.Type, false, $"{input.Name} ({input.Type.Name})");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var output in outputs ?? [])
|
||||||
|
{
|
||||||
|
AddInputOutputElement(archetype, output.Type, true, $"{output.Name} ({output.Type.Name})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var element in archetype.Elements)
|
||||||
|
{
|
||||||
|
if (element.Type is not (NodeElementType.Input or NodeElementType.Output))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var typeText = element.ConnectionsType ? element.ConnectionsType.Name : archetype.ConnectionsHints.ToString();
|
||||||
|
AddInputOutputElement(archetype, element.ConnectionsType, element.Type == NodeElementType.Output, $"{element.Text} ({typeText})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set declaring type icon color
|
||||||
|
_surfaceStyle.GetConnectionColor(declaringType, archetype.ConnectionsHints, out var declaringTypeColor);
|
||||||
|
_descriptionDeclaringClassImage.Color = declaringTypeColor;
|
||||||
|
_descriptionDeclaringClassImage.MouseOverColor = declaringTypeColor;
|
||||||
|
|
||||||
|
// Calculate the description panel height. (I am doing this manually since working with autoSize on horizontal/vertical panels didn't work, especially with nesting - Nils)
|
||||||
|
float panelHeight = _descriptionSignatureLabel.Height;
|
||||||
|
|
||||||
|
// If thee is no description we move the signature label down a bit to align it with the icon. Just a cosmetic check
|
||||||
|
if (string.IsNullOrEmpty(archetype.Description))
|
||||||
|
{
|
||||||
|
_descriptionSignatureLabel.Y = 15;
|
||||||
|
_descriptionLabel.Text = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_descriptionSignatureLabel.Y = 8;
|
||||||
|
_descriptionLabel.Y = _descriptionSignatureLabel.Bounds.Bottom + 6f;
|
||||||
|
// Replacing multiple whitespaces with a linebreak for better readability. (Mainly doing this because the ToolTip fetching system replaces linebreaks with whitespaces - Nils)
|
||||||
|
_descriptionLabel.Text = Regex.Replace(archetype.Description, @"\s{2,}", "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some padding and moving elements around
|
||||||
|
_descriptionPanelSeparator.Y = _descriptionLabel.Bounds.Bottom + 8f;
|
||||||
|
panelHeight += _descriptionLabel.Height + 32f;
|
||||||
|
_descriptionInputPanel.Y = panelHeight;
|
||||||
|
_descriptionOutputPanel.Y = panelHeight;
|
||||||
|
panelHeight += Mathf.Max(_descriptionInputPanel.Height, _descriptionOutputPanel.Height);
|
||||||
|
|
||||||
|
// Forcing the description panel to at least have a minimum height to not make the window size change too much in order to reduce jittering
|
||||||
|
// TODO: Remove the Mathf.Max and just set the height to panelHeight once the window jitter issue is fixed - Nils
|
||||||
|
_descriptionPanel.Height = Mathf.Max(140f, panelHeight);
|
||||||
|
Height = DefaultHeight + _descriptionPanel.Height;
|
||||||
|
UpdateWindowSize();
|
||||||
|
_descriptionPanelVisible = true;
|
||||||
|
|
||||||
|
Profiler.EndEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddInputOutputElement(NodeArchetype nodeArchetype, ScriptType type, bool isOutput, string text)
|
||||||
|
{
|
||||||
|
// Using a panel instead of a vertical panel because auto sizing is unreliable - so we are doing this manually here as well
|
||||||
|
var elementPanel = new Panel()
|
||||||
|
{
|
||||||
|
Parent = isOutput ? _descriptionOutputPanel : _descriptionInputPanel,
|
||||||
|
Width = Width * 0.5f,
|
||||||
|
Height = 16,
|
||||||
|
AnchorPreset = AnchorPresets.TopLeft
|
||||||
|
};
|
||||||
|
|
||||||
|
_surfaceStyle.GetConnectionColor(type, nodeArchetype.ConnectionsHints, out var typeColor);
|
||||||
|
elementPanel.AddChild(new Image(2, 0, 12, 12)
|
||||||
|
{
|
||||||
|
Brush = new SpriteBrush(_surfaceStyle.Icons.BoxOpen),
|
||||||
|
Color = typeColor,
|
||||||
|
MouseOverColor = typeColor,
|
||||||
|
AutoFocus = false,
|
||||||
|
}).SetAnchorPreset(AnchorPresets.TopLeft, true);
|
||||||
|
|
||||||
|
// Forcing the first letter to be capital and removing the '&' char from pointer-references
|
||||||
|
text = (char.ToUpper(text[0]) + text.Substring(1)).Replace("&", "");
|
||||||
|
var elementText = new Label(16, 0, Width * 0.5f - 32, 16)
|
||||||
|
{
|
||||||
|
Text = text,
|
||||||
|
HorizontalAlignment = TextAlignment.Near,
|
||||||
|
VerticalAlignment = TextAlignment.Near,
|
||||||
|
Wrapping = TextWrapping.WrapWords,
|
||||||
|
AutoHeight = true,
|
||||||
|
};
|
||||||
|
elementText.SetAnchorPreset(AnchorPresets.TopLeft, true);
|
||||||
|
elementPanel.AddChild(elementText);
|
||||||
|
elementPanel.Height = elementText.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides the description panel and resets the context menu to its original size
|
||||||
|
/// </summary>
|
||||||
|
private void HideDescriptionPanel()
|
||||||
|
{
|
||||||
|
if (!_descriptionPanelVisible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_descriptionInputPanel.RemoveChildren();
|
||||||
|
_descriptionOutputPanel.RemoveChildren();
|
||||||
|
Height = DefaultHeight;
|
||||||
|
UpdateWindowSize();
|
||||||
|
_descriptionPanelVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnKeyDown(KeyboardKeys key)
|
public override bool OnKeyDown(KeyboardKeys key)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEditor.Surface.Elements;
|
using FlaxEditor.Surface.Elements;
|
||||||
using FlaxEditor.Utilities;
|
using FlaxEditor.Utilities;
|
||||||
@@ -62,7 +63,7 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
Group = group;
|
Group = group;
|
||||||
_groupArchetype = groupArchetype;
|
_groupArchetype = groupArchetype;
|
||||||
_archetype = archetype;
|
_archetype = archetype;
|
||||||
TooltipText = _archetype.Description;
|
TooltipText = GetTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -315,6 +316,23 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback when selected by the visject CM
|
||||||
|
/// </summary>
|
||||||
|
public void OnSelect()
|
||||||
|
{
|
||||||
|
Group.ContextMenu.SetDescriptionPanelArchetype(_archetype);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetTooltip()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append(string.IsNullOrEmpty(_archetype.Signature) ? _archetype.Title : _archetype.Signature);
|
||||||
|
if (!string.IsNullOrEmpty(_archetype.Description))
|
||||||
|
sb.Append("\n" + _archetype.Description);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||||
{
|
{
|
||||||
@@ -338,6 +356,14 @@ namespace FlaxEditor.Surface.ContextMenu
|
|||||||
return base.OnMouseUp(location, button);
|
return base.OnMouseUp(location, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnMouseEnter(Float2 location)
|
||||||
|
{
|
||||||
|
Group.ContextMenu.SetDescriptionPanelArchetype(_archetype);
|
||||||
|
|
||||||
|
base.OnMouseEnter(location);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnMouseLeave()
|
public override void OnMouseLeave()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -90,10 +90,15 @@ namespace FlaxEditor.Surface
|
|||||||
public delegate SurfaceNode CreateCustomNodeFunc(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch);
|
public delegate SurfaceNode CreateCustomNodeFunc(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the given type is compatible with the given node archetype. Used for custom nodes
|
/// Checks if the given type is compatible with the given node archetype. Used for custom nodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public delegate bool IsCompatible(NodeArchetype nodeArch, ScriptType portType, ConnectionsHint hint, VisjectSurfaceContext context);
|
public delegate bool IsCompatible(NodeArchetype nodeArch, ScriptType portType, ConnectionsHint hint, VisjectSurfaceContext context);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets description of inputs and outputs of the archetype. Used for special cases for the description panel.
|
||||||
|
/// </summary>
|
||||||
|
public delegate void GetElementsDescriptionFunc(NodeArchetype nodeArch, out (string Name, ScriptType Type)[] inputs, out (string Name, ScriptType Type)[] outputs);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unique node type ID within a single group.
|
/// Unique node type ID within a single group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -134,11 +139,21 @@ namespace FlaxEditor.Surface
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string SubTitle;
|
public string SubTitle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Node signature for tooltip and description purposes
|
||||||
|
/// </summary>
|
||||||
|
public string Signature;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Short node description.
|
/// Short node description.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Description;
|
public string Description;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom function to get descriptions of input and output elements. Used for description panel (optional).
|
||||||
|
/// </summary>
|
||||||
|
public GetElementsDescriptionFunc GetInputOutputDescription;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Alternative node titles.
|
/// Alternative node titles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -210,7 +225,9 @@ namespace FlaxEditor.Surface
|
|||||||
Flags = Flags,
|
Flags = Flags,
|
||||||
Title = Title,
|
Title = Title,
|
||||||
SubTitle = SubTitle,
|
SubTitle = SubTitle,
|
||||||
|
Signature = Signature,
|
||||||
Description = Description,
|
Description = Description,
|
||||||
|
GetInputOutputDescription = GetInputOutputDescription,
|
||||||
AlternativeTitles = (string[])AlternativeTitles?.Clone(),
|
AlternativeTitles = (string[])AlternativeTitles?.Clone(),
|
||||||
Tag = Tag,
|
Tag = Tag,
|
||||||
SortScore = SortScore,
|
SortScore = SortScore,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEditor.Surface.Elements;
|
using FlaxEditor.Surface.Elements;
|
||||||
using FlaxEditor.Surface.Undo;
|
using FlaxEditor.Surface.Undo;
|
||||||
@@ -124,7 +125,7 @@ namespace FlaxEditor.Surface
|
|||||||
Archetype = nodeArch;
|
Archetype = nodeArch;
|
||||||
GroupArchetype = groupArch;
|
GroupArchetype = groupArch;
|
||||||
AutoFocus = false;
|
AutoFocus = false;
|
||||||
TooltipText = nodeArch.Description;
|
TooltipText = GetTooltip();
|
||||||
CullChildren = false;
|
CullChildren = false;
|
||||||
BackgroundColor = Style.Current.BackgroundNormal;
|
BackgroundColor = Style.Current.BackgroundNormal;
|
||||||
|
|
||||||
@@ -851,6 +852,15 @@ namespace FlaxEditor.Surface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetTooltip()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append(string.IsNullOrEmpty(Archetype.Signature) ? Archetype.Title : Archetype.Signature);
|
||||||
|
if (!string.IsNullOrEmpty(Archetype.Description))
|
||||||
|
sb.Append("\n" + Archetype.Description);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override bool ShowTooltip => base.ShowTooltip && _headerRect.Contains(ref _mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened;
|
protected override bool ShowTooltip => base.ShowTooltip && _headerRect.Contains(ref _mousePosition) && !Surface.IsLeftMouseButtonDown && !Surface.IsRightMouseButtonDown && !Surface.IsPrimaryMenuOpened;
|
||||||
|
|
||||||
|
|||||||
@@ -440,12 +440,23 @@ namespace FlaxEditor.Surface
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetVisualScriptMemberInfoDescription(ScriptMemberInfo member)
|
internal static string GetVisualScriptMemberInfoSignature(ScriptMemberInfo member)
|
||||||
{
|
{
|
||||||
var name = member.Name;
|
var name = member.Name;
|
||||||
var declaringType = member.DeclaringType;
|
var declaringType = member.DeclaringType;
|
||||||
var valueType = member.ValueType;
|
var valueType = member.ValueType;
|
||||||
|
|
||||||
|
// Getter/setter method of the property - we can return early here
|
||||||
|
if (member.IsMethod && (name.StartsWith("get_") || name.StartsWith("set_")))
|
||||||
|
{
|
||||||
|
var flags = member.IsStatic ? BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly : BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
||||||
|
var property = declaringType.GetMembers(name.Substring(4), MemberTypes.Property, flags);
|
||||||
|
if (property != null && property.Length != 0)
|
||||||
|
{
|
||||||
|
return GetVisualScriptMemberInfoSignature(property[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
if (member.IsStatic)
|
if (member.IsStatic)
|
||||||
sb.Append("static ");
|
sb.Append("static ");
|
||||||
@@ -456,32 +467,19 @@ namespace FlaxEditor.Surface
|
|||||||
sb.Append(declaringType.Name);
|
sb.Append(declaringType.Name);
|
||||||
sb.Append('.');
|
sb.Append('.');
|
||||||
sb.Append(name);
|
sb.Append(name);
|
||||||
|
|
||||||
if (member.IsMethod)
|
if (member.IsMethod)
|
||||||
{
|
{
|
||||||
// Getter/setter method of the property
|
sb.Append('(');
|
||||||
if (name.StartsWith("get_") || name.StartsWith("set_"))
|
var parameters = member.GetParameters();
|
||||||
|
for (int i = 0; i < parameters.Length; i++)
|
||||||
{
|
{
|
||||||
var flags = member.IsStatic ? BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly : BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
if (i != 0)
|
||||||
var property = declaringType.GetMembers(name.Substring(4), MemberTypes.Property, flags);
|
sb.Append(", ");
|
||||||
if (property != null && property.Length != 0)
|
ref var param = ref parameters[i];
|
||||||
{
|
param.ToString(sb);
|
||||||
return GetVisualScriptMemberInfoDescription(property[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Method
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append('(');
|
|
||||||
var parameters = member.GetParameters();
|
|
||||||
for (int i = 0; i < parameters.Length; i++)
|
|
||||||
{
|
|
||||||
if (i != 0)
|
|
||||||
sb.Append(", ");
|
|
||||||
ref var param = ref parameters[i];
|
|
||||||
param.ToString(sb);
|
|
||||||
}
|
|
||||||
sb.Append(')');
|
|
||||||
}
|
}
|
||||||
|
sb.Append(')');
|
||||||
}
|
}
|
||||||
else if (member.IsProperty)
|
else if (member.IsProperty)
|
||||||
{
|
{
|
||||||
@@ -495,8 +493,35 @@ namespace FlaxEditor.Surface
|
|||||||
sb.Append('}');
|
sb.Append('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetVisualScriptMemberShortDescription(ScriptMemberInfo member)
|
||||||
|
{
|
||||||
|
var name = member.Name;
|
||||||
|
var declaringType = member.DeclaringType;
|
||||||
|
|
||||||
|
// Getter/setter method of the property - we can return early here
|
||||||
|
if (member.IsMethod && (name.StartsWith("get_") || name.StartsWith("set_")))
|
||||||
|
{
|
||||||
|
var flags = member.IsStatic ? BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly : BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
|
||||||
|
var property = declaringType.GetMembers(name.Substring(4), MemberTypes.Property, flags);
|
||||||
|
if (property != null && property.Length != 0)
|
||||||
|
{
|
||||||
|
return GetVisualScriptMemberShortDescription(property[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Editor.Instance.CodeDocs.GetTooltip(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetVisualScriptMemberInfoDescription(ScriptMemberInfo member)
|
||||||
|
{
|
||||||
|
var signature = GetVisualScriptMemberInfoSignature(member);
|
||||||
|
var sb = new StringBuilder(signature);
|
||||||
|
|
||||||
// Tooltip
|
// Tooltip
|
||||||
var tooltip = Editor.Instance.CodeDocs.GetTooltip(member);
|
var tooltip = GetVisualScriptMemberShortDescription(member);
|
||||||
if (!string.IsNullOrEmpty(tooltip))
|
if (!string.IsNullOrEmpty(tooltip))
|
||||||
sb.Append("\n").Append(tooltip);
|
sb.Append("\n").Append(tooltip);
|
||||||
|
|
||||||
|
|||||||
@@ -237,11 +237,13 @@ namespace FlaxEditor.Surface
|
|||||||
return new VisjectCM(new VisjectCM.InitInfo
|
return new VisjectCM(new VisjectCM.InitInfo
|
||||||
{
|
{
|
||||||
CanSetParameters = CanSetParameters,
|
CanSetParameters = CanSetParameters,
|
||||||
|
UseDescriptionPanel = UseContextMenuDescriptionPanel,
|
||||||
Groups = NodeArchetypes,
|
Groups = NodeArchetypes,
|
||||||
CanSpawnNode = CanUseNodeType,
|
CanSpawnNode = CanUseNodeType,
|
||||||
ParametersGetter = () => Parameters,
|
ParametersGetter = () => Parameters,
|
||||||
CustomNodesGroup = GetCustomNodes(),
|
CustomNodesGroup = GetCustomNodes(),
|
||||||
ParameterGetNodeArchetype = GetParameterGetterNodeArchetype(out _),
|
ParameterGetNodeArchetype = GetParameterGetterNodeArchetype(out _),
|
||||||
|
Style = Style,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -535,6 +535,11 @@ namespace FlaxEditor.Surface
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool CanSetParameters => false;
|
public virtual bool CanSetParameters => false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True of the context menu should make use of a description panel drawn at the bottom of the menu
|
||||||
|
/// </summary>
|
||||||
|
public virtual bool UseContextMenuDescriptionPanel => false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether surface supports/allows live previewing graph modifications due to value sliders and color pickers. True by default but disabled for shader surfaces that generate and compile shader source at flight.
|
/// Gets a value indicating whether surface supports/allows live previewing graph modifications due to value sliders and color pickers. True by default but disabled for shader surfaces that generate and compile shader source at flight.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ namespace FlaxEditor.Surface
|
|||||||
{
|
{
|
||||||
TypeID = originalNodeId,
|
TypeID = originalNodeId,
|
||||||
Title = "Missing Node :(",
|
Title = "Missing Node :(",
|
||||||
|
Signature = "Missing Node :(",
|
||||||
Description = ":(",
|
Description = ":(",
|
||||||
Flags = NodeFlags.AllGraphs,
|
Flags = NodeFlags.AllGraphs,
|
||||||
Size = new Float2(200, 70),
|
Size = new Float2(200, 70),
|
||||||
|
|||||||
@@ -174,6 +174,9 @@ namespace FlaxEditor.Surface
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanSetParameters => true;
|
public override bool CanSetParameters => true;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool UseContextMenuDescriptionPanel => true;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool CanUseNodeType(GroupArchetype groupArchetype, NodeArchetype nodeArchetype)
|
public override bool CanUseNodeType(GroupArchetype groupArchetype, NodeArchetype nodeArchetype)
|
||||||
{
|
{
|
||||||
@@ -235,10 +238,12 @@ namespace FlaxEditor.Surface
|
|||||||
|
|
||||||
var node = (NodeArchetype)Archetypes.Function.Nodes[2].Clone();
|
var node = (NodeArchetype)Archetypes.Function.Nodes[2].Clone();
|
||||||
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
node.Description = Editor.Instance.CodeDocs.GetTooltip(member);
|
node.Signature = SurfaceUtils.GetVisualScriptMemberInfoSignature(member);
|
||||||
|
node.Description = SurfaceUtils.GetVisualScriptMemberShortDescription(member);
|
||||||
node.DefaultValues[0] = name;
|
node.DefaultValues[0] = name;
|
||||||
node.DefaultValues[1] = parameters.Length;
|
node.DefaultValues[1] = parameters.Length;
|
||||||
node.Title = "Override " + name;
|
node.Title = "Override " + name;
|
||||||
|
node.Tag = member;
|
||||||
nodes.Add(node);
|
nodes.Add(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,6 +281,7 @@ namespace FlaxEditor.Surface
|
|||||||
node.DefaultValues[0] = Activator.CreateInstance(scriptType.Type);
|
node.DefaultValues[0] = Activator.CreateInstance(scriptType.Type);
|
||||||
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
node.Title = scriptTypeName;
|
node.Title = scriptTypeName;
|
||||||
|
node.Signature = scriptTypeName;
|
||||||
node.Description = Editor.Instance.CodeDocs.GetTooltip(scriptType);
|
node.Description = Editor.Instance.CodeDocs.GetTooltip(scriptType);
|
||||||
|
|
||||||
// Create group archetype
|
// Create group archetype
|
||||||
@@ -326,6 +332,7 @@ namespace FlaxEditor.Surface
|
|||||||
node.DefaultValues[0] = scriptTypeTypeName;
|
node.DefaultValues[0] = scriptTypeTypeName;
|
||||||
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
node.Title = "Pack " + scriptTypeName;
|
node.Title = "Pack " + scriptTypeName;
|
||||||
|
node.Signature = "Pack " + scriptTypeName;
|
||||||
node.Description = tooltip;
|
node.Description = tooltip;
|
||||||
((IList<NodeArchetype>)group.Archetypes).Add(node);
|
((IList<NodeArchetype>)group.Archetypes).Add(node);
|
||||||
|
|
||||||
@@ -334,6 +341,7 @@ namespace FlaxEditor.Surface
|
|||||||
node.DefaultValues[0] = scriptTypeTypeName;
|
node.DefaultValues[0] = scriptTypeTypeName;
|
||||||
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
node.Title = "Unpack " + scriptTypeName;
|
node.Title = "Unpack " + scriptTypeName;
|
||||||
|
node.Signature = "Unpack " + scriptTypeName;
|
||||||
node.Description = tooltip;
|
node.Description = tooltip;
|
||||||
((IList<NodeArchetype>)group.Archetypes).Add(node);
|
((IList<NodeArchetype>)group.Archetypes).Add(node);
|
||||||
}
|
}
|
||||||
@@ -367,7 +375,8 @@ namespace FlaxEditor.Surface
|
|||||||
node.DefaultValues[2] = parameters.Length;
|
node.DefaultValues[2] = parameters.Length;
|
||||||
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
node.Title = SurfaceUtils.GetMethodDisplayName((string)node.DefaultValues[1]);
|
node.Title = SurfaceUtils.GetMethodDisplayName((string)node.DefaultValues[1]);
|
||||||
node.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member);
|
node.Signature = SurfaceUtils.GetVisualScriptMemberInfoSignature(member);
|
||||||
|
node.Description = SurfaceUtils.GetVisualScriptMemberShortDescription(member);
|
||||||
node.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
node.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
||||||
node.Tag = member;
|
node.Tag = member;
|
||||||
|
|
||||||
@@ -415,8 +424,10 @@ namespace FlaxEditor.Surface
|
|||||||
node.DefaultValues[3] = member.IsStatic;
|
node.DefaultValues[3] = member.IsStatic;
|
||||||
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
node.Title = "Get " + name;
|
node.Title = "Get " + name;
|
||||||
node.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member);
|
node.Signature = SurfaceUtils.GetVisualScriptMemberInfoSignature(member);
|
||||||
|
node.Description = SurfaceUtils.GetVisualScriptMemberShortDescription(member);
|
||||||
node.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
node.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
||||||
|
node.Tag = member;
|
||||||
|
|
||||||
// Create group archetype
|
// Create group archetype
|
||||||
var groupKey = new KeyValuePair<string, ushort>(scriptTypeName, 16);
|
var groupKey = new KeyValuePair<string, ushort>(scriptTypeName, 16);
|
||||||
@@ -449,8 +460,10 @@ namespace FlaxEditor.Surface
|
|||||||
node.DefaultValues[3] = member.IsStatic;
|
node.DefaultValues[3] = member.IsStatic;
|
||||||
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
node.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
node.Title = "Set " + name;
|
node.Title = "Set " + name;
|
||||||
node.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member);
|
node.Signature = SurfaceUtils.GetVisualScriptMemberInfoSignature(member);
|
||||||
|
node.Description = SurfaceUtils.GetVisualScriptMemberShortDescription(member);
|
||||||
node.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
node.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
||||||
|
node.Tag = member;
|
||||||
|
|
||||||
// Create group archetype
|
// Create group archetype
|
||||||
var groupKey = new KeyValuePair<string, ushort>(scriptTypeName, 16);
|
var groupKey = new KeyValuePair<string, ushort>(scriptTypeName, 16);
|
||||||
@@ -507,8 +520,10 @@ namespace FlaxEditor.Surface
|
|||||||
bindNode.DefaultValues[1] = name;
|
bindNode.DefaultValues[1] = name;
|
||||||
bindNode.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
bindNode.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
bindNode.Title = "Bind " + name;
|
bindNode.Title = "Bind " + name;
|
||||||
bindNode.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member);
|
bindNode.Signature = SurfaceUtils.GetVisualScriptMemberInfoSignature(member);
|
||||||
|
bindNode.Description = SurfaceUtils.GetVisualScriptMemberShortDescription(member);
|
||||||
bindNode.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
bindNode.SubTitle = string.Format(" (in {0})", scriptTypeName);
|
||||||
|
bindNode.Tag = member;
|
||||||
((IList<NodeArchetype>)group.Archetypes).Add(bindNode);
|
((IList<NodeArchetype>)group.Archetypes).Add(bindNode);
|
||||||
|
|
||||||
// Add Unbind event node
|
// Add Unbind event node
|
||||||
@@ -517,8 +532,10 @@ namespace FlaxEditor.Surface
|
|||||||
unbindNode.DefaultValues[1] = name;
|
unbindNode.DefaultValues[1] = name;
|
||||||
unbindNode.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
unbindNode.Flags &= ~NodeFlags.NoSpawnViaGUI;
|
||||||
unbindNode.Title = "Unbind " + name;
|
unbindNode.Title = "Unbind " + name;
|
||||||
|
unbindNode.Signature = bindNode.Signature;
|
||||||
unbindNode.Description = bindNode.Description;
|
unbindNode.Description = bindNode.Description;
|
||||||
unbindNode.SubTitle = bindNode.SubTitle;
|
unbindNode.SubTitle = bindNode.SubTitle;
|
||||||
|
unbindNode.Tag = member;
|
||||||
((IList<NodeArchetype>)group.Archetypes).Add(unbindNode);
|
((IList<NodeArchetype>)group.Archetypes).Add(unbindNode);
|
||||||
|
|
||||||
#if DEBUG_EVENTS_SEARCHING
|
#if DEBUG_EVENTS_SEARCHING
|
||||||
|
|||||||
Reference in New Issue
Block a user