User:Crond/sandbox/openglEventExample2

From CEGUI Wiki - Crazy Eddie's GUI System (Open Source)
Jump to: navigation, search

Written for CEGUI 0.7


Works with versions 0.7.x (obsolete)

Requires at least version
0.7.5





Introduction

This presents a slightly refined example of using subscriptions to respond to events. The example will generate some text on the console when an Editbox receives input, and when Enter/Return is pressed while the Editbox has focus.

Requirements

  • Python 2.6
  • PyCEGUI
  • PyOpenGL

Notes

The source code uses a modified version of the OpenGL example posted here.

Source

#!/usr/bin/env python
#
#
# example.py
 
 
# Import: std
import sys
 
# Import: PyOpenGL
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
 
# Import: PyCEGUI
import PyCEGUI
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer
 
# Constants
PATH_RESOURCES = './'
 
# Keymap: ASCII
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,
                13 : PyCEGUI.Key.Scan.Return,
                27 : PyCEGUI.Key.Scan.Escape,
                127 : PyCEGUI.Key.Scan.Delete}
 
# Keymap: GLUT
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}
 
 
# Application
class Application(object):
 
    # Constructor
    def __init__(self):
        super(Application, self).__init__()
        self.lastFrameTime = 0
        self.updateFPS = 0
        return
 
    # Initialize: OpenGL
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT
    #   documentation.
    def initializeOpenGL(self):
        glutInit()
        glutDestroyWindow(glutCreateWindow(''))
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowSize(1024, 768)
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out
        glutCreateWindow("Crazy Eddie's GUI Mk-2 - glut Base Application")
        glutSetCursor(GLUT_CURSOR_NONE)
        return
 
    # Initialize: Handlers
    # - Setup the methods which will be called when events happen.
    def initializeHandlers(self):
        glutDisplayFunc(self.handlerDisplay)
        glutReshapeFunc(self.handlerResize)
        glutKeyboardFunc(self.handlerKeyboard)
        glutSpecialFunc(self.handlerKeyboardSpecial)
        glutMouseFunc(self.handlerMouse)
        glutMotionFunc(self.handlerMouseMotion)
        glutPassiveMotionFunc(self.handlerMouseMotion)
        return
 
    # Initialize: PyCEGUI
    # - Store some components; saves a lot of typing.
    def initializePyCEGUI(self):
        Renderer.bootstrapSystem()
        self.sys = PyCEGUI.System.getSingleton()
        self.rp = self.sys.getResourceProvider()
        self.scheme = PyCEGUI.SchemeManager.getSingleton()
        self.wm = PyCEGUI.WindowManager.getSingleton()
        return
 
    # Initialize: Defaults
    # - Resource locations.
    def initializeDefaults(self):
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')
        PyCEGUI.Font.setDefaultResourceGroup('fonts')
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')
        parser = self.sys.getXMLParser()
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')
        return
 
    # Initialize: GUI
    # - This is where we are actually setting up the windows we will see.
    def initializeGUI(self):
        self.scheme.create('VanillaSkin.scheme')
        self.scheme.create('TaharezLook.scheme')
 
        # GUISheet
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')
        self.sys.setGUISheet(self.rootWindow)
 
        # Cursor
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')
 
        # An extra window
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')
        self.rootWindow.addChildWindow(w)
        return
 
    # Initialize: Subscriptions
    def initializeSubscriptions(self):
 
        # In order to be able to access the buttons, we need to get a copy of their parent.
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')
 
        # Now, we get the buttons.
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')
        self.editboxText = self.windowNewNode.getChild('Demo/NewNode/Editbox')
 
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextChanged, self, 'handlerTextChanged')
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextAccepted, self, 'handlerTextAccepted')
        return
 
    # Initialize
    def Initialize(self):
        self.initializeOpenGL()
        self.initializeHandlers()
        self.initializePyCEGUI()
        self.initializeDefaults()
        self.initializeGUI()
        self.initializeSubscriptions()
        return
 
    # Handler: Display
    def handlerDisplay(self):
 
        # Injecting the time allows CEGUI to know how much time has passed, and
        # use that to coordinate certain activities - fading, animation, tooltips,
        # etc.
        now = glutGet(GLUT_ELAPSED_TIME)
        elapsed = (now - self.lastFrameTime) / 1000.0
        self.lastFrameTime = now
        self.updateFPS = self.updateFPS - elapsed
        self.sys.injectTimePulse(elapsed)
 
        # Actual rendering
        # - `renderGUI` updates CEGUI's picture of the GUI.
        # - `glutPostRedisplay` is what actually marks the window as needing to
        #   be redrawn by OpenGL.
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        self.sys.renderGUI()
        glutPostRedisplay()
        glutSwapBuffers()
        return
 
    # Handler: Resize
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.
    def handlerResize(self, width, height):
        glViewport(0, 0, width, height)
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))
        return
 
    # Handler: Assist keyboard
    def handlerAssistKeyboard(self, key):
        try:
            self.sys.injectKeyDown(KEYMAP_ASCII[key])
        except KeyError:
            return False
        return True
 
    # Handler: Keyboard
    def handlerKeyboard(self, key, x, y):
        k = ord(key)
        if not self.handlerAssistKeyboard(k):
            self.sys.injectChar(ord(key))
        return
 
    # Handler: Keyboard special
    def handlerKeyboardSpecial(self, key, x, y):
        try:
            self.sys.injectKeyDown(KEYMAP_GLUT[key])
        except KeyError:
            # Ignore it.
            pass
        return
 
    # Handler: Mouse buttons
    def handlerMouse(self, button, state, x, y):
        if button == GLUT_LEFT_BUTTON:
            if state == GLUT_UP:
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)
            else:
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)
        elif button == GLUT_RIGHT_BUTTON:
            if state == GLUT_UP:
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)
            else:
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)
        return
 
    # Handler: Mouse motion
    def handlerMouseMotion(self, x, y):
        self.sys.injectMousePosition(x, y)
        return
 
    # Handler: buttonOkayClicked
    def buttonOkayClicked(self, args):
        print('Okay has been clicked.')
        return
 
    # Handler: buttonCancelClicked
    def buttonCancelClicked(self, args):
        print('Cancel has been clicked.')
        return
 
    # Handler: Text changed
    def handlerTextChanged(self, args):
        print('Text has changed.')
        return
 
    # Handler: Text accepted
    def handlerTextAccepted(self, args):
        print('Text [{0}]has been accepted.'.format(self.editboxText.getText()))
        return
 
    # Run
    def Run(self):
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)
        glutMainLoop()
        return
 
# Main
def main():
    app = Application()
    app.Initialize()
    app.Run()
    return 0
 
 
# Guard
if __name__ == '__main__':
    sys.exit(main())

Demonstration

Enter some text into the Editbox, and/or press Return while the Editbox has focus.

Examination

In the context of the previous examples, this is all pretty straightforward; this simply demonstrates some additional events which are relevant to an Editbox.

As an exercise for the reader, consider the implications of removing the mapping of the return key from `KEYMAP_ASCII`, and why the effects are what they are.