Browse Source

Merge branch 'master' into deploy-ng

Mitchell Stokes 7 years ago
parent
commit
bf1b486e5a

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

@@ -2672,15 +2672,18 @@ class ShowBase(DirectObject.DirectObject):
           output file name (e.g. if sd = 4, movie_0001.png)
           output file name (e.g. if sd = 4, movie_0001.png)
         - source is the Window, Buffer, DisplayRegion, or Texture from which
         - source is the Window, Buffer, DisplayRegion, or Texture from which
           to save the resulting images.  The default is the main window.
           to save the resulting images.  The default is the main window.
+
+        The task is returned, so that it can be awaited.
         """
         """
         globalClock.setMode(ClockObject.MNonRealTime)
         globalClock.setMode(ClockObject.MNonRealTime)
         globalClock.setDt(1.0/float(fps))
         globalClock.setDt(1.0/float(fps))
-        t = taskMgr.add(self._movieTask, namePrefix + '_task')
+        t = self.taskMgr.add(self._movieTask, namePrefix + '_task')
         t.frameIndex = 0  # Frame 0 is not captured.
         t.frameIndex = 0  # Frame 0 is not captured.
         t.numFrames = int(duration * fps)
         t.numFrames = int(duration * fps)
         t.source = source
         t.source = source
         t.outputString = namePrefix + '_%0' + repr(sd) + 'd.' + format
         t.outputString = namePrefix + '_%0' + repr(sd) + 'd.' + format
         t.setUponDeath(lambda state: globalClock.setMode(ClockObject.MNormal))
         t.setUponDeath(lambda state: globalClock.setMode(ClockObject.MNormal))
+        return t
 
 
     def _movieTask(self, state):
     def _movieTask(self, state):
         if state.frameIndex != 0:
         if state.frameIndex != 0:

+ 75 - 8
direct/src/showbase/Transitions.py

@@ -23,7 +23,9 @@ class Transitions:
                  scale=3.0,
                  scale=3.0,
                  pos=Vec3(0, 0, 0)):
                  pos=Vec3(0, 0, 0)):
         self.transitionIval = None
         self.transitionIval = None
+        self.__transitionFuture = None
         self.letterboxIval = None
         self.letterboxIval = None
+        self.__letterboxFuture = None
         self.iris = None
         self.iris = None
         self.fade = None
         self.fade = None
         self.letterbox = None
         self.letterbox = None
@@ -94,7 +96,9 @@ class Transitions:
         """
         """
         #self.noTransitions() masad: this creates a one frame pop, is it necessary?
         #self.noTransitions() masad: this creates a one frame pop, is it necessary?
         self.loadFade()
         self.loadFade()
