nodecanvas插件的黑魔法:一行代码避免拖拽节点的意外脱离
简介
在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的位置。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)