mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 11:26:27 +00:00
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:
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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user