mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-18 12:43:44 -04:00
add replace_node()
This commit is contained in:
parent
6cf3110653
commit
d6b8d30bca
@ -1500,6 +1500,168 @@ list_tags(ostream &out, const string &separator) const {
|
|||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PandaNode::copy_all_properties
|
||||||
|
// Access: Published
|
||||||
|
// Description: Copies the TransformState, RenderState,
|
||||||
|
// RenderEffects, tags, Python tags, and the show/hide
|
||||||
|
// state from the other node onto this one. Typically
|
||||||
|
// this is used to prepare a node to replace another
|
||||||
|
// node in the scene graph (also see replace_node()).
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PandaNode::
|
||||||
|
copy_all_properties(PandaNode *other) {
|
||||||
|
if (other == this) {
|
||||||
|
// Trivial.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool any_transform_changed = false;
|
||||||
|
bool any_state_changed = false;
|
||||||
|
bool any_draw_mask_changed = false;
|
||||||
|
Thread *current_thread = Thread::get_current_thread();
|
||||||
|
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||||
|
CDStageWriter cdataw(_cycler, pipeline_stage, current_thread);
|
||||||
|
CDStageReader cdatar(other->_cycler, pipeline_stage, current_thread);
|
||||||
|
|
||||||
|
if (cdataw->_transform != cdatar->_transform) {
|
||||||
|
any_transform_changed = true;
|
||||||
|
}
|
||||||
|
if (cdataw->_state != cdatar->_state) {
|
||||||
|
any_state_changed = true;
|
||||||
|
}
|
||||||
|
if (cdataw->_draw_control_mask != cdatar->_draw_control_mask ||
|
||||||
|
cdataw->_draw_show_mask != cdatar->_draw_show_mask) {
|
||||||
|
any_draw_mask_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdataw->_transform = cdatar->_transform;
|
||||||
|
cdataw->_prev_transform = cdatar->_prev_transform;
|
||||||
|
cdataw->_state = cdatar->_state;
|
||||||
|
cdataw->_effects = cdatar->_effects;
|
||||||
|
cdataw->_draw_control_mask = cdatar->_draw_control_mask;
|
||||||
|
cdataw->_draw_show_mask = cdatar->_draw_show_mask;
|
||||||
|
|
||||||
|
TagData::const_iterator ti;
|
||||||
|
for (ti = cdatar->_tag_data.begin();
|
||||||
|
ti != cdatar->_tag_data.end();
|
||||||
|
++ti) {
|
||||||
|
cdataw->_tag_data[(*ti).first] = (*ti).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PYTHON
|
||||||
|
PythonTagData::const_iterator pti;
|
||||||
|
for (pti = cdatar->_python_tag_data.begin();
|
||||||
|
pti != cdatar->_python_tag_data.end();
|
||||||
|
++pti) {
|
||||||
|
const string &key = (*pti).first;
|
||||||
|
PyObject *value = (*pti).second;
|
||||||
|
Py_XINCREF(value);
|
||||||
|
|
||||||
|
pair<PythonTagData::iterator, bool> result;
|
||||||
|
result = cdataw->_python_tag_data.insert(PythonTagData::value_type(key, value));
|
||||||
|
|
||||||
|
if (!result.second) {
|
||||||
|
// The insert was unsuccessful; that means the key was already
|
||||||
|
// present in the map. In this case, we should decrement the
|
||||||
|
// original value's reference count and replace it with the new
|
||||||
|
// object.
|
||||||
|
PythonTagData::iterator wpti = result.first;
|
||||||
|
PyObject *old_value = (*wpti).second;
|
||||||
|
Py_XDECREF(old_value);
|
||||||
|
(*wpti).second = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
|
static const int change_bits = (FB_transform | FB_state | FB_effects |
|
||||||
|
FB_tag | FB_draw_mask);
|
||||||
|
cdataw->_fancy_bits =
|
||||||
|
(cdataw->_fancy_bits & ~change_bits) |
|
||||||
|
(cdatar->_fancy_bits & change_bits);
|
||||||
|
|
||||||
|
if (pipeline_stage == 0) {
|
||||||
|
if (cdataw->_transform != cdataw->_prev_transform) {
|
||||||
|
set_dirty_prev_transform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
||||||
|
|
||||||
|
if (any_transform_changed || any_state_changed || any_draw_mask_changed) {
|
||||||
|
mark_bounds_stale(current_thread);
|
||||||
|
|
||||||
|
if (any_transform_changed) {
|
||||||
|
transform_changed();
|
||||||
|
}
|
||||||
|
if (any_state_changed) {
|
||||||
|
state_changed();
|
||||||
|
}
|
||||||
|
if (any_draw_mask_changed) {
|
||||||
|
draw_mask_changed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PandaNode::replace_node
|
||||||
|
// Access: Published
|
||||||
|
// Description: Inserts this node into the scene graph in place of
|
||||||
|
// the other one, and removes the other node. All scene
|
||||||
|
// graph attributes (TransformState, RenderState, etc.)
|
||||||
|
// are copied to this node.
|
||||||
|
//
|
||||||
|
// All children are moved to this node, and removed from
|
||||||
|
// the old node. The new node is left in the same place
|
||||||
|
// in the old node's parent's list of children.
|
||||||
|
//
|
||||||
|
// Even NodePaths that reference the old node are
|
||||||
|
// updated in-place to reference the new node instead.
|
||||||
|
//
|
||||||
|
// This method is intended to be used to replace a node
|
||||||
|
// of a given type in the scene graph with a node of a
|
||||||
|
// different type.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PandaNode::
|
||||||
|
replace_node(PandaNode *other) {
|
||||||
|
nassertv(Thread::get_current_pipeline_stage() == 0);
|
||||||
|
|
||||||
|
if (other == this) {
|
||||||
|
// Trivial.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the other node is not destructed during the
|
||||||
|
// execution of this method.
|
||||||
|
PT(PandaNode) keep_other = other;
|
||||||
|
|
||||||
|
// Get all the important scene graph properties.
|
||||||
|
copy_all_properties(other);
|
||||||
|
|
||||||
|
// Fix up the NodePaths.
|
||||||
|
{
|
||||||
|
MutexHolder holder1(other->_paths_lock);
|
||||||
|
MutexHolder holder2(_paths_lock);
|
||||||
|
Paths::iterator pi;
|
||||||
|
for (pi = other->_paths.begin(); pi != other->_paths.end(); ++pi) {
|
||||||
|
(*pi)->_node = this;
|
||||||
|
_paths.insert(*pi);
|
||||||
|
}
|
||||||
|
other->_paths.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the children.
|
||||||
|
steal_children(other);
|
||||||
|
|
||||||
|
// Switch the parents.
|
||||||
|
Thread *current_thread = Thread::get_current_thread();
|
||||||
|
Parents parents = other->get_parents();
|
||||||
|
for (int i = 0; i < parents.get_num_parents(); ++i) {
|
||||||
|
PandaNode *parent = parents.get_parent(i);
|
||||||
|
parent->replace_child(other, this, current_thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PandaNode::adjust_draw_mask
|
// Function: PandaNode::adjust_draw_mask
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -2282,7 +2444,7 @@ stage_remove_child(PandaNode *child_node, int pipeline_stage,
|
|||||||
// First, look for the parent in the child's up list, to ensure the
|
// First, look for the parent in the child's up list, to ensure the
|
||||||
// child is known.
|
// child is known.
|
||||||
CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
|
CDStageWriter cdata_child(child_node->_cycler, pipeline_stage,
|
||||||
current_thread);
|
current_thread);
|
||||||
int parent_index = child_node->do_find_parent(this, cdata_child);
|
int parent_index = child_node->do_find_parent(this, cdata_child);
|
||||||
if (parent_index < 0) {
|
if (parent_index < 0) {
|
||||||
// Nope, no relation.
|
// Nope, no relation.
|
||||||
@ -2346,6 +2508,11 @@ stage_replace_child(PandaNode *orig_child, PandaNode *new_child,
|
|||||||
// Don't let orig_child be destructed yet.
|
// Don't let orig_child be destructed yet.
|
||||||
PT(PandaNode) keep_orig_child = orig_child;
|
PT(PandaNode) keep_orig_child = orig_child;
|
||||||
|
|
||||||
|
// If we already have new_child as a child, remove it first.
|
||||||
|
if (stage_remove_child(new_child, pipeline_stage, current_thread)) {
|
||||||
|
sever_connection(this, new_child, pipeline_stage, current_thread);
|
||||||
|
}
|
||||||
|
|
||||||
int child_index = do_find_child(orig_child, cdata);
|
int child_index = do_find_child(orig_child, cdata);
|
||||||
if (child_index >= 0) {
|
if (child_index >= 0) {
|
||||||
// The child exists; replace it.
|
// The child exists; replace it.
|
||||||
|
@ -199,6 +199,9 @@ PUBLISHED:
|
|||||||
void copy_tags(PandaNode *other);
|
void copy_tags(PandaNode *other);
|
||||||
void list_tags(ostream &out, const string &separator = "\n") const;
|
void list_tags(ostream &out, const string &separator = "\n") const;
|
||||||
|
|
||||||
|
void copy_all_properties(PandaNode *other);
|
||||||
|
void replace_node(PandaNode *other);
|
||||||
|
|
||||||
INLINE static DrawMask get_overall_bit();
|
INLINE static DrawMask get_overall_bit();
|
||||||
INLINE static DrawMask get_all_camera_mask();
|
INLINE static DrawMask get_all_camera_mask();
|
||||||
INLINE bool is_overall_hidden() const;
|
INLINE bool is_overall_hidden() const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user