Browse Source

Merge branch 'master' into deploy-ng

Mitchell Stokes 7 years ago
parent
commit
b16f9f8f4f

+ 4 - 1
direct/src/interval/FunctionInterval.py

@@ -77,7 +77,10 @@ class FunctionInterval(Interval.Interval):
 
 
     @staticmethod
     @staticmethod
     def makeUniqueName(func, suffix = ''):
     def makeUniqueName(func, suffix = ''):
-        name = 'Func-%s-%d' % (getattr(func, '__name__', str(func)), FunctionInterval.functionIntervalNum)
+        func_name = getattr(func, '__name__', None)
+        if func_name is None:
+            func_name = str(func)
+        name = 'Func-%s-%d' % (func_name, FunctionInterval.functionIntervalNum)
         FunctionInterval.functionIntervalNum += 1
         FunctionInterval.functionIntervalNum += 1
         if suffix:
         if suffix:
             name = '%s-%s' % (name, str(suffix))
             name = '%s-%s' % (name, str(suffix))

+ 2 - 0
dtool/src/dtoolbase/dtoolbase.h

@@ -63,8 +63,10 @@
 /* Windows likes to define min() and max() macros, which will conflict with
 /* Windows likes to define min() and max() macros, which will conflict with
    std::min() and std::max() respectively, unless we do this: */
    std::min() and std::max() respectively, unless we do this: */
 #ifdef WIN32
 #ifdef WIN32
+#ifndef NOMINMAX
 #define NOMINMAX
 #define NOMINMAX
 #endif
 #endif
+#endif
 
 
 #ifndef __has_builtin
 #ifndef __has_builtin
 #define __has_builtin(x) 0
 #define __has_builtin(x) 0

+ 5 - 2
dtool/src/interrogatedb/py_panda.cxx

@@ -720,10 +720,13 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
       if (main_module == NULL) {
       if (main_module == NULL) {
         interrogatedb_cat.warning() << "Unable to import __main__\n";
         interrogatedb_cat.warning() << "Unable to import __main__\n";
       }
       }
-
+      
       // Extract the __file__ attribute, if present.
       // Extract the __file__ attribute, if present.
       Filename main_dir;
       Filename main_dir;
-      PyObject *file_attr = PyObject_GetAttrString(main_module, "__file__");
+      PyObject *file_attr = nullptr;
+      if (main_module != nullptr) {
+        file_attr = PyObject_GetAttrString(main_module, "__file__");
+      }
       if (file_attr == nullptr) {
       if (file_attr == nullptr) {
         // Must be running in the interactive interpreter.  Use the CWD.
         // Must be running in the interactive interpreter.  Use the CWD.
         main_dir = ExecutionEnvironment::get_cwd();
         main_dir = ExecutionEnvironment::get_cwd();

+ 27 - 25
makepanda/makepanda.py

@@ -3255,10 +3255,10 @@ CopyAllHeaders('panda/src/movies')
 CopyAllHeaders('panda/src/pgraphnodes')
 CopyAllHeaders('panda/src/pgraphnodes')
 CopyAllHeaders('panda/src/pgraph')
 CopyAllHeaders('panda/src/pgraph')
 CopyAllHeaders('panda/src/cull')
 CopyAllHeaders('panda/src/cull')
+CopyAllHeaders('panda/src/display')
 CopyAllHeaders('panda/src/chan')
 CopyAllHeaders('panda/src/chan')
 CopyAllHeaders('panda/src/char')
 CopyAllHeaders('panda/src/char')
 CopyAllHeaders('panda/src/dgraph')
 CopyAllHeaders('panda/src/dgraph')
-CopyAllHeaders('panda/src/display')
 CopyAllHeaders('panda/src/device')
 CopyAllHeaders('panda/src/device')
 CopyAllHeaders('panda/src/pnmtext')
 CopyAllHeaders('panda/src/pnmtext')
 CopyAllHeaders('panda/src/text')
 CopyAllHeaders('panda/src/text')
@@ -3971,6 +3971,31 @@ if (not RUNTIME):
   TargetAdd('libp3cull.in', opts=['IMOD:panda3d.core', 'ILIB:libp3cull', 'SRCDIR:panda/src/cull'])
   TargetAdd('libp3cull.in', opts=['IMOD:panda3d.core', 'ILIB:libp3cull', 'SRCDIR:panda/src/cull'])
   TargetAdd('libp3cull_igate.obj', input='libp3cull.in', opts=["DEPENDENCYONLY"])
   TargetAdd('libp3cull_igate.obj', input='libp3cull.in', opts=["DEPENDENCYONLY"])
 
 
+#
+# DIRECTORY: panda/src/display/
+#
+
+if (not RUNTIME):
+  OPTS=['DIR:panda/src/display', 'BUILDING:PANDA']
+  TargetAdd('p3display_graphicsStateGuardian.obj', opts=OPTS, input='graphicsStateGuardian.cxx')
+  TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
+  TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.cxx')
+
+  OPTS=['DIR:panda/src/display', 'PYTHON']
+  IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
+  IGATEFILES.remove("renderBuffer.h")
+  TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
+  TargetAdd('libp3display.in', opts=['IMOD:panda3d.core', 'ILIB:libp3display', 'SRCDIR:panda/src/display'])
+  TargetAdd('libp3display_igate.obj', input='libp3display.in', opts=["DEPENDENCYONLY"])
+  TargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx')
+  TargetAdd('p3display_graphicsWindow_ext.obj', opts=OPTS, input='graphicsWindow_ext.cxx')
+  TargetAdd('p3display_pythonGraphicsWindowProc.obj', opts=OPTS, input='pythonGraphicsWindowProc.cxx')
+
+  if RTDIST and GetTarget() == 'darwin':
+    OPTS=['DIR:panda/src/display']
+    TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
+    TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
+
 #
 #
 # DIRECTORY: panda/src/chan/
 # DIRECTORY: panda/src/chan/
 #
 #
@@ -4018,30 +4043,6 @@ if (not RUNTIME):
   TargetAdd('libp3dgraph.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph'])
   TargetAdd('libp3dgraph.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph'])
   TargetAdd('libp3dgraph_igate.obj', input='libp3dgraph.in', opts=["DEPENDENCYONLY"])
   TargetAdd('libp3dgraph_igate.obj', input='libp3dgraph.in', opts=["DEPENDENCYONLY"])
 
 
