Browse Source

Merge branch 'release/1.10.x'

rdb 6 years ago
parent
commit
d5788d9422

+ 25 - 15
direct/src/tkpanels/ParticlePanel.py

@@ -214,23 +214,23 @@ class ParticlePanel(AppShell):
             ('System', 'Pool Size',
             ('System', 'Pool Size',
              'Max number of simultaneous particles',
              'Max number of simultaneous particles',
              self.setSystemPoolSize,
              self.setSystemPoolSize,
-             1.0, 1.0),
+             1.0, 2000000, 1.0),
             ('System', 'Birth Rate',
             ('System', 'Birth Rate',
              'Seconds between particle births',
              'Seconds between particle births',
              self.setSystemBirthRate,
              self.setSystemBirthRate,
-             0.0, None),
+             0.0, None, None),
             ('System', 'Litter Size',
             ('System', 'Litter Size',
              'Number of particle created at each birth',
              'Number of particle created at each birth',
              self.setSystemLitterSize,
              self.setSystemLitterSize,
-             1.0, 1.0),
+             1.0, 0x7fffffff, 1.0),
             ('System', 'Litter Spread',
             ('System', 'Litter Spread',
              'Variation in litter size',
              'Variation in litter size',
              self.setSystemLitterSpread,
              self.setSystemLitterSpread,
-             0.0, 1.0),
+             0.0, 0x7fffffff, 1.0),
             ('System', 'Lifespan',
             ('System', 'Lifespan',
              'Age in seconds at which the system (vs. particles) should die',
              'Age in seconds at which the system (vs. particles) should die',
              self.setSystemLifespan,
              self.setSystemLifespan,
-             0.0, None)
+             0.0, None, None)
             )
             )
         self.createFloaters(systemPage, systemFloaterDefs)
         self.createFloaters(systemPage, systemFloaterDefs)
 
 
