Unity开发笔记-Editor扩展用GraphView实现逻辑表达式(2)表达式逻辑Node扩展

本篇我们将实现表达式编辑器的UI功能部分

0 操作数节点FloatNode

既然我们的目标是实现一个逻辑表达式,我们需要一个FloatNode作为基本的操作数。你也可以实现自己的Int版本
我们在Node的ContentContainer中加入FloatField输入框让用户输入内容

  `
   public class YaoJZFloatNodeView:Node
{
    private FloatField _floatField;

    public Port OutputPort;
    
    public YaoJZFloatNodeView()
    {
        title = "Float";
        
        OutputPort = Port.Create<Edge>(Orientation.Horizontal, Direction.Output, Port.Capacity.Single, typeof(Port));
        outputContainer.Add(OutputPort);
        
        _floatField = new FloatField();                                          //添加一个floatfield输入框
        _floatField.RegisterValueChangedCallback(OnFloatValueChanged);
        contentContainer.Add(_floatField);
        RefreshExpandedState();
    }

    private void OnFloatValueChanged(ChangeEvent<float> evt)
    {
           //输入内容变化了
    }

    public float Value
    {
        get{return _floatField.value;}
        set { _floatField.value = value; }
    }
}
  `

1 BinaryOpNode二元操作节点

现在我们实现一个二元操作功能的Node,这个Node实现二院表达式,我们先实现数学运算的加减乘除

BinaryOpNode有2个输入Port,分别来连接左操作数节点和右操作数节点
另外需要一个Output的Port,代表操作后的结果输出

  public class YaoJZBinaryOpNodeView:Node
    {
    public Port LeftInput;            //左操作数节点端口
    public Port RightInput;            //右操作数节点端口

    public Port OutputPort;
    
    public YaoJZBinaryOpNodeView()
    {
        this.title = "BinaryOp";
        
        OutputPort = Port.Create<Edge>(Orientation.Horizontal, Direction.Output, Port.Capacity.Single, typeof(Port));
        outputContainer.Add(OutputPort);
        
        LeftInput = Port.Create<Edge>(Orientation.Horizontal, Direction.Input, Port.Capacity.Single, typeof(Port));
        inputContainer.Add(LeftInput);
        
        RightInput = Port.Create<Edge>(Orientation.Horizontal, Direction.Input, Port.Capacity.Single, typeof(Port));
        inputContainer.Add(RightInput);
        
    }
}

`

我们需要定义一个操作方法枚举,代表我们可以进行的操作行为类型

  public enum BinaryNodeOpType
    {
        Add,
        Sub,
        Divide,
        Mutiply,
    }

然后我们添加一个EnumField,让用户可以在Node中选择自己想要的BinaryNodeOpType

YaoJZBinaryOpNodeView.cs类

  public class YaoJZBinaryOpNodeView:Node
{

  private EnumField _opEnumField;
    
    public Enums.BinaryNodeOpType OpType
    {
        get { return (Enums.BinaryNodeOpType)_opEnumField.value; }
        set { _opEnumField.value = value; }
    }

  public YaoJZBinaryOpNodeView()
    {

  //...之前的代码

  _opEnumField = new EnumField();
        _opEnumField.Init(Enums.BinaryNodeOpType.Add);
        contentContainer.Add(_opEnumField);
  }
    }

别忘了将节点添加到ISearchWindowProvider的右键菜单中

  public class YaoJZSearchMenuWindowProvider:ScriptableObject, ISearchWindowProvider
{
        public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
    {
        var entries = new List<SearchTreeEntry>();
        entries.Add(new SearchTreeGroupEntry(new GUIContent("Create Node")));

        entries.Add(new SearchTreeGroupEntry(new GUIContent("Example")) { level = 1 });

        entries.Add(new SearchTreeEntry(new GUIContent("float")) { level = 2, userData = typeof(YaoJZFloatNodeView) });
        entries.Add(new SearchTreeEntry(new GUIContent("binary")) { level = 2, userData = typeof(YaoJZBinaryOpNodeView) });
        return entries;
    }
  }

改进:每次添加新节点未免有些麻烦,我们可以通过Attribute功能,利用反射将节点添加到右键菜单中。

现在我们连接一下看看最终的效果

我们的表达式编辑器的UI部分已经实现的差不多了,下一篇我们实现表达式的运行时逻辑

原文地址:https://www.cnblogs.com/terrynoya/p/14089517.html