-        transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX),
+
+        parent = aspect2d if self.fadeModel else render2d
+        transitionIval = Sequence(Func(self.fade.reparentTo, parent, DGG.FADE_SORT_INDEX),
                                   Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                   Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                   self.lerpFunc(self.fade, t,
                                   self.lerpFunc(self.fade, t,
                                                 self.alphaOff,
                                                 self.alphaOff,
@@ -115,7 +119,8 @@ class Transitions:
         self.noTransitions()
         self.noTransitions()
         self.loadFade()
         self.loadFade()
 
 
-        transitionIval = Sequence(Func(self.fade.reparentTo,aspect2d,DGG.FADE_SORT_INDEX),
+        parent = aspect2d if self.fadeModel else render2d
+        transitionIval = Sequence(Func(self.fade.reparentTo, parent, DGG.FADE_SORT_INDEX),
                                   Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                   Func(self.fade.showThrough),  # in case aspect2d is hidden for some reason
                                   self.lerpFunc(self.fade, t,
                                   self.lerpFunc(self.fade, t,
                                                 self.alphaOn,
                                                 self.alphaOn,
@@ -148,11 +153,17 @@ class Transitions:
             self.noTransitions()
             self.noTransitions()
             self.loadFade()
             self.loadFade()
             self.fade.detachNode()
             self.fade.detachNode()
+            fut = AsyncFuture()
+            fut.setResult(None)
+            return fut
         else:
         else:
             # Create a sequence that lerps the color out, then
             # Create a sequence that lerps the color out, then
             # parents the fade to hidden
             # parents the fade to hidden
             self.transitionIval = self.getFadeInIval(t, finishIval)
             self.transitionIval = self.getFadeInIval(t, finishIval)
+            self.transitionIval.append(Func(self.__finishTransition))
+            self.__transitionFuture = AsyncFuture()
             self.transitionIval.start()
             self.transitionIval.start()
+            return self.__transitionFuture
 
 
     def fadeOut(self, t=0.5, finishIval=None):
     def fadeOut(self, t=0.5, finishIval=None):
         """
         """
@@ -167,7 +178,9 @@ class Transitions:
             # Fade out immediately with no lerp
             # Fade out immediately with no lerp
             self.noTransitions()
             self.noTransitions()
             self.loadFade()
             self.loadFade()
-            self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
+
+            parent = aspect2d if self.fadeModel else render2d
+            self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX)
             self.fade.setColor(self.alphaOn)
             self.fade.setColor(self.alphaOn)
         elif ConfigVariableBool('no-loading-screen', False):
         elif ConfigVariableBool('no-loading-screen', False):
             if finishIval:
             if finishIval:
@@ -176,8 +189,16 @@ class Transitions:
         else:
         else:
             # Create a sequence that lerps the color out, then
             # Create a sequence that lerps the color out, then
             # parents the fade to hidden
             # parents the fade to hidden
-            self.transitionIval = self.getFadeOutIval(t,finishIval)
+            self.transitionIval = self.getFadeOutIval(t, finishIval)
+            self.transitionIval.append(Func(self.__finishTransition))
+            self.__transitionFuture = AsyncFuture()
             self.transitionIval.start()
             self.transitionIval.start()
+            return self.__transitionFuture
+
+        # Immediately done, so return a dummy future.
+        fut = AsyncFuture()
+        fut.setResult(None)
+        return fut
 
 
     def fadeOutActive(self):
     def fadeOutActive(self):
         return self.fade and self.fade.getColor()[3] > 0
         return self.fade and self.fade.getColor()[3] > 0
@@ -191,7 +212,9 @@ class Transitions:
         #print "transitiosn: fadeScreen"
         #print "transitiosn: fadeScreen"
         self.noTransitions()
         self.noTransitions()
         self.loadFade()
         self.loadFade()
-        self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
+
+        parent = aspect2d if self.fadeModel else render2d
+        self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX)
         self.fade.setColor(self.alphaOn[0],
         self.fade.setColor(self.alphaOn[0],
                            self.alphaOn[1],
                            self.alphaOn[1],
                            self.alphaOn[2],
                            self.alphaOn[2],
@@ -206,7 +229,9 @@ class Transitions:
         #print "transitiosn: fadeScreenColor"
         #print "transitiosn: fadeScreenColor"
         self.noTransitions()
         self.noTransitions()
         self.loadFade()
         self.loadFade()
-        self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
+
+        parent = aspect2d if self.fadeModel else render2d
+        self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX)
         self.fade.setColor(color)
         self.fade.setColor(color)
 
 
     def noFade(self):
     def noFade(self):
@@ -217,6 +242,9 @@ class Transitions:
         if self.transitionIval:
         if self.transitionIval:
             self.transitionIval.pause()
             self.transitionIval.pause()
             self.transitionIval = None
             self.transitionIval = None
+        if self.__transitionFuture:
+            self.__transitionFuture.cancel()
+            self.__transitionFuture = None
         if self.fade:
         if self.fade:
             # Make sure to reset the color, since fadeOutActive() is looking at it
             # Make sure to reset the color, since fadeOutActive() is looking at it
             self.fade.setColor(self.alphaOff)
             self.fade.setColor(self.alphaOff)
@@ -247,18 +275,25 @@ class Transitions:
         self.loadIris()
         self.loadIris()
         if (t == 0):
         if (t == 0):
             self.iris.detachNode()
             self.iris.detachNode()
+            fut = AsyncFuture()
+            fut.setResult(None)
+            return fut
         else:
         else:
             self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
             self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
 
 
+            scale = 0.18 * max(base.a2dRight, base.a2dTop)
             self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
             self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
-                                                   scale = 0.18,
+                                                   scale = scale,
                                                    startScale = 0.01),
                                                    startScale = 0.01),
                                  Func(self.iris.detachNode),
                                  Func(self.iris.detachNode),
+                                 Func(self.__finishTransition),
                                  name = self.irisTaskName,
                                  name = self.irisTaskName,
                                  )
                                  )
+            self.__transitionFuture = AsyncFuture()
             if finishIval:
             if finishIval:
                 self.transitionIval.append(finishIval)
                 self.transitionIval.append(finishIval)
             self.transitionIval.start()
             self.transitionIval.start()
+            return self.__transitionFuture
 
 
     def irisOut(self, t=0.5, finishIval=None):
     def irisOut(self, t=0.5, finishIval=None):
         """
         """
@@ -274,20 +309,27 @@ class Transitions:
         if (t == 0):
         if (t == 0):
             self.iris.detachNode()
             self.iris.detachNode()
             self.fadeOut(0)
             self.fadeOut(0)
+            fut = AsyncFuture()
+            fut.setResult(None)
+            return fut
         else:
         else:
             self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
             self.iris.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
 
 
+            scale = 0.18 * max(base.a2dRight, base.a2dTop)
             self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
             self.transitionIval = Sequence(LerpScaleInterval(self.iris, t,
                                                    scale = 0.01,
                                                    scale = 0.01,
-                                                   startScale = 0.18),
+                                                   startScale = scale),
                                  Func(self.iris.detachNode),
                                  Func(self.iris.detachNode),
                                  # Use the fade to cover up the hole that the iris would leave
                                  # Use the fade to cover up the hole that the iris would leave
                                  Func(self.fadeOut, 0),
                                  Func(self.fadeOut, 0),
+                                 Func(self.__finishTransition),
                                  name = self.irisTaskName,
                                  name = self.irisTaskName,
                                  )
                                  )