@@ -269,27 +269,27 @@ class ParticlePanel(AppShell):
             ('Factory', 'Life Span',
             ('Factory', 'Life Span',
              'Average particle lifespan in seconds',
              'Average particle lifespan in seconds',
              self.setFactoryLifeSpan,
              self.setFactoryLifeSpan,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Life Span Spread',
             ('Factory', 'Life Span Spread',
              'Variation in lifespan',
              'Variation in lifespan',
              self.setFactoryLifeSpanSpread,
              self.setFactoryLifeSpanSpread,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Mass',
             ('Factory', 'Mass',
              'Average particle mass',
              'Average particle mass',
              self.setFactoryParticleMass,
              self.setFactoryParticleMass,
-             0.001, None),
+             0.001, None, None),
             ('Factory', 'Mass Spread',
             ('Factory', 'Mass Spread',
              'Variation in particle mass',
              'Variation in particle mass',
              self.setFactoryParticleMassSpread,
              self.setFactoryParticleMassSpread,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Terminal Velocity',
             ('Factory', 'Terminal Velocity',
              'Cap on average particle velocity',
              'Cap on average particle velocity',
              self.setFactoryTerminalVelocity,
              self.setFactoryTerminalVelocity,
-             0.0, None),
+             0.0, None, None),
             ('Factory', 'Terminal Vel. Spread',
             ('Factory', 'Terminal Vel. Spread',
              'Variation in terminal velocity',
              'Variation in terminal velocity',
              self.setFactoryTerminalVelocitySpread,
              self.setFactoryTerminalVelocitySpread,
-             0.0, None),
+             0.0, None, None),
         )
         )
         self.createFloaters(factoryPage, factoryWidgets)
         self.createFloaters(factoryPage, factoryWidgets)
 
 
@@ -966,19 +966,29 @@ class ParticlePanel(AppShell):
 
 
     def createFloaters(self, parent, widgetDefinitions):
     def createFloaters(self, parent, widgetDefinitions):
         widgets = []
         widgets = []
-        for category, label, balloonHelp, command, min, resolution in widgetDefinitions:
+        for category, label, balloonHelp, command, min, max, resolution in widgetDefinitions:
             widgets.append(
             widgets.append(
                 self.createFloater(parent, category, label, balloonHelp,
                 self.createFloater(parent, category, label, balloonHelp,
-                                   command, min, resolution)
+                                   command, min, max, resolution)
                 )
                 )
         return widgets
         return widgets
 
 
     def createFloater(self, parent, category, text, balloonHelp,
     def createFloater(self, parent, category, text, balloonHelp,
-                      command = None, min = 0.0, resolution = None,
-                      numDigits = 3, **kw):
+                      command = None, min = 0.0, max = None, resolution = None,
+                      numDigits = None, **kw):
         kw['text'] = text
         kw['text'] = text
         kw['min'] = min
         kw['min'] = min
+        if max is not None:
+            kw['max'] = max
         kw['resolution'] = resolution
         kw['resolution'] = resolution
+        if numDigits is None:
+            # If this is apparently an integer setting, show no decimals.
+            if resolution is not None and int(resolution) == resolution and \
+                (min is None or int(min) == min) and \
+                (max is None or int(max) == max):
+                numDigits = 0
+            else:
+                numDigits = 3
         kw['numDigits'] = numDigits
         kw['numDigits'] = numDigits
         widget = Floater.Floater(parent, **kw)
         widget = Floater.Floater(parent, **kw)
         # Do this after the widget so command isn't called on creation
         # Do this after the widget so command isn't called on creation

+ 15 - 3
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -6408,9 +6408,21 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap,
       TypeManager::is_vector_unsigned_char(type)) {
       TypeManager::is_vector_unsigned_char(type)) {
     // Most types are now handled by the many overloads of Dtool_WrapValue,
     // Most types are now handled by the many overloads of Dtool_WrapValue,
     // defined in py_panda.h.
     // defined in py_panda.h.
-    indent(out, indent_level)
-      << "return Dtool_WrapValue(" << return_expr << ");\n";
-
+    if (!remap->_has_this && remap->_cppfunc != nullptr &&
+        remap->_cppfunc->get_simple_name() == "encrypt_string" &&
+        return_expr == "return_value") {
+      // Temporary hack to fix #684 to avoid an ABI change.
+      out << "#if PY_MAJOR_VERSION >= 3\n";
+      indent(out, indent_level)
+        << "return PyBytes_FromStringAndSize((char *)return_value.data(), (Py_ssize_t)return_value.size());\n";
+      out << "#else\n";
+      indent(out, indent_level)
+        << "return PyString_FromStringAndSize((char *)return_value.data(), (Py_ssize_t)return_value.size());\n";
+      out << "#endif\n";
+    } else {
+      indent(out, indent_level)
+        << "return Dtool_WrapValue(" << return_expr << ");\n";
+    }
   } else if (TypeManager::is_pointer(type)) {
   } else if (TypeManager::is_pointer(type)) {
     bool is_const = TypeManager::is_const_pointer_to_anything(type);
     bool is_const = TypeManager::is_const_pointer_to_anything(type);
     bool owns_memory = remap->_return_value_needs_management;
     bool owns_memory = remap->_return_value_needs_management;

+ 4 - 0
makepanda/makepanda.py

@@ -924,6 +924,10 @@ if (COMPILER=="GCC"):
         else:
         else:
             PkgDisable("OPENCV")
             PkgDisable("OPENCV")
 
 
+        if GetTarget() == "darwin" and not PkgSkip("OPENAL"):
+            LibName("OPENAL", "-framework AudioToolbox")
+            LibName("OPENAL", "-framework CoreAudio")
+
         if not PkgSkip("ASSIMP") and \
         if not PkgSkip("ASSIMP") and \
             os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
             os.path.isfile(GetThirdpartyDir() + "assimp/lib/libassimp.a"):
             # Also pick up IrrXML, which is needed when linking statically.
             # Also pick up IrrXML, which is needed when linking statically.

+ 4 - 4
panda/src/gobj/geomPrimitive.cxx

@@ -1612,7 +1612,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
       // Find the first non-NaN vertex.
       // Find the first non-NaN vertex.
       while (!found_any && i < cdata->_num_vertices) {
       while (!found_any && i < cdata->_num_vertices) {
         reader.set_row(cdata->_first_vertex + i);
         reader.set_row(cdata->_first_vertex + i);
-        LPoint3 first_vertex = mat.xform_point(reader.get_data3());
+        LPoint3 first_vertex = mat.xform_point_general(reader.get_data3());
         if (!first_vertex.is_nan()) {
         if (!first_vertex.is_nan()) {
           min_point = first_vertex;
           min_point = first_vertex;
           max_point = first_vertex;
           max_point = first_vertex;
@@ -1624,7 +1624,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
 
 
       for (; i < cdata->_num_vertices; ++i) {
       for (; i < cdata->_num_vertices; ++i) {
         reader.set_row_unsafe(cdata->_first_vertex + i);
         reader.set_row_unsafe(cdata->_first_vertex + i);
-        LPoint3 vertex = mat.xform_point(reader.get_data3());
+        LPoint3 vertex = mat.xform_point_general(reader.get_data3());
 
 
         min_point.set(min(min_point[0], vertex[0]),
         min_point.set(min(min_point[0], vertex[0]),
                       min(min_point[1], vertex[1]),
                       min(min_point[1], vertex[1]),
@@ -1677,7 +1677,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
         int ii = index.get_data1i();
         int ii = index.get_data1i();
         if (ii != strip_cut_index) {
         if (ii != strip_cut_index) {
           reader.set_row(ii);
           reader.set_row(ii);
-          LPoint3 first_vertex = mat.xform_point(reader.get_data3());
+          LPoint3 first_vertex = mat.xform_point_general(reader.get_data3());
           if (!first_vertex.is_nan()) {
           if (!first_vertex.is_nan()) {
             min_point = first_vertex;
             min_point = first_vertex;
             max_point = first_vertex;
             max_point = first_vertex;
@@ -1693,7 +1693,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
           continue;
           continue;
         }
         }
         reader.set_row_unsafe(ii);
         reader.set_row_unsafe(ii);
-        LPoint3 vertex = mat.xform_point(reader.get_data3());
+        LPoint3 vertex = mat.xform_point_general(reader.get_data3());
 
 
         min_point.set(min(min_point[0], vertex[0]),
         min_point.set(min(min_point[0], vertex[0]),
                       min(min_point[1], vertex[1]),
                       min(min_point[1], vertex[1]),

+ 60 - 0
panda/src/pgraph/nodePath.cxx

@@ -3136,6 +3136,19 @@ get_texture(TextureStage *stage) const {
   return nullptr;
   return nullptr;
 }
 }
 
 
+/**
+ * Recursively searches the scene graph for references to the given texture,
+ * and replaces them with the new texture.
+ */
+void NodePath::
+replace_texture(Texture *tex, Texture *new_tex) {
+  nassertv_always(!is_empty());
+  nassertv(tex != nullptr);
+  nassertv(new_tex != nullptr);
+
+  r_replace_texture(node(), tex, new_tex);
+}
+
 /**
 /**
  * Returns the sampler state that has been given for the base-level texture
  * Returns the sampler state that has been given for the base-level texture
  * that has been set on this particular node.  If no sampler state was given,
  * that has been set on this particular node.  If no sampler state was given,
@@ -6425,6 +6438,53 @@ r_find_all_textures(PandaNode *node, TextureStage *stage,
   }
   }
 }
 }
 
 
+/**
+ * Recursively replaces references to the given texture on this section of the
+ * scene graph with the given other texture.
+ */
+void NodePath::
+r_replace_texture(PandaNode *node, Texture *tex, Texture *new_tex) {
+  // Consider the state of the node itself.
+  {
+    CPT(RenderState) node_state = node->get_state();
+    const TextureAttrib *ta;
+    if (node_state->get_attrib(ta)) {
+      CPT(RenderAttrib) new_ta = ta->replace_texture(tex, new_tex);
+      if (new_ta != ta) {
+        node->set_state(node_state->set_attrib(new_ta));
+      }
+    }
+  }
+
+  // If this is a GeomNode, consider the state of any of its Geoms.
+  if (node->is_geom_node()) {
+    GeomNode *gnode;
+    DCAST_INTO_V(gnode, node);
+
+    int num_geoms = gnode->get_num_geoms();
+    for (int i = 0; i < num_geoms; i++) {
+      CPT(RenderState) geom_state = gnode->get_geom_state(i);
+
+      // Look for a TextureAttrib on the state.
+      const TextureAttrib *ta;
+      if (geom_state->get_attrib(ta)) {
+        CPT(RenderAttrib) new_ta = ta->replace_texture(tex, new_tex);
+        if (new_ta != ta) {
+          gnode->set_geom_state(i, geom_state->set_attrib(new_ta));
+        }
+      }
+    }
+  }
+
+  // Now consider children.
+  PandaNode::Children cr = node->get_children();
+  size_t num_children = cr.get_num_children();
+  for (size_t i = 0; i < num_children; ++i) {
+    PandaNode *child = cr.get_child(i);
+    r_replace_texture(child, tex, new_tex);
+  }
+}
+
 /**
 /**
  *
  *
  */
  */

+ 2 - 0
panda/src/pgraph/nodePath.h

@@ -620,6 +620,7 @@ PUBLISHED:
   bool has_texture_off(TextureStage *stage) const;
   bool has_texture_off(TextureStage *stage) const;
   Texture *get_texture() const;
   Texture *get_texture() const;
   Texture *get_texture(TextureStage *stage) const;
   Texture *get_texture(TextureStage *stage) const;
+  void replace_texture(Texture *tex, Texture *new_tex);
   const SamplerState &get_texture_sampler() const;
   const SamplerState &get_texture_sampler() const;
   const SamplerState &get_texture_sampler(TextureStage *stage) const;
   const SamplerState &get_texture_sampler(TextureStage *stage) const;
 
 
@@ -1003,6 +1004,7 @@ private:
   Texture *r_find_texture(PandaNode *node, TextureStage *stage) const;
   Texture *r_find_texture(PandaNode *node, TextureStage *stage) const;
   void r_find_all_textures(PandaNode *node, TextureStage *stage,
   void r_find_all_textures(PandaNode *node, TextureStage *stage,
                            Textures &textures) const;
                            Textures &textures) const;
+  static void r_replace_texture(PandaNode *node, Texture *tex, Texture *new_tex);
 
 
   typedef phash_set<TextureStage *, pointer_hash> TextureStages;
   typedef phash_set<TextureStage *, pointer_hash> TextureStages;
   TextureStage *r_find_texture_stage(PandaNode *node, const RenderState *state,
   TextureStage *r_find_texture_stage(PandaNode *node, const RenderState *state,

+ 1 - 1
panda/src/pgraph/scissorAttrib.cxx

@@ -101,7 +101,7 @@ int ScissorAttrib::
 compare_to_impl(const RenderAttrib *other) const {
 compare_to_impl(const RenderAttrib *other) const {
   const ScissorAttrib *ta = (const ScissorAttrib *)other;
   const ScissorAttrib *ta = (const ScissorAttrib *)other;
 
 
-  if (!_off && !ta->_off) {
+  if (_off && ta->_off) {
     return 0;
     return 0;
   }
   }
 
 

+ 26 - 0
panda/src/pgraph/textureAttrib.cxx

@@ -250,6 +250,32 @@ unify_texture_stages(TextureStage *stage) const {
   return return_new(attrib);
   return return_new(attrib);
 }
 }
 
 
+/**
+ * Returns a new TextureAttrib, just like this one, but with all references to
+ * the given texture replaced with the new texture.
+ */
+CPT(RenderAttrib) TextureAttrib::
+replace_texture(Texture *tex, Texture *new_tex) const {
+  TextureAttrib *attrib = nullptr;
+
+  for (size_t i = 0; i < _on_stages.size(); ++i) {
+    const StageNode &sn = _on_stages[i];
+    if (sn._texture == tex) {
+      if (attrib == nullptr) {
+        attrib = new TextureAttrib(*this);
+      }
+
+      attrib->_on_stages[i]._texture = new_tex;
+    }
+  }
+
+  if (attrib != nullptr) {
+    return return_new(attrib);
+  } else {
+    return this;
+  }
+}
+
 /**
 /**
  * Returns a new TextureAttrib, very much like this one, but with the number
  * Returns a new TextureAttrib, very much like this one, but with the number
  * of on_stages reduced to be no more than max_texture_stages.  The number of
  * of on_stages reduced to be no more than max_texture_stages.  The number of

+ 1 - 0
panda/src/pgraph/textureAttrib.h

@@ -89,6 +89,7 @@ PUBLISHED:
   CPT(RenderAttrib) add_off_stage(TextureStage *stage, int override = 0) const;
   CPT(RenderAttrib) add_off_stage(TextureStage *stage, int override = 0) const;
   CPT(RenderAttrib) remove_off_stage(TextureStage *stage) const;
   CPT(RenderAttrib) remove_off_stage(TextureStage *stage) const;
   CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
   CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
+  CPT(RenderAttrib) replace_texture(Texture *tex, Texture *new_tex) const;
 
 
 public:
 public:
   CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;
   CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;

+ 3 - 3
panda/src/text/textAssembler.cxx

@@ -1843,10 +1843,10 @@ get_character_glyphs(int character, const TextProperties *properties,
   // Maybe we should remap the character to something else--e.g.  a small
   // Maybe we should remap the character to something else--e.g.  a small
   // capital.
   // capital.
   const UnicodeLatinMap::Entry *map_entry =
   const UnicodeLatinMap::Entry *map_entry =
-    UnicodeLatinMap::look_up(character);
+    UnicodeLatinMap::look_up((char32_t)character);
   if (map_entry != nullptr) {
   if (map_entry != nullptr) {
     if (properties->get_small_caps() &&
     if (properties->get_small_caps() &&
-        map_entry->_toupper_character != character) {
+        map_entry->_toupper_character != (char32_t)character) {
       character = map_entry->_toupper_character;
       character = map_entry->_toupper_character;
       map_entry = UnicodeLatinMap::look_up(character);
       map_entry = UnicodeLatinMap::look_up(character);
       glyph_scale = properties->get_small_caps_scale();
       glyph_scale = properties->get_small_caps_scale();
@@ -1871,7 +1871,7 @@ get_character_glyphs(int character, const TextProperties *properties,
       got_glyph = font->get_glyph(map_entry->_ascii_equiv, glyph);
       got_glyph = font->get_glyph(map_entry->_ascii_equiv, glyph);
     }
     }
 
 
-    if (!got_glyph && map_entry->_toupper_character != character) {
+    if (!got_glyph && map_entry->_toupper_character != (char32_t)character) {
       // If we still couldn't find it, try the uppercase equivalent.
       // If we still couldn't find it, try the uppercase equivalent.
       character = map_entry->_toupper_character;
       character = map_entry->_toupper_character;
       map_entry = UnicodeLatinMap::look_up(character);
       map_entry = UnicodeLatinMap::look_up(character);

+ 19 - 0
tests/pgraph/test_nodepath.py

@@ -149,3 +149,22 @@ def test_nodepath_python_tags():
     rc1 = sys.getrefcount(path.python_tags)
     rc1 = sys.getrefcount(path.python_tags)
     rc2 = sys.getrefcount(path.python_tags)
     rc2 = sys.getrefcount(path.python_tags)
     assert rc1 == rc2
     assert rc1 == rc2
+
+
+def test_nodepath_replace_texture():
+    from panda3d.core import NodePath, Texture
+
+    tex1 = Texture()
+    tex2 = Texture()
+
+    path1 = NodePath("node1")
+    path1.set_texture(tex1)
+    path1.replace_texture(tex1, tex2)
+    assert path1.get_texture() == tex2
+
+    path1 = NodePath("node1")
+    path2 = path1.attach_new_node("node2")
+    path2.set_texture(tex1)
+    path1.replace_texture(tex1, tex2)
+    assert not path1.has_texture()
+    assert path2.get_texture() == tex2