简介
在nodecanvas
造轮子的过程,遇到了鼠标拖拽太快,节点经常会脱离控制的情况。但是nodecanvas
却不会有这个问题。
一番折腾发现是nodecanvas
调用了GUI.DragWindow()
,而我觉得这个函数没啥用给删除了的原因。。
GUI.DragWindow()
在MouseDown
事件触发时,会调用GrabMouseControl
函数,以及在MouseUp
事件时,调用ReleaseMouseControl
函数。
而调用GUILayout.Window
时传入的GUI.WindowFunc
回调会在BeginWindows
函数和EndWindows
函数中被调用。
对于MouseDown
事件,BeginWindows
会找到包含鼠标的window,将其设置为FocusedWindow
。
对于MouseDrag
事件,BeginWindows
会挑选一个注册的window调用它的GUI回调函数。 如果有hotControl,那么会选择FocusedWindow
,否则挑选包含鼠标的window,如果没有则返回null。
由于没有对应设置hotControl的代码,MouseDrag
事件时,unity会去找鼠标所在的window,拖拽太快的话,会导致鼠标超出当前窗口的位置,由于window为null,就不会触发对应的GUI回调。
而nodecanvs
的更新节点位置的代码,就是在GUI回调里面实现的,不触发回调,就不会更新节点的位置。
对应的,如果想修复节点会脱离控制的情况,在mousedown
事件时,设置一个hotControl,在mouseup
事件的时候,重置hotcontrol为0即可。
BeginWindows,GUILayout.Window,EndWindows
编辑器代码中调用GUILayout.Window
,需要将其放置在BeginWindows/EndWindows(点我)
中间。
游戏中不需要调用Begin/EndWindows
是因为unity帮你调用了。
这里按照触发顺序,依次介绍每个函数的作用。
GUILayout.Window
GUILayout.Window
函数主要起到注册窗口的作用。
调用Window
函数时,需要传入id,这个id不是controlID,而是windowID,如果当前state没有注册这个id,那么会生成一个GUIWindow
类放置到m_WindowList
中。 接着会尝试更新窗口的rect。
EndWindows
注册完函数后会调用 EndWindows
,这个函数主要处理Layout
事件和Repaint
事件。GUILayout.Window
注册的每个窗口回调都会收到这两个事件。
BeginWindows
BeginWindows
处理Layout
和Repaint
之外的事件.
首先它会选出一个窗口,然后传递当前的事件到这个窗口的GUI回调中。所以最多只有一个窗口回调会收到对应的事件。
基本上,Unity会使用FindWindowUnderMouse
找到对应的窗口。
对于MouseUp
,MouseMove
,MouseDrag
事件,Unity会增加HotControl的判断,如果当前有hotControl,那么就用MouseDown事件时设置的FocusedWindow。
DragWindow
由于DragWindow
通常是在GUILayout.Window
注册的GUI回调中被调用,所以对于Mouse事件,同一时间只会有一个窗口被调用这个函数。
GUI.DragWindow()
在MouseDown
事件触发时,会调用GrabMouseControl
函数,以及在MouseUp
事件时,调用ReleaseMouseControl
函数。 在MouseDrag
事件触发时,会更新当前window的位置。