-#
-# DIRECTORY: panda/src/display/
-#
-
-if (not RUNTIME):
-  OPTS=['DIR:panda/src/display', 'BUILDING:PANDA']
-  TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
-  TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.cxx')
-
-  OPTS=['DIR:panda/src/display', 'PYTHON']
-  IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
-  IGATEFILES.remove("renderBuffer.h")
-  TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
-  TargetAdd('libp3display.in', opts=['IMOD:panda3d.core', 'ILIB:libp3display', 'SRCDIR:panda/src/display'])
-  TargetAdd('libp3display_igate.obj', input='libp3display.in', opts=["DEPENDENCYONLY"])
-  TargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx')
-  TargetAdd('p3display_graphicsWindow_ext.obj', opts=OPTS, input='graphicsWindow_ext.cxx')
-  TargetAdd('p3display_pythonGraphicsWindowProc.obj', opts=OPTS, input='pythonGraphicsWindowProc.cxx')
-
-  if RTDIST and GetTarget() == 'darwin':
-    OPTS=['DIR:panda/src/display']
-    TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
-    TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
-
 #
 #
 # DIRECTORY: panda/src/device/
 # DIRECTORY: panda/src/device/
 #
 #
@@ -4263,6 +4264,7 @@ if (not RUNTIME):
   TargetAdd('libpanda.dll', input='p3device_composite2.obj')
   TargetAdd('libpanda.dll', input='p3device_composite2.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite1.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite1.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite2.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite2.obj')
+  TargetAdd('libpanda.dll', input='p3display_graphicsStateGuardian.obj')
   TargetAdd('libpanda.dll', input='p3display_composite1.obj')
   TargetAdd('libpanda.dll', input='p3display_composite1.obj')
   TargetAdd('libpanda.dll', input='p3display_composite2.obj')
   TargetAdd('libpanda.dll', input='p3display_composite2.obj')
   TargetAdd('libpanda.dll', input='p3pipeline_composite1.obj')
   TargetAdd('libpanda.dll', input='p3pipeline_composite1.obj')

+ 2 - 2
panda/src/chan/animControl.cxx

@@ -32,14 +32,14 @@ AnimControl(const std::string &name, PartBundle *part,
   Namable(name),
   Namable(name),
   _pending_lock(name),
   _pending_lock(name),
   _pending_cvar(_pending_lock),
   _pending_cvar(_pending_lock),
-  _bound_joints(BitArray::all_on())
+  _bound_joints(BitArray::all_on()),
+  _part(part)
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, get_class_type());
   MemoryUsage::update_type(this, get_class_type());
 #endif
 #endif
 
 
   _pending = true;
   _pending = true;
-  _part = part;
   _anim = nullptr;
   _anim = nullptr;
   _channel_index = -1;
   _channel_index = -1;
   set_frame_rate(frame_rate);
   set_frame_rate(frame_rate);

+ 3 - 1
panda/src/chan/animControl.h

@@ -39,6 +39,8 @@ class EXPCL_PANDA_CHAN AnimControl : public TypedReferenceCount, public AnimInte
 public:
 public:
   AnimControl(const std::string &name, PartBundle *part,
   AnimControl(const std::string &name, PartBundle *part,
               double frame_rate, int num_frames);
               double frame_rate, int num_frames);
+  AnimControl(const AnimControl &copy) = delete;
+
   void setup_anim(PartBundle *part, AnimBundle *anim, int channel_index,
   void setup_anim(PartBundle *part, AnimBundle *anim, int channel_index,
                   const BitArray &bound_joints);
                   const BitArray &bound_joints);
   void set_bound_joints(const BitArray &bound_joints);
   void set_bound_joints(const BitArray &bound_joints);
@@ -82,7 +84,7 @@ private:
   // This is a PT(PartGroup) instead of a PT(PartBundle), just because we
   // This is a PT(PartGroup) instead of a PT(PartBundle), just because we
   // can't include partBundle.h for circular reasons.  But it actually keeps a
   // can't include partBundle.h for circular reasons.  But it actually keeps a
   // pointer to a PartBundle.
   // pointer to a PartBundle.
