<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://cegui.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Crond</id>
		<title>CEGUI Wiki - Crazy Eddie's GUI System (Open Source) - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://cegui.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Crond"/>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/Special:Contributions/Crond"/>
		<updated>2026-05-03T11:41:53Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.24.1</generator>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4572</id>
		<title>User:Crond</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4572"/>
				<updated>2011-07-11T00:51:20Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Places */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Todo ==&lt;br /&gt;
* Finish the PyCEGUI page&lt;br /&gt;
** Application&lt;br /&gt;
* Add Python code examples for 'In Practice' series.&lt;br /&gt;
* Find the Triforce - except there is no try. (Two references in one sentence - put that in your pipe and smoke it).&lt;br /&gt;
&lt;br /&gt;
== Places ==&lt;br /&gt;
[[User:Crond/sandbox|Sandbox]]&amp;lt;br /&amp;gt;&lt;br /&gt;
Inspiration to continue [http://www.youtube.com/watch?v=y-I7gjPNJbE the application].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4571</id>
		<title>User:Crond</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4571"/>
				<updated>2011-07-10T21:36:20Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Todo */ beers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Todo ==&lt;br /&gt;
* Finish the PyCEGUI page&lt;br /&gt;
** Application&lt;br /&gt;
* Add Python code examples for 'In Practice' series.&lt;br /&gt;
* Find the Triforce - except there is no try. (Two references in one sentence - put that in your pipe and smoke it).&lt;br /&gt;
&lt;br /&gt;
== Places ==&lt;br /&gt;
[[User:Crond/sandbox|Sandbox]]&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4570</id>
		<title>User:Crond</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4570"/>
				<updated>2011-07-10T15:23:38Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Todo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Todo ==&lt;br /&gt;
* Finish the PyCEGUI page&lt;br /&gt;
** Application&lt;br /&gt;
* Add Python code examples for 'In Practice' series.&lt;br /&gt;
&lt;br /&gt;
== Places ==&lt;br /&gt;
[[User:Crond/sandbox|Sandbox]]&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4569</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4569"/>
				<updated>2011-07-10T15:22:48Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* OpenGL driver bugs */ someone elses problem&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Future release (0.8+) ===&lt;br /&gt;
'''TODO: Resolve repetition.'''&amp;lt;br /&amp;gt;&lt;br /&gt;
In the future, the signatures have been changed to be much more flexible and Pythonic. 'subscribeEvent' now takes any callable object (bound member function, free function, lambda, functor, etc). Moving from the old syntax to the new syntax, the following&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, instance, &amp;quot;someMethod&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, instance.someMethod)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending release (0.8+)'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL driver bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset, which are outside the scope of [Py]CEGUI to deal with.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== Application from scratch ===&lt;br /&gt;
* See [[User:Crond/sandbox/application1|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4568</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4568"/>
				<updated>2011-07-10T15:20:11Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: rm  more user data; update&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Future release (0.8+) ===&lt;br /&gt;
'''TODO: Resolve repetition.'''&amp;lt;br /&amp;gt;&lt;br /&gt;
In the future, the signatures have been changed to be much more flexible and Pythonic. 'subscribeEvent' now takes any callable object (bound member function, free function, lambda, functor, etc). Moving from the old syntax to the new syntax, the following&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, instance, &amp;quot;someMethod&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
becomes this&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, instance.someMethod)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending release (0.8+)'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL driver bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== Application from scratch ===&lt;br /&gt;
* See [[User:Crond/sandbox/application1|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4567</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4567"/>
				<updated>2011-07-10T15:13:03Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Known issues */ rm user data&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending release'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL driver bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== Application from scratch ===&lt;br /&gt;
* See [[User:Crond/sandbox/application1|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=Build_PyCEGUI_from_source_for_Windows&amp;diff=4566</id>
		<title>Build PyCEGUI from source for Windows</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=Build_PyCEGUI_from_source_for_Windows&amp;diff=4566"/>
				<updated>2011-07-10T15:10:51Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Windows 7 (x64) */ ce&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Windows 7 (x64) ==&lt;br /&gt;
The main documentation (found [http://www.cegui.org.uk/docs/current/compiling.html here]) does a good job of explaining the process. However, a caveat with x64 is that consistency needs to be maintained across several software packages. In the context of CEGUI, this is particularly relevant in regards to Python and Boost; which is to say that if you are trying to build the PyCEGUI project from the generated solution, and are getting a lot of unresolved linker errors, you are probably trying to link against a 64bit installation of Python.&lt;br /&gt;
&lt;br /&gt;
The solution, as might be expected, is to uninstall the existing 64bit version of Python, and to install a 32bit variant.&lt;br /&gt;
&lt;br /&gt;
=== Who this affects ===&lt;br /&gt;
An assumption is that this is only a problem for people who installed precompiled versions of boost as provided by [http://boostpro.com/download/ these fine people]; if you compiled the boost libraries yourself, this may not be an issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:HowTo]]&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=Build_PyCEGUI_from_source_for_Windows&amp;diff=4565</id>
		<title>Build PyCEGUI from source for Windows</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=Build_PyCEGUI_from_source_for_Windows&amp;diff=4565"/>
				<updated>2011-07-10T12:06:42Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: created; mainly, to document the architecture mismatch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Windows 7 (x64) ==&lt;br /&gt;
The main documentation (found [http://www.cegui.org.uk/docs/current/compiling.html here]) does a good job of explaining the process. However, a caveat with x64 is that consistency needs to be maintained across several software packages. In the context of CEGUI, this is particularly relevant in regards to Python and Boost; which is to say that if you are trying to build the PyCEGUI project from the generated solution, and are getting a lot of unresolved linker errors, you are probably trying to link against a 64bit installation of Python.&lt;br /&gt;
&lt;br /&gt;
The solution, as might be expected, is to uninstall the existing 64bit version of Python, and reinstall a 32bit variant.&lt;br /&gt;
&lt;br /&gt;
=== Who this affects ===&lt;br /&gt;
An assumption is that this is only a problem for people who installed precompiled versions of boost as provided by [http://boostpro.com/download/ these fine people]; if you compiled the boost libraries yourself, this may not be an issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:HowTo]]&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=Talk:Build_PyCEGUI_from_source_for_Linux&amp;diff=4564</id>
		<title>Talk:Build PyCEGUI from source for Linux</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=Talk:Build_PyCEGUI_from_source_for_Linux&amp;diff=4564"/>
				<updated>2011-07-10T11:30:18Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: sign; header&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Thoughts ==&lt;br /&gt;
A good topic, one close to my heart.&lt;br /&gt;
&lt;br /&gt;
I am curious, though; in this snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
sudo rmdir /usr/local/lib/python2.6/site-packages&lt;br /&gt;
sudo ln -s /usr/local/lib/python2.6/dist-packages/ /usr/local/lib/python2.6/site-packages&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* If 'site-packages' is not empty, that command will fail; an 'rm -r' would be necessary, but in that case it means the directory might have valuable contents.&lt;br /&gt;
* Which leads to my next question: is deleting that directory a good idea? Could it cause future problems with some other arbitrary piece of software?&lt;br /&gt;
- [[User:Crond|Crond]] 11:30, 10 July 2011 (UTC)&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=Talk:Build_PyCEGUI_from_source_for_Linux&amp;diff=4563</id>
		<title>Talk:Build PyCEGUI from source for Linux</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=Talk:Build_PyCEGUI_from_source_for_Linux&amp;diff=4563"/>
				<updated>2011-07-10T11:29:24Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: blather&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A good topic, one close to my heart.&lt;br /&gt;
&lt;br /&gt;
I am curious, though; in this snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
sudo rmdir /usr/local/lib/python2.6/site-packages&lt;br /&gt;
sudo ln -s /usr/local/lib/python2.6/dist-packages/ /usr/local/lib/python2.6/site-packages&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* If 'site-packages' is not empty, that command will fail; an 'rm -r' would be necessary, but in that case it means the directory might have valuable contents.&lt;br /&gt;
* Which leads to my next question: is deleting that directory a good idea? Could it cause future problems with some other arbitrary piece of software?&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=Build_PyCEGUI_from_source_for_Linux&amp;diff=4562</id>
		<title>Build PyCEGUI from source for Linux</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=Build_PyCEGUI_from_source_for_Linux&amp;diff=4562"/>
				<updated>2011-07-10T11:26:09Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: made python version the same across code snippets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.4}}&lt;br /&gt;
= Ubuntu 11.04 =&lt;br /&gt;
Version shipped in repositories is 0.6.0 (as of 7th July 2011) so if we want 0.7.x we need to build it from source.&lt;br /&gt;
&lt;br /&gt;
* Install dependency packages: &amp;lt;code&amp;gt;sudo apt-get install build-essential pkg-config python-dev libfreetype6-dev libpcre3-dev libboost-python-dev libglut3-dev libpng-dev libmng-dev libjpeg-dev libfreeimage-dev&amp;lt;/code&amp;gt;&lt;br /&gt;
* Obtain a copy of CEGUI [http://prdownloads.sourceforge.net/crayzedsgui/CEGUI-0.7.5.tar.gz?download here]&lt;br /&gt;
* Extract to a folder&lt;br /&gt;
* Before we build, we have to symlink the site-packages directory correctly, so it installs to the correct place. &lt;br /&gt;
 sudo rmdir /usr/local/lib/python2.6/site-packages&lt;br /&gt;
 sudo ln -s /usr/local/lib/python2.6/dist-packages/ /usr/local/lib/python2.6/site-packages&lt;br /&gt;
* Build CEGUI with python support&lt;br /&gt;
 ./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; sudo make install &amp;amp;&amp;amp; sudo ldconfig&lt;br /&gt;
* ''Note: On some Ubuntu systems it seems that CEGUI's configure system does not correctly detect the Python headers. To solve this, do the following:''&lt;br /&gt;
 export CXXFLAGS=-I/usr/include/python2.6&lt;br /&gt;
 ./configure &amp;amp;&amp;amp; make &amp;amp;&amp;amp; sudo make install &amp;amp;&amp;amp; sudo ldconfig&lt;br /&gt;
&lt;br /&gt;
= Still not working? =&lt;br /&gt;
You can try running your program with:&lt;br /&gt;
 PYTHONPATH=&amp;quot;/usr/local/lib/python2.6/site-packages:$PYTHONPATH&amp;quot; python &amp;lt;file.py&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note for Panda3D users'''&lt;br /&gt;
You can run your program at the same way, using:&lt;br /&gt;
 PYTHONPATH=&amp;quot;/usr/local/lib/python2.6/site-packages:$PYTHONPATH&amp;quot; ppython &amp;lt;file.py&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:HowTo]]&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4554</id>
		<title>User:Crond</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond&amp;diff=4554"/>
				<updated>2011-06-22T07:25:41Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Todo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Todo ==&lt;br /&gt;
* Finish the PyCEGUI page&lt;br /&gt;
** Test the UserData hypothesis.&lt;br /&gt;
* Add Python code examples for 'In Practice' series.&lt;br /&gt;
* Some new demos/examples?&lt;br /&gt;
* Application&lt;br /&gt;
&lt;br /&gt;
== Places ==&lt;br /&gt;
[[User:Crond/sandbox|Sandbox]]&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/application1&amp;diff=4553</id>
		<title>User:Crond/sandbox/application1</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/application1&amp;diff=4553"/>
				<updated>2011-06-21T16:51:40Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: preliminary outline&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/application1&amp;diff=4551</id>
		<title>User:Crond/sandbox/application1</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/application1&amp;diff=4551"/>
				<updated>2011-06-20T16:02:42Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Requirements */ superfluous&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
{{Series|PyCEGUI: BeerTracker|1}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is the first in a series of articles, designed to build an application from the ground up - that is to say, the planning, construction, and utilization of the application are all documented.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== What is the application? ==&lt;br /&gt;
I gave this a good amount of thought, then I realized that I am sitting here, thinking, while drinking beer. Thus, the wonderful idea of writing an application to track the amount of beer I drank, as well as my thoughts on each individual beer, formed; not only will it do these wonderful things, it will be persistent - the application will remember whatever it is told. Finally, it will have a history feature: which is to say, a user can go back to a specific date and read about how they felt about the beer they drank that day - you know, in case they don't remember.&lt;br /&gt;
&lt;br /&gt;
== Why this application? ==&lt;br /&gt;
I'm pretty sure this is self-explanatory.&lt;br /&gt;
&lt;br /&gt;
== Series ==&lt;br /&gt;
* n&lt;br /&gt;
* n+1&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
* Create initial application; then post it.&lt;br /&gt;
* Create category for series '''only after''' the initial application is done.&lt;br /&gt;
* ETA of initial application: 6/24+&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

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

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample2&amp;diff=4549</id>
		<title>User:Crond/sandbox/openglEventExample2</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample2&amp;diff=4549"/>
				<updated>2011-06-20T15:55:25Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Notes */ fix link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
        self.editboxText = self.windowNewNode.getChild('Demo/NewNode/Editbox')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextChanged, self, 'handlerTextChanged')&lt;br /&gt;
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextAccepted, self, 'handlerTextAccepted')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Text changed&lt;br /&gt;
    def handlerTextChanged(self, args):&lt;br /&gt;
        print('Text has changed.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Text accepted&lt;br /&gt;
    def handlerTextAccepted(self, args):&lt;br /&gt;
        print('Text has been accepted.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Enter some text into the Editbox, and/or press Return while the Editbox has focus.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
In the context of the previous examples, this is all pretty straightforward; this simply demonstrates some additional events which are relevant to an Editbox.&lt;br /&gt;
&lt;br /&gt;
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.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4548</id>
		<title>User:Crond/sandbox/openglEventExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4548"/>
				<updated>2011-06-20T15:54:36Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Notes */ change link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents the basics of using subscriptions to respond to events. The example retrieves two buttons and defines a method to be called when they are each clicked.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Just click either of the two buttons on the 'NewNode' frame window; some output will appear on the console.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== Layout to Python ===&lt;br /&gt;
To subscribe to an event, the application needs two fundamental details: the layout, and the widget that should respond to an event. The layout is simple - we just pass the name of it to the PyCEGUI WindowManager object; getting child windows and/or widgets can be a little more subtle - to do this, we have to know the name of the window in question.&lt;br /&gt;
&lt;br /&gt;
In the case of the example above, we want to respond to events on the 'NewNode' frame window, so we first retrieve a copy of it - as indicated by this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we need a copy of the buttons which we want to listen for events, as indicated by these lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we want to set what events we respond to and how we respond to them. We do this by defining methods on our object, and telling PyCEGUI to call them when specific events happen. This is indicated by the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument is specifying what event to listen for (in this case, the clicking of the button), and the second/third arguments specify what function/method should be invoked when the event in question happens.&lt;br /&gt;
&lt;br /&gt;
'''Note: Future versions do not require the latter two arguments; in their place, a function/method object is sufficient.'''&lt;br /&gt;
&lt;br /&gt;
=== Layout editing ===&lt;br /&gt;
The exact name of the widgets you want to access can be determined via the XML 'Name' property, as found in the layout files.&lt;br /&gt;
&lt;br /&gt;
In the event you are not creating your layout files by hand, the names can be found via the CELayoutEditor under the 'Name' property in the Main Dialog.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample2&amp;diff=4547</id>
		<title>User:Crond/sandbox/openglEventExample2</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample2&amp;diff=4547"/>
				<updated>2011-06-20T15:52:08Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Requirements */ superfluous&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/opengEventExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
        self.editboxText = self.windowNewNode.getChild('Demo/NewNode/Editbox')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextChanged, self, 'handlerTextChanged')&lt;br /&gt;
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextAccepted, self, 'handlerTextAccepted')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Text changed&lt;br /&gt;
    def handlerTextChanged(self, args):&lt;br /&gt;
        print('Text has changed.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Text accepted&lt;br /&gt;
    def handlerTextAccepted(self, args):&lt;br /&gt;
        print('Text has been accepted.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Enter some text into the Editbox, and/or press Return while the Editbox has focus.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
In the context of the previous examples, this is all pretty straightforward; this simply demonstrates some additional events which are relevant to an Editbox.&lt;br /&gt;
&lt;br /&gt;
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.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4546</id>
		<title>User:Crond/sandbox/openglEventExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4546"/>
				<updated>2011-06-20T15:51:43Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Requirements */ superfluous&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents the basics of using subscriptions to respond to events. The example retrieves two buttons and defines a method to be called when they are each clicked.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Just click either of the two buttons on the 'NewNode' frame window; some output will appear on the console.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== Layout to Python ===&lt;br /&gt;
To subscribe to an event, the application needs two fundamental details: the layout, and the widget that should respond to an event. The layout is simple - we just pass the name of it to the PyCEGUI WindowManager object; getting child windows and/or widgets can be a little more subtle - to do this, we have to know the name of the window in question.&lt;br /&gt;
&lt;br /&gt;
In the case of the example above, we want to respond to events on the 'NewNode' frame window, so we first retrieve a copy of it - as indicated by this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we need a copy of the buttons which we want to listen for events, as indicated by these lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we want to set what events we respond to and how we respond to them. We do this by defining methods on our object, and telling PyCEGUI to call them when specific events happen. This is indicated by the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument is specifying what event to listen for (in this case, the clicking of the button), and the second/third arguments specify what function/method should be invoked when the event in question happens.&lt;br /&gt;
&lt;br /&gt;
'''Note: Future versions do not require the latter two arguments; in their place, a function/method object is sufficient.'''&lt;br /&gt;
&lt;br /&gt;
=== Layout editing ===&lt;br /&gt;
The exact name of the widgets you want to access can be determined via the XML 'Name' property, as found in the layout files.&lt;br /&gt;
&lt;br /&gt;
In the event you are not creating your layout files by hand, the names can be found via the CELayoutEditor under the 'Name' property in the Main Dialog.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4545</id>
		<title>User:Crond/sandbox/openglSpecialKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4545"/>
				<updated>2011-06-20T15:51:19Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Requirements */ superfluous&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic keyboard processing OpenGL application, as found [[User:Crond/sandbox/openglKeyboardExample|here]]. The goal is to present a further refinement of keyboard processing, specifically the handling of &amp;quot;special&amp;quot; keys, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
As before, we can see that this works by running the application, typing into the Editbox, and pressing the arrow keys, or any of the other keys.&lt;br /&gt;
&lt;br /&gt;
Several keys, such as Escape and Return, are not readily testable (i.e. produce no discernible effects on the application), although they do work. It is left as an exercise to the reader to prove it.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== GLUT, ASCII, PyCEGUI ===&lt;br /&gt;
It can be a little tricky, at times, to separate them all. A good rule of thumb is that using the `ord` function on any input received via GLUT will produce the ASCII value, which can then be handled in whatever way the application desires - e.g. mapping it to a PyCEGUI value.&lt;br /&gt;
&lt;br /&gt;
An additional note is that what GLUT considers to be a &amp;quot;special&amp;quot; key is not exactly what PyCEGUI (or any other library, for that matter) considers to be special. For this reason, the `KEYMAP_ASCII` exists and helps define additional keys that are special, whatever that may mean in a particular context.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4544</id>
		<title>User:Crond/sandbox/openglKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4544"/>
				<updated>2011-06-20T15:50:58Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Requirements */ superfluous&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic OpenGL application, as found [[User:Crond/sandbox/openglExample|here]]. The goal is to present the basics of keyboard processing, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
We can see that this works by running the application, and typing into the Editbox, as provided by the 'New Node' frame window.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== 'ord' function ===&lt;br /&gt;
The 'ord' function is a built-in Python function, which converts a single character (or a string of length one, if you prefer) to its Unicode/ASCII value; for further details, see the Python documentation [http://docs.python.org/release/2.6.5/library/functions.html#ord here].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglExample&amp;diff=4543</id>
		<title>User:Crond/sandbox/openglExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglExample&amp;diff=4543"/>
				<updated>2011-06-20T15:50:27Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Requirements */ superfluous&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents a minimal PyCEGUI application, using OpenGL as the renderer. The goal is to familiarize the reader with the basics of how to get PyCEGUI up and running, and to provide a few pointers along the way.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4539</id>
		<title>User:Crond/sandbox/openglEventExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4539"/>
				<updated>2011-06-20T07:50:25Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Layout to Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents the basics of using subscriptions to respond to events. The example retrieves two buttons and defines a method to be called when they are each clicked.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Just click either of the two buttons on the 'NewNode' frame window; some output will appear on the console.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== Layout to Python ===&lt;br /&gt;
To subscribe to an event, the application needs two fundamental details: the layout, and the widget that should respond to an event. The layout is simple - we just pass the name of it to the PyCEGUI WindowManager object; getting child windows and/or widgets can be a little more subtle - to do this, we have to know the name of the window in question.&lt;br /&gt;
&lt;br /&gt;
In the case of the example above, we want to respond to events on the 'NewNode' frame window, so we first retrieve a copy of it - as indicated by this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we need a copy of the buttons which we want to listen for events, as indicated by these lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we want to set what events we respond to and how we respond to them. We do this by defining methods on our object, and telling PyCEGUI to call them when specific events happen. This is indicated by the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument is specifying what event to listen for (in this case, the clicking of the button), and the second/third arguments specify what function/method should be invoked when the event in question happens.&lt;br /&gt;
&lt;br /&gt;
'''Note: Future versions do not require the latter two arguments; in their place, a function/method object is sufficient.'''&lt;br /&gt;
&lt;br /&gt;
=== Layout editing ===&lt;br /&gt;
The exact name of the widgets you want to access can be determined via the XML 'Name' property, as found in the layout files.&lt;br /&gt;
&lt;br /&gt;
In the event you are not creating your layout files by hand, the names can be found via the CELayoutEditor under the 'Name' property in the Main Dialog.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4538</id>
		<title>User:Crond/sandbox/openglEventExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4538"/>
				<updated>2011-06-20T07:50:02Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Layout to Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents the basics of using subscriptions to respond to events. The example retrieves two buttons and defines a method to be called when they are each clicked.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Just click either of the two buttons on the 'NewNode' frame window; some output will appear on the console.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== Layout to Python ===&lt;br /&gt;
To subscribe to an event, the application needs two fundamental details: the layout, and the widget that should respond to an event. The layout is simple - we just pass the name of it to the PyCEGUI WindowManager object; getting child windows and/or widgets can be a little more subtle - to do this, we have to know the name of the window in question.&lt;br /&gt;
&lt;br /&gt;
In the case of the example above, we want to respond to events on the 'NewNode' frame window, so we first retrieve a copy of it - as indicated by this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we need a copy of the buttons which we want to listen for events, as indicated by these lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we want to set what events we respond to and how we respond to them. We do this by defining methods on our object, and telling PyCEGUI to call them when specific events happen. This is indicated by the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument is specifying what event to listen for (in this case, the clicking of the button), and the second/third arguments specify what function/method should be invoked when the event in question happens.&lt;br /&gt;
&lt;br /&gt;
'''Note: Future versions do not require the latter two arguments; rather, a function/method object.'''&lt;br /&gt;
&lt;br /&gt;
=== Layout editing ===&lt;br /&gt;
The exact name of the widgets you want to access can be determined via the XML 'Name' property, as found in the layout files.&lt;br /&gt;
&lt;br /&gt;
In the event you are not creating your layout files by hand, the names can be found via the CELayoutEditor under the 'Name' property in the Main Dialog.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4537</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4537"/>
				<updated>2011-06-18T22:03:22Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* OpenGL bugs */ specificity&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
'''Todo: Is this true? And if it's not, why did I think it was?'''&amp;lt;br /&amp;gt;&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL driver bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== Application from scratch ===&lt;br /&gt;
* See [[User:Crond/sandbox/application1|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/application1&amp;diff=4536</id>
		<title>User:Crond/sandbox/application1</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/application1&amp;diff=4536"/>
				<updated>2011-06-18T22:01:32Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: initial placeholder&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
{{Series|PyCEGUI: BeerTracker|1}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is the first in a series of articles, designed to build an application from the ground up - that is to say, the planning, construction, and utilization of the application are all documented.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== What is the application? ==&lt;br /&gt;
I gave this a good amount of thought, then I realized that I am sitting here, thinking, while drinking beer. Thus, the wonderful idea of writing an application to track the amount of beer I drank, as well as my thoughts on each individual beer, formed; not only will it do these wonderful things, it will be persistent - the application will remember whatever it is told. Finally, it will have a history feature: which is to say, a user can go back to a specific date and read about how they felt about the beer they drank that day - you know, in case they don't remember.&lt;br /&gt;
&lt;br /&gt;
== Why this application? ==&lt;br /&gt;
I'm pretty sure this is self-explanatory.&lt;br /&gt;
&lt;br /&gt;
== Series ==&lt;br /&gt;
* n&lt;br /&gt;
* n+1&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
== TODO ==&lt;br /&gt;
* Create initial application; then post it.&lt;br /&gt;
* Create category for series '''only after''' the initial application is done.&lt;br /&gt;
* ETA of initial application: 6/24+&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4535</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4535"/>
				<updated>2011-06-18T21:49:17Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Application from scratch */ placeholder&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
'''Todo: Is this true? And if it's not, why did I think it was?'''&amp;lt;br /&amp;gt;&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== Application from scratch ===&lt;br /&gt;
* See [[User:Crond/sandbox/application1|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4534</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4534"/>
				<updated>2011-06-18T21:37:32Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Examples */ to be done&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
'''Todo: Is this true? And if it's not, why did I think it was?'''&amp;lt;br /&amp;gt;&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== Application from scratch ===&lt;br /&gt;
* n&lt;br /&gt;
* n+1&lt;br /&gt;
* ...&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=PyCEGUI/Example&amp;diff=4533</id>
		<title>PyCEGUI/Example</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=PyCEGUI/Example&amp;diff=4533"/>
				<updated>2011-06-18T21:35:55Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: oops&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
This is an example which creates a light, non-comprehensive framework for PyCEGUI, with the rendering system used being [Py]OpenGL. The reason OpenGL is used is because it's free, easy to get on any Ubuntu system (which this was written on), and portable. Also, it's the one demonstrated on the official [[PyCEGUI]] page.&lt;br /&gt;
&lt;br /&gt;
== Links of interest ==&lt;br /&gt;
*[http://docs.python.org/release/2.6.5/ Python 2.6.5 documentation]&lt;br /&gt;
*[http://pyopengl.sourceforge.net/documentation/manual-3.0/index.xhtml PyOpenGL reference]&lt;br /&gt;
*[http://pyopengl.sourceforge.net/documentation/manual-3.0/index.xhtml#GLUT PyOpenGL GLUT reference]&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== General ===&lt;br /&gt;
*Python 2.6&lt;br /&gt;
*PyCEGUI&lt;br /&gt;
*PyOpenGL, GLU, GLUT&lt;br /&gt;
=== Datafiles ===&lt;br /&gt;
This example assumes the CEGUI datafiles are in the same directory as `demo.py`; see the following section.&lt;br /&gt;
=== Directory hierarchy ===&lt;br /&gt;
*/home/foo/bar/demo&lt;br /&gt;
**demo.py&lt;br /&gt;
**datafiles/&lt;br /&gt;
***datafiles/layouts/demomenu.layout&lt;br /&gt;
**config/&lt;br /&gt;
***constants.py&lt;br /&gt;
**error/&lt;br /&gt;
***errors.py&lt;br /&gt;
**input/&lt;br /&gt;
***input.py&lt;br /&gt;
**video/&lt;br /&gt;
***video.py&lt;br /&gt;
**gui/&lt;br /&gt;
***gui.py&lt;br /&gt;
***demomenu.py&lt;br /&gt;
&lt;br /&gt;
== General notes ==&lt;br /&gt;
This is not intended to be fully comprehensive; rather, the intention is to illustrate '''one way''' of setting up a GUI system. A minimal amount of thought was given to &amp;quot;problems down the road;&amp;quot; which is to say that there is no guarantee that a particular design constraint will not render the framework unsuitable for a particular purpose.&lt;br /&gt;
&lt;br /&gt;
In short: your mileage may vary.&lt;br /&gt;
&lt;br /&gt;
== Comments, improvements, etc ==&lt;br /&gt;
Use the discussion page.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
=== constants.py ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#&lt;br /&gt;
# constants.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Constant values.&lt;br /&gt;
&lt;br /&gt;
Values currently contained in this file include:&lt;br /&gt;
&lt;br /&gt;
    Version information&lt;br /&gt;
    Window name(s)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: psyco&lt;br /&gt;
try:&lt;br /&gt;
    import psyco&lt;br /&gt;
    psyco.full()&lt;br /&gt;
except ImportError:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Versioning&lt;br /&gt;
MINOR_VERSION = '01'&lt;br /&gt;
MAJOR_VERSION = '0'&lt;br /&gt;
FULL_VERSION = '.'.join([MAJOR_VERSION, MINOR_VERSION])&lt;br /&gt;
&lt;br /&gt;
# Name: Root window&lt;br /&gt;
NAME_ROOT_WINDOW = 'Demo: %s' % FULL_VERSION&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== errors.py ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#&lt;br /&gt;
# errors.py&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Errors.&lt;br /&gt;
&lt;br /&gt;
Currently defined errors include:&lt;br /&gt;
&lt;br /&gt;
    InitializationError&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: psyco&lt;br /&gt;
try:&lt;br /&gt;
    import psyco&lt;br /&gt;
    psyco.full()&lt;br /&gt;
except ImportError:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# InitializationError&lt;br /&gt;
class InitializationError(Exception):&lt;br /&gt;
    def __init__(self, msg):&lt;br /&gt;
        self.msg = msg&lt;br /&gt;
    def __str__(self):&lt;br /&gt;
        return ('InitializationError: %s' % self.msg)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== video.py ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#&lt;br /&gt;
# video.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Video functionality.&lt;br /&gt;
&lt;br /&gt;
This class brings together PyCEGUI and OpenGL into a comfortable interface.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: psyco&lt;br /&gt;
try:&lt;br /&gt;
    import psyco&lt;br /&gt;
    psyco.full()&lt;br /&gt;
except ImportError:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
# Import: OpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Import: User&lt;br /&gt;
from constants import *&lt;br /&gt;
from errors import InitializationError&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Video&lt;br /&gt;
class Video(object):&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1)&lt;br /&gt;
        glutCreateWindow(NAME_ROOT_WINDOW)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
&lt;br /&gt;
        # Handlers&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerReshape)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        self.renderer = Renderer.bootstrapSystem()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        try:&lt;br /&gt;
            self.initializeOpenGL()&lt;br /&gt;
            self.initializePyCEGUI()&lt;br /&gt;
        except Exception, msg:&lt;br /&gt;
            raise InitializationError(msg)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Shutdown&lt;br /&gt;
    # - For implicit use, use the Python special method `__del__`.&lt;br /&gt;
    def Shutdown(self):&lt;br /&gt;
        self.renderer.destroySystem()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    # - This is called to refresh the screen.&lt;br /&gt;
    # - See PyOpenGL documentation.&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
        thisTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (thisTime - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = thisTime&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        PyCEGUI.System.getSingleton().injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Render this frame&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        PyCEGUI.System.getSingleton().renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Reshape&lt;br /&gt;
    # - This is called when the window is resized and/or switches to fullscreen.&lt;br /&gt;
    # - See PyOpenGL documentation.&lt;br /&gt;
    def handlerReshape(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        glMatrixMode(GL_PROJECTION)&lt;br /&gt;
        glLoadIdentity()&lt;br /&gt;
        gluPerspective(60.0, width / height, 1.0, 50.0)&lt;br /&gt;
        glMatrixMode(GL_MODELVIEW)&lt;br /&gt;
        PyCEGUI.System.getSingleton().notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Main loop&lt;br /&gt;
    # - Set the initial values.&lt;br /&gt;
    # - This never returns; once this gets called, the application is driven entirely by events.&lt;br /&gt;
    def EnterMainLoop(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== input.py ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#&lt;br /&gt;
# input.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Input functionality.&lt;br /&gt;
&lt;br /&gt;
This class sets up input processing by creating handlers for GLUT that inject&lt;br /&gt;
input into PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: psyco&lt;br /&gt;
try:&lt;br /&gt;
    import psyco&lt;br /&gt;
    psyco.full()&lt;br /&gt;
except ImportError:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
# Import: OpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
&lt;br /&gt;
# Import: User&lt;br /&gt;
from constants import *&lt;br /&gt;
from errors import InitializationError&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Input&lt;br /&gt;
class Input(object):&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyDown)&lt;br /&gt;
        glutMouseFunc(self.handlerMouseButton)&lt;br /&gt;
&lt;br /&gt;
        # The difference between these two is that the passive one is called when there is&lt;br /&gt;
        # mouse motion while no buttons are pressed, and the other is called when there&lt;br /&gt;
        # is mouse motion while buttons are pressed. See PyOpenGL documentation.&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        try:&lt;br /&gt;
            self.initializeHandlers()&lt;br /&gt;
        except Exception, msg:&lt;br /&gt;
            raise InitializationError(msg)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Key Down&lt;br /&gt;
    # - `ord` is a built-in Python function.&lt;br /&gt;
    def handlerKeyDown(self, key, x, y):&lt;br /&gt;
        PyCEGUI.System.getSingleton().injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse Button&lt;br /&gt;
    def handlerMouseButton(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                PyCEGUI.System.getSingleton().injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                PyCEGUI.System.getSingleton().injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
&lt;br /&gt;
        # A thought is to turn this into an `else` clause; however, this implies that any&lt;br /&gt;
        # button besides the left is interpreted as the right button - this seems undesirable&lt;br /&gt;
        # for any mouse with more than two buttons.&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                PyCEGUI.System.getSingleton().injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                PyCEGUI.System.getSingleton().injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
&lt;br /&gt;
        # An `else` clause could also go here to perform some arbitrary action on unhandled&lt;br /&gt;
        # mouse input; this is left as an exercise for the reader. Instead, we just implicitly&lt;br /&gt;
        # ignore it.&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse Motion&lt;br /&gt;
    # - This might seem arbitrary, but in fact this is required or else the position of the mouse&lt;br /&gt;
    # will never be updated inside the window.&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        PyCEGUI.System.getSingleton().injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== gui.py ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#&lt;br /&gt;
# gui.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;GUI.&lt;br /&gt;
&lt;br /&gt;
This class is the entry point for the GUI; which is to say that it starts the&lt;br /&gt;
main menu and the rest is event driven.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: psyco&lt;br /&gt;
try:&lt;br /&gt;
    import psyco&lt;br /&gt;
    psyco.full()&lt;br /&gt;
except ImportError:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
&lt;br /&gt;
# Import: User&lt;br /&gt;
from errors import InitializationError&lt;br /&gt;
import demomenu&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# GUI&lt;br /&gt;
class GUI(object):&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Resources&lt;br /&gt;
    def initializeResources(self):&lt;br /&gt;
        rp = PyCEGUI.System.getSingleton().getResourceProvider()&lt;br /&gt;
        rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = PyCEGUI.System.getSingleton().getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        sm = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        sm.create('VanillaSkin.scheme')&lt;br /&gt;
        sm.create('TaharezLook.scheme')&lt;br /&gt;
        PyCEGUI.System.getSingleton().setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        try:&lt;br /&gt;
            self.initializeResources()&lt;br /&gt;
            self.initializeDefaults()&lt;br /&gt;
&lt;br /&gt;
            # GUISheet&lt;br /&gt;
            self.GUISheet = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'Root')&lt;br /&gt;
            PyCEGUI.System.getSingleton().setGUISheet(self.GUISheet)&lt;br /&gt;
        except Exception, msg:&lt;br /&gt;
            raise InitializationError(msg)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Setup&lt;br /&gt;
    # - Important: the instance of `demomenu.DemoMenu` has to be bound to this object; if it is&lt;br /&gt;
    # a local variable (read: destroyed when it goes out of scope), exceptions will be raised&lt;br /&gt;
    # about the `buttonClicked` method not existing. This is a drawback of the type of setup&lt;br /&gt;
    # this example uses, and as a consequence of Python being a garbage collected language.&lt;br /&gt;
    def Setup(self):&lt;br /&gt;
        self.demoMenu = demomenu.DemoMenu()&lt;br /&gt;
        self.demoMenu.Initialize()&lt;br /&gt;
        self.demoMenu.Setup()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Setup: Interface&lt;br /&gt;
    def setupInterface(self):&lt;br /&gt;
        self.Setup()&lt;br /&gt;
        return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== demomenu.py ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#&lt;br /&gt;
# demomenu.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;DemoMenu.&lt;br /&gt;
&lt;br /&gt;
This class represents a demonstration of how to control a menu with PyCEGUI and PyOpenGL.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: psyco&lt;br /&gt;
try:&lt;br /&gt;
    import psyco&lt;br /&gt;
    psyco.full()&lt;br /&gt;
except ImportError:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
&lt;br /&gt;
# Import: User&lt;br /&gt;
from errors import InitializationError&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# DemoMenu&lt;br /&gt;
class DemoMenu(object):&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.GUISheet = PyCEGUI.System.getSingleton().getGUISheet()&lt;br /&gt;
&lt;br /&gt;
        # Load the layout&lt;br /&gt;
        self.menu = PyCEGUI.WindowManager.getSingleton().loadWindowLayout('DemoMenu.layout')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # connectHandlers&lt;br /&gt;
    # - Wrapper method to define the subscription/listener relationships.&lt;br /&gt;
    # - If there are a lot, it may behoove the coder to encapsulate them in methods, then call those methods here.&lt;br /&gt;
    def connectHandlers(self):&lt;br /&gt;
        self.menu.getChild('DemoMenu/Button').subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Setup&lt;br /&gt;
    def Setup(self):&lt;br /&gt;
&lt;br /&gt;
        # Connect the handlers&lt;br /&gt;
        self.connectHandlers()&lt;br /&gt;
&lt;br /&gt;
        # Attach&lt;br /&gt;
        self.GUISheet.addChildWindow(self.menu)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonClicked&lt;br /&gt;
    def buttonClicked(self, args):&lt;br /&gt;
        print('buttonClicked')&lt;br /&gt;
        return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== demo.py ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
#&lt;br /&gt;
# demo.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;Demo entry point.&lt;br /&gt;
&lt;br /&gt;
A demonstration; mildly comprehensive, but not really.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os.path&lt;br /&gt;
sys.path.append(os.path.join(os.getcwd(), 'config'))&lt;br /&gt;
sys.path.append(os.path.join(os.getcwd(), 'error'))&lt;br /&gt;
sys.path.append(os.path.join(os.getcwd(), 'input'))&lt;br /&gt;
sys.path.append(os.path.join(os.getcwd(), 'video'))&lt;br /&gt;
sys.path.append(os.path.join(os.getcwd(), 'gui'))&lt;br /&gt;
&lt;br /&gt;
# Import: psyco&lt;br /&gt;
try:&lt;br /&gt;
    import psyco&lt;br /&gt;
    psyco.full()&lt;br /&gt;
except ImportError:&lt;br /&gt;
    pass&lt;br /&gt;
&lt;br /&gt;
# Import: User&lt;br /&gt;
from errors import InitializationError&lt;br /&gt;
from input import Input&lt;br /&gt;
from video import Video&lt;br /&gt;
from gui import GUI&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    gfx = Video()&lt;br /&gt;
    inp = Input()&lt;br /&gt;
    gui = GUI()&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    try:&lt;br /&gt;
        gfx.Initialize()&lt;br /&gt;
        inp.Initialize()&lt;br /&gt;
        gui.Initialize()&lt;br /&gt;
    except InitializationError as error:&lt;br /&gt;
        print(error)&lt;br /&gt;
        return 1&lt;br /&gt;
&lt;br /&gt;
    # Setup the interface&lt;br /&gt;
    gui.setupInterface()&lt;br /&gt;
&lt;br /&gt;
    # Main Loop&lt;br /&gt;
    gfx.EnterMainLoop()&lt;br /&gt;
&lt;br /&gt;
    # Done&lt;br /&gt;
    # - We will never actually get here.&lt;br /&gt;
    gfx.Shutdown()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== demomenu.layout ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;GUILayout &amp;gt;&lt;br /&gt;
    &amp;lt;Window Type=&amp;quot;TaharezLook/FrameWindow&amp;quot; Name=&amp;quot;DemoMenu&amp;quot; &amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;Font&amp;quot; Value=&amp;quot;DejaVuSans-10&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;Text&amp;quot; Value=&amp;quot;Demo Menu&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;TitlebarFont&amp;quot; Value=&amp;quot;DejaVuSans-10&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;RollUpEnabled&amp;quot; Value=&amp;quot;False&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;TitlebarEnabled&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;UnifiedAreaRect&amp;quot; Value=&amp;quot;{{0.157031,0},{0.194911,0},{0.783984,0},{0.687913,0}}&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;DragMovingEnabled&amp;quot; Value=&amp;quot;False&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;CloseButtonEnabled&amp;quot; Value=&amp;quot;False&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;EWSizingCursorImage&amp;quot; Value=&amp;quot;set:Vanilla-Images image:MouseArrow&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;InheritsTooltipText&amp;quot; Value=&amp;quot;False&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;NSSizingCursorImage&amp;quot; Value=&amp;quot;set:Vanilla-Images image:MouseArrow&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;NESWSizingCursorImage&amp;quot; Value=&amp;quot;set:Vanilla-Images image:MouseArrow&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Property Name=&amp;quot;NWSESizingCursorImage&amp;quot; Value=&amp;quot;set:Vanilla-Images image:MouseArrow&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;Window Type=&amp;quot;TaharezLook/StaticText&amp;quot; Name=&amp;quot;DemoMenu/Text&amp;quot; &amp;gt;&lt;br /&gt;
            &amp;lt;Property Name=&amp;quot;Text&amp;quot; Value=&amp;quot;Enter some text&amp;quot; /&amp;gt;&lt;br /&gt;
            &amp;lt;Property Name=&amp;quot;UnifiedAreaRect&amp;quot; Value=&amp;quot;{{0.0212363,0},{0.619781,0},{0.346946,0},{0.751932,0}}&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;/Window&amp;gt;&lt;br /&gt;
        &amp;lt;Window Type=&amp;quot;TaharezLook/Editbox&amp;quot; Name=&amp;quot;DemoMenu/Edit&amp;quot; &amp;gt;&lt;br /&gt;
            &amp;lt;Property Name=&amp;quot;MaxTextLength&amp;quot; Value=&amp;quot;1073741823&amp;quot; /&amp;gt;&lt;br /&gt;
            &amp;lt;Property Name=&amp;quot;UnifiedAreaRect&amp;quot; Value=&amp;quot;{{0.36704,0},{0.623671,0},{0.769671,0},{0.750419,0}}&amp;quot; /&amp;gt;&lt;br /&gt;
            &amp;lt;Property Name=&amp;quot;TextParsingEnabled&amp;quot; Value=&amp;quot;False&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;/Window&amp;gt;&lt;br /&gt;
        &amp;lt;Window Type=&amp;quot;TaharezLook/Button&amp;quot; Name=&amp;quot;DemoMenu/Button&amp;quot; &amp;gt;&lt;br /&gt;
            &amp;lt;Property Name=&amp;quot;Text&amp;quot; Value=&amp;quot;Click me&amp;quot; /&amp;gt;&lt;br /&gt;
            &amp;lt;Property Name=&amp;quot;UnifiedAreaRect&amp;quot; Value=&amp;quot;{{0.78567,0},{0.620646,0},{0.979596,0},{0.749355,0}}&amp;quot; /&amp;gt;&lt;br /&gt;
        &amp;lt;/Window&amp;gt;&lt;br /&gt;
    &amp;lt;/Window&amp;gt;&lt;br /&gt;
&amp;lt;/GUILayout&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Modifications ==&lt;br /&gt;
=== demomenu.py ===&lt;br /&gt;
To further demonstrate usage of how to manipulate the widgets and branch the script/code divide, consider the following modification to the `demomenu.DemoMenu.buttonClicked` method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def buttonClicked(self, args):&lt;br /&gt;
    editbox = self.menu.getChild('DemoMenu/Edit')&lt;br /&gt;
    print(editbox.getText())&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, when the button is clicked, it will print to the console whatever has been typed in the box.&lt;br /&gt;
&lt;br /&gt;
As an exercise to the reader, consider adding support for Backspace/Delete/Arrow keys (hint: Special) keys.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=PyCEGUI/Example&amp;diff=4532</id>
		<title>PyCEGUI/Example</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=PyCEGUI/Example&amp;diff=4532"/>
				<updated>2011-06-18T21:35:30Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: Delete me.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Delete me.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample2&amp;diff=4531</id>
		<title>User:Crond/sandbox/openglEventExample2</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample2&amp;diff=4531"/>
				<updated>2011-06-18T21:34:12Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: Created page with &amp;quot;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}} &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  == Introduction == This presents a slightly refined example of using subscriptions to respond to events. T...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/opengEventExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
        self.editboxText = self.windowNewNode.getChild('Demo/NewNode/Editbox')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextChanged, self, 'handlerTextChanged')&lt;br /&gt;
        self.editboxText.subscribeEvent(PyCEGUI.Editbox.EventTextAccepted, self, 'handlerTextAccepted')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Text changed&lt;br /&gt;
    def handlerTextChanged(self, args):&lt;br /&gt;
        print('Text has changed.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Text accepted&lt;br /&gt;
    def handlerTextAccepted(self, args):&lt;br /&gt;
        print('Text has been accepted.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Enter some text into the Editbox, and/or press Return while the Editbox has focus.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
In the context of the previous examples, this is all pretty straightforward; this simply demonstrates some additional events which are relevant to an Editbox.&lt;br /&gt;
&lt;br /&gt;
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.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4530</id>
		<title>User:Crond/sandbox/openglEventExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4530"/>
				<updated>2011-06-18T21:23:01Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Source */ add keyboard support&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents the basics of using subscriptions to respond to events. The example retrieves two buttons and defines a method to be called when they are each clicked.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Just click either of the two buttons on the 'NewNode' frame window; some output will appear on the console.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== Layout to Python ===&lt;br /&gt;
To subscribe to an event, the application needs two fundamental details: the layout, and the widget that should respond to an event. The layout is simple - we just pass the name of it to the PyCEGUI WindowManager object; getting child windows and/or widgets can be a little more subtle - to do this, we have to know the name of the window in question.&lt;br /&gt;
&lt;br /&gt;
In the case of the example above, we want to respond to events on the 'NewNode' frame window, so we first retrieve a copy of it - as indicated by this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we need a copy of the buttons which we want to listen for events, as indicated by these lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we want to set what events we respond to and how we respond to them. We do this by defining methods on our object, and telling PyCEGUI to call them when specific events happen. This is indicated by the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument is specifying what event to listen for (in this case, the clicking of the button), and the second/third arguments specify what function/method should be invoked when the event in question happens.&lt;br /&gt;
&lt;br /&gt;
'''Note: Future versions do not require the 'self' argument.'''&lt;br /&gt;
&lt;br /&gt;
=== Layout editing ===&lt;br /&gt;
The exact name of the widgets you want to access can be determined via the XML 'Name' property, as found in the layout files.&lt;br /&gt;
&lt;br /&gt;
In the event you are not creating your layout files by hand, the names can be found via the CELayoutEditor under the 'Name' property in the Main Dialog.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4529</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4529"/>
				<updated>2011-06-18T21:18:46Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Persistence */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
'''Todo: Is this true? And if it's not, why did I think it was?'''&amp;lt;br /&amp;gt;&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== todo: Multi-class example ===&lt;br /&gt;
See [[PyCEGUI/Example|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4528</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4528"/>
				<updated>2011-06-18T21:18:35Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Persistence */ hmm&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
'''Todo: Is this true? And if it's not, why did I think it was?'''&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== todo: Multi-class example ===&lt;br /&gt;
See [[PyCEGUI/Example|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4527</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4527"/>
				<updated>2011-06-18T21:17:46Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Subscriptions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A basic demonstration of subscribing to events can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
* A further demonstration of event subscriptions can be found [[User:Crond/sandbox/openglEventExample2|here]].&lt;br /&gt;
&lt;br /&gt;
=== todo: Multi-class example ===&lt;br /&gt;
See [[PyCEGUI/Example|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4526</id>
		<title>User:Crond/sandbox/openglEventExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4526"/>
				<updated>2011-06-18T21:13:34Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents the basics of using subscriptions to respond to events. The example retrieves two buttons and defines a method to be called when they are each clicked.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
Just click either of the two buttons on the 'NewNode' frame window; some output will appear on the console.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== Layout to Python ===&lt;br /&gt;
To subscribe to an event, the application needs two fundamental details: the layout, and the widget that should respond to an event. The layout is simple - we just pass the name of it to the PyCEGUI WindowManager object; getting child windows and/or widgets can be a little more subtle - to do this, we have to know the name of the window in question.&lt;br /&gt;
&lt;br /&gt;
In the case of the example above, we want to respond to events on the 'NewNode' frame window, so we first retrieve a copy of it - as indicated by this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, we need a copy of the buttons which we want to listen for events, as indicated by these lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, we want to set what events we respond to and how we respond to them. We do this by defining methods on our object, and telling PyCEGUI to call them when specific events happen. This is indicated by the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument is specifying what event to listen for (in this case, the clicking of the button), and the second/third arguments specify what function/method should be invoked when the event in question happens.&lt;br /&gt;
&lt;br /&gt;
'''Note: Future versions do not require the 'self' argument.'''&lt;br /&gt;
&lt;br /&gt;
=== Layout editing ===&lt;br /&gt;
The exact name of the widgets you want to access can be determined via the XML 'Name' property, as found in the layout files.&lt;br /&gt;
&lt;br /&gt;
In the event you are not creating your layout files by hand, the names can be found via the CELayoutEditor under the 'Name' property in the Main Dialog.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4525</id>
		<title>User:Crond/sandbox/openglEventExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglEventExample&amp;diff=4525"/>
				<updated>2011-06-18T21:01:01Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: Created page with &amp;quot;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}} &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  == Introduction == This presents the basics of using subscriptions to respond to events. The example retri...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents the basics of using subscriptions to respond to events. The example retrieves two buttons and defines a method to be called when they are each clicked.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
The source code uses a modified version of the OpenGL example posted [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', './datafiles/schemes')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', './datafiles/imagesets')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', './datafiles/fonts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', './datafiles/layouts')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', './datafiles/looknfeel')&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', './datafiles/xml_schemas')&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Subscriptions&lt;br /&gt;
    def initializeSubscriptions(self):&lt;br /&gt;
&lt;br /&gt;
        # In order to be able to access the buttons, we need to get a copy of their parent.&lt;br /&gt;
        self.windowNewNode = self.rootWindow.getChild('Demo/NewNode')&lt;br /&gt;
&lt;br /&gt;
        # Now, we get the buttons.&lt;br /&gt;
        self.buttonOkay = self.windowNewNode.getChild('Demo/NewNode/Okay')&lt;br /&gt;
        self.buttonCancel = self.windowNewNode.getChild('Demo/NewNode/Cancel')&lt;br /&gt;
&lt;br /&gt;
        # And subscribe to the events, telling PyCEGUI what method it should call when the event happens.&lt;br /&gt;
        self.buttonOkay.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonOkayClicked')&lt;br /&gt;
        self.buttonCancel.subscribeEvent(PyCEGUI.PushButton.EventClicked, self, 'buttonCancelClicked')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        self.initializeSubscriptions()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonOkayClicked&lt;br /&gt;
    def buttonOkayClicked(self, args):&lt;br /&gt;
        print('Okay has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: buttonCancelClicked&lt;br /&gt;
    def buttonCancelClicked(self, args):&lt;br /&gt;
        print('Cancel has been clicked.')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4524</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4524"/>
				<updated>2011-06-18T20:54:27Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A demonstration of subscribing to events in the context of a single class can be found [[User:Crond/sandbox/openglEventExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== todo: Multi-class example ===&lt;br /&gt;
See [[PyCEGUI/Example|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/eventExample1&amp;diff=4523</id>
		<title>User:Crond/sandbox/eventExample1</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/eventExample1&amp;diff=4523"/>
				<updated>2011-06-18T20:53:23Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: delete me&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Delete me.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4522</id>
		<title>User:Crond/sandbox/openglSpecialKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4522"/>
				<updated>2011-06-18T20:52:16Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Source */ pep8&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic keyboard processing OpenGL application, as found [[User:Crond/sandbox/openglKeyboardExample|here]]. The goal is to present a further refinement of keyboard processing, specifically the handling of &amp;quot;special&amp;quot; keys, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Assist keyboard&lt;br /&gt;
    def handlerAssistKeyboard(self, key):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            return False&lt;br /&gt;
        return True&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        k = ord(key)&lt;br /&gt;
        if not self.handlerAssistKeyboard(k):&lt;br /&gt;
            self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard special&lt;br /&gt;
    def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
        try:&lt;br /&gt;
            self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
        except KeyError:&lt;br /&gt;
            # Ignore it.&lt;br /&gt;
            pass&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
As before, we can see that this works by running the application, typing into the Editbox, and pressing the arrow keys, or any of the other keys.&lt;br /&gt;
&lt;br /&gt;
Several keys, such as Escape and Return, are not readily testable (i.e. produce no discernible effects on the application), although they do work. It is left as an exercise to the reader to prove it.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== GLUT, ASCII, PyCEGUI ===&lt;br /&gt;
It can be a little tricky, at times, to separate them all. A good rule of thumb is that using the `ord` function on any input received via GLUT will produce the ASCII value, which can then be handled in whatever way the application desires - e.g. mapping it to a PyCEGUI value.&lt;br /&gt;
&lt;br /&gt;
An additional note is that what GLUT considers to be a &amp;quot;special&amp;quot; key is not exactly what PyCEGUI (or any other library, for that matter) considers to be special. For this reason, the `KEYMAP_ASCII` exists and helps define additional keys that are special, whatever that may mean in a particular context.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4521</id>
		<title>User:Crond/sandbox/openglKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4521"/>
				<updated>2011-06-18T20:51:08Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Source */ pep8&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic OpenGL application, as found [[User:Crond/sandbox/openglExample|here]]. The goal is to present the basics of keyboard processing, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Keyboard&lt;br /&gt;
    def handlerKeyboard(self, key, x, y):&lt;br /&gt;
        self.sys.injectChar(ord(key))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
We can see that this works by running the application, and typing into the Editbox, as provided by the 'New Node' frame window.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== 'ord' function ===&lt;br /&gt;
The 'ord' function is a built-in Python function, which converts a single character (or a string of length one, if you prefer) to its Unicode/ASCII value; for further details, see the Python documentation [http://docs.python.org/release/2.6.5/library/functions.html#ord here].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglExample&amp;diff=4520</id>
		<title>User:Crond/sandbox/openglExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglExample&amp;diff=4520"/>
				<updated>2011-06-18T20:49:00Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Source */ pep8&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This presents a minimal PyCEGUI application, using OpenGL as the renderer. The goal is to familiarize the reader with the basics of how to get PyCEGUI up and running, and to provide a few pointers along the way.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
    # Constructor&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        super(Application, self).__init__()&lt;br /&gt;
        self.lastFrameTime = 0&lt;br /&gt;
        self.updateFPS = 0&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: OpenGL&lt;br /&gt;
    # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
    #   documentation.&lt;br /&gt;
    def initializeOpenGL(self):&lt;br /&gt;
        glutInit()&lt;br /&gt;
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
        glutInitWindowSize(1024, 768)&lt;br /&gt;
        glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
        glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
        glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Handlers&lt;br /&gt;
    # - Setup the methods which will be called when events happen.&lt;br /&gt;
    def initializeHandlers(self):&lt;br /&gt;
        glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
        glutReshapeFunc(self.handlerResize)&lt;br /&gt;
        glutMouseFunc(self.handlerMouse)&lt;br /&gt;
        glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: PyCEGUI&lt;br /&gt;
    # - Store some components; saves a lot of typing.&lt;br /&gt;
    def initializePyCEGUI(self):&lt;br /&gt;
        Renderer.bootstrapSystem()&lt;br /&gt;
        self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
        self.rp = self.sys.getResourceProvider()&lt;br /&gt;
        self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
        self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: Defaults&lt;br /&gt;
    # - Resource locations.&lt;br /&gt;
    def initializeDefaults(self):&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
        self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
        PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
        PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
        PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
        PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
        PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
        parser = self.sys.getXMLParser()&lt;br /&gt;
        if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
            parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize: GUI&lt;br /&gt;
    # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
    def initializeGUI(self):&lt;br /&gt;
        self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
        self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
        # GUISheet&lt;br /&gt;
        self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
        self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
        # Cursor&lt;br /&gt;
        self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
        # An extra window&lt;br /&gt;
        w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
        self.rootWindow.addChildWindow(w)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Initialize&lt;br /&gt;
    def Initialize(self):&lt;br /&gt;
        self.initializeOpenGL()&lt;br /&gt;
        self.initializeHandlers()&lt;br /&gt;
        self.initializePyCEGUI()&lt;br /&gt;
        self.initializeDefaults()&lt;br /&gt;
        self.initializeGUI()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Display&lt;br /&gt;
    def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
        # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
        # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
        # etc.&lt;br /&gt;
        now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
        self.lastFrameTime = now&lt;br /&gt;
        self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
        self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
        # Actual rendering&lt;br /&gt;
        # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
        # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
        #   be redrawn by OpenGL.&lt;br /&gt;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
        self.sys.renderGUI()&lt;br /&gt;
        glutPostRedisplay()&lt;br /&gt;
        glutSwapBuffers()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Resize&lt;br /&gt;
    # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
    def handlerResize(self, width, height):&lt;br /&gt;
        glViewport(0, 0, width, height)&lt;br /&gt;
        self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse buttons&lt;br /&gt;
    def handlerMouse(self, button, state, x, y):&lt;br /&gt;
        if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
        elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
            if state == GLUT_UP:&lt;br /&gt;
                self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
            else:&lt;br /&gt;
                self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Handler: Mouse motion&lt;br /&gt;
    def handlerMouseMotion(self, x, y):&lt;br /&gt;
        self.sys.injectMousePosition(x, y)&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
    # Run&lt;br /&gt;
    def Run(self):&lt;br /&gt;
        self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
        glutMainLoop()&lt;br /&gt;
        return&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
    app = Application()&lt;br /&gt;
    app.Initialize()&lt;br /&gt;
    app.Run()&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
    sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4519</id>
		<title>User:Crond/sandbox/openglSpecialKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4519"/>
				<updated>2011-06-18T20:42:29Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* GLUT, ASCII, PyCEGUI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic keyboard processing OpenGL application, as found [[User:Crond/sandbox/openglKeyboardExample|here]]. The goal is to present a further refinement of keyboard processing, specifically the handling of &amp;quot;special&amp;quot; keys, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
  # Constructor&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Application, self).__init__()&lt;br /&gt;
    self.lastFrameTime = 0&lt;br /&gt;
    self.updateFPS = 0&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: OpenGL&lt;br /&gt;
  # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
  #   documentation.&lt;br /&gt;
  def initializeOpenGL(self):&lt;br /&gt;
    glutInit()&lt;br /&gt;
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
    glutInitWindowSize(1024, 768)&lt;br /&gt;
    glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
    glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
    glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Handlers&lt;br /&gt;
  # - Setup the methods which will be called when events happen.&lt;br /&gt;
  def initializeHandlers(self):&lt;br /&gt;
    glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
    glutReshapeFunc(self.handlerResize)&lt;br /&gt;
    glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
    glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
    glutMouseFunc(self.handlerMouse)&lt;br /&gt;
    glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: PyCEGUI&lt;br /&gt;
  # - Store some components; saves a lot of typing.&lt;br /&gt;
  def initializePyCEGUI(self):&lt;br /&gt;
    Renderer.bootstrapSystem()&lt;br /&gt;
    self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
    self.rp = self.sys.getResourceProvider()&lt;br /&gt;
    self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
    self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Defaults&lt;br /&gt;
  # - Resource locations.&lt;br /&gt;
  def initializeDefaults(self):&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
    PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
    PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
    PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
    PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
    PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
    parser = self.sys.getXMLParser()&lt;br /&gt;
    if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
      parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: GUI&lt;br /&gt;
  # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
  def initializeGUI(self):&lt;br /&gt;
    self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
    self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
    # GUISheet&lt;br /&gt;
    self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
    self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
    # Cursor&lt;br /&gt;
    self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
    # An extra window&lt;br /&gt;
    w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
    self.rootWindow.addChildWindow(w)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize&lt;br /&gt;
  def Initialize(self):&lt;br /&gt;
    self.initializeOpenGL()&lt;br /&gt;
    self.initializeHandlers()&lt;br /&gt;
    self.initializePyCEGUI()&lt;br /&gt;
    self.initializeDefaults()&lt;br /&gt;
    self.initializeGUI()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Display&lt;br /&gt;
  def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
    # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
    # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
    # etc.&lt;br /&gt;
    now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
    self.lastFrameTime = now&lt;br /&gt;
    self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
    self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
    # Actual rendering&lt;br /&gt;
    # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
    # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
    #   be redrawn by OpenGL.&lt;br /&gt;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
    self.sys.renderGUI()&lt;br /&gt;
    glutPostRedisplay()&lt;br /&gt;
    glutSwapBuffers()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Resize&lt;br /&gt;
  # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
  def handlerResize(self, width, height):&lt;br /&gt;
    glViewport(0, 0, width, height)&lt;br /&gt;
    self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Assist keyboard&lt;br /&gt;
  def handlerAssistKeyboard(self, key):&lt;br /&gt;
    try:&lt;br /&gt;
      self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
    except KeyError:&lt;br /&gt;
      return False&lt;br /&gt;
  return True&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard&lt;br /&gt;
  def handlerKeyboard(self, key, x, y):&lt;br /&gt;
    k = ord(key)&lt;br /&gt;
    if not self.handlerAssistKeyboard(k):&lt;br /&gt;
      self.sys.injectChar(ord(key))&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard special&lt;br /&gt;
  def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
    try:&lt;br /&gt;
      self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
    except KeyError:&lt;br /&gt;
      # Ignore it.&lt;br /&gt;
      pass&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse buttons&lt;br /&gt;
  def handlerMouse(self, button, state, x, y):&lt;br /&gt;
    if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
    elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse motion&lt;br /&gt;
  def handlerMouseMotion(self, x, y):&lt;br /&gt;
    self.sys.injectMousePosition(x, y)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Run&lt;br /&gt;
  def Run(self):&lt;br /&gt;
    self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    glutMainLoop()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
  app = Application()&lt;br /&gt;
  app.Initialize()&lt;br /&gt;
  app.Run()&lt;br /&gt;
  return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
As before, we can see that this works by running the application, typing into the Editbox, and pressing the arrow keys, or any of the other keys.&lt;br /&gt;
&lt;br /&gt;
Several keys, such as Escape and Return, are not readily testable (i.e. produce no discernible effects on the application), although they do work. It is left as an exercise to the reader to prove it.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== GLUT, ASCII, PyCEGUI ===&lt;br /&gt;
It can be a little tricky, at times, to separate them all. A good rule of thumb is that using the `ord` function on any input received via GLUT will produce the ASCII value, which can then be handled in whatever way the application desires - e.g. mapping it to a PyCEGUI value.&lt;br /&gt;
&lt;br /&gt;
An additional note is that what GLUT considers to be a &amp;quot;special&amp;quot; key is not exactly what PyCEGUI (or any other library, for that matter) considers to be special. For this reason, the `KEYMAP_ASCII` exists and helps define additional keys that are special, whatever that may mean in a particular context.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4518</id>
		<title>User:Crond/sandbox/openglSpecialKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4518"/>
				<updated>2011-06-18T20:39:34Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic keyboard processing OpenGL application, as found [[User:Crond/sandbox/openglKeyboardExample|here]]. The goal is to present a further refinement of keyboard processing, specifically the handling of &amp;quot;special&amp;quot; keys, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
  # Constructor&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Application, self).__init__()&lt;br /&gt;
    self.lastFrameTime = 0&lt;br /&gt;
    self.updateFPS = 0&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: OpenGL&lt;br /&gt;
  # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
  #   documentation.&lt;br /&gt;
  def initializeOpenGL(self):&lt;br /&gt;
    glutInit()&lt;br /&gt;
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
    glutInitWindowSize(1024, 768)&lt;br /&gt;
    glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
    glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
    glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Handlers&lt;br /&gt;
  # - Setup the methods which will be called when events happen.&lt;br /&gt;
  def initializeHandlers(self):&lt;br /&gt;
    glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
    glutReshapeFunc(self.handlerResize)&lt;br /&gt;
    glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
    glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
    glutMouseFunc(self.handlerMouse)&lt;br /&gt;
    glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: PyCEGUI&lt;br /&gt;
  # - Store some components; saves a lot of typing.&lt;br /&gt;
  def initializePyCEGUI(self):&lt;br /&gt;
    Renderer.bootstrapSystem()&lt;br /&gt;
    self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
    self.rp = self.sys.getResourceProvider()&lt;br /&gt;
    self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
    self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Defaults&lt;br /&gt;
  # - Resource locations.&lt;br /&gt;
  def initializeDefaults(self):&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
    PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
    PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
    PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
    PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
    PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
    parser = self.sys.getXMLParser()&lt;br /&gt;
    if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
      parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: GUI&lt;br /&gt;
  # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
  def initializeGUI(self):&lt;br /&gt;
    self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
    self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
    # GUISheet&lt;br /&gt;
    self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
    self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
    # Cursor&lt;br /&gt;
    self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
    # An extra window&lt;br /&gt;
    w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
    self.rootWindow.addChildWindow(w)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize&lt;br /&gt;
  def Initialize(self):&lt;br /&gt;
    self.initializeOpenGL()&lt;br /&gt;
    self.initializeHandlers()&lt;br /&gt;
    self.initializePyCEGUI()&lt;br /&gt;
    self.initializeDefaults()&lt;br /&gt;
    self.initializeGUI()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Display&lt;br /&gt;
  def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
    # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
    # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
    # etc.&lt;br /&gt;
    now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
    self.lastFrameTime = now&lt;br /&gt;
    self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
    self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
    # Actual rendering&lt;br /&gt;
    # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
    # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
    #   be redrawn by OpenGL.&lt;br /&gt;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
    self.sys.renderGUI()&lt;br /&gt;
    glutPostRedisplay()&lt;br /&gt;
    glutSwapBuffers()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Resize&lt;br /&gt;
  # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
  def handlerResize(self, width, height):&lt;br /&gt;
    glViewport(0, 0, width, height)&lt;br /&gt;
    self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Assist keyboard&lt;br /&gt;
  def handlerAssistKeyboard(self, key):&lt;br /&gt;
    try:&lt;br /&gt;
      self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
    except KeyError:&lt;br /&gt;
      return False&lt;br /&gt;
  return True&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard&lt;br /&gt;
  def handlerKeyboard(self, key, x, y):&lt;br /&gt;
    k = ord(key)&lt;br /&gt;
    if not self.handlerAssistKeyboard(k):&lt;br /&gt;
      self.sys.injectChar(ord(key))&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard special&lt;br /&gt;
  def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
    try:&lt;br /&gt;
      self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
    except KeyError:&lt;br /&gt;
      # Ignore it.&lt;br /&gt;
      pass&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse buttons&lt;br /&gt;
  def handlerMouse(self, button, state, x, y):&lt;br /&gt;
    if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
    elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse motion&lt;br /&gt;
  def handlerMouseMotion(self, x, y):&lt;br /&gt;
    self.sys.injectMousePosition(x, y)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Run&lt;br /&gt;
  def Run(self):&lt;br /&gt;
    self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    glutMainLoop()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
  app = Application()&lt;br /&gt;
  app.Initialize()&lt;br /&gt;
  app.Run()&lt;br /&gt;
  return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
As before, we can see that this works by running the application, typing into the Editbox, and pressing the arrow keys, or any of the other keys.&lt;br /&gt;
&lt;br /&gt;
Several keys, such as Escape and Return, are not readily testable (i.e. produce no discernible effects on the application), although they do work. It is left as an exercise to the reader to prove it.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== GLUT, ASCII, PyCEGUI ===&lt;br /&gt;
It can be a little tricky, at times, to separate them all. A good rule of thumb is that using the `ord` function on any input received via GLUT will produce the ASCII value, which can then be handled in whatever way the application desires - e.g. mapping it to a PyCEGUI value.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4517</id>
		<title>User:Crond/sandbox/openglSpecialKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglSpecialKeyboardExample&amp;diff=4517"/>
				<updated>2011-06-18T20:37:31Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: Created page with &amp;quot;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}} &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  == Introduction == This is a simple modification of the basic OpenGL application, as found [[User:Crond/sa...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic OpenGL application, as found [[User:Crond/sandbox/openglExample|here]]. The goal is to present the basics of keyboard processing, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
# Keymap: ASCII&lt;br /&gt;
KEYMAP_ASCII = {8 : PyCEGUI.Key.Scan.Backspace,&lt;br /&gt;
                13 : PyCEGUI.Key.Scan.Return,&lt;br /&gt;
                27 : PyCEGUI.Key.Scan.Escape,&lt;br /&gt;
                127 : PyCEGUI.Key.Scan.Delete}&lt;br /&gt;
&lt;br /&gt;
# Keymap: GLUT&lt;br /&gt;
KEYMAP_GLUT = {GLUT_KEY_LEFT : PyCEGUI.Key.Scan.ArrowLeft,&lt;br /&gt;
               GLUT_KEY_RIGHT : PyCEGUI.Key.Scan.ArrowRight,&lt;br /&gt;
               GLUT_KEY_HOME : PyCEGUI.Key.Scan.Home,&lt;br /&gt;
               GLUT_KEY_END : PyCEGUI.Key.Scan.End}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
  # Constructor&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Application, self).__init__()&lt;br /&gt;
    self.lastFrameTime = 0&lt;br /&gt;
    self.updateFPS = 0&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: OpenGL&lt;br /&gt;
  # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
  #   documentation.&lt;br /&gt;
  def initializeOpenGL(self):&lt;br /&gt;
    glutInit()&lt;br /&gt;
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
    glutInitWindowSize(1024, 768)&lt;br /&gt;
    glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
    glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
    glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Handlers&lt;br /&gt;
  # - Setup the methods which will be called when events happen.&lt;br /&gt;
  def initializeHandlers(self):&lt;br /&gt;
    glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
    glutReshapeFunc(self.handlerResize)&lt;br /&gt;
    glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
    glutSpecialFunc(self.handlerKeyboardSpecial)&lt;br /&gt;
    glutMouseFunc(self.handlerMouse)&lt;br /&gt;
    glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: PyCEGUI&lt;br /&gt;
  # - Store some components; saves a lot of typing.&lt;br /&gt;
  def initializePyCEGUI(self):&lt;br /&gt;
    Renderer.bootstrapSystem()&lt;br /&gt;
    self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
    self.rp = self.sys.getResourceProvider()&lt;br /&gt;
    self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
    self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Defaults&lt;br /&gt;
  # - Resource locations.&lt;br /&gt;
  def initializeDefaults(self):&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
    PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
    PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
    PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
    PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
    PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
    parser = self.sys.getXMLParser()&lt;br /&gt;
    if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
      parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: GUI&lt;br /&gt;
  # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
  def initializeGUI(self):&lt;br /&gt;
    self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
    self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
    # GUISheet&lt;br /&gt;
    self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
    self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
    # Cursor&lt;br /&gt;
    self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
    # An extra window&lt;br /&gt;
    w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
    self.rootWindow.addChildWindow(w)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize&lt;br /&gt;
  def Initialize(self):&lt;br /&gt;
    self.initializeOpenGL()&lt;br /&gt;
    self.initializeHandlers()&lt;br /&gt;
    self.initializePyCEGUI()&lt;br /&gt;
    self.initializeDefaults()&lt;br /&gt;
    self.initializeGUI()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Display&lt;br /&gt;
  def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
    # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
    # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
    # etc.&lt;br /&gt;
    now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
    self.lastFrameTime = now&lt;br /&gt;
    self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
    self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
    # Actual rendering&lt;br /&gt;
    # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
    # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
    #   be redrawn by OpenGL.&lt;br /&gt;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
    self.sys.renderGUI()&lt;br /&gt;
    glutPostRedisplay()&lt;br /&gt;
    glutSwapBuffers()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Resize&lt;br /&gt;
  # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
  def handlerResize(self, width, height):&lt;br /&gt;
    glViewport(0, 0, width, height)&lt;br /&gt;
    self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Assist keyboard&lt;br /&gt;
  def handlerAssistKeyboard(self, key):&lt;br /&gt;
    try:&lt;br /&gt;
      self.sys.injectKeyDown(KEYMAP_ASCII[key])&lt;br /&gt;
    except KeyError:&lt;br /&gt;
      return False&lt;br /&gt;
  return True&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard&lt;br /&gt;
  def handlerKeyboard(self, key, x, y):&lt;br /&gt;
    k = ord(key)&lt;br /&gt;
    if not self.handlerAssistKeyboard(k):&lt;br /&gt;
      self.sys.injectChar(ord(key))&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard special&lt;br /&gt;
  def handlerKeyboardSpecial(self, key, x, y):&lt;br /&gt;
    try:&lt;br /&gt;
      self.sys.injectKeyDown(KEYMAP_GLUT[key])&lt;br /&gt;
    except KeyError:&lt;br /&gt;
      # Ignore it.&lt;br /&gt;
      pass&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse buttons&lt;br /&gt;
  def handlerMouse(self, button, state, x, y):&lt;br /&gt;
    if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
    elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse motion&lt;br /&gt;
  def handlerMouseMotion(self, x, y):&lt;br /&gt;
    self.sys.injectMousePosition(x, y)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Run&lt;br /&gt;
  def Run(self):&lt;br /&gt;
    self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    glutMainLoop()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
  app = Application()&lt;br /&gt;
  app.Initialize()&lt;br /&gt;
  app.Run()&lt;br /&gt;
  return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
As before, we can see that this works by running the application, typing into the Editbox, and pressing the arrow keys, or any of the other keys.&lt;br /&gt;
&lt;br /&gt;
Several keys, such as Escape and Return, are not readily testable (i.e. produce no discernible effects on the application), although they do work. It is left as an exercise to the reader to prove it.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== GLUT, ASCII, PyCEGUI ===&lt;br /&gt;
It can be a little tricky, at times, to separate them all. A good rule of thumb is that using the `ord` function on any input received via GLUT will produce the ASCII value, which can then be handled in whatever way the application desires - e.g. mapping it to a PyCEGUI value.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4516</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4516"/>
				<updated>2011-06-18T20:21:29Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Basic OpenGL */ more link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
*A further modification, which adds special keyboard support, can be found [[User:Crond/sandbox/openglSpecialKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A demonstration of subscribing to events in the context of a single class can be found [[User:Crond/sandbox/eventExample1|here]].&lt;br /&gt;
* A demonstration of subscribing to events in the context of multiple classes can be found [[User:Crond/sandbox/eventExample2|here]].&lt;br /&gt;
* A demonstration of subscribing to events using the Observer pattern can be found [[User:Crond/sandbox/eventExample3|here]].&lt;br /&gt;
&lt;br /&gt;
=== todo: Multi-class example ===&lt;br /&gt;
See [[PyCEGUI/Example|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4515</id>
		<title>User:Crond/sandbox/openglKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4515"/>
				<updated>2011-06-18T20:19:32Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: ord&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic OpenGL application, as found [[User:Crond/sandbox/openglExample|here]]. The goal is to present the basics of keyboard processing, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
  # Constructor&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Application, self).__init__()&lt;br /&gt;
    self.lastFrameTime = 0&lt;br /&gt;
    self.updateFPS = 0&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: OpenGL&lt;br /&gt;
  # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
  #   documentation.&lt;br /&gt;
  def initializeOpenGL(self):&lt;br /&gt;
    glutInit()&lt;br /&gt;
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
    glutInitWindowSize(1024, 768)&lt;br /&gt;
    glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
    glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
    glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Handlers&lt;br /&gt;
  # - Setup the methods which will be called when events happen.&lt;br /&gt;
  def initializeHandlers(self):&lt;br /&gt;
    glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
    glutReshapeFunc(self.handlerResize)&lt;br /&gt;
    glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
    glutMouseFunc(self.handlerMouse)&lt;br /&gt;
    glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: PyCEGUI&lt;br /&gt;
  # - Store some components; saves a lot of typing.&lt;br /&gt;
  def initializePyCEGUI(self):&lt;br /&gt;
    Renderer.bootstrapSystem()&lt;br /&gt;
    self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
    self.rp = self.sys.getResourceProvider()&lt;br /&gt;
    self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
    self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Defaults&lt;br /&gt;
  # - Resource locations.&lt;br /&gt;
  def initializeDefaults(self):&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
    PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
    PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
    PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
    PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
    PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
    parser = self.sys.getXMLParser()&lt;br /&gt;
    if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
      parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: GUI&lt;br /&gt;
  # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
  def initializeGUI(self):&lt;br /&gt;
    self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
    self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
    # GUISheet&lt;br /&gt;
    self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
    self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
    # Cursor&lt;br /&gt;
    self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
    # An extra window&lt;br /&gt;
    w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
    self.rootWindow.addChildWindow(w)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize&lt;br /&gt;
  def Initialize(self):&lt;br /&gt;
    self.initializeOpenGL()&lt;br /&gt;
    self.initializeHandlers()&lt;br /&gt;
    self.initializePyCEGUI()&lt;br /&gt;
    self.initializeDefaults()&lt;br /&gt;
    self.initializeGUI()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Display&lt;br /&gt;
  def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
    # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
    # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
    # etc.&lt;br /&gt;
    now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
    self.lastFrameTime = now&lt;br /&gt;
    self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
    self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
    # Actual rendering&lt;br /&gt;
    # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
    # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
    #   be redrawn by OpenGL.&lt;br /&gt;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
    self.sys.renderGUI()&lt;br /&gt;
    glutPostRedisplay()&lt;br /&gt;
    glutSwapBuffers()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Resize&lt;br /&gt;
  # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
  def handlerResize(self, width, height):&lt;br /&gt;
    glViewport(0, 0, width, height)&lt;br /&gt;
    self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard&lt;br /&gt;
  def handlerKeyboard(self, key, x, y):&lt;br /&gt;
    self.sys.injectChar(ord(key))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse buttons&lt;br /&gt;
  def handlerMouse(self, button, state, x, y):&lt;br /&gt;
    if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
    elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse motion&lt;br /&gt;
  def handlerMouseMotion(self, x, y):&lt;br /&gt;
    self.sys.injectMousePosition(x, y)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Run&lt;br /&gt;
  def Run(self):&lt;br /&gt;
    self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    glutMainLoop()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
  app = Application()&lt;br /&gt;
  app.Initialize()&lt;br /&gt;
  app.Run()&lt;br /&gt;
  return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
We can see that this works by running the application, and typing into the Editbox, as provided by the 'New Node' frame window.&lt;br /&gt;
&lt;br /&gt;
== Examination ==&lt;br /&gt;
=== 'ord' function ===&lt;br /&gt;
The 'ord' function is a built-in Python function, which converts a single character (or a string of length one, if you prefer) to its Unicode/ASCII value; for further details, see the Python documentation [http://docs.python.org/release/2.6.5/library/functions.html#ord here].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4514</id>
		<title>User:Crond/sandbox/openglKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4514"/>
				<updated>2011-06-18T20:14:55Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic OpenGL application, as found [[User:Crond/sandbox/openglExample|here]]. The goal is to present the basics of keyboard processing, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
  # Constructor&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Application, self).__init__()&lt;br /&gt;
    self.lastFrameTime = 0&lt;br /&gt;
    self.updateFPS = 0&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: OpenGL&lt;br /&gt;
  # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
  #   documentation.&lt;br /&gt;
  def initializeOpenGL(self):&lt;br /&gt;
    glutInit()&lt;br /&gt;
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
    glutInitWindowSize(1024, 768)&lt;br /&gt;
    glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
    glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
    glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Handlers&lt;br /&gt;
  # - Setup the methods which will be called when events happen.&lt;br /&gt;
  def initializeHandlers(self):&lt;br /&gt;
    glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
    glutReshapeFunc(self.handlerResize)&lt;br /&gt;
    glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
    glutMouseFunc(self.handlerMouse)&lt;br /&gt;
    glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: PyCEGUI&lt;br /&gt;
  # - Store some components; saves a lot of typing.&lt;br /&gt;
  def initializePyCEGUI(self):&lt;br /&gt;
    Renderer.bootstrapSystem()&lt;br /&gt;
    self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
    self.rp = self.sys.getResourceProvider()&lt;br /&gt;
    self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
    self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Defaults&lt;br /&gt;
  # - Resource locations.&lt;br /&gt;
  def initializeDefaults(self):&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
    PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
    PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
    PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
    PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
    PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
    parser = self.sys.getXMLParser()&lt;br /&gt;
    if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
      parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: GUI&lt;br /&gt;
  # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
  def initializeGUI(self):&lt;br /&gt;
    self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
    self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
    # GUISheet&lt;br /&gt;
    self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
    self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
    # Cursor&lt;br /&gt;
    self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
    # An extra window&lt;br /&gt;
    w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
    self.rootWindow.addChildWindow(w)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize&lt;br /&gt;
  def Initialize(self):&lt;br /&gt;
    self.initializeOpenGL()&lt;br /&gt;
    self.initializeHandlers()&lt;br /&gt;
    self.initializePyCEGUI()&lt;br /&gt;
    self.initializeDefaults()&lt;br /&gt;
    self.initializeGUI()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Display&lt;br /&gt;
  def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
    # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
    # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
    # etc.&lt;br /&gt;
    now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
    self.lastFrameTime = now&lt;br /&gt;
    self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
    self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
    # Actual rendering&lt;br /&gt;
    # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
    # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
    #   be redrawn by OpenGL.&lt;br /&gt;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
    self.sys.renderGUI()&lt;br /&gt;
    glutPostRedisplay()&lt;br /&gt;
    glutSwapBuffers()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Resize&lt;br /&gt;
  # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
  def handlerResize(self, width, height):&lt;br /&gt;
    glViewport(0, 0, width, height)&lt;br /&gt;
    self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard&lt;br /&gt;
  def handlerKeyboard(self, key, x, y):&lt;br /&gt;
    self.sys.injectChar(ord(key))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse buttons&lt;br /&gt;
  def handlerMouse(self, button, state, x, y):&lt;br /&gt;
    if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
    elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse motion&lt;br /&gt;
  def handlerMouseMotion(self, x, y):&lt;br /&gt;
    self.sys.injectMousePosition(x, y)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Run&lt;br /&gt;
  def Run(self):&lt;br /&gt;
    self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    glutMainLoop()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
  app = Application()&lt;br /&gt;
  app.Initialize()&lt;br /&gt;
  app.Run()&lt;br /&gt;
  return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
We can see that this works by running the application, and typing into the Editbox, as provided by the 'New Node' frame window.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4513</id>
		<title>User:Crond/sandbox/openglKeyboardExample</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox/openglKeyboardExample&amp;diff=4513"/>
				<updated>2011-06-18T20:14:35Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: Created page with &amp;quot;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}} &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  == Introduction == This is a simple modification of the basic OpenGL application, as found [User:Crond/san...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
This is a simple modification of the basic OpenGL application, as found [User:Crond/sandbox/openglExample|here]. The goal is to present the basics of keyboard processing, via OpenGL and PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
* Python 2.6 (untested on Python 3.+)&lt;br /&gt;
* PyCEGUI&lt;br /&gt;
* PyOpenGL (GLU and GLUT, as well)&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
This example assumes you have the CEGUI resources located in the same directory as the script; change `PATH_RESOURCES` if they are elsewhere.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# example.py&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Import: std&lt;br /&gt;
import sys, os&lt;br /&gt;
&lt;br /&gt;
# Import: PyOpenGL&lt;br /&gt;
from OpenGL.GL import *&lt;br /&gt;
from OpenGL.GLU import *&lt;br /&gt;
from OpenGL.GLUT import *&lt;br /&gt;
&lt;br /&gt;
# Import: PyCEGUI&lt;br /&gt;
import PyCEGUI&lt;br /&gt;
from PyCEGUIOpenGLRenderer import OpenGLRenderer as Renderer&lt;br /&gt;
&lt;br /&gt;
# Constants&lt;br /&gt;
PATH_RESOURCES = './'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Application&lt;br /&gt;
class Application(object):&lt;br /&gt;
&lt;br /&gt;
  # Constructor&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Application, self).__init__()&lt;br /&gt;
    self.lastFrameTime = 0&lt;br /&gt;
    self.updateFPS = 0&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: OpenGL&lt;br /&gt;
  # - A full list of values for `glutInitDisplayMode` can be found in the GLUT&lt;br /&gt;
  #   documentation.&lt;br /&gt;
  def initializeOpenGL(self):&lt;br /&gt;
    glutInit()&lt;br /&gt;
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)&lt;br /&gt;
    glutInitWindowSize(1024, 768)&lt;br /&gt;
    glutInitWindowPosition(-1, -1) # Let the windowing system figure it out&lt;br /&gt;
    glutCreateWindow(&amp;quot;Crazy Eddie's GUI Mk-2 - glut Base Application&amp;quot;)&lt;br /&gt;
    glutSetCursor(GLUT_CURSOR_NONE)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Handlers&lt;br /&gt;
  # - Setup the methods which will be called when events happen.&lt;br /&gt;
  def initializeHandlers(self):&lt;br /&gt;
    glutDisplayFunc(self.handlerDisplay)&lt;br /&gt;
    glutReshapeFunc(self.handlerResize)&lt;br /&gt;
    glutKeyboardFunc(self.handlerKeyboard)&lt;br /&gt;
    glutMouseFunc(self.handlerMouse)&lt;br /&gt;
    glutMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    glutPassiveMotionFunc(self.handlerMouseMotion)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: PyCEGUI&lt;br /&gt;
  # - Store some components; saves a lot of typing.&lt;br /&gt;
  def initializePyCEGUI(self):&lt;br /&gt;
    Renderer.bootstrapSystem()&lt;br /&gt;
    self.sys = PyCEGUI.System.getSingleton()&lt;br /&gt;
    self.rp = self.sys.getResourceProvider()&lt;br /&gt;
    self.scheme = PyCEGUI.SchemeManager.getSingleton()&lt;br /&gt;
    self.wm = PyCEGUI.WindowManager.getSingleton()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: Defaults&lt;br /&gt;
  # - Resource locations.&lt;br /&gt;
  def initializeDefaults(self):&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemes', os.path.join(PATH_RESOURCES, 'datafiles/schemes'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('imagesets', os.path.join(PATH_RESOURCES, 'datafiles/imagesets'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('fonts', os.path.join(PATH_RESOURCES, 'datafiles/fonts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('layouts', os.path.join(PATH_RESOURCES, 'datafiles/layouts'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('looknfeels', os.path.join(PATH_RESOURCES, 'datafiles/looknfeel'))&lt;br /&gt;
    self.rp.setResourceGroupDirectory('schemas', os.path.join(PATH_RESOURCES, 'datafiles/xml_schemas'))&lt;br /&gt;
    PyCEGUI.Imageset.setDefaultResourceGroup('imagesets')&lt;br /&gt;
    PyCEGUI.Font.setDefaultResourceGroup('fonts')&lt;br /&gt;
    PyCEGUI.Scheme.setDefaultResourceGroup('schemes')&lt;br /&gt;
    PyCEGUI.WidgetLookManager.setDefaultResourceGroup('looknfeels')&lt;br /&gt;
    PyCEGUI.WindowManager.setDefaultResourceGroup('layouts')&lt;br /&gt;
    parser = self.sys.getXMLParser()&lt;br /&gt;
    if parser.isPropertyPresent('SchemaDefaultResourceGroup'):&lt;br /&gt;
      parser.setProperty('SchemaDefaultResourceGroup', 'schemas')&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize: GUI&lt;br /&gt;
  # - This is where we are actually setting up the windows we will see.&lt;br /&gt;
  def initializeGUI(self):&lt;br /&gt;
    self.scheme.create('VanillaSkin.scheme')&lt;br /&gt;
    self.scheme.create('TaharezLook.scheme')&lt;br /&gt;
&lt;br /&gt;
    # GUISheet&lt;br /&gt;
    self.rootWindow = self.wm.loadWindowLayout('VanillaWindows.layout')&lt;br /&gt;
    self.sys.setGUISheet(self.rootWindow)&lt;br /&gt;
&lt;br /&gt;
    # Cursor&lt;br /&gt;
    self.sys.setDefaultMouseCursor('Vanilla-Images', 'MouseArrow')&lt;br /&gt;
&lt;br /&gt;
    # An extra window&lt;br /&gt;
    w = self.wm.createWindow('TaharezLook/FrameWindow', 'Demo window')&lt;br /&gt;
    self.rootWindow.addChildWindow(w)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Initialize&lt;br /&gt;
  def Initialize(self):&lt;br /&gt;
    self.initializeOpenGL()&lt;br /&gt;
    self.initializeHandlers()&lt;br /&gt;
    self.initializePyCEGUI()&lt;br /&gt;
    self.initializeDefaults()&lt;br /&gt;
    self.initializeGUI()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Display&lt;br /&gt;
  def handlerDisplay(self):&lt;br /&gt;
&lt;br /&gt;
    # Injecting the time allows CEGUI to know how much time has passed, and&lt;br /&gt;
    # use that to coordinate certain activities - fading, animation, tooltips,&lt;br /&gt;
    # etc.&lt;br /&gt;
    now = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    elapsed = (now - self.lastFrameTime) / 1000.0&lt;br /&gt;
    self.lastFrameTime = now&lt;br /&gt;
    self.updateFPS = self.updateFPS - elapsed&lt;br /&gt;
    self.sys.injectTimePulse(elapsed)&lt;br /&gt;
&lt;br /&gt;
    # Actual rendering&lt;br /&gt;
    # - `renderGUI` updates CEGUI's picture of the GUI.&lt;br /&gt;
    # - `glutPostRedisplay` is what actually marks the window as needing to&lt;br /&gt;
    #   be redrawn by OpenGL.&lt;br /&gt;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)&lt;br /&gt;
    self.sys.renderGUI()&lt;br /&gt;
    glutPostRedisplay()&lt;br /&gt;
    glutSwapBuffers()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Resize&lt;br /&gt;
  # - `glViewport` modifies the OpenGL viewport to whatever the window size is.&lt;br /&gt;
  def handlerResize(self, width, height):&lt;br /&gt;
    glViewport(0, 0, width, height)&lt;br /&gt;
    self.sys.notifyDisplaySizeChanged(PyCEGUI.Size(width, height))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Keyboard&lt;br /&gt;
  def handlerKeyboard(self, key, x, y):&lt;br /&gt;
    self.sys.injectChar(ord(key))&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse buttons&lt;br /&gt;
  def handlerMouse(self, button, state, x, y):&lt;br /&gt;
    if button == GLUT_LEFT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.LeftButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.LeftButton)&lt;br /&gt;
    elif button == GLUT_RIGHT_BUTTON:&lt;br /&gt;
      if state == GLUT_UP:&lt;br /&gt;
        self.sys.injectMouseButtonUp(PyCEGUI.RightButton)&lt;br /&gt;
      else:&lt;br /&gt;
        self.sys.injectMouseButtonDown(PyCEGUI.RightButton)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Handler: Mouse motion&lt;br /&gt;
  def handlerMouseMotion(self, x, y):&lt;br /&gt;
    self.sys.injectMousePosition(x, y)&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
  # Run&lt;br /&gt;
  def Run(self):&lt;br /&gt;
    self.lastFrameTime = glutGet(GLUT_ELAPSED_TIME)&lt;br /&gt;
    glutMainLoop()&lt;br /&gt;
    return&lt;br /&gt;
&lt;br /&gt;
# Main&lt;br /&gt;
def main():&lt;br /&gt;
  app = Application()&lt;br /&gt;
  app.Initialize()&lt;br /&gt;
  app.Run()&lt;br /&gt;
  return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Guard&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Demonstration ==&lt;br /&gt;
We can see that this works by running the application, and typing into the Editbox, as provided by the 'New Node' frame window.&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	<entry>
		<id>http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4512</id>
		<title>User:Crond/sandbox</title>
		<link rel="alternate" type="text/html" href="http://cegui.org/wiki/index.php?title=User:Crond/sandbox&amp;diff=4512"/>
				<updated>2011-06-18T20:09:45Z</updated>
		
		<summary type="html">&lt;p&gt;Crond: /* Basic OpenGL */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{VersionBadge|0.7}} {{VersionAtLeast|0.7.5}}&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
== History ==&lt;br /&gt;
Since the release of CEGUI 0.7.5, official Python bindings have been provided, primarily prompted by the fact that the new CEGUI tools are written in Python. A beneficial side effect of this is that the bindings are free for anyone to use in their Python, or embedded Python, applications.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Windows: [http://pypi.python.org/pypi/PyCEGUI/0.7.5 PyPi repository]&lt;br /&gt;
* For other platforms, download the SDK and use the bindings contained within.&lt;br /&gt;
* If you use embedded Python, it may be easier to use the Win32 bindings from the SDK.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
The PyCEGUI API resembles the C++ version as closely as possible - mainly to avoid confusion and to provide familiarity between the two. The doxygen API docs (found [http://www.cegui.org.uk/docs/current here]) apply for most of the classes; additionally, doxygen comments are extracted and added as docstrings to all Python objects. This means that using Python docstrings is possible, although not perfect.&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
PyCEGUI uses [http://freshmeat.net/projects/pyplusplus Py++] and [http://www.boost.org/doc/libs/1_46_1/libs/python/doc/ Boost.Python] - this allows rapid development of the bindings and easy maintenance. It may be a bit slower than [http://www.swig.org/ SWIG], and certainly slower than hand written bindings; but, since neither of those will happen, be content with what is provided. The slowness is very unlikely to be noticeable at all unless you do synthetic tests.&lt;br /&gt;
&lt;br /&gt;
== User data ==&lt;br /&gt;
C++ CEGUI has accessor methods `[get/set]UserData` in several classes, which are not exposed to Python. The reason for this is because of the mutable nature of most Python objects: that is to say, the majority of Python objects can have attributes defined or deleted on the fly. Consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
someObject = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
someObject.randomAttribute = 'Toga! Toga!'&lt;br /&gt;
print(someObject.randomAttribute)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It should be obvious, here, why `[...]UserData` functions from CEGUI are not necessary. In the happenstance that it is not, let us be very clear: any application can define a new attribute (or method, etc) on any mutable Python object, and the same rules apply to PyCEGUI objects, thus rendering &amp;quot;user data&amp;quot; methods superfluous.&lt;br /&gt;
&lt;br /&gt;
== Subscriptions ==&lt;br /&gt;
One major thing that isn't documented in doxygen or other wiki docs and that is important is how subscriptions work in PyCEGUI.&lt;br /&gt;
&lt;br /&gt;
Subscribing to listenerClass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, listenerClass, 'methodInThatClass')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subscribing to a free function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
wnd.subscribeEvent(PyCEGUI.Window.EventMouseEnters, PythonModule.freeFunction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
For the folks who are exploring both CEGUI and PyCEGUI, consider that attributes and methods defined in Python do not persist when passed back into C++; that is to say, if an attribute is defined on some arbitrary PyCEGUI object, and that object is passed (indirectly) into C++, there should be no expectation that the aforementioned attribute will exist.&lt;br /&gt;
&lt;br /&gt;
=== Reference counting ===&lt;br /&gt;
'''Note: Fixed; pending'''&amp;lt;br /&amp;gt;&lt;br /&gt;
C++, like C, gives the programmer a pretty free hand in allocating memory, passing it around, and possibly forgetting that it ever exists; while certainly not the recommended way of doing things, it is possible. Python, however, is a different creature altogether - by default, it has a garbage collection system which is implemented via reference counting (the specifics of this are not important, and left as an exercise to the reader if they are that interested). Basically, what this means, is that when an object is no longer needed, it is deleted.&lt;br /&gt;
&lt;br /&gt;
This can play havoc with a C++ binding, if not considered carefully. For example, if a Python application has an object it wishes to let PyCEGUI (and, by association, C++ CEGUI) know about, it must take care to remember that Python is tracking the number of times the object in question has been referenced, but C++ is not. Thus, the conflict here is that Python will destroy (or garbage collect, if you prefer) the object in question, while C++ will be none the wiser; the inevitable conclusion here is an invalid pointer, segmentation fault, or other equally nasty bug.&lt;br /&gt;
&lt;br /&gt;
Let us illustrate just exactly what we are talking about here; consider the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def outsideContext(argListbox):&lt;br /&gt;
  item1 = PyCEGUI.ListboxTextItem('item1')&lt;br /&gt;
  item2 = PyCEGUI.ListboxTextItem('item2')&lt;br /&gt;
  argListbox.addItem(item1)&lt;br /&gt;
  argListbox.addItem(item2)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
  theListbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'theListbox')&lt;br /&gt;
  outsideContext(theListbox)&lt;br /&gt;
  return&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
  sys.exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the function `outsideContext`, two items are created in that scope (and registered with the Python garbage collection system), and then added to a Listbox; when the function is finished, Python is under the impression that it no longer needs the items and so it destroys the objects. Under the hood, however, pointers have been arranged that refer to these two items; in the future, when the Listbox tries to manipulate the items or when the Listbox itself is garbage collected, segmentation faults will more than likely occur.&lt;br /&gt;
&lt;br /&gt;
One solution to this issue, if possible, is to bind the items to an object - preferably, the one which the Listbox is bound to, so that when the Listbox itself is no longer needed, the items will be cleaned up at the same time. Such a strategy might go as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class someObject(object):&lt;br /&gt;
  def __init__(self):&lt;br /&gt;
    super(Object, self).__init__()&lt;br /&gt;
    self.memory = []&lt;br /&gt;
    return&lt;br /&gt;
  def anInitializationMethod(self):&lt;br /&gt;
    self.listbox = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/Listbox', 'someListbox')&lt;br /&gt;
    return&lt;br /&gt;
  def anotherMethod(self, stringList):&lt;br /&gt;
    for s in stringList:&lt;br /&gt;
      buffer = PyCEGUI.ListboxTextItem(s)&lt;br /&gt;
      self.memory.append(buffer)&lt;br /&gt;
      self.listbox.addItem(buffer)&lt;br /&gt;
    return&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The key point here is to have Python keep the object alive until the Listbox in question is no longer needed; the implementation of it is irrelevant.&lt;br /&gt;
&lt;br /&gt;
=== Dangling pointers ===&lt;br /&gt;
Another issue is almost the opposite of what was outlined previously - that is to say, PyCEGUI objects can be destroyed and Python will still think they are valid (in some sense, they are - just not functional). An example of this is creating a window, storing it in a variable, then destroying the window; a code snippet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
rootWindow = PyCEGUI.WindowManager.getSingleton().createWindow('DefaultWindow', 'root')&lt;br /&gt;
PyCEGUI.System.getSingleton().setGUISheet(rootWindow)&lt;br /&gt;
&lt;br /&gt;
someWindow = PyCEGUI.WindowManager.getSingleton().createWindow('TaharezLook/FrameWindow', 'someWindow')&lt;br /&gt;
rootWindow.addChildWindow(someWindow)&lt;br /&gt;
&lt;br /&gt;
# ... things happen ...&lt;br /&gt;
&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().destroyWindow(someWindow)&lt;br /&gt;
PyCEGUI.WindowManager.getSingleton().cleanDeadPool()&lt;br /&gt;
&lt;br /&gt;
# Death&lt;br /&gt;
# - Any functional method will crash the program; the choice of `disable` is totally arbitrary.&lt;br /&gt;
someWindow.disable()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a contrived example, and most programs will have some form of logic that will prevent this, but it is worth noting.&lt;br /&gt;
&lt;br /&gt;
== Panda3D integration ==&lt;br /&gt;
morgul has integrated CEGUI with Panda via [http://www.panda3d.org/forums/viewtopic.php?t=10814 these bindings].&lt;br /&gt;
&lt;br /&gt;
== OpenGL bugs ==&lt;br /&gt;
If an Intel 915GM, 910GML, or similar chipset is used, it might be necessary to create/destroy a window before the display mode is initialized via OpenGL. The following illustrates:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# This will segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Instead, the following can be done to circumvent this problem:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
glutInit()&lt;br /&gt;
&lt;br /&gt;
# Kludge&lt;br /&gt;
glutDestroyWindow(glutCreateWindow(''))&lt;br /&gt;
&lt;br /&gt;
# This will no longer segfault the application&lt;br /&gt;
glutInitDisplayMode(0)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional complications may arise via this chipset.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Basic OpenGL ===&lt;br /&gt;
*A demonstration of a basic application using PyCEGUI and OpenGL can be found [[User:Crond/sandbox/openglExample|here]].&lt;br /&gt;
*A simple modification, which adds rudimentary keyboard support, can be found [[User:Crond/sandbox/openglKeyboardExample|here]].&lt;br /&gt;
&lt;br /&gt;
=== Subscriptions ===&lt;br /&gt;
* A demonstration of subscribing to events in the context of a single class can be found [[User:Crond/sandbox/eventExample1|here]].&lt;br /&gt;
* A demonstration of subscribing to events in the context of multiple classes can be found [[User:Crond/sandbox/eventExample2|here]].&lt;br /&gt;
* A demonstration of subscribing to events using the Observer pattern can be found [[User:Crond/sandbox/eventExample3|here]].&lt;br /&gt;
&lt;br /&gt;
=== todo: Multi-class example ===&lt;br /&gt;
See [[PyCEGUI/Example|here]].&lt;/div&gt;</summary>
		<author><name>Crond</name></author>	</entry>

	</feed>