浏览代码

Merge branch 'release/1.10.x'

rdb 5 年之前
父节点
当前提交
f524f00e8e

+ 1 - 1
direct/src/gui/DirectScrolledList.py

@@ -210,7 +210,7 @@ class DirectScrolledList(DirectFrame):
         numItemsVisible = self["numItemsVisible"]
         numItemsTotal = len(self["items"])
         if(centered):
-            self.index = index - (numItemsVisible/2)
+            self.index = index - (numItemsVisible // 2)
         else:
             self.index = index
 

+ 97 - 16
panda/src/egg2pg/eggSaver.cxx

@@ -345,18 +345,61 @@ convert_anim_node(AnimBundleNode *node, const WorkingNodePath &node_path,
  */
 void EggSaver::
 convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, CharacterJointMap *joint_map) {
+  convert_character_bundle(bundleNode, egg_parent, joint_map, nullptr);
+}
+
+/**
+ * Converts the indicated Character Bundle to the corresponding Egg joints
+ * structure.
+ */
+void EggSaver::
+convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent,
+                         CharacterJointMap *joint_map, const CharacterJoint *parent_joint) {
   int num_children = bundleNode->get_num_children();
 
+  const CharacterJoint *character_joint = nullptr;
+
   EggGroupNode *joint_group = egg_parent;
   if (bundleNode->is_of_type(CharacterJoint::get_class_type())) {
-    CharacterJoint *character_joint = DCAST(CharacterJoint, bundleNode);
+    character_joint = DCAST(CharacterJoint, bundleNode);
 
-    LMatrix4 transformf;
-    character_joint->get_transform(transformf);
-    LMatrix4d transformd(LCAST(double, transformf));
     EggGroup *joint = new EggGroup(bundleNode->get_name());
-    joint->add_matrix4(transformd);
     joint->set_group_type(EggGroup::GT_joint);
+
+    // The default_value originally passed to the CharacterJoint is what is used
+    // for skinning.  However, the _default_value can be changed after joint
+    // construction (such as via a <DefaultPose>), so we can't just pull the
+    // current _default_value.
+    //
+    // We have to instead work back from the _initial_net_transform_inverse,
+    // which is computed at construction time from the original default_value:
+    //
+    //   _net_transform = default_value * parent_joint->_net_transform;
+    //   _initial_net_transform_inverse = invert(_net_transform);
+    //
+    // So we should be able to reconstruct the original default_value like so:
+    //
+    //   default_value = invert(_initial_net_transform_inverse)
+    //                 * parent_joint->_initial_net_transform_inverse;
+    //
+    LMatrix4d net_transform = invert(LCAST(double, character_joint->_initial_net_transform_inverse));
+    if (parent_joint != nullptr) {
+      if (parent_joint->_initial_net_transform_inverse != character_joint->_initial_net_transform_inverse) {
+        LMatrix4d parent_inverse = LCAST(double, parent_joint->_initial_net_transform_inverse);
+        joint->add_matrix4(net_transform * parent_inverse);
+      }
+    } else if (!net_transform.is_identity()) {
+      joint->add_matrix4(net_transform);
+    }
+
+    // The joint's _default_value, if different, goes into a <DefaultPose>.
+    LMatrix4d default_pose = LCAST(double, character_joint->_default_value);
+    if (default_pose != joint->get_transform3d()) {
+      EggTransform transform;
+      transform.add_matrix4(LCAST(double, default_pose));
+      joint->set_default_pose(transform);
+    }
+
     joint_group = joint;
     egg_parent->add_child(joint_group);
     if (joint_map != nullptr) {
@@ -373,7 +416,7 @@ convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, Charac
 
   for (int i = 0; i < num_children ; i++) {
     PartGroup *partGroup= bundleNode->get_child(i);
-    convert_character_bundle(partGroup, joint_group, joint_map);
+    convert_character_bundle(partGroup, joint_group, joint_map, character_joint);
   }
 
 }
@@ -707,6 +750,7 @@ convert_primitive(const GeomVertexData *vertex_data,
                   const LMatrix4 &net_mat, EggGroupNode *egg_parent,
                   CharacterJointMap *joint_map) {
   GeomVertexReader reader(vertex_data);
+  const GeomVertexFormat *format = vertex_data->get_format();
 
   // Make a zygote that will be duplicated for each primitive.
   PT(EggPrimitive) egg_prim;
@@ -765,14 +809,14 @@ convert_primitive(const GeomVertexData *vertex_data,
   // Check for a texture.
   const TextureAttrib *ta;
   if (net_state->get_attrib(ta)) {
-    EggTexture *egg_tex = get_egg_texture(ta->get_texture());
+    for (size_t i = 0; i < ta->get_num_on_stages(); ++i) {
+      TextureStage *tex_stage = ta->get_on_stage(i);
 
-    if (egg_tex != nullptr) {
-      TextureStage *tex_stage = ta->get_on_stage(0);
-      if (tex_stage != nullptr) {
+      EggTexture *egg_tex = get_egg_texture(ta->get_on_texture(tex_stage));
+      if (egg_tex != nullptr) {
         switch (tex_stage->get_mode()) {
         case TextureStage::M_modulate:
-          if (has_color_off == true) {
+          if (has_color_off == true && i == 0) {
             egg_tex->set_env_type(EggTexture::ET_replace);
           } else {
             egg_tex->set_env_type(EggTexture::ET_modulate);
@@ -793,12 +837,44 @@ convert_primitive(const GeomVertexData *vertex_data,
         case TextureStage::M_blend_color_scale:
           egg_tex->set_env_type(EggTexture::ET_blend_color_scale);
           break;
+        case TextureStage::M_modulate_glow:
+          egg_tex->set_env_type(EggTexture::ET_modulate_glow);
+          break;
+        case TextureStage::M_modulate_gloss:
+          egg_tex->set_env_type(EggTexture::ET_modulate_gloss);
+          break;
+        case TextureStage::M_normal:
+          egg_tex->set_env_type(EggTexture::ET_normal);
+          break;
+        case TextureStage::M_normal_height:
+          egg_tex->set_env_type(EggTexture::ET_normal_height);
+          break;
+        case TextureStage::M_glow:
+          egg_tex->set_env_type(EggTexture::ET_glow);
+          break;
+        case TextureStage::M_gloss:
+          egg_tex->set_env_type(EggTexture::ET_gloss);
+          break;
+        case TextureStage::M_height:
+          egg_tex->set_env_type(EggTexture::ET_height);
+          break;
+        case TextureStage::M_selector:
+          egg_tex->set_env_type(EggTexture::ET_selector);
+          break;
+        case TextureStage::M_normal_gloss:
+          egg_tex->set_env_type(EggTexture::ET_normal_gloss);
+          break;
         default:
           break;
         }
-      }
 
-      egg_prim->set_texture(egg_tex);
+        const InternalName *name = tex_stage->get_texcoord_name();
+        if (name != nullptr && name != InternalName::get_texcoord()) {
+          egg_tex->set_uv_name(name->get_basename());
+        }
+
+        egg_prim->add_texture(egg_tex);
+      }
     }
   }
 
@@ -863,10 +939,15 @@ convert_primitive(const GeomVertexData *vertex_data,
                                   color[3] * color_scale[3]));
       }
 
-      if (vertex_data->has_column(InternalName::get_texcoord())) {
-        reader.set_column(InternalName::get_texcoord());
+      for (size_t ti = 0; ti < format->get_num_texcoords(); ++ti) {
+        const InternalName *texcoord_name = format->get_texcoord(ti);
+        reader.set_column(texcoord_name);
         LTexCoord uv = reader.get_data2();
-        egg_vert.set_uv(LCAST(double, uv));
+        if (texcoord_name == InternalName::get_texcoord()) {
+          egg_vert.set_uv(LCAST(double, uv));
+        } else {
+          egg_vert.set_uv(texcoord_name->get_basename(), LCAST(double, uv));
+        }
       }
 
       EggVertex *new_egg_vert = _vpool->create_unique_vertex(egg_vert);

+ 3 - 0
panda/src/egg2pg/eggSaver.h

@@ -78,6 +78,9 @@ private:
   void convert_character_node(Character *node, const WorkingNodePath &node_path,
                         EggGroupNode *egg_parent, bool has_decal);
   void convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, CharacterJointMap *jointMap);
+  void convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent,
+                                CharacterJointMap *jointMap,
+                                const CharacterJoint *parent_joint);
   void convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
                               EggGroupNode *egg_parent, bool has_decal,
                               CharacterJointMap *joint_map);

+ 15 - 0
panda/src/express/referenceCount.I

@@ -317,6 +317,21 @@ ref_if_nonzero() const {
   return true;
 }
 
+/**
+ * Atomically decreases the reference count of this object if it is one.
+ * Do not use this.  This exists only to implement a special case with the
+ * state cache.
+ * @return false if the reference count was decremented to zero.
+ */
+INLINE bool ReferenceCount::
+unref_if_one() const {
+#ifdef _DEBUG
+  nassertr(test_ref_count_integrity(), 0);
+  nassertr(_ref_count > 0, 0);
+#endif
+  return (AtomicAdjust::compare_and_exchange(_ref_count, 1, 0) != 1);
+}
+
 /**
  * This global helper function will unref the given ReferenceCount object, and
  * if the reference count reaches zero, automatically delete it.  It can't be

+ 1 - 0
panda/src/express/referenceCount.h

@@ -64,6 +64,7 @@ public:
   INLINE void weak_unref();
 
   INLINE bool ref_if_nonzero() const;
+  INLINE bool unref_if_one() const;
 
 protected:
   bool do_test_ref_count_integrity() const;

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

@@ -209,14 +209,15 @@ garbage_collect() {
 
   do {
     RenderAttrib *attrib = (RenderAttrib *)_attribs.get_key(si);
-    if (attrib->get_ref_count() == 1) {
+    if (!attrib->unref_if_one()) {
       // This attrib has recently been unreffed to 1 (the one we added when
       // we stored it in the cache).  Now it's time to delete it.  This is
       // safe, because we're holding the _attribs_lock, so it's not possible
       // for some other thread to find the attrib in the cache and ref it
-      // while we're doing this.
+      // while we're doing this.  Also, we've just made sure to unref it to 0,
+      // to ensure that another thread can't get it via a weak pointer.
       attrib->release_new();
-      unref_delete(attrib);
+      delete attrib;
 
       // When we removed it from the hash map, it swapped the last element
       // with the one we just removed.  So the current index contains one we

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

@@ -925,15 +925,17 @@ garbage_collect() {
       }
     }
 
-    if (state->get_ref_count() == 1) {
+    if (!state->unref_if_one()) {
       // This state has recently been unreffed to 1 (the one we added when
       // we stored it in the cache).  Now it's time to delete it.  This is
       // safe, because we're holding the _states_lock, so it's not possible
       // for some other thread to find the state in the cache and ref it
-      // while we're doing this.
+      // while we're doing this.  Also, we've just made sure to unref it to 0,
+      // to ensure that another thread can't get it via a weak pointer.
+
       state->release_new();
       state->remove_cache_pointers();
-      state->cache_unref();
+      state->cache_unref_only();
       delete state;
 
       // When we removed it from the hash map, it swapped the last element

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

@@ -1195,15 +1195,16 @@ garbage_collect() {
       }
     }
 
-    if (state->get_ref_count() == 1) {
+    if (!state->unref_if_one()) {
       // This state has recently been unreffed to 1 (the one we added when
       // we stored it in the cache).  Now it's time to delete it.  This is
       // safe, because we're holding the _states_lock, so it's not possible
       // for some other thread to find the state in the cache and ref it
-      // while we're doing this.
+      // while we're doing this.  Also, we've just made sure to unref it to 0,
+      // to ensure that another thread can't get it via a weak pointer.
       state->release_new();
       state->remove_cache_pointers();
-      state->cache_unref();
+      state->cache_unref_only();
       delete state;
 
       // When we removed it from the hash map, it swapped the last element