Re #752 (CEGUIDemo) Fixed keyboard management (grabbed from Python port of Falagard console demo by Leftium)

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@5078 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 74f1d3c2c69646fa530553ad90a2b33bd15cec02
Former-commit-id: 0a2d48033409c5f3ffc096f185ff5dc38e4a3b6a
This commit is contained in:
pouillot 2012-12-23 15:33:20 +00:00
parent ab74aa48aa
commit 7f915d150b
4 changed files with 166 additions and 21 deletions

View file

@ -9,10 +9,14 @@
This class sets up input processing by creating handlers for GLUT that inject
input into PyCEGUI.
GLUT to CEGUI keyboard mapping from Leftium's PyCEGUI port of Falagard demo console
(http://www.cegui.org.uk/phpBB2/viewtopic.php?f=4&t=5425)
"""
# Import: std
import sys
import string
# Import: OpenGL
from OpenGL.GL import *
@ -30,11 +34,92 @@ from errors import InitializationError
# Input
class Input(object):
# GLUT to CEGUI keyboard mapping.
mapping = dict([(ord(c), getattr(PyCEGUI.Key, c.upper()))
for c in string.ascii_letters])
mapping.update({
96: PyCEGUI.Key.Grave, 126: PyCEGUI.Key.Grave,
49: PyCEGUI.Key.One, 33: PyCEGUI.Key.One,
50: PyCEGUI.Key.Two, 64: PyCEGUI.Key.At,
51: PyCEGUI.Key.Three, 35: PyCEGUI.Key.Three,
52: PyCEGUI.Key.Four, 36: PyCEGUI.Key.Four,
53: PyCEGUI.Key.Five, 37: PyCEGUI.Key.Five,
54: PyCEGUI.Key.Six, 94: PyCEGUI.Key.Six,
55: PyCEGUI.Key.Seven, 38: PyCEGUI.Key.Seven,
56: PyCEGUI.Key.Eight, 42: PyCEGUI.Key.Multiply,
57: PyCEGUI.Key.Nine, 40: PyCEGUI.Key.Nine,
48: PyCEGUI.Key.Zero, 41: PyCEGUI.Key.Zero,
45: PyCEGUI.Key.Minus, 95: PyCEGUI.Key.Underline,
61: PyCEGUI.Key.Equals, 43: PyCEGUI.Key.Equals,
91: PyCEGUI.Key.LeftBracket, 123: PyCEGUI.Key.LeftBracket,
93: PyCEGUI.Key.RightBracket, 125: PyCEGUI.Key.RightBracket,
59: PyCEGUI.Key.Semicolon, 58: PyCEGUI.Key.Colon,
39: PyCEGUI.Key.Apostrophe, 34: PyCEGUI.Key.Apostrophe,
92: PyCEGUI.Key.Backslash, 124: PyCEGUI.Key.Backslash,
44: PyCEGUI.Key.Comma, 60: PyCEGUI.Key.Comma,
46: PyCEGUI.Key.Period, 62: PyCEGUI.Key.Period,
47: PyCEGUI.Key.Slash, 63: PyCEGUI.Key.Slash,
13: PyCEGUI.Key.Return,
8: PyCEGUI.Key.Backspace,
9: PyCEGUI.Key.Tab,
32: PyCEGUI.Key.Space,
127: PyCEGUI.Key.Delete,
27: PyCEGUI.Key.Escape})
specialKeyMap = {
GLUT_KEY_F1: PyCEGUI.Key.F1,
GLUT_KEY_F2: PyCEGUI.Key.F2,
GLUT_KEY_F3: PyCEGUI.Key.F3,
GLUT_KEY_F4: PyCEGUI.Key.F4,
GLUT_KEY_F5: PyCEGUI.Key.F5,
GLUT_KEY_F6: PyCEGUI.Key.F6,
GLUT_KEY_F7: PyCEGUI.Key.F7,
GLUT_KEY_F8: PyCEGUI.Key.F8,
GLUT_KEY_F9: PyCEGUI.Key.F9,
GLUT_KEY_F10: PyCEGUI.Key.F10,
GLUT_KEY_F11: PyCEGUI.Key.F11,
GLUT_KEY_F12: PyCEGUI.Key.F12,
GLUT_KEY_LEFT: PyCEGUI.Key.ArrowLeft,
GLUT_KEY_UP: PyCEGUI.Key.ArrowUp,
GLUT_KEY_RIGHT: PyCEGUI.Key.ArrowRight,
GLUT_KEY_DOWN: PyCEGUI.Key.ArrowDown,
GLUT_KEY_PAGE_UP: PyCEGUI.Key.PageUp,
GLUT_KEY_PAGE_DOWN: PyCEGUI.Key.PageDown,
GLUT_KEY_HOME: PyCEGUI.Key.Home,
GLUT_KEY_END: PyCEGUI.Key.End,
GLUT_KEY_INSERT: PyCEGUI.Key.Insert }
def ascii2Scancode(self, a):
a = ord(a)
return self.mapping[a] if (a in self.mapping) else 0
def special2Scancode(self, c):
return self.specialKeyMap[c] if (c in self.specialKeyMap) else 0
# Constructor.
def __init__(self):
self.glut_modifiers = \
dict(shift = dict(is_held=False,
bit_flag=GLUT_ACTIVE_SHIFT,
scancode=PyCEGUI.Key.LeftShift),
ctrl = dict(is_held=False,
bit_flag=GLUT_ACTIVE_CTRL,
scancode=PyCEGUI.Key.LeftControl),
alt = dict(is_held=False,
bit_flag=GLUT_ACTIVE_ALT,
scancode=PyCEGUI.Key.LeftAlt))
# Initialize: Handlers
def initializeHandlers(self):
glutKeyboardFunc(self.handlerKeyDown)
glutMouseFunc(self.handlerMouseButton)
glutKeyboardFunc(self.handlerNormalKeyDown)
glutSpecialFunc(self.handlerSpecialKeyDown)
glutKeyboardUpFunc(self.handlerNormalKeyUp)
glutSpecialUpFunc(self.handlerSpecialKeyUp)
# The difference between these two is that the passive one is called when there is
# mouse motion while no buttons are pressed, and the other is called when there
@ -42,6 +127,8 @@ class Input(object):
glutMotionFunc(self.handlerMouseMotion)
glutPassiveMotionFunc(self.handlerMouseMotion)
glutMouseFunc(self.handlerMouseButton)
# Initialize
def initialize(self):
@ -50,12 +137,63 @@ class Input(object):
except Exception, msg:
raise InitializationError(msg)
# Handler: Key Down
# - `ord` is a built-in Python function.
def handlerKeyDown(self, key, x, y):
def handleModifierKeys(self):
status = glutGetModifiers()
for name, key in self.glut_modifiers.items():
if (status & key['bit_flag']):
if not key['is_held']:
key['is_held'] = True
PyCEGUI.System.getSingleton().injectKeyDown(key['scancode'])
elif key['is_held']:
key['is_held'] = False
PyCEGUI.System.getSingleton().injectKeyUp(key['scancode'])
# Handler: Normal Key Down
def handlerNormalKeyDown(self, key, x, y):
key = key.encode('ascii', 'ignore')
self.handleModifierKeys()
scancode = self.ascii2Scancode(key)
if scancode:
PyCEGUI.System.getSingleton().injectKeyDown(int(scancode))
PyCEGUI.System.getSingleton().injectChar(ord(key))
return False
# Handler: Normal Key Up
def handlerNormalKeyUp(self, key, x, y):
key = key.encode('ascii', 'ignore')
self.handleModifierKeys()
scancode = self.ascii2Scancode(key)
if scancode:
PyCEGUI.System.getSingleton().injectKeyDown(int(scancode))
PyCEGUI.System.getSingleton().injectKeyUp(int(scancode))
return False
# Handler: Special Key Down
def handlerSpecialKeyDown(self, key, x, y):
self.handleModifierKeys()
scancode = self.special2Scancode(key)
if scancode:
PyCEGUI.System.getSingleton().injectKeyDown(int(scancode))
return False
# Handler: Special Key Up
def handlerSpecialKeyUp(self, key, x, y):
self.handleModifierKeys()
scancode = self.special2Scancode(key)
if scancode:
PyCEGUI.System.getSingleton().injectKeyUp(int(scancode))
return False
# Handler: Mouse Button
def handlerMouseButton(self, button, state, x, y):
@ -78,9 +216,13 @@ class Input(object):
# mouse input; this is left as an exercise for the reader. Instead, we just implicitly
# ignore it.
return False
# Handler: Mouse Motion
# - This might seem arbitrary, but in fact this is required or else the position of the mouse
# will never be updated inside the window.
def handlerMouseMotion(self, x, y):
PyCEGUI.System.getSingleton().injectMousePosition(x, y)
return False

View file

@ -103,14 +103,13 @@ class Menu(object):
self.txtTitle = window.getChild(name + "/TxtTitle")
self.txtFrameRate = window.getChild(name + "/TxtFrameRate")
# Trace info. about children.
#print "Menu: Children (n=%d) :" % self.window.getChildCount()
#for chldInd in range(self.window.getChildCount()):
# print " #%d : name=%r" % (chldInd, self.window.getChildAtIdx(chldInd).getName())
return window
def onKeyDown(self, keyArgs):
# Nothing special to do here (see derived classes)
print "Menu.onKeyDown:", keyArgs
return False # Or True ?
# connectHandlers
# - Wrapper method to define the subscription/listener relationships.
# - If there are a lot, it may behoove the coder to encapsulate them in methods, then call those methods here.
@ -118,7 +117,7 @@ class Menu(object):
# Event subscriptions :
# * keyboard : Does not work.
self.window.subscribeEvent(PyCEGUI.Window.EventCharacterKey, self, 'onCharacterKey');
self.window.subscribeEvent(PyCEGUI.Window.EventKeyDown, self, 'onKeyDown');
# * window update (for the frame rate indicator).
self.window.subscribeEvent(PyCEGUI.Window.EventWindowUpdated, self, 'onUpdate');
@ -142,6 +141,9 @@ class Menu(object):
self.nFrames = 0
self.lastTime = glutGet(GLUT_ELAPSED_TIME)
# Give focus to the root window (needed for EventKeyDown being received).
self.window.activate()
# Return to the previous menu.
def back(self):
@ -161,7 +163,8 @@ class Menu(object):
self.nFrames = 0
self.lastTime = thisTime
def onCharacterKey(self, keyArgs):
pass # Just in case not specialised in actual class.
def onKeyDown(self, keyArgs):
# Just in case not specialised in actual class.
print "Menu.onKeyDown: sc=", keyArgs.scancode
return False # Or True ?

View file

@ -104,10 +104,6 @@ class MenuStandard(Menu):
# - If there are a lot, it may behoove the coder to encapsulate them in methods, then call those methods here.
def connectHandlers(self):
print "Menu: Children (n=%d) :" % self.window.getChildCount()
for chldInd in range(self.window.getChildCount()):
print " #%d : name=%r" % (chldInd, self.window.getChildAtIdx(chldInd).getName())
# Inherited connections.
Menu.connectHandlers(self)
@ -145,9 +141,9 @@ class MenuStandard(Menu):
print("Exiting (on exit button) ...")
sys.exit(0)
def onCharacterKey(self, keyArgs):
def onKeyDown(self, keyArgs):
print "MenuStandard.onCharacterKey: scan=%d, " % (keyArgs.scancode, )
print "MenuStandard.onKeyDown: sc=%d, " % (keyArgs.scancode, )
if keyArgs.scancode == PyCEGUI.Key.Escape:
keyArgs.handled += 1

View file

@ -34,6 +34,10 @@ from configuration import TheConfig
# Video
class Video(object):
def __del__(self):
OpenGLRenderer.destroySystem()
# Initialize: OpenGL
def initializeOpenGL(self):