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 处理LayoutRepaint之外的事件.
首先它会选出一个窗口,然后传递当前的事件到这个窗口的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的位置。

posted @   dewxin  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示