Node editor - Added node creation by dropping cables in empty space

Node editor - Added undo/redo to static value nodes
UI - Throw exception when binding a non-reactive view to an activatable view model
This commit is contained in:
Robert committed 2022-03-26 19:13:51 +01:00
1 parent 06ab2c5bb6
commit 2ae1f5f56c
31 files changed
+630 -253

No files matched your search

@@ -192,6 +192,52 @@ namespace Artemis.Core
return enumerableType?.GenericTypeArguments[0];
}
/// <summary>
/// Determines if the <paramref name="typeToCheck"></paramref> is of a certain <paramref name="genericType"/>.
/// </summary>
/// <param name="typeToCheck">The type to check.</param>
/// <param name="genericType">The generic type it should be or implement</param>
public static bool IsOfGenericType(this Type typeToCheck, Type genericType)
{
return typeToCheck.IsOfGenericType(genericType, out Type _);
}
private static bool IsOfGenericType(this Type typeToCheck, Type genericType, out Type concreteGenericType)
{
while (true)
{
concreteGenericType = null;
if (genericType == null)
throw new ArgumentNullException(nameof(genericType));
if (!genericType.IsGenericTypeDefinition)
throw new ArgumentException("The definition needs to be a GenericTypeDefinition", nameof(genericType));
if (typeToCheck == null || typeToCheck == typeof(object))
return false;
if (typeToCheck == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if ((typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck) == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if (genericType.IsInterface)
foreach (var i in typeToCheck.GetInterfaces())
if (i.IsOfGenericType(genericType, out concreteGenericType))
return true;
typeToCheck = typeToCheck.BaseType;
}
}
/// <summary>
/// Determines a display name for the given type
/// </summary>
+110 -76
View File
@@ -1,83 +1,117 @@
using System;
using Artemis.Storage.Entities.Profile.Nodes;
namespace Artemis.Core
namespace Artemis.Core;
/// <summary>
/// Represents node data describing a certain <see cref="INode" />
/// </summary>
public class NodeData
{
/// <summary>
/// Represents node data describing a certain <see cref="INode" />
/// </summary>
public class NodeData
#region Constructors
internal NodeData(Plugin plugin, Type type, string name, string description, string category, Type? inputType, Type? outputType, Func<INodeScript, NodeEntity?, INode> create)
{
#region Constructors
internal NodeData(Plugin plugin, Type type, string name, string description, string category, Type? inputType, Type? outputType, Func<INodeScript, NodeEntity?, INode> create)
{
Plugin = plugin;
Type = type;
Name = name;
Description = description;
Category = category;
InputType = inputType;
OutputType = outputType;
_create = create;
}
#endregion
#region Methods
/// <summary>
/// Creates a new instance of the node this data represents
/// </summary>
/// <param name="script">The script to create the node for</param>
/// <param name="entity">An optional storage entity to apply to the node</param>
/// <returns>The returning node of type <see cref="Type" /></returns>
public INode CreateNode(INodeScript script, NodeEntity? entity)
{
return _create(script, entity);
}
#endregion
#region Properties & Fields
/// <summary>
/// Gets the plugin that provided this node data
/// </summary>
public Plugin Plugin { get; }
/// <summary>
/// Gets the type of <see cref="INode" /> this data represents
/// </summary>
public Type Type { get; }
/// <summary>
/// Gets the name of the node this data represents
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the description of the node this data represents
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the category of the node this data represents
/// </summary>
public string Category { get; }
/// <summary>
/// Gets the primary input type of the node this data represents
/// </summary>
public Type? InputType { get; }
/// <summary>
/// Gets the primary output of the node this data represents
/// </summary>
public Type? OutputType { get; }
private readonly Func<INodeScript, NodeEntity?, INode> _create;
#endregion
Plugin = plugin;
Type = type;
Name = name;
Description = description;
Category = category;
InputType = inputType;
OutputType = outputType;
_create = create;
}
#endregion
#region Methods
/// <summary>
/// Creates a new instance of the node this data represents
/// </summary>
/// <param name="script">The script to create the node for</param>
/// <param name="entity">An optional storage entity to apply to the node</param>
/// <returns>The returning node of type <see cref="Type" /></returns>
public INode CreateNode(INodeScript script, NodeEntity? entity)
{
return _create(script, entity);
}
#endregion
/// <summary>
/// Determines whether the given pin is compatible with this node data's node.
/// </summary>
/// <param name="pin">
/// The pin to check compatibility with, if <see langword="null" /> then the node data is always
/// considered compatible.
/// </param>
/// <returns>
/// <see langword="true" /> if the pin is compatible with this node data's node; otherwise <see langword="false" />.
/// </returns>
public bool IsCompatibleWithPin(IPin? pin)
{
if (pin == null)
return true;
if (pin.Direction == PinDirection.Input)
return OutputType != null && pin.IsTypeCompatible(OutputType);
return InputType != null && pin.IsTypeCompatible(InputType);
}
/// <summary>
/// Determines whether the given text matches this node data for a search query.
/// </summary>
/// <param name="text">The text to search for.</param>
/// <returns>
/// <see langword="true" /> if the node matches; otherwise <see langword="false" />.
/// </returns>
public bool MatchesSearch(string text)
{
text = text.Trim();
return Name.Contains(text, StringComparison.InvariantCultureIgnoreCase) ||
Description.Contains(text, StringComparison.InvariantCultureIgnoreCase) ||
Category.Contains(text, StringComparison.InvariantCultureIgnoreCase);
}
#region Properties & Fields
/// <summary>
/// Gets the plugin that provided this node data
/// </summary>
public Plugin Plugin { get; }
/// <summary>
/// Gets the type of <see cref="INode" /> this data represents
/// </summary>
public Type Type { get; }
/// <summary>
/// Gets the name of the node this data represents
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the description of the node this data represents
/// </summary>
public string Description { get; }
/// <summary>
/// Gets the category of the node this data represents
/// </summary>
public string Category { get; }
/// <summary>
/// Gets the primary input type of the node this data represents
/// </summary>
public Type? InputType { get; }
/// <summary>
/// Gets the primary output of the node this data represents
/// </summary>
public Type? OutputType { get; }
private readonly Func<INodeScript, NodeEntity?, INode> _create;
#endregion
}