+            self.__transitionFuture = AsyncFuture()
             if finishIval:
             if finishIval:
                 self.transitionIval.append(finishIval)
                 self.transitionIval.append(finishIval)
             self.transitionIval.start()
             self.transitionIval.start()
+            return self.__transitionFuture
 
 
     def noIris(self):
     def noIris(self):
         """
         """
@@ -311,6 +353,11 @@ class Transitions:
         # Letterbox is not really a transition, it is a screen overlay
         # Letterbox is not really a transition, it is a screen overlay
         # self.noLetterbox()
         # self.noLetterbox()
 
 
+    def __finishTransition(self):
+        if self.__transitionFuture:
+            self.__transitionFuture.setResult(None)
+            self.__transitionFuture = None
+
     ##################################################
     ##################################################
     # Letterbox
     # Letterbox
     ##################################################
     ##################################################
@@ -383,9 +430,17 @@ class Transitions:
         if self.letterboxIval:
         if self.letterboxIval:
             self.letterboxIval.pause()
             self.letterboxIval.pause()
             self.letterboxIval = None
             self.letterboxIval = None
+        if self.__letterboxFuture:
+            self.__letterboxFuture.cancel()
+            self.__letterboxFuture = None
         if self.letterbox:
         if self.letterbox:
             self.letterbox.stash()
             self.letterbox.stash()
 
 
+    def __finishLetterbox(self):
+        if self.__letterboxFuture:
+            self.__letterboxFuture.setResult(None)
+            self.__letterboxFuture = None
+
     def letterboxOn(self, t=0.25, finishIval=None):
     def letterboxOn(self, t=0.25, finishIval=None):
         """
         """
         Move black bars in over t seconds.
         Move black bars in over t seconds.