-  PT(PartGroup) _part;
+  const PT(PartGroup) _part;
   PT(AnimBundle) _anim;
   PT(AnimBundle) _anim;
   int _channel_index;
   int _channel_index;
 
 

+ 7 - 0
panda/src/chan/partBundle.cxx

@@ -556,8 +556,15 @@ control_removed(AnimControl *control) {
     CDStageWriter cdata(_cycler, pipeline_stage);
     CDStageWriter cdata(_cycler, pipeline_stage);
     ChannelBlend::iterator cbi = cdata->_blend.find(control);
     ChannelBlend::iterator cbi = cdata->_blend.find(control);
     if (cbi != cdata->_blend.end()) {
     if (cbi != cdata->_blend.end()) {
+      cdata->_net_blend -= cbi->second;
       cdata->_blend.erase(cbi);
       cdata->_blend.erase(cbi);
       cdata->_anim_changed = true;
       cdata->_anim_changed = true;
+
+      // We need to make sure that any _effective_channel pointers that point
+      // to this control are cleared.
+      if (pipeline_stage == 0) {
+        determine_effective_channels(cdata);
+      }
     }
     }
   }
   }
   CLOSE_ITERATE_ALL_STAGES(_cycler);
   CLOSE_ITERATE_ALL_STAGES(_cycler);

+ 14 - 28
panda/src/display/graphicsPipeSelection.cxx

@@ -18,7 +18,6 @@
 #include "load_dso.h"
 #include "load_dso.h"
 #include "config_display.h"
 #include "config_display.h"
 #include "typeRegistry.h"
 #include "typeRegistry.h"
-#include "pset.h"
 #include "config_putil.h"
 #include "config_putil.h"
 
 
 #include <algorithm>
 #include <algorithm>
