showbase: Allow destroy() to be called from non-main thread

Also adds an error message when `run()` is called from non-main thread

Closes #1436
Fixes #1269

Co-authored-by: rdb <git@rdb.name>
This commit is contained in:
David Crompton 2023-01-16 14:13:08 +01:00 committed by rdb
parent 4d90ce5c5a
commit a88b6ee8db

View File

@ -583,7 +583,17 @@ class ShowBase(DirectObject.DirectObject):
exitfunc and will be called at application exit time exitfunc and will be called at application exit time
automatically. automatically.
This function is designed to be safe to call multiple times.""" This function is designed to be safe to call multiple times.
When called from a thread other than the main thread, this will create
a task to schedule the destroy on the main thread, and wait for this to
complete.
"""
if Thread.getCurrentThread() != Thread.getMainThread():
task = taskMgr.add(self.destroy, extraArgs=[])
task.wait()
return
for cb in self.finalExitCallbacks[:]: for cb in self.finalExitCallbacks[:]:
cb() cb()
@ -3336,7 +3346,13 @@ class ShowBase(DirectObject.DirectObject):
not running from within a p3d file. When we *are* within a p3d not running from within a p3d file. When we *are* within a p3d
file, the Panda3D runtime has to be responsible for running the file, the Panda3D runtime has to be responsible for running the
main loop, so we can't allow the application to do it. main loop, so we can't allow the application to do it.
This method must be called from the main thread, otherwise an error is
thrown.
""" """
if Thread.getCurrentThread() != Thread.getMainThread():
self.notify.error("run() must be called from the main thread.")
return
if self.appRunner is None or self.appRunner.dummy or \ if self.appRunner is None or self.appRunner.dummy or \
(self.appRunner.interactiveConsole and not self.appRunner.initialAppImport): (self.appRunner.interactiveConsole and not self.appRunner.initialAppImport):