@@ -396,7 +451,11 @@ class Transitions:
         if (t == 0):
         if (t == 0):
             self.letterboxBottom.setPos(0, 0, -1)
             self.letterboxBottom.setPos(0, 0, -1)
             self.letterboxTop.setPos(0, 0, 0.8)
             self.letterboxTop.setPos(0, 0, 0.8)
+            fut = AsyncFuture()
+            fut.setResult(None)
+            return fut
         else:
         else:
+            self.__letterboxFuture = AsyncFuture()
             self.letterboxIval = Sequence(Parallel(
             self.letterboxIval = Sequence(Parallel(
                 LerpPosInterval(self.letterboxBottom,
                 LerpPosInterval(self.letterboxBottom,
                                 t,
                                 t,
@@ -409,11 +468,13 @@ class Transitions:
                                 # startPos = Vec3(0, 0, 1),
                                 # startPos = Vec3(0, 0, 1),
                                 ),
                                 ),
                 ),
                 ),
+                                          Func(self.__finishLetterbox),
                                           name = self.letterboxTaskName,
                                           name = self.letterboxTaskName,
                                           )
                                           )
             if finishIval:
             if finishIval:
                 self.letterboxIval.append(finishIval)
                 self.letterboxIval.append(finishIval)
             self.letterboxIval.start()
             self.letterboxIval.start()
+            return self.__letterboxFuture
 
 
     def letterboxOff(self, t=0.25, finishIval=None):
     def letterboxOff(self, t=0.25, finishIval=None):
         """
         """
@@ -424,7 +485,11 @@ class Transitions:
         self.letterbox.unstash()
         self.letterbox.unstash()
         if (t == 0):
         if (t == 0):
             self.letterbox.stash()
             self.letterbox.stash()
+            fut = AsyncFuture()
+            fut.setResult(None)
+            return fut
         else:
         else:
+            self.__letterboxFuture = AsyncFuture()
             self.letterboxIval = Sequence(Parallel(
             self.letterboxIval = Sequence(Parallel(
                 LerpPosInterval(self.letterboxBottom,
                 LerpPosInterval(self.letterboxBottom,
                                 t,
                                 t,
@@ -438,9 +503,11 @@ class Transitions:
                                 ),
                                 ),
                 ),
                 ),
                                           Func(self.letterbox.stash),
                                           Func(self.letterbox.stash),
+                                          Func(self.__finishLetterbox),
                                           Func(messenger.send,'letterboxOff'),
                                           Func(messenger.send,'letterboxOff'),
                                           name = self.letterboxTaskName,
                                           name = self.letterboxTaskName,
                                           )
                                           )
             if finishIval:
             if finishIval:
                 self.letterboxIval.append(finishIval)
                 self.letterboxIval.append(finishIval)
             self.letterboxIval.start()
             self.letterboxIval.start()
+            return self.__letterboxFuture

+ 5 - 0
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -122,6 +122,11 @@ typedef ios::seekdir ios_seekdir;
 // Apple has an outdated libstdc++.  Not all is lost, though, as we can fill
 // Apple has an outdated libstdc++.  Not all is lost, though, as we can fill
 // in some important missing functions.
 // in some important missing functions.
 #if defined(__GLIBCXX__) && __GLIBCXX__ <= 20070719
 #if defined(__GLIBCXX__) && __GLIBCXX__ <= 20070719
+#include <tr1/tuple>
+
+using std::tr1::tuple;
+using std::tr1::tie;
+
 typedef decltype(nullptr) nullptr_t;
 typedef decltype(nullptr) nullptr_t;
 
 
 template<class T> struct remove_reference      {typedef T type;};
 template<class T> struct remove_reference      {typedef T type;};

+ 1 - 0
panda/src/event/asyncTask.h

@@ -119,6 +119,7 @@ protected:
   double _wake_time;
   double _wake_time;
   int _sort;
   int _sort;
   int _priority;
   int _priority;
