After the window containing GLUT graphics appears, I would like to enter input in the terminal:
user@computer: python woop.py
# Now displaying a beautiful landscape
(cmd): season winter
# Now changing season to winter
(cmd): event meteor
# Now meteoring otherwise peaceful landscape
(cmd): season summer
# Now changing season to summer
(cmd): exit
#bye ^_^
user@computer:
Ideally I would like to integrate python cmd with GLUT's glutKeyboardFunc. My attempts failed (allows one or the other at once, not both. Also problems with whether the window or terminal had focus).
Here is some example code, which displays a spinning teapot. Currently, pressing 'm' will invoke meteory goodness (stub), but being able to enter e.g. "meteor 500" would be preferable.
#! /usr/bin/env python
'''
Code is a reduced version of http://www.seethroughskin.com/blog/?p=771
'''
import OpenGL
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import time, sys
class dizzyTea:
global rotY
def __init__(self):
self.main()
def InitGL(self,Width, Height):
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glShadeModel(GL_SMOOTH)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
# The main drawing function.
def DrawGLScene(self):
global rotY
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity() # Reset The View
glTranslatef(-0.5, 0.0, -6.0)
glRotatef(rotY,0.0,1.0,0.0)
glutWireTeapot(1.0)
glScalef(0.3,0.3,0.3)
glutSwapBuffers()
rotY += 1.0
# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)
def keyPressed(self,*args):
# If escape is pressed, kill everything.
if args[0] == '\x1b':
sys.exit()
elif args[0] == 'm':
print "Now meteoring otherwise peaceful teapot"
# meteor shenanigans
def main(self):
global window
global rotY
glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(640, 480)
glutInitWindowPosition(0, 0)
window = glutCreateWindow("Jeff Molofee's desecrated GL Code Tutorial")
glutDisplayFunc(self.DrawGLScene)
glutIdleFunc(self.DrawGLScene)
glutKeyboardFunc(self.keyPressed)
self.InitGL(800, 600)
rotY = 0.0
glutMainLoop()
if __name__ == "__main__":
x = dizzyTea()
I can collect characters into a global string using glutKeyboardFunc, giving the same functional effect, however the user would be typing blind. "print somestring," allows printing on the same line, however the comma means the output does not get displayed whilst typing. Also "print '\b'" (backspace) doesn't work universally...
basically I don't want to have:
user@computer: python woop.py
# Now displaying a beautiful landscape
(cmd): s
(cmd): se
(cmd): sea
(cmd): seas
...etc
to type out one command
Restriction of using:
(Though other answers are welcome for wayward future-people looking to solve a different problem)
# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)
def keyPressed(self,*args):
if args[0] == '\x08':
self.keyCache = self.keyCache[:-1]
elif args[0] == '\x1b':
sys.exit()
elif args[0] == 'm':
print "Now meteoring otherwise peaceful teapot"
# meteor shenanigans
else:
self.keyCache += args[0]
sys.stdout.write(self.keyCache +" \r")#print "keypress: <",self.keyCache,">"
sys.stdout.flush()
And add a new class variable 'keyCache'.
Then just use normal print flushing to write data to the same line. The only hacky bit is that you have to write several blank spaces after the cached keystrokes, otherwise when you use backspace the deleted elements will still be on the screen.
Another alternative would be a parallel keyboard thread just to handle keystrokes from the command line. The big problem there is that glut doesn't provide a nice call back for when the window closes so you'd have to figure out an alternative way to kill your thread.