Last active
December 14, 2015 21:59
-
-
Save croxis/5154756 to your computer and use it in GitHub Desktop.
Attempt at combining bpython with panda3d. Currently does not show input until enter is pressed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Overrides for bpython to work under panda's loop and modified urwid ## | |
import os | |
import urwid | |
from urwid.display_common import INPUT_DESCRIPTORS_CHANGED | |
# urwid overrides to work with Panda3D's task system # | |
class PandaEventLoop(urwid.SelectEventLoop): | |
'''urwid defaults classes expect to be managing the master loop. | |
This does otherwise''' | |
def run(self): | |
try: | |
self._did_something = True | |
self._loop() | |
except urwid.ExitMainLoop: | |
pass | |
'''try: | |
self._did_something = True | |
try: | |
self._loop() | |
except select.error, e: | |
if e.args[0] != 4: | |
raise | |
except urwid.ExitMainLoop: | |
pass''' | |
class PandaMainLoop(urwid.MainLoop): | |
'''urwid.MainLoop run function is designed to run forever. This does | |
otherwise and splits cleanup into a different function.''' | |
pandaSetup = False | |
def run(self, task=None): | |
try: | |
if self.screen.started: | |
self._run() | |
else: | |
self.screen.run_wrapper(self._run) | |
if task: | |
return task.cont | |
except urwid.ExitMainLoop: | |
return task.done | |
def _run(self, task=None): | |
'''This must be called each tick from Panda3D main thread.''' | |
if not self.pandaSetup: | |
if self.handle_mouse: | |
self.screen.set_mouse_tracking() | |
if not hasattr(self.screen, 'get_input_descriptors'): | |
return self._run_screen_event_loop() | |
self.draw_screen() | |
fd_handles = [] | |
def reset_input_descriptors(only_remove=False): | |
for handle in fd_handles: | |
self.event_loop.remove_watch_file(handle) | |
if only_remove: | |
del fd_handles[:] | |
else: | |
fd_handles[:] = [ | |
self.event_loop.watch_file(fd, self._update) | |
for fd in self.screen.get_input_descriptors()] | |
if not fd_handles and self._input_timeout is not None: | |
self.event_loop.remove_alarm(self._input_timeout) | |
try: | |
urwid.signals.connect_signal( | |
self.screen, INPUT_DESCRIPTORS_CHANGED, | |
reset_input_descriptors | |
) | |
except NameError: | |
pass | |
# watch our input descriptors | |
reset_input_descriptors() | |
idle_handle = self.event_loop.enter_idle(self.entering_idle) | |
self.pandaSetup = True | |
# Go.. | |
self.event_loop.run() | |
if task: | |
return task.cont | |
def pandaCleanup(self): | |
# tidy up | |
self.event_loop.remove_enter_idle(idle_handle) | |
reset_input_descriptors(True) | |
signals.disconnect_signal(self.screen, INPUT_DESCRIPTORS_CHANGED, | |
reset_input_descriptors) | |
import bpython | |
import locale | |
from bpython import args as bpargs, repl | |
from bpython.importcompletion import find_coroutine | |
import bpython.urwid as bp | |
import sys | |
# This are ripped from bpython-urwid.main() # | |
COLORMAP = { | |
'k': 'black', | |
'r': 'dark red', # or light red? | |
'g': 'dark green', # or light green? | |
'y': 'yellow', | |
'b': 'dark blue', # or light blue? | |
'm': 'dark magenta', # or light magenta? | |
'c': 'dark cyan', # or light cyan? | |
'w': 'white', | |
'd': 'default', | |
} | |
bp.translations.init() | |
config, options, exec_args = bpargs.parse(None, ('Urwid options', None, [])) | |
palette = [(name, COLORMAP[color.lower()], 'default', 'bold' if color.isupper() else 'default') for name, color in config.color_scheme.iteritems()] | |
palette.extend([('bold ' + name, color + ',bold', background, monochrome) for name, color, background, monochrome in palette]) | |
interpreter = bpython.repl.Interpreter(globals(), locale.getpreferredencoding()) | |
myrepl = bp.URWIDRepl(None, palette, interpreter, config) | |
orig_stdin = sys.stdin | |
orig_stdout = sys.stdout | |
orig_stderr = sys.stderr | |
if config.flush_output and not options.quiet: | |
sys.stdout.write(myrepl.getstdout()) | |
if hasattr(sys.stdout, "flush"): | |
sys.stdout.flush() | |
myrepl.main_loop = PandaMainLoop( | |
myrepl.frame, palette, unhandled_input=myrepl.handle_input, | |
event_loop=PandaEventLoop() | |
) | |
if config.flush_output and not options.quiet: | |
sys.stdout.write(myrepl.getstdout()) | |
if hasattr(sys.stdout, "flush"): | |
sys.stdout.flush() | |
repl.extract_exit_value(myrepl.exit_value) | |
def run_with_screen_before_mainloop(): | |
sys.stdin = None # FakeStdin(myrepl) | |
sys.stdout = myrepl | |
sys.stderr = myrepl | |
myrepl.main_loop.set_alarm_in(0, start) | |
# This needs more thought. What needs to happen inside the mainloop? | |
def start(main_loop, user_data): | |
if exec_args: | |
bpargs.exec_code(interpreter, exec_args) | |
if not options.interactive: | |
raise urwid.ExitMainLoop() | |
if not exec_args: | |
sys.path.insert(0, '') | |
# this is CLIRepl.startup inlined. | |
filename = os.environ.get('PYTHONSTARTUP') | |
if filename and os.path.isfile(filename): | |
with open(filename, 'r') as f: | |
interpreter.runsource(f.read(), filename, 'exec', encode=False) | |
myrepl.start() | |
#myrepl.main_loop.screen.start() | |
# This bypasses main_loop.set_alarm_in because we must *not* | |
# hit the draw_screen call (it's unnecessary and slow). | |
def run_find_coroutine(): | |
if find_coroutine(): | |
main_loop.event_loop.alarm(0, run_find_coroutine) | |
run_find_coroutine() | |
if __name__ == '__main__': | |
from direct.showbase.ShowBase import ShowBase | |
from math import pi, sin, cos | |
from direct.task import Task | |
def spinCameraTask(task): | |
angleDegrees = task.time * 6.0 | |
angleRadians = angleDegrees * (pi / 180.0) | |
app.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3) | |
app.camera.setHpr(angleDegrees, 0, 0) | |
return Task.cont | |
class MyApp(ShowBase): | |
def __init__(self): | |
ShowBase.__init__(self) | |
self.environ = self.loader.loadModel("models/environment") | |
self.environ.reparentTo(self.render) | |
self.environ.setScale(0.25, 0.25, 0.25) | |
self.environ.setPos(-8, 42, 0) | |
app = MyApp() | |
#This results in a working urwid screen, but not bpython | |
myrepl.main_loop.screen.start() | |
#This results in a non working screen | |
#myrepl.main_loop.screen.run_wrapper(run_with_screen_before_mainloop) | |
run_with_screen_before_mainloop() | |
app.taskMgr.add(spinCameraTask, "SpinCameraTask") | |
app.taskMgr.add(myrepl.main_loop.run, 'cgui') | |
app.run() | |
myrepl.main_loop.pandaCleanup() | |
sys.stdin = orig_stdin | |
sys.stderr = orig_stderr | |
sys.stdout = orig_stdout | |
if config.flush_output and not options.quiet: | |
sys.stdout.write(myrepl.getstdout()) | |
if hasattr(sys.stdout, "flush"): | |
sys.stdout.flush() | |
repl.extract_exit_value(myrepl.exit_value) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment