上一篇有讲到CEGUI对与事件响应的流程并以mousemove为列列举出了大概步骤。此篇主要了解一些其他相关事件的实现.
能注入到CEGUI中的事件主要有:injectChar, injectKeyDown, injectKeyUp, injectMouseButtonDown, injectMouseButtonUp, injectMouseButtonClick, injectMouseButtonDoubleClick, injectMouseButtonTripleClick, injectMouseLeaves, injecMouseMove, injectMousePosition, injectMouseWheelChang, injectTimePulse。可以看到其实就是鼠标消息和键盘消息加上一个时间脉冲,其中有些时间是相关的如如果允许CEGUI自己产生鼠标click事件那么我们可以不使用鼠标单击双击事件的注入。
injectChar(code_point): args(getKeyboardTargetWindow)用当前能响应键盘输入消息的window来构建KeyEventArgs,如果存在该窗口则继续设定args的codepoint 和syskeys属性,然后调用它的onCharacter(args)函数。
injectKeyDown(key_code): 首先要更新d_sysKeys状态 d_sysKeys |= keyCodeToSyskey((Key::Scan)key_code, true);其下步骤与injectChar基本一样,最后调用窗口的onKeyDown函数。
injectKeyUp与injectKeyDown基本过程一样,首先要更新d_sysKeys状态d_sysKeys &= ~keyCodeToSyskey((Key::Scan)key_code, false)注意最后一个参数的值及计算方式。最后调用的是窗口的onKeyUp。
injiectMouseButtonDow(mouseButton): 首先同过d_sysKeys |= mouseButtonToSyskey(button);来更新sysKey,随后定义MuseEventArgs ma并设置它的一些参数ma.position = MouseCursor::getSingleton().getPosition();ma.moveDelta = Vector2(0.0f, 0.0f);ma.button = button;ma.sysKeys = d_sysKeys;ma.wheelChange = 0;ma.window = getTargetWindow(ma.position, false); 如果ma.window存在则需要根据window来重新计算一次position,然后得到对当前鼠标按钮的跟踪器的引用tkr并更新tkr的clickCount, clickarea, tartetwindow。最后把tkr记录的clickCount赋值给ma.clickCount并根据该值和系统设定(系统是否自己产生鼠标点击和多击)确定是调用onMouseButtonDown,onMouseDoubleClicked, onMouseTripleClicked中的哪一个。最后将tkr的时间重置。
injectMouseButtonUp:基本上同injiectMouseButtonDow过程相同,主要注意到sysKey变化的方式和最后调用函数的方式就可以了。再这里除了必定产生onMousetButtonUp外还是产生onMouseClicked的地方(在donw中会产onMousButtonDown和onMouseDoubleClicked等),由于可以同时产生onMouseButtonDown和onMouseClicked所以在产生mouseButtonDown之前要把ma的window 和 handled先记录下来。
injectMouseButtonClick,injectMouseButtonDoubleClick:和前面产生的onMouseClicked/doubleClicked基本一样, 只是又外面直接注入单击事件到sys中的。
injectMouseLeaves:只是产生onMouseLeaves。onMouseEnters和onMouseLeaves都有可能随injectMouseMove产生。因为鼠标移动的时候就有可能改变鼠标但钱所指的ui。还有一个injectMousePosition函数其实他最终产生的效果也跟move一样,可以从代码中看到在设置好ma的参数后都是调用的mouseMoveInjection_impl。injectMouseWheelChange与鼠标击键差不多只是ma的参数稍微不同。最后还有一个时间脉冲,用来定时调用所有窗口的update函数。
从前面分析中可以看到有些部分是重叠的,只是入口方式不一样而已:像onMouseClicked,onMouseDoubleClicked, onMouseButtonDow/up间的关系--injectMouseButtonDow一定会产生而且只能产生onMouseButtonDow,onMouseDoubleClicked/tripClicked里面的一个调用,而injectMouseButtonUp则一定会产生一个onMouseButtonUp并且有可能产生一个onMouseCliced。同时onMouseButtonClicked,doubleClicked等又可以直接通过inject注入来产生。鼠标事件间的关系是一个injectMouseButtonDown不一定会有onMouseButtonDow消息产生,而一个injectMouseButtonUp一定有onMouseButtonUp消息产生你。双击是在down的过程中产生,单击是在up过程中,所以鼠标产生一个doubleClic一定是dow,up, doubleClick, up这个消息顺序。
在上面的这些事件中有个问题就是这个on开头的消息到底发送给哪个ui元素呢?是如何找到事件接受的对象呢?虽然最后都是同过ma.window.onXXX。要得到那个window是同过system 的getKeyboardTargetWindow和getTargetWindow来得到,当然具体的方式就得看window内部的机制了。以后再分析吧。