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 This class sets up input processing by creating handlers for GLUT that inject
input into PyCEGUI. 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: std
import sys import sys
import string
# Import: OpenGL # Import: OpenGL
from OpenGL.GL import * from OpenGL.GL import *
@ -30,11 +34,92 @@ from errors import InitializationError
# Input # Input
class Input(object): 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 # Initialize: Handlers
def initializeHandlers(self): def initializeHandlers(self):
glutKeyboardFunc(self.handlerKeyDown) glutKeyboardFunc(self.handlerNormalKeyDown)
glutMouseFunc(self.handlerMouseButton) glutSpecialFunc(self.handlerSpecialKeyDown)
glutKeyboardUpFunc(self.handlerNormalKeyUp)
glutSpecialUpFunc(self.handlerSpecialKeyUp)
# The difference between these two is that the passive one is called when there is # 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 # mouse motion while no buttons are pressed, and the other is called when there
@ -42,6 +127,8 @@ class Input(object):
glutMotionFunc(self.handlerMouseMotion) glutMotionFunc(self.handlerMouseMotion)
glutPassiveMotionFunc(self.handlerMouseMotion) glutPassiveMotionFunc(self.handlerMouseMotion)
glutMouseFunc(self.handlerMouseButton)
# Initialize # Initialize
def initialize(self): def initialize(self):
@ -50,12 +137,63 @@ class Input(object):
except Exception, msg: except Exception, msg:
raise InitializationError(msg) raise InitializationError(msg)
# Handler: Key Down def handleModifierKeys(self):
# - `ord` is a built-in Python function.
def handlerKeyDown(self, key, x, y):
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)) 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 # Handler: Mouse Button
def handlerMouseButton(self, button, state, x, y): 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 # mouse input; this is left as an exercise for the reader. Instead, we just implicitly
# ignore it. # ignore it.
return False
# Handler: Mouse Motion # Handler: Mouse Motion
# - This might seem arbitrary, but in fact this is required or else the position of the mouse # - This might seem arbitrary, but in fact this is required or else the position of the mouse
# will never be updated inside the window. # will never be updated inside the window.
def handlerMouseMotion(self, x, y): def handlerMouseMotion(self, x, y):
PyCEGUI.System.getSingleton().injectMousePosition(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.txtTitle = window.getChild(name + "/TxtTitle")
self.txtFrameRate = window.getChild(name + "/TxtFrameRate") 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 return window
def onKeyDown(self, keyArgs):
# Nothing special to do here (see derived classes)
print "Menu.onKeyDown:", keyArgs
return False # Or True ?
# connectHandlers # connectHandlers
# - Wrapper method to define the subscription/listener relationships. # - 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. # - 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 : # Event subscriptions :
# * keyboard : Does not work. # * 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). # * window update (for the frame rate indicator).
self.window.subscribeEvent(PyCEGUI.Window.EventWindowUpdated, self, 'onUpdate'); self.window.subscribeEvent(PyCEGUI.Window.EventWindowUpdated, self, 'onUpdate');
@ -142,6 +141,9 @@ class Menu(object):
self.nFrames = 0 self.nFrames = 0
self.lastTime = glutGet(GLUT_ELAPSED_TIME) 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. # Return to the previous menu.
def back(self): def back(self):
@ -161,7 +163,8 @@ class Menu(object):
self.nFrames = 0 self.nFrames = 0
self.lastTime = thisTime self.lastTime = thisTime
def onCharacterKey(self, keyArgs): def onKeyDown(self, keyArgs):
pass # Just in case not specialised in actual class.
# 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. # - If there are a lot, it may behoove the coder to encapsulate them in methods, then call those methods here.
def connectHandlers(self): 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. # Inherited connections.
Menu.connectHandlers(self) Menu.connectHandlers(self)
@ -145,9 +141,9 @@ class MenuStandard(Menu):
print("Exiting (on exit button) ...") print("Exiting (on exit button) ...")
sys.exit(0) 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: if keyArgs.scancode == PyCEGUI.Key.Escape:
keyArgs.handled += 1 keyArgs.handled += 1

View file

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