소스 검색

Merge branch 'release/1.9.x'

rdb 9 년 전
부모
커밋
4283a63a7d

+ 22 - 5
direct/src/showbase/ShowBase.py

@@ -201,7 +201,9 @@ class ShowBase(DirectObject.DirectObject):
         ## This is used to store the wx.Application object used when want-wx is
         ## set or base.startWx() is called.
         self.wxApp = None
+        self.wxAppCreated = False
         self.tkRoot = None
+        self.tkRootCreated = False
 
         # This is used for syncing multiple PCs in a distributed cluster
         try:
@@ -259,6 +261,17 @@ class ShowBase(DirectObject.DirectObject):
             random.seed(seed)
             #whrandom.seed(seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff)
 
+        # For some reason, wx needs to be initialized before the graphics window
+        if sys.platform == "darwin":
+            if self.config.GetBool("want-wx", 0):
+                wx = importlib.import_module('wx')
+                self.wxApp = wx.App()
+
+            # Same goes for Tk, which uses a conflicting NSApplication
+            if self.config.GetBool("want-tk", 0):
+                Pmw = importlib.import_module('Pmw')
+                self.tkRoot = Pmw.initialise()
+
         # Open the default rendering window.
         if self.windowType != 'none':
             props = WindowProperties.getDefault()
@@ -2821,7 +2834,7 @@ class ShowBase(DirectObject.DirectObject):
         updated, but wxPython owns the main loop (which seems to make
         it happier than the other way around). """
 
-        if self.wxApp:
+        if self.wxAppCreated:
             # Don't do this twice.
             return
 
@@ -2831,8 +2844,9 @@ class ShowBase(DirectObject.DirectObject):
         # by modulefinder when packaging an application.
         wx = importlib.import_module('wx')
 
-        # Create a new base.wxApp.
-        self.wxApp = wx.PySimpleApp(redirect = False)
+        if not self.wxApp:
+            # Create a new base.wxApp.
+            self.wxApp = wx.PySimpleApp(redirect = False)
 
         if ConfigVariableBool('wx-main-loop', True):
             # Put wxPython in charge of the main loop.  It really
@@ -2867,6 +2881,7 @@ class ShowBase(DirectObject.DirectObject):
                 return task.again
 
             self.taskMgr.add(wxLoop, 'wxLoop')
+        self.wxAppCreated = True
 
     def __wxTimerCallback(self, event):
         if Thread.getCurrentThread().getCurrentTask():
@@ -2901,7 +2916,7 @@ class ShowBase(DirectObject.DirectObject):
         updated, but Tkinter owns the main loop (which seems to make
         it happier than the other way around). """
 
-        if self.tkRoot:
+        if self.tkRootCreated:
             # Don't do this twice.
             return
 
@@ -2911,7 +2926,8 @@ class ShowBase(DirectObject.DirectObject):
         Pmw = importlib.import_module('Pmw')
 
         # Create a new Tk root.
-        self.tkRoot = Pmw.initialise()
+        if not self.tkRoot:
+            self.tkRoot = Pmw.initialise()
         builtins.tkroot = self.tkRoot
 
         init_app_for_gui()
@@ -2947,6 +2963,7 @@ class ShowBase(DirectObject.DirectObject):
                 return task.again
 
             self.taskMgr.add(tkLoop, 'tkLoop')
+        self.tkRootCreated = True
 
     def __tkTimerCallback(self):
         if not Thread.getCurrentThread().getCurrentTask():

+ 2 - 1
dtool/src/interrogate/interfaceMaker.cxx

@@ -133,7 +133,8 @@ check_protocols() {
     if (func->_ifunc.get_name() == "__traverse__") {
       // If we have a method named __traverse__, we implement Python's cyclic
       // garbage collection protocol.
-      _protocol_types |= PT_python_gc;
+      //XXX disabled for now because it's too unstable.
+      //_protocol_types |= PT_python_gc;
     }
   }
 

+ 6 - 5
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -2862,10 +2862,9 @@ write_module_class(ostream &out, Object *obj) {
   }
 
   string gcflag;
-  // Disabled for now because it's too unstable.
-  /*if (obj->_protocol_types & Object::PT_python_gc) {
+  if (obj->_protocol_types & Object::PT_python_gc) {
     gcflag = " | Py_TPFLAGS_HAVE_GC";
-  }*/
+  }
 
   // long tp_flags;
   if (has_local_getbuffer) {
@@ -2891,10 +2890,12 @@ write_module_class(ostream &out, Object *obj) {
   }
 
   // traverseproc tp_traverse;
-  write_function_slot(out, 4, slots, "tp_traverse");
+  out << "    0, // tp_traverse\n";
+  //write_function_slot(out, 4, slots, "tp_traverse");
 
   // inquiry tp_clear;
-  write_function_slot(out, 4, slots, "tp_clear");
+  out << "    0, // tp_clear\n";
+  //write_function_slot(out, 4, slots, "tp_clear");
 
   // richcmpfunc tp_richcompare;
   if (has_local_richcompare) {

+ 20 - 0
panda/src/cocoadisplay/cocoaPandaApp.mm

@@ -25,4 +25,24 @@
     [super sendEvent: event];
   }
 }
+
+- (void) _setup: (void *) interp {
+  // This is called by Tk when it launches and naively assumes that it is
+  // the first to create an NSApplication.  We can't do anything about it
+  // at this point except display an error message.
+
+  cocoadisplay_cat.error()
+    << "Detected attempt to initialize Tk after creating a Panda window.  "
+       "This will likely cause a crash.\n"
+       "To fix this, set 'want-tk true' in Config.prc to force "
+       "initialization of Tk before opening the Panda window.\n";
+}
+
+- (void) _setupEventLoop {
+  NSAutoreleasePool *pool = [NSAutoreleasePool new];
+  [self finishLaunching];
+  [self setWindowsNeedUpdate:YES];
+  [pool drain];
+}
+
 @end

+ 4 - 3
samples/particles/particle_panel.py

@@ -17,13 +17,14 @@ try:
 except:
     sys.exit("Please install Python megawidgets")
 
+# Makes sure that Panda is configured to play nice with Tkinter
+from panda3d.core import *
+loadPrcFileData("", "want-tk true")
+
 # Open the Panda window
 from direct.showbase.ShowBase import ShowBase
 base = ShowBase()
 
-# Makes sure that Panda is configured to play nice with Tkinter
-base.startTk()
-
 from direct.tkpanels.ParticlePanel import ParticlePanel
 
 pp = ParticlePanel()             # Create the panel