@@ -61,8 +60,8 @@ GraphicsPipeSelection() : _lock("GraphicsPipeSelection") {
 
 
   // Also get the set of modules named in the various aux-display Config
   // Also get the set of modules named in the various aux-display Config
   // variables.  We'll want to know this when we call load_modules() later.
   // variables.  We'll want to know this when we call load_modules() later.
-  int num_aux = aux_display.get_num_unique_values();
-  for (int i = 0; i < num_aux; i++) {
+  size_t num_aux = aux_display.get_num_unique_values();
+  for (size_t i = 0; i < num_aux; ++i) {
     string name = aux_display.get_unique_value(i);
     string name = aux_display.get_unique_value(i);
     if (name != _default_display_module) {
     if (name != _default_display_module) {
       _display_modules.push_back(name);
       _display_modules.push_back(name);
@@ -124,9 +123,7 @@ print_pipe_types() const {
 
 
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
   nout << "Known pipe types:" << std::endl;
   nout << "Known pipe types:" << std::endl;
-  PipeTypes::const_iterator pi;
-  for (pi = _pipe_types.begin(); pi != _pipe_types.end(); ++pi) {
-    const PipeType &pipe_type = (*pi);
+  for (const PipeType &pipe_type : _pipe_types) {
     nout << "  " << pipe_type._type << "\n";
     nout << "  " << pipe_type._type << "\n";
   }
   }
   if (_display_modules.empty()) {
   if (_display_modules.empty()) {
@@ -187,11 +184,9 @@ make_pipe(const string &type_name, const string &module_name) {
 PT(GraphicsPipe) GraphicsPipeSelection::
 PT(GraphicsPipe) GraphicsPipeSelection::
 make_pipe(TypeHandle type) {
 make_pipe(TypeHandle type) {
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  PipeTypes::const_iterator ti;
 
 
   // First, look for an exact match of the requested type.
   // First, look for an exact match of the requested type.
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type == type) {
     if (ptype._type == type) {
       // Here's an exact match.
       // Here's an exact match.
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -202,8 +197,7 @@ make_pipe(TypeHandle type) {
   }
   }
 
 
   // Now look for a more-specific type.
   // Now look for a more-specific type.
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type.is_derived_from(type)) {
     if (ptype._type.is_derived_from(type)) {
       // Here's an approximate match.
       // Here's an approximate match.
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -215,8 +209,7 @@ make_pipe(TypeHandle type) {
 
 
   // Couldn't find any match; load the default module and try again.
   // Couldn't find any match; load the default module and try again.
   load_default_module();
   load_default_module();
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type.is_derived_from(type)) {
     if (ptype._type.is_derived_from(type)) {
       // Here's an approximate match.
       // Here's an approximate match.
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -260,13 +253,11 @@ make_default_pipe() {
   load_default_module();
   load_default_module();
 
 
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  PipeTypes::const_iterator ti;
 
 
   if (!_default_pipe_name.empty()) {
   if (!_default_pipe_name.empty()) {
     // First, look for an exact match of the default type name from the
     // First, look for an exact match of the default type name from the
     // Configrc file (excepting case and hyphenunderscore).
     // Configrc file (excepting case and hyphenunderscore).
-    for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-      const PipeType &ptype = (*ti);
+    for (const PipeType &ptype : _pipe_types) {
       if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
       if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
         // Here's an exact match.
         // Here's an exact match.
         PT(GraphicsPipe) pipe = (*ptype._constructor)();
         PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -278,8 +269,7 @@ make_default_pipe() {
 
 
     // No match; look for a substring match.
     // No match; look for a substring match.
     string preferred_name = downcase(_default_pipe_name);
     string preferred_name = downcase(_default_pipe_name);
-    for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-      const PipeType &ptype = (*ti);
+    for (const PipeType &ptype : _pipe_types) {
       string ptype_name = downcase(ptype._type.get_name());
       string ptype_name = downcase(ptype._type.get_name());
       if (ptype_name.find(preferred_name) != string::npos) {
       if (ptype_name.find(preferred_name) != string::npos) {
         // Here's a substring match.
         // Here's a substring match.
@@ -292,8 +282,7 @@ make_default_pipe() {
   }
   }
 
 
   // Couldn't find a matching pipe type; choose the first one on the list.
   // Couldn't find a matching pipe type; choose the first one on the list.
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     PT(GraphicsPipe) pipe = (*ptype._constructor)();
     PT(GraphicsPipe) pipe = (*ptype._constructor)();
     if (pipe != nullptr) {
     if (pipe != nullptr) {
       return pipe;
       return pipe;
@@ -310,9 +299,8 @@ make_default_pipe() {
  */
  */
 void GraphicsPipeSelection::
 void GraphicsPipeSelection::
 load_aux_modules() {
 load_aux_modules() {
-  DisplayModules::iterator di;
-  for (di = _display_modules.begin(); di != _display_modules.end(); ++di) {
-    load_named_module(*di);
+  for (const string &module : _display_modules) {
+    load_named_module(module);
   }
   }
 
 
   _display_modules.clear();
   _display_modules.clear();
@@ -337,9 +325,7 @@ add_pipe_type(TypeHandle type, PipeConstructorFunc *func) {
 
 
   // First, make sure we don't already have a GraphicsPipe of this type.
   // First, make sure we don't already have a GraphicsPipe of this type.
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  PipeTypes::const_iterator ti;
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type == type) {
     if (ptype._type == type) {
       display_cat->warning()
       display_cat->warning()
         << "Attempt to register GraphicsPipe type " << type
         << "Attempt to register GraphicsPipe type " << type
@@ -375,8 +361,8 @@ do_load_default_module() {
   load_named_module(_default_display_module);
   load_named_module(_default_display_module);
 
 
   DisplayModules::iterator di =
   DisplayModules::iterator di =
-    find(_display_modules.begin(), _display_modules.end(),
-         _default_display_module);
+    std::find(_display_modules.begin(), _display_modules.end(),
+              _default_display_module);
   if (di != _display_modules.end()) {
   if (di != _display_modules.end()) {
     _display_modules.erase(di);
     _display_modules.erase(di);
   }
   }

+ 47 - 39
panda/src/display/graphicsStateGuardian.cxx

@@ -24,7 +24,6 @@
 #include "renderBuffer.h"
 #include "renderBuffer.h"
 #include "light.h"
 #include "light.h"
 #include "planeNode.h"
 #include "planeNode.h"
-#include "ambientLight.h"
 #include "throw_event.h"
 #include "throw_event.h"
 #include "clockObject.h"
 #include "clockObject.h"
 #include "pStatTimer.h"
 #include "pStatTimer.h"
@@ -60,7 +59,6 @@
 #include "fogAttrib.h"
 #include "fogAttrib.h"
 #include "config_pstatclient.h"
 #include "config_pstatclient.h"
 
 
-#include <algorithm>
 #include <limits.h>
 #include <limits.h>
 
 
 using std::string;
 using std::string;
@@ -932,12 +930,12 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
   }
   }
   case Shader::SMO_frame_time: {
   case Shader::SMO_frame_time: {
     PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time();
     PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time();
-    t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_frame_delta: {
   case Shader::SMO_frame_delta: {
     PN_stdfloat dt = ClockObject::get_global_clock()->get_dt();
     PN_stdfloat dt = ClockObject::get_global_clock()->get_dt();
-    t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_texpad_x: {
   case Shader::SMO_texpad_x: {
@@ -949,7 +947,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     double cx = (sx * 0.5) / tex->get_x_size();
     double cx = (sx * 0.5) / tex->get_x_size();
     double cy = (sy * 0.5) / tex->get_y_size();
     double cy = (sy * 0.5) / tex->get_y_size();
     double cz = (sz * 0.5) / tex->get_z_size();
     double cz = (sz * 0.5) / tex->get_z_size();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cx, cy, cz, 0);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_texpix_x: {
   case Shader::SMO_texpix_x: {
@@ -958,7 +956,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     double px = 1.0 / tex->get_x_size();
     double px = 1.0 / tex->get_x_size();
     double py = 1.0 / tex->get_y_size();
     double py = 1.0 / tex->get_y_size();
     double pz = 1.0 / tex->get_z_size();
     double pz = 1.0 / tex->get_z_size();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, px, py, pz, 0);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_material: {
   case Shader::SMO_attr_material: {
@@ -966,7 +964,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
     // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
     // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
     if (target_material->is_off()) {
     if (target_material->is_off()) {
-      t = LMatrix4(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0);
+      t.set(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
       return &t;
       return &t;
     }
     }
     Material *m = target_material->get_material();
     Material *m = target_material->get_material();
@@ -975,17 +973,17 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     LVecBase4 const &emm = m->get_emission();
     LVecBase4 const &emm = m->get_emission();
     LVecBase4 spc = m->get_specular();
     LVecBase4 spc = m->get_specular();
     spc[3] = m->get_shininess();
     spc[3] = m->get_shininess();
-    t = LMatrix4(amb[0],amb[1],amb[2],amb[3],
-                  dif[0],dif[1],dif[2],dif[3],
-                  emm[0],emm[1],emm[2],emm[3],
-                  spc[0],spc[1],spc[2],spc[3]);
+    t.set(amb[0], amb[1], amb[2], amb[3],
+          dif[0], dif[1], dif[2], dif[3],
+          emm[0], emm[1], emm[2], emm[3],
+          spc[0], spc[1], spc[2], spc[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_material2: {
   case Shader::SMO_attr_material2: {
     const MaterialAttrib *target_material = (const MaterialAttrib *)
     const MaterialAttrib *target_material = (const MaterialAttrib *)
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
     if (target_material->is_off()) {
     if (target_material->is_off()) {
-      t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
       return &t;
       return &t;
     }
     }
     Material *m = target_material->get_material();
     Material *m = target_material->get_material();
@@ -1000,7 +998,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       return &LMatrix4::ones_mat();
       return &LMatrix4::ones_mat();
     }
     }
     LVecBase4 c = target_color->get_color();
     LVecBase4 c = target_color->get_color();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_colorscale: {
   case Shader::SMO_attr_colorscale: {
@@ -1010,7 +1008,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       return &LMatrix4::ones_mat();
       return &LMatrix4::ones_mat();
     }
     }
     LVecBase4 cs = target_color->get_scale();
     LVecBase4 cs = target_color->get_scale();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cs[0],cs[1],cs[2],cs[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cs[0], cs[1], cs[2], cs[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_fog: {
   case Shader::SMO_attr_fog: {
@@ -1022,7 +1020,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     }
     }
     PN_stdfloat start, end;
     PN_stdfloat start, end;
     fog->get_linear_range(start, end);
     fog->get_linear_range(start, end);
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,fog->get_exp_density(),start,end,1.0f/(end-start));
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+          fog->get_exp_density(), start, end, 1.0f / (end - start));
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_fogcolor: {
   case Shader::SMO_attr_fogcolor: {
@@ -1033,7 +1032,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       return &LMatrix4::ones_mat();
       return &LMatrix4::ones_mat();
     }
     }
     LVecBase4 c = fog->get_color();
     LVecBase4 c = fog->get_color();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_alight_x: {
   case Shader::SMO_alight_x: {
@@ -1042,7 +1041,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     AmbientLight *lt;
     AmbientLight *lt;
     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
     LColor const &c = lt->get_color();
     LColor const &c = lt->get_color();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_satten_x: {
   case Shader::SMO_satten_x: {
@@ -1052,7 +1051,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
     DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
     LVecBase3 const &a = lt->get_attenuation();
     LVecBase3 const &a = lt->get_attenuation();
     PN_stdfloat x = lt->get_exponent();
     PN_stdfloat x = lt->get_exponent();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,a[0],a[1],a[2],x);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a[0], a[1], a[2], x);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_dlight_x: {
   case Shader::SMO_dlight_x: {
@@ -1069,7 +1068,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     d.normalize();
     d.normalize();
     LVecBase3 h = d + LVecBase3(0,-1,0);
     LVecBase3 h = d + LVecBase3(0,-1,0);
     h.normalize();
     h.normalize();
-    t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],c[3],d[0],d[1],d[2],0,h[0],h[1],h[2],0);
+    t.set(c[0], c[1], c[2], c[3],
+          s[0], s[1], s[2], c[3],
+          d[0], d[1], d[2], 0,
+          h[0], h[1], h[2], 0);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_plight_x: {
   case Shader::SMO_plight_x: {
@@ -1087,7 +1089,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     Lens *lens = lt->get_lens(0);
     Lens *lens = lt->get_lens(0);
     PN_stdfloat lnear = lens->get_near();
     PN_stdfloat lnear = lens->get_near();
     PN_stdfloat lfar = lens->get_far();
     PN_stdfloat lfar = lens->get_far();
-    t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],lnear,a[0],a[1],a[2],lfar);
+    t.set(c[0], c[1], c[2], c[3],
+          s[0], s[1], s[2], s[3],
+          p[0], p[1], p[2], lnear,
+          a[0], a[1], a[2], lfar);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_slight_x: {
   case Shader::SMO_slight_x: {
@@ -1105,7 +1110,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       _scene_setup->get_world_transform()->get_mat();
       _scene_setup->get_world_transform()->get_mat();
     LVecBase3 p = t.xform_point(lens->get_nodal_point());
     LVecBase3 p = t.xform_point(lens->get_nodal_point());
     LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
     LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
-    t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff);
+    t.set(c[0], c[1], c[2], c[3],
+          s[0], s[1], s[2], s[3],
+          p[0], p[1], p[2], 0,
+          d[0], d[1], d[2], cutoff);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_light_ambient: {
   case Shader::SMO_light_ambient: {
@@ -1149,7 +1157,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
     if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
         index < ta->get_num_on_stages()) {
         index < ta->get_num_on_stages()) {
       LVecBase3 scale = tma->get_transform(ta->get_on_stage(index))->get_scale();
       LVecBase3 scale = tma->get_transform(ta->get_on_stage(index))->get_scale();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,scale[0],scale[1],scale[2],0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, scale[0], scale[1], scale[2], 0);
       return &t;
       return &t;
     } else {
     } else {
       return &LMatrix4::ident_mat();
       return &LMatrix4::ident_mat();
@@ -1173,7 +1181,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
         index < ta->get_num_on_stages()) {
         index < ta->get_num_on_stages()) {
       TextureStage *ts = ta->get_on_stage(index);
       TextureStage *ts = ta->get_on_stage(index);
       PN_stdfloat v = (ta->get_on_texture(ts)->get_format() == Texture::F_alpha);
       PN_stdfloat v = (ta->get_on_texture(ts)->get_format() == Texture::F_alpha);
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,v,v,v,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, v, v, v, 0);
       return &t;
       return &t;
     } else {
     } else {
       return &LMatrix4::zeros_mat();
       return &LMatrix4::zeros_mat();
@@ -1185,7 +1193,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     const PlaneNode *plane_node;
     const PlaneNode *plane_node;
     DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
     DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
     LPlane p = plane_node->get_plane();
     LPlane p = plane_node->get_plane();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, p[0], p[1], p[2], p[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_clipplane_x: {
   case Shader::SMO_clipplane_x: {
@@ -1235,10 +1243,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
   case Shader::SMO_vec_constant_x: {
   case Shader::SMO_vec_constant_x: {
     const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
     const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
     const PN_stdfloat *data = input.get_data();
     const PN_stdfloat *data = input.get_data();
-    t = LMatrix4(data[0],data[1],data[2],data[3],
-                 data[0],data[1],data[2],data[3],
-                 data[0],data[1],data[2],data[3],
-                 data[0],data[1],data[2],data[3]);
+    t.set(data[0], data[1], data[2], data[3],
+          data[0], data[1], data[2], data[3],
+          data[0], data[1], data[2], data[3],
+          data[0], data[1], data[2], data[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_world_to_view: {
   case Shader::SMO_world_to_view: {
@@ -1394,10 +1402,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       // There is an input specifying precisely this whole thing, with dot and
       // There is an input specifying precisely this whole thing, with dot and
       // all.  Support this, even if only for backward compatibility.
       // all.  Support this, even if only for backward compatibility.
       const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
       const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
-      t = LMatrix4(data[0],data[1],data[2],data[3],
-                   data[0],data[1],data[2],data[3],
-                   data[0],data[1],data[2],data[3],
-                   data[0],data[1],data[2],data[3]);
+      t.set(data[0], data[1], data[2], data[3],
+            data[0], data[1], data[2], data[3],
+            data[0], data[1], data[2], data[3],
+            data[0], data[1], data[2], data[3]);
       return &t;
       return &t;
     }
     }
 
 
@@ -1578,11 +1586,11 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
 
 
   } else if (attrib == IN_position) {
   } else if (attrib == IN_position) {
     if (np.is_empty()) {
     if (np.is_empty()) {
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
       return &t;
       return &t;
     } else if (node->is_ambient_light()) {
     } else if (node->is_ambient_light()) {
       // Ambient light has no position.
       // Ambient light has no position.
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
       return &t;
       return &t;
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
       DirectionalLight *light;
       DirectionalLight *light;
@@ -1591,7 +1599,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
       CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
       CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
       LVector3 dir = -(light->get_direction() * transform->get_mat());
       LVector3 dir = -(light->get_direction() * transform->get_mat());
       dir *= _scene_setup->get_cs_world_transform()->get_mat();
       dir *= _scene_setup->get_cs_world_transform()->get_mat();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 0);
       return &t;
       return &t;
     } else {
     } else {
       LightLensNode *light;
       LightLensNode *light;
@@ -1611,11 +1619,11 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
 
 
   } else if (attrib == IN_halfVector) {
   } else if (attrib == IN_halfVector) {
     if (np.is_empty()) {
     if (np.is_empty()) {
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
       return &t;
       return &t;
     } else if (node->is_ambient_light()) {
     } else if (node->is_ambient_light()) {
       // Ambient light has no half-vector.
       // Ambient light has no half-vector.
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
       return &t;
       return &t;
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
       DirectionalLight *light;
       DirectionalLight *light;
@@ -1627,7 +1635,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
       dir.normalize();
       dir.normalize();
       dir += LVector3(0, 0, 1);
       dir += LVector3(0, 0, 1);
       dir.normalize();
       dir.normalize();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],1);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 1);
       return &t;
       return &t;
     } else {
     } else {
       LightLensNode *light;
       LightLensNode *light;
@@ -1644,7 +1652,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
       pos.normalize();
       pos.normalize();
       pos += LVector3(0, 0, 1);
       pos += LVector3(0, 0, 1);
       pos.normalize();
       pos.normalize();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,pos[0],pos[1],pos[2],1);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pos[0],pos[1],pos[2], 1);
       return &t;
       return &t;
     }
     }
 
 

+ 0 - 1
panda/src/display/p3display_composite2.cxx

@@ -1,5 +1,4 @@
 #include "graphicsPipeSelection.cxx"
 #include "graphicsPipeSelection.cxx"
-#include "graphicsStateGuardian.cxx"
 #include "graphicsThreadingModel.cxx"
 #include "graphicsThreadingModel.cxx"
 #include "graphicsWindow.cxx"
 #include "graphicsWindow.cxx"
 #include "graphicsWindowProc.cxx"
 #include "graphicsWindowProc.cxx"

+ 3 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -8925,6 +8925,9 @@ get_panda_wrap_mode(GLenum wm) {
   case GL_REPEAT:
   case GL_REPEAT:
     return SamplerState::WM_repeat;
     return SamplerState::WM_repeat;
 
 
+  case GL_MIRRORED_REPEAT:
+    return SamplerState::WM_mirror;
+
 #ifndef OPENGLES
 #ifndef OPENGLES
   case GL_MIRROR_CLAMP_EXT:
   case GL_MIRROR_CLAMP_EXT:
   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
   case GL_MIRROR_CLAMP_TO_EDGE_EXT:

+ 2 - 0
panda/src/gobj/geomVertexData.I

@@ -772,7 +772,9 @@ set_object(const GeomVertexData *object) {
   _cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
   _cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
   _got_array_readers = false;
   _got_array_readers = false;
 
 
+#ifdef DO_PIPELINING
   _cdata->ref();
   _cdata->ref();
+#endif  // DO_PIPELINING
 }
 }
 
 
 /**
 /**

+ 3 - 0
panda/src/pgraph/cullTraverserData.cxx

@@ -54,6 +54,9 @@ apply_transform_and_state(CullTraverser *trav) {
     CPT(TransformState) node_transform = _node_reader.get_transform();
     CPT(TransformState) node_transform = _node_reader.get_transform();
     node_effects->cull_callback(trav, *this, node_transform, node_state);
     node_effects->cull_callback(trav, *this, node_transform, node_state);
     apply_transform(node_transform);
     apply_transform(node_transform);
+
+    // The cull callback may have changed the node properties.
+    _node_reader.check_cached(false);
   }
   }
 
 
   if (!node_state->is_empty()) {
   if (!node_state->is_empty()) {

+ 4 - 1
panda/src/pgraph/renderAttrib.cxx

@@ -211,7 +211,7 @@ garbage_collect() {
   }
   }
 
 
   num_this_pass = std::min(num_this_pass, size);
   num_this_pass = std::min(num_this_pass, size);
-  size_t stop_at_element = (_garbage_index + num_this_pass) % size;
+  size_t stop_at_element = (si + num_this_pass) % size;
 
 
   do {
   do {
     RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
     RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
@@ -229,6 +229,9 @@ garbage_collect() {
       // still need to visit.
       // still need to visit.
       --size;
       --size;
       --si;
       --si;
+      if (stop_at_element > 0) {
+        --stop_at_element;
+      }
     }
     }
 
 
     si = (si + 1) % size;
     si = (si + 1) % size;

+ 3 - 0
panda/src/pgraph/renderState.cxx

@@ -950,6 +950,9 @@ garbage_collect() {
       // still need to visit.
       // still need to visit.
       --size;
       --size;
       --si;
       --si;
+      if (stop_at_element > 0) {
+        --stop_at_element;
+      }
     }
     }
 
 
     si = (si + 1) % size;
     si = (si + 1) % size;

+ 3 - 0
panda/src/pgraph/transformState.cxx

@@ -1216,6 +1216,9 @@ garbage_collect() {
       // still need to visit.
       // still need to visit.
       --size;
       --size;
       --si;
       --si;
+      if (stop_at_element > 0) {
+        --stop_at_element;
+      }
     }
     }
 
 
     si = (si + 1) % size;
     si = (si + 1) % size;

+ 3 - 0
panda/src/pipeline/config_pipeline.cxx

@@ -71,7 +71,10 @@ init_libpipeline() {
   }
   }
   initialized = true;
   initialized = true;
 
 
+#ifdef DO_PIPELINING
   CycleData::init_type();
   CycleData::init_type();
+#endif
+
   MainThread::init_type();
   MainThread::init_type();
   ExternalThread::init_type();
   ExternalThread::init_type();
   GenericThread::init_type();
   GenericThread::init_type();

+ 3 - 0
panda/src/pipeline/cycleData.h

@@ -54,6 +54,9 @@ public:
   INLINE CycleData(const CycleData &copy) = default;
   INLINE CycleData(const CycleData &copy) = default;
   virtual ~CycleData();
   virtual ~CycleData();
 
 
+  CycleData &operator = (CycleData &&from) = default;
+  CycleData &operator = (const CycleData &copy) = default;
+
   virtual CycleData *make_copy() const=0;
   virtual CycleData *make_copy() const=0;
 
 
   virtual void write_datagram(BamWriter *, Datagram &) const;
   virtual void write_datagram(BamWriter *, Datagram &) const;

+ 37 - 14
panda/src/pipeline/cycleDataLockedStageReader.I

@@ -47,6 +47,20 @@ CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> &copy
   _cycler->increment_read(_pointer);
   _cycler->increment_read(_pointer);
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE CycleDataLockedStageReader<CycleDataType>::
+CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
+  _cycler(from._cycler),
+  _current_thread(from._current_thread),
+  _pointer(from._pointer),
+  _stage(from._stage)
+{
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -64,20 +78,6 @@ operator = (const CycleDataLockedStageReader<CycleDataType> &copy) {
   _cycler->increment_read(_pointer);
   _cycler->increment_read(_pointer);
 }
 }
 
 
-/**
- *
- */
-template<class CycleDataType>
-INLINE CycleDataLockedStageReader<CycleDataType>::
-CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
-  _cycler(from._cycler),
-  _current_thread(from._current_thread),
-  _pointer(from._pointer),
-  _stage(from._stage)
-{
-  from._pointer = nullptr;
-}
-
 /**
 /**
  *
  *
  */
  */
@@ -174,6 +174,17 @@ CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> &copy
 {
 {
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE CycleDataLockedStageReader<CycleDataType>::
+CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
+  _pointer(from._cycler)
+{
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -183,6 +194,18 @@ operator = (const CycleDataLockedStageReader<CycleDataType> &copy) {
   _pointer = copy._pointer;
   _pointer = copy._pointer;
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE void CycleDataLockedStageReader<CycleDataType>::
+operator = (CycleDataLockedStageReader<CycleDataType> &&from) noexcept {
+  nassertv(_pointer == nullptr);
+
+  _pointer = from._pointer;
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */

+ 40 - 17
panda/src/pipeline/cycleDataStageWriter.I

@@ -62,23 +62,6 @@ CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy) :
   _cycler->increment_write(_pointer);
   _cycler->increment_write(_pointer);
 }
 }
 
 
-/**
- *
- */
-template<class CycleDataType>
-INLINE void CycleDataStageWriter<CycleDataType>::
-operator = (const CycleDataStageWriter<CycleDataType> &copy) {
-  nassertv(_pointer == nullptr);
-  nassertv(_current_thread == copy._current_thread);
-
-  _cycler = copy._cycler;
-  _pointer = copy._pointer;
-  _stage = copy._stage;
-
-  nassertv(_pointer != nullptr);
-  _cycler->increment_write(_pointer);
-}
-
 /**
 /**
  * This flavor of the constructor elevates the pointer from the
  * This flavor of the constructor elevates the pointer from the
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates
@@ -128,6 +111,23 @@ CycleDataStageWriter(CycleDataStageWriter<CycleDataType> &&from) noexcept :
   from._pointer = nullptr;
   from._pointer = nullptr;
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE void CycleDataStageWriter<CycleDataType>::
+operator = (const CycleDataStageWriter<CycleDataType> &copy) {
+  nassertv(_pointer == nullptr);
+  nassertv(_current_thread == copy._current_thread);
+
+  _cycler = copy._cycler;
+  _pointer = copy._pointer;
+  _stage = copy._stage;
+
+  nassertv(_pointer != nullptr);
+  _cycler->increment_write(_pointer);
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -227,6 +227,17 @@ CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy) :
 {
 {
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE CycleDataStageWriter<CycleDataType>::
+CycleDataStageWriter(CycleDataStageWriter<CycleDataType> &&from) noexcept :
+  _pointer(from._pointer)
+{
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -236,6 +247,18 @@ operator = (const CycleDataStageWriter<CycleDataType> &copy) {
   _pointer = copy._pointer;
   _pointer = copy._pointer;
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE void CycleDataStageWriter<CycleDataType>::
+operator = (CycleDataStageWriter<CycleDataType> &&from) noexcept {
+  nassertv(_pointer == nullptr);
+
+  _pointer = from._pointer;
+  from._pointer = nullptr;
+}
+
 /**
 /**
  * This flavor of the constructor elevates the pointer from the
  * This flavor of the constructor elevates the pointer from the
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates

+ 8 - 1
tests/event/test_futures.py

@@ -1,6 +1,5 @@
 from panda3d import core
 from panda3d import core
 import pytest
 import pytest
-import threading
 import time
 import time
 import sys
 import sys
 
 
@@ -39,7 +38,11 @@ def test_future_timeout():
         fut.result(0.001)
         fut.result(0.001)
 
 
 
 
[email protected](not core.Thread.is_threading_supported(),
+                    reason="Threading support disabled")
 def test_future_wait():
 def test_future_wait():
+    threading = pytest.importorskip("direct.stdpy.threading")
+
     fut = core.AsyncFuture()
     fut = core.AsyncFuture()
 
 
     # Launch a thread to set the result value.
     # Launch a thread to set the result value.
@@ -59,7 +62,11 @@ def test_future_wait():
     assert fut.result() is None
     assert fut.result() is None
 
 
 
 
[email protected](not core.Thread.is_threading_supported(),
+                    reason="Threading support disabled")
 def test_future_wait_cancel():
 def test_future_wait_cancel():
+    threading = pytest.importorskip("direct.stdpy.threading")
+
     fut = core.AsyncFuture()
     fut = core.AsyncFuture()
 
 
     # Launch a thread to cancel the future.
     # Launch a thread to cancel the future.