diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 9d473304b6..1832e18e5a 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -4163,6 +4163,20 @@ get_material() const { return nullptr; } +/** + * Recursively searches the scene graph for references to the given material, + * and replaces them with the new material. + */ +void NodePath:: +replace_material(Material *mat, Material *new_mat) { + nassertv_always(!is_empty()); + nassertv(mat != nullptr); + nassertv(new_mat != nullptr); + + CPT(RenderAttrib) new_attrib = MaterialAttrib::make(new_mat); + r_replace_material(node(), mat, (const MaterialAttrib *)new_attrib.p()); +} + /** * Sets the geometry at this level and below to render using the indicated * fog. @@ -6632,6 +6646,52 @@ r_find_all_materials(PandaNode *node, const RenderState *state, } } +/** + * + */ +void NodePath:: +r_replace_material(PandaNode *node, Material *mat, + const MaterialAttrib *new_attrib) { + // Consider the state of the node itself. + { + CPT(RenderState) node_state = node->get_state(); + const MaterialAttrib *ma; + if (node_state->get_attrib(ma)) { + if (mat == ma->get_material()) { + node->set_state(node_state->set_attrib(new_attrib)); + } + } + } + + // 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 MaterialAttrib on the state. + const MaterialAttrib *ma; + if (geom_state->get_attrib(ma)) { + if (mat == ma->get_material()) { + // Replace it + gnode->set_geom_state(i, geom_state->set_attrib(new_attrib)); + } + } + } + } + + // 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_material(child, mat, new_attrib); + } +} + /** * Writes the contents of this object to the datagram for shipping out to a * Bam file. diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 9c047c0728..3d5d4a6aa3 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -771,6 +771,7 @@ PUBLISHED: void clear_material(); bool has_material() const; PT(Material) get_material() const; + void replace_material(Material *mat, Material *new_mat); void set_fog(Fog *fog, int priority = 0); void set_fog_off(int priority = 0); @@ -1016,6 +1017,8 @@ private: const GlobPattern &glob) const; void r_find_all_materials(PandaNode *node, const RenderState *state, Materials &materials) const; + static void r_replace_material(PandaNode *node, Material *mat, + const MaterialAttrib *new_attrib); PT(NodePathComponent) _head; int _backup_key;