输入处理入门
通过学习前面的教程,你现在可以渲染GUI,载入文件甚至创建窗口。这时,你也许想给你的GUI添加用户交互了。本教程将讲述这些。
CEGUI 输入处理简介
坏消息
令人吃惊的是:CEGUI不会自动捕获任何用户输入,由程序决定CEGUI需要处理哪些输入。这意味着:每当产生按键或鼠标移动等消息时,你就得把它们传递给CEGUI。尽管初次看起来很奇怪,这其实也给了你更多的控制权 ---- 我们并没有把输入绑定到特定的系统,你也可以筛选、传递CEGUI需要获得的输入。
传递你的输入!
我们创建了一个接口用来向CEGUI传递输入信息。它由CEGUI::System类的一组成员函数组成 ---- 对于每种基本的输入类型都有一个函数与之对应:
bool injectMouseMove( float delta_x, float delta_y );
bool injectMousePosition( float x_pos, float y_pos );
bool injectMouseLeaves( void );
bool injectMouseButtonDown( MouseButton button );
bool injectMouseButtonUp( MouseButton button );
bool injectKeyDown( uint key_code );
bool injectKeyUp( uint key_code );
bool injectChar( utf32 code_point );
bool injectMouseWheelChange( float delta );
bool injectTimePulse( float timeElapsed );
bool injectMouseMove( float delta_x, float delta_y );
bool injectMousePosition( float x_pos, float y_pos );
bool injectMouseLeaves( void );
bool injectMouseButtonDown( MouseButton button );
bool injectMouseButtonUp( MouseButton button );
bool injectKeyDown( uint key_code );
bool injectKeyUp( uint key_code );
bool injectChar( utf32 code_point );
bool injectMouseWheelChange( float delta );
bool injectTimePulse( float timeElapsed );
是的,看起来很多。你可能注意到,它们中有些看起来有点重复了,比如"mouse move"和"mouse position"有点重复,"key down"和"char"等。其实这么做是为了方便使用:对于鼠标,可以传递相对位移(injectMouseMove)或绝对坐标(injectMousePosition),具体选择哪种很大程度上取决于你使用的输入库支持的类型。对于按键,可以传递按下、抬起(injectKeyDown/injectKeyUp)以及字符(injectChar)消息,这样做有两个原因:第一,不是所有的按键都产生字符消息(比如shift,alt等等);第二,这允许你自定义按键映射和自动重复按键(CEGUI目前不提供那些函数)。
另外要说明的是函数的布尔返回值。它是用来告诉程序CEGUI是否处理了此消息。如果返回false,说明CEGUI没有处理此消息,此时你的程序可能需要另外做一些处理。
那些函数是用来干什么的
下面,我们将要简要的讨论每个函数的作用,它需要的参数,它用输入做了什么。
bool injectMouseMove( float delta_x, float delta_y )
bool injectMouseMove( float delta_x, float delta_y )
此函数用来传递鼠标移动信息。参数“delta_x”和“delta_y”分别用来指明鼠标在X轴和Y轴上所移动的位移(有方向)。这将导致鼠标做相应的移动(具体移动的大小可以通过CEGUI::System::setMouseMoveScaling设置比例因子改变)。如果你用此函数,基本上就不需要使用injectMousePosition函数了。
bool injectMousePosition( float x_pos, float y_pos )
bool injectMousePosition( float x_pos, float y_pos )
此函数用来传递鼠标当前的绝对坐标。参数“x_pos”和“y_pos”用来指明鼠标的绝对坐标,坐标系的原点(0, 0)在CEGUI窗口的左上角(所以,在窗口模式下,原点在窗口左上角而不是整个桌面的左上角)。这将把鼠标移动到新的位置。如果你用此函数,基本上就不需要使用injectMouseMove函数了。
bool injectMouseLeaves( void )
bool injectMouseLeaves( void )
此函数用来告诉系统鼠标已经离开程序窗口了。在窗口模式下,此方法很有用。
bool injectMouseButtonDown( MouseButton button )
bool injectMouseButtonDown( MouseButton button )
此函数用来告诉系统某个鼠标按键被按下了。参数“button”可以取如下所示的CEGUI::MouseButton枚举值:
enum MouseButton
{
LeftButton,
RightButton,
MiddleButton,
X1Button,
X2Button,
MouseButtonCount,
NoButton
};
enum MouseButton
{
LeftButton,
RightButton,
MiddleButton,
X1Button,
X2Button,
MouseButtonCount,
NoButton
};
如果你的输入库和上面的不吻合,你必须自己转化。另外,要注意:NoButton的值不是0。
bool injectMouseButtonUp( MouseButton button )
bool injectMouseButtonUp( MouseButton button )
此函数用来告诉系统某个鼠标按键被释放了。它的参数和injectMouseButtonDown是一样的。
bool injectKeyDown( uint key_code )
bool injectKeyDown( uint key_code )
此函数用来告诉系统某个按键被按下了。它的参数“key_code”是那个按键的扫描码(不是ASCII码或其他的字符编码)。所有的扫描码在CEGUI::Key::Scan枚举变量中有定义。微软的DirectInput库输出的扫描码和我们的是一样的,如果使用其他的库,你可能需要做一些转换。目前看来,并不需要传递所有的按键按下/释放消息,一般需要这些消息的是:backspace,delete,回车,shift以及方向箭头按键。
目前没有实现按键到字符的映射,也没有提供自动重复按键的函数(这些也许在以后会实现)。如果你需要自动重复按键功能,你可以使用输入库提供的函数或者自己编码实现。你肯定需要输入字符,请看下面的injectChar函数。
bool injectKeyUp( uint key_code )
bool injectKeyUp( uint key_code )
此函数用来告诉系统某个按键被释放了。和injectKeyDown的参数一样,“key_code”是按键的扫描码。
bool injectChar( utf32 code_point )
bool injectChar( utf32 code_point )
此函数用来告诉系统一个字符按键被按下。在输入文本的时候,你需要用此函数。参数“code_point”是一个字符的Unicode UTF32编码(欲了解Unicode请参看此 Unicode 网站)。怎样获得这个值取决于你所使用的输入库。对于ASCII字符,你只需直接以ASCII码的形式传递给它即可,因为Unicode码和ASCII码的0到127部分是相同的。对于其他字符,你使用的输入库应该会有相关的API(比如:通过微软的Windows消息泵可以获得字符的UTF32编码),具体怎么做不属于本教程的范围。
bool injectMouseWheelChange( float delta )
bool injectMouseWheelChange( float delta )
此函数用来告诉系统鼠标滚轮的使用情况。正数表示向前滚动(远离用户方向),负数表示向后滚动(接近用户方向)。
bool injectTimePulse( float timeElapsed )
bool injectTimePulse( float timeElapsed )
此函数用来告诉系统相关时间信息。参数“timeElapsed”表示自上次调用此函数或运行CEGUI以来所经过的秒数。此函数越来越重要了,它被用来控制控件的消失,为工具提示、菜单以及鼠标按键的自动重复提供计时等。
总结
目前,我们学习了CEGUI获取输入的函数,以及那些函数的作用、参数等。
与前面几篇教程不同,此篇并未提供具体的示例代码。主要是想使教程适当的简短,以防因对特定的输入库编码而杂乱无章。将特定输入库的使用放在单独的文章中讲述更合理。
如果想看一些具体的例子,这里提供两个:
* 我们在wiki上有一些很牛的例子
o Using CEGUI with SDL and OpenGL
o Using CEGUI with Producer and OpenGL
* 使用示例框架代码写成的例子被保存在cegui_mk2/Samples/common/src:
o Win32AppHelper.cpp - contains a windows message procedure injecting
mouse and character inputs into CEGUI, and using DirectInput
for keyboard up and down messages.
o CEGuiOgreBaseApplication.cpp - contains an example Ogre::FrameListener
class which takes inputs generated by the OIS Library and
injects these into CEGUI.
o CEGuiOpenGLBaseApplication.cpp - registers callback functions with glut
to process inputs, and also shows the use of a key
translation table.
此外,使用Irrlicht的同学可以使用Irrlicht自带的event pusher ---- 每当一个输入产生的时候你可以使用Irrlicht Renderer的OnEvent函数处理它(你只需用injectTimePulse处理时间)。
原文作者:CrazyEddie
原作日期:03:46, 9 February 2008 (PST)
原文地址:The Beginner Guide to Injecting Inputs
翻 译 者:天外|OutSky
翻译日期:2008-10-01 15:30
以前,我曾幻想自己做所有东西,包括游戏GUI。现在,我才发现这种想法多么幼稚。更体会到开源精神的伟大!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pepper6681747/archive/2008/10/26/3151320.aspx