孙广东 2018.5.13
csdn 的产品 , 真垃圾, 不想吐槽了, 文章保存就丢! 没办法 。 怎么不满意, 还是得继续用, 哎~~~
第二部分 在Unity中序列化基于节点的编辑器
重温基于节点的编辑器
上一篇文章 《
在Unity中创建基于Node节点的编辑器 (一)
》
重温XML序列化
有许多序列化选项,例如JSON或Unity自己的序列化系统。 我们以前已经介绍过XML序列化 我们将使用
XMLOp
类和本文中的一些XML属性。
添加一个菜单栏(添加保存, 加载等按钮)
我们将从添加菜单栏开始,然后从控制台窗口clone中复制它(一起弄的一个 仿Unity Console窗口的脚本):
private
float
menuBarHeight
=
20f
;
private
Rect
menuBar
;
|
private
void
OnGUI
()
{
DrawGrid
(
20
,
0.2f
,
Color
.
gray
);
DrawGrid
(
100
,
0.4f
,
Color
.
gray
);
DrawMenuBar
();
DrawNodes
();
DrawConnections
();
DrawConnectionLine
(
Event
.
current
);
ProcessNodeEvents
(
Event
.
current
);
ProcessEvents
(
Event
.
current
);
if
(
GUI
.
changed
)
Repaint
();
}
private
void
DrawMenuBar
()
{
menuBar
=
new
Rect
(
0
,
0
,
position
.
width
,
menuBarHeight
);
GUILayout
.
BeginArea
(
menuBar
,
EditorStyles
.
toolbar
);
GUILayout
.
BeginHorizontal
();
GUILayout
.
Button
(
new
GUIContent
(
"Save"
),
EditorStyles
.
toolbarButton
,
GUILayout
.
Width
(
35
));
GUILayout
.
Space
(
5
);
GUILayout
.
Button
(
new
GUIContent
(
"Load"
),
EditorStyles
.
toolbarButton
,
GUILayout
.
Width
(
35
));
GUILayout
.
EndHorizontal
();
GUILayout
.
EndArea
();
}
|
在第56行,我们调用
DrawMenuBar()方法,并在第69-82行之间创建菜单栏。控制台窗口克隆有一个
button和6个
toggles,但由于我们只是序列化和反序列化,所以我们不需要两个以上的按钮。请记住,编辑器GUI系统具有绘制顺序,并按照您调用它们的顺序从后向前绘制元素。这就是我们绘制网格后绘制菜单栏的原因。否则,网格将被拖到菜单栏上。
DrawMenuBar() 在 DrawGrid() 之前被调用,因此在菜单栏上有一个丑陋的网格。
目前,保存和加载按钮什么都不做,但我们会做到。
序列化
接下来,我们需要准备我们的类(节点
Node和连接
Connection)进行序列化。让我们记住关于XML序列化的两个重要关键点:
- XML序列化程序只能序列化public 字段。
- 要序列化的类应该有一个无参数的构造函数。
规则1号不会导致很多问题(它仍然会导致一些问题,但我们会做到这一点),但规则编号2是有问题的。我们的两个类都有带参数的构造函数。首先解决这个问题:
public
Node
()
{
}
public
Node
(
Vector2
position
,
float
width
,
float
height
,
GUIStyle
nodeStyle
,
GUIStyle
selectedStyle
,
GUIStyle
inPointStyle
,
GUIStyle
outPointStyle
,
Action
<
ConnectionPoint
>
OnClickInPoint
,
Action
<
ConnectionPoint
>
OnClickOutPoint
,
Action
<
Node
>
OnClickRemoveNode
)
{
rect
=
new
Rect
(
position
.
x
,
position
.
y
,
width
,
height
);
style
=
nodeStyle
;
inPoint
=
new
ConnectionPoint
(
this
,
ConnectionPointType
.
In
,
inPointStyle
,
OnClickInPoint
);
outPoint
=
new
ConnectionPoint
(
this
,
ConnectionPointType
.
Out
,
outPointStyle
,
OnClickOutPoint
);
defaultNodeStyle
=
nodeStyle
;
selectedNodeStyle
=
selectedStyle
;
OnRemoveNode
=
OnClickRemoveNode
;
}
|
public
Connection
()
{
}
public
Connection
(
ConnectionPoint
inPoint
,
ConnectionPoint
outPoint
,
Action
<
Connection
>
OnClickRemoveConnection
)
{
this
.
inPoint
=
inPoint
;
this
.
outPoint
=
outPoint
;
this
.
OnClickRemoveConnection
=
OnClickRemoveConnection
;
}
|
接下来,我们将忽略无法序列化或不需要序列化的属性。 例如,在
Node
类中,
GUIStyle
s 可以不用序列化,因为它们已经由编辑器自己提供。 我们不需要
isDragged或
isSelected。 实际上,Node类只有一个需要序列化的属性:
rect。 让我们来看看如何正确地忽略不必要和不可序列化的属性后Node类的样子:
public
class
Node
{
public
Rect
rect
;
[
XmlIgnore
]
public
string
title
;
[
XmlIgnore
]
public
bool
isDragged
;
[
XmlIgnore
]
public
bool
isSelected
;
[
XmlIgnore
]
public
ConnectionPoint
inPoint
;
[
XmlIgnore
]
public
ConnectionPoint
outPoint
;
[
XmlIgnore
]
public
GUIStyle
style
;
[
XmlIgnore
]
public
|