本篇我們將實現表達式編輯器的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部分已經實現的差不多了,下一篇我們實現表達式的運行時邏輯