Browse Source

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 <[email protected]>
David Crompton 2 years ago
parent
commit
a88b6ee8db
1 changed files with 17 additions and 1 deletions
  1. 17 1
      direct/src/showbase/ShowBase.py

+ 17 - 1
direct/src/showbase/ShowBase.py

@@ -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):