namespace TagFighter.ExtensionMethods
{
public static class TypeExtensions
{
public static System.Type GetSubclassOfRawGeneric(this System.Type baseType, System.Type rawGenericType) {
var curType = baseType;
while (curType != null && !(curType.IsGenericType && curType.GetGenericTypeDefinition() == rawGenericType)) {
curType = curType.BaseType;
}
return curType;
}
}
}
namespace TagFighter.UI.Editor
{
using System;
using System.Collections.Generic;
using System.Reflection;
using TagFighter.Effects.Steps;
using TagFighter.ExtensionMethods;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEditor;
using System.Linq;
public class EffectStepNodeView : UnityEditor.Experimental.GraphView.Node
{
public Action<EffectStepNodeView> OnNodeSelected;
public EffectStepNode Node;
const string InvalidClassName = "InvalidStep";
const Orientation DefaultOrientation = Orientation.Horizontal;
public EffectStepNodeView(EffectStepNode node) {
Node = node;
title = Node.ToString();
viewDataKey = Node.Guid;
style.left = Node.Position.x;
style.top = Node.Position.y;
CreateInputPorts();
CreateOutputPorts();
SetClasses();
}
public void RefreshDisplay(EffectStepValidatedEventArgs e) {
title = e.DisplayName;
if (e.IsValid) {
RemoveFromClassList(InvalidClassName);
}
else {
AddToClassList(InvalidClassName);
}
}
void SetClasses() {
var stepType = Node.GetType().GetTypeInfo().GetCustomAttribute<StepTypeAttribute>();
if (stepType != null) {
AddToClassList($"{stepType.Name}Step");
}
if (!Node.IsValid) {
AddToClassList(InvalidClassName);
}
}
string GetPortDisplayName(System.Type portType) {
(var subType, var arrayMarker) = portType.IsGenericType && portType.GetGenericTypeDefinition() == typeof(IEnumerable<>) ?
(portType.GenericTypeArguments[0], "[]") : (portType, "");
return $"({subType.Name}{arrayMarker})";
}
void CreateInputPorts() {
var direction = Direction.Input;
const string InPortDisplayName = "In";
foreach (var port in Node.Inputs.Where(port => port != null)) {
var portView = port.Capacity switch {
PortCapacity.Single => InstantiatePort(DefaultOrientation, direction, Port.Capacity.Single, port.GetType().GenericTypeArguments[0]),
_ => InstantiatePort(DefaultOrientation, direction, Port.Capacity.Multi, port.GetType().GenericTypeArguments[0])
};
portView.portName = port.DisplayName != null && port.DisplayName != "" ? port.DisplayName : InPortDisplayName;
portView.portName += GetPortDisplayName(portView.portType);
portView.userData = (port, Node);
inputContainer.Add(portView);
}
}
void CreateOutputPorts() {
var direction = Direction.Output;
const string OutPortDisplayName = "Out";
var genericStepType = Node.GetType().GetSubclassOfRawGeneric(typeof(OutputStep<>));
if (genericStepType != null) {
var portView = InstantiatePort(DefaultOrientation, direction, Port.Capacity.Single, genericStepType.GenericTypeArguments[0]);
portView.portName = OutPortDisplayName + GetPortDisplayName(portView.portType);
outputContainer.Add(portView);
}
}
public override void SetPosition(Rect newPos) {
base.SetPosition(newPos);
Undo.RecordObject(Node, "Update Node Position");
Node.Position.x = newPos.xMin;
Node.Position.y = newPos.yMin;
EditorUtility.SetDirty(Node);
}
public override void OnSelected() {
base.OnSelected();
OnNodeSelected?.Invoke(this);
}
}
}