mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 00:06:44 -04:00
pgraph: add NodePath.replace_texture()
This commit is contained in:
parent
ab238bd153
commit
bac376541f
@ -3136,6 +3136,19 @@ get_texture(TextureStage *stage) const {
|
||||
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
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -620,6 +620,7 @@ PUBLISHED:
|
||||
bool has_texture_off(TextureStage *stage) const;
|
||||
Texture *get_texture() 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(TextureStage *stage) const;
|
||||
|
||||
@ -1003,6 +1004,7 @@ private:
|
||||
Texture *r_find_texture(PandaNode *node, TextureStage *stage) const;
|
||||
void r_find_all_textures(PandaNode *node, TextureStage *stage,
|
||||
Textures &textures) const;
|
||||
static void r_replace_texture(PandaNode *node, Texture *tex, Texture *new_tex);
|
||||
|
||||
typedef phash_set<TextureStage *, pointer_hash> TextureStages;
|
||||
TextureStage *r_find_texture_stage(PandaNode *node, const RenderState *state,
|
||||
|
@ -250,6 +250,32 @@ unify_texture_stages(TextureStage *stage) const {
|
||||
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
|
||||
* of on_stages reduced to be no more than max_texture_stages. The number of
|
||||
|
@ -89,6 +89,7 @@ PUBLISHED:
|
||||
CPT(RenderAttrib) add_off_stage(TextureStage *stage, int override = 0) const;
|
||||
CPT(RenderAttrib) remove_off_stage(TextureStage *stage) const;
|
||||
CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const;
|
||||
CPT(RenderAttrib) replace_texture(Texture *tex, Texture *new_tex) const;
|
||||
|
||||
public:
|
||||
CPT(TextureAttrib) filter_to_max(int max_texture_stages) const;
|
||||
|
@ -149,3 +149,22 @@ def test_nodepath_python_tags():
|
||||
rc1 = sys.getrefcount(path.python_tags)
|
||||
rc2 = sys.getrefcount(path.python_tags)
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user