diff --git a/src/tools/ceguidemo/input.py b/src/tools/ceguidemo/input.py index cba4f3f4a..2dfbcc346 100644 --- a/src/tools/ceguidemo/input.py +++ b/src/tools/ceguidemo/input.py @@ -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,11 +137,62 @@ 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): @@ -77,6 +215,8 @@ class Input(object): # An `else` clause could also go here to perform some arbitrary action on unhandled # 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 @@ -84,3 +224,5 @@ class Input(object): def handlerMouseMotion(self, x, y): PyCEGUI.System.getSingleton().injectMousePosition(x, y) + + return False diff --git a/src/tools/ceguidemo/menu.py b/src/tools/ceguidemo/menu.py index 7d8d962ca..cc5a6e1f2 100644 --- a/src/tools/ceguidemo/menu.py +++ b/src/tools/ceguidemo/menu.py @@ -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'); @@ -141,6 +140,9 @@ class Menu(object): # Initialize frame rate data. 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): + 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 ? diff --git a/src/tools/ceguidemo/menustandard.py b/src/tools/ceguidemo/menustandard.py index 5594d6134..41f8d17ad 100644 --- a/src/tools/ceguidemo/menustandard.py +++ b/src/tools/ceguidemo/menustandard.py @@ -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 diff --git a/src/tools/ceguidemo/video.py b/src/tools/ceguidemo/video.py index 5d76132c7..e33d36626 100644 --- a/src/tools/ceguidemo/video.py +++ b/src/tools/ceguidemo/video.py @@ -34,6 +34,10 @@ from configuration import TheConfig # Video class Video(object): + def __del__(self): + + OpenGLRenderer.destroySystem() + # Initialize: OpenGL def initializeOpenGL(self):