+  unsigned int _implicit_sort;
 
 
   State _state;
   State _state;
   Thread *_servicing_thread;
   Thread *_servicing_thread;

+ 5 - 1
panda/src/event/asyncTaskChain.cxx

@@ -51,7 +51,8 @@ AsyncTaskChain(AsyncTaskManager *manager, const string &name) :
   _needs_cleanup(false),
   _needs_cleanup(false),
   _current_frame(0),
   _current_frame(0),
   _time_in_frame(0.0),
   _time_in_frame(0.0),
-  _block_till_next_frame(false)
+  _block_till_next_frame(false),
+  _next_implicit_sort(0)
 {
 {
 }
 }
 
 
@@ -418,6 +419,9 @@ do_add(AsyncTask *task) {
   task->_start_time = now;
   task->_start_time = now;
   task->_start_frame = _manager->_clock->get_frame_count();
   task->_start_frame = _manager->_clock->get_frame_count();
 
 
+  // Remember the order in which tasks were added to the chain.
+  task->_implicit_sort = _next_implicit_sort++;
+
   _manager->add_task_by_name(task);
   _manager->add_task_by_name(task);
 
 
   if (task->has_delay()) {
   if (task->has_delay()) {

+ 8 - 1
panda/src/event/asyncTaskChain.h

@@ -146,7 +146,12 @@ protected:
       if (a->get_priority() != b->get_priority()) {
       if (a->get_priority() != b->get_priority()) {
         return a->get_priority() < b->get_priority();
         return a->get_priority() < b->get_priority();
       }
       }
-      return a->get_start_time() > b->get_start_time();
+      if (a->get_start_time() != b->get_start_time()) {
+        return a->get_start_time() > b->get_start_time();
+      }
+      // Failing any other ordering criteria, we sort the tasks based on the
+      // order in which they were added to the task chain.
+      return a->_implicit_sort > b->_implicit_sort;
     }
     }
   };
   };
 
 
@@ -186,6 +191,8 @@ protected:
   double _time_in_frame;
   double _time_in_frame;
   bool _block_till_next_frame;
   bool _block_till_next_frame;
 
 
+  unsigned int _next_implicit_sort;
+
   static PStatCollector _task_pcollector;
   static PStatCollector _task_pcollector;
   static PStatCollector _wait_pcollector;
   static PStatCollector _wait_pcollector;
 
 

+ 3 - 0
panda/src/event/pythonTask.cxx

@@ -94,6 +94,9 @@ PythonTask::
     PyErr_Restore(_exception, _exc_value, _exc_traceback);
     PyErr_Restore(_exception, _exc_value, _exc_traceback);
     PyErr_Print();
     PyErr_Print();
     PyErr_Restore(nullptr, nullptr, nullptr);
     PyErr_Restore(nullptr, nullptr, nullptr);
+    _exception = nullptr;
+    _exc_value = nullptr;
+    _exc_traceback = nullptr;
   }
   }
 #endif
 #endif
 
 

+ 1 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -12647,7 +12647,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
   int depth = tex->get_expected_mipmap_z_size(mipmap_bias);
   int depth = tex->get_expected_mipmap_z_size(mipmap_bias);
 
 
   // Determine the number of images to upload.
   // Determine the number of images to upload.
-  int num_levels = 1;
+  int num_levels = mipmap_bias + 1;
   if (uses_mipmaps) {
   if (uses_mipmaps) {
     num_levels = tex->get_expected_num_mipmap_levels();
     num_levels = tex->get_expected_num_mipmap_levels();
   }
   }

+ 28 - 2
panda/src/putil/bamWriter.cxx

@@ -94,6 +94,10 @@ BamWriter::
   for (si = _state_map.begin(); si != _state_map.end(); ++si) {
   for (si = _state_map.begin(); si != _state_map.end(); ++si) {
     TypedWritable *object = (TypedWritable *)(*si).first;
     TypedWritable *object = (TypedWritable *)(*si).first;
     object->remove_bam_writer(this);
     object->remove_bam_writer(this);
+
+    if ((*si).second._refcount != nullptr) {
+      unref_delete((*si).second._refcount);
+    }
   }
   }
 }
 }
 
 
@@ -529,6 +533,9 @@ object_destructs(TypedWritable *object) {
     // we're in trouble when we do write it out.
     // we're in trouble when we do write it out.
     nassertv(!(*si).second._written_seq.is_initial());
     nassertv(!(*si).second._written_seq.is_initial());
 
 
+    // This cannot be called if we are still holding a reference to it.
+    nassertv((*si).second._refcount == nullptr);
+
     int object_id = (*si).second._object_id;
     int object_id = (*si).second._object_id;
     _freed_object_ids.push_back(object_id);
     _freed_object_ids.push_back(object_id);
 
 
@@ -606,8 +613,10 @@ enqueue_object(const TypedWritable *object) {
     // No, it hasn't, so assign it the next number in sequence arbitrarily.
     // No, it hasn't, so assign it the next number in sequence arbitrarily.
     object_id = _next_object_id;
     object_id = _next_object_id;
 
 
-    bool inserted =
-      _state_map.insert(StateMap::value_type(object, StoreState(_next_object_id))).second;
+    StateMap::iterator si;
+    bool inserted;
+    tie(si, inserted) =
+      _state_map.insert(StateMap::value_type(object, StoreState(_next_object_id)));
     nassertr(inserted, false);
     nassertr(inserted, false);
 
 
     // Store ourselves on the TypedWritable so that we get notified when it
     // Store ourselves on the TypedWritable so that we get notified when it
@@ -615,6 +624,14 @@ enqueue_object(const TypedWritable *object) {
     (const_cast<TypedWritable*>(object))->add_bam_writer(this);
     (const_cast<TypedWritable*>(object))->add_bam_writer(this);
     _next_object_id++;
     _next_object_id++;
 
 
+    // Increase the reference count if this inherits from ReferenceCount,
+    // until we get a chance to write this object for the first time.
+    const ReferenceCount *rc = ((TypedWritable *)object)->as_reference_count();
+    if (rc != nullptr) {
+      rc->ref();
+      (*si).second._refcount = rc;
+    }
+
   } else {
   } else {
     // Yes, it has; get the object ID.
     // Yes, it has; get the object ID.
     object_id = (*si).second._object_id;
     object_id = (*si).second._object_id;
@@ -703,6 +720,15 @@ flush_queue() {
       (*si).second._written_seq = _writing_seq;
       (*si).second._written_seq = _writing_seq;
       (*si).second._modified = object->get_bam_modified();
       (*si).second._modified = object->get_bam_modified();
 
 
+      // Now release any reference we hold to it, so that it may destruct.
+      const ReferenceCount *rc = (*si).second._refcount;
+      if (rc != nullptr) {
+        // We need to assign this pointer to null before deleting the object,
+        // since that may end up calling object_destructs.
+        (*si).second._refcount = nullptr;
+        unref_delete(rc);
+      }
+
     } else {
     } else {
       // On subsequent times when we write a particular object, we write
       // On subsequent times when we write a particular object, we write
       // simply TypeHandle::none(), followed by the object ID. The occurrence
       // simply TypeHandle::none(), followed by the object ID. The occurrence

+ 2 - 1
panda/src/putil/bamWriter.h

@@ -140,8 +140,9 @@ private:
     int _object_id;
     int _object_id;
     UpdateSeq _written_seq;
     UpdateSeq _written_seq;
     UpdateSeq _modified;
     UpdateSeq _modified;
+    const ReferenceCount *_refcount;
 
 
-    StoreState(int object_id) : _object_id(object_id) {}
+    StoreState(int object_id) : _object_id(object_id), _refcount(nullptr) {}
   };
   };
   typedef phash_map<const TypedWritable *, StoreState, pointer_hash> StateMap;
   typedef phash_map<const TypedWritable *, StoreState, pointer_hash> StateMap;
   StateMap _state_map;
   StateMap _state_map;