mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
bam 6.40: support writing NodePaths, allows instanced lights and clip planes
This commit is contained in:
parent
9b4ce5ec0a
commit
41fad59ae8
@ -694,6 +694,34 @@ pop_back() {
|
||||
_vector.pop_back();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::resize
|
||||
// Access: Public
|
||||
// Description: Resizes the vector to contain n elements. This
|
||||
// should not be used except to populate the vector
|
||||
// for the first time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare, class Vector>
|
||||
INLINE void ordered_vector<Key, Compare, Vector>::
|
||||
resize(SIZE_TYPE n) {
|
||||
TAU_PROFILE("ordered_vector::resize()", " ", TAU_USER);
|
||||
_vector.resize(n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::resize
|
||||
// Access: Public
|
||||
// Description: Resizes the vector to contain n elements. This
|
||||
// should not be used except to populate the vector
|
||||
// for the first time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Key, class Compare, class Vector>
|
||||
INLINE void ordered_vector<Key, Compare, Vector>::
|
||||
resize(SIZE_TYPE n, const VALUE_TYPE &value) {
|
||||
TAU_PROFILE("ordered_vector::resize()", " ", TAU_USER);
|
||||
_vector.resize(n, value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ordered_vector::nci
|
||||
// Access: Private
|
||||
|
@ -219,6 +219,8 @@ public:
|
||||
|
||||
INLINE void push_back(const VALUE_TYPE &key);
|
||||
INLINE void pop_back();
|
||||
INLINE void resize(SIZE_TYPE n);
|
||||
INLINE void resize(SIZE_TYPE n, const VALUE_TYPE &value);
|
||||
|
||||
private:
|
||||
INLINE ITERATOR nci(CONST_ITERATOR i);
|
||||
|
@ -341,7 +341,7 @@ ns_load_texture(const Filename &orig_filename, int primary_file_num_channels,
|
||||
|
||||
if (store_record && tex->is_cacheable()) {
|
||||
// Store the on-disk cache record for next time.
|
||||
record->set_data(tex, tex);
|
||||
record->set_data(tex);
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
@ -473,7 +473,7 @@ ns_load_texture(const Filename &orig_filename,
|
||||
|
||||
if (store_record && tex->is_cacheable()) {
|
||||
// Store the on-disk cache record for next time.
|
||||
record->set_data(tex, tex);
|
||||
record->set_data(tex);
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
@ -585,7 +585,7 @@ ns_load_3d_texture(const Filename &filename_pattern,
|
||||
|
||||
if (store_record && tex->is_cacheable()) {
|
||||
// Store the on-disk cache record for next time.
|
||||
record->set_data(tex, tex);
|
||||
record->set_data(tex);
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
@ -691,7 +691,7 @@ ns_load_2d_texture_array(const Filename &filename_pattern,
|
||||
|
||||
if (store_record && tex->is_cacheable()) {
|
||||
// Store the on-disk cache record for next time.
|
||||
record->set_data(tex, tex);
|
||||
record->set_data(tex);
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
@ -790,7 +790,7 @@ ns_load_cube_map(const Filename &filename_pattern, bool read_mipmaps,
|
||||
|
||||
if (store_record && tex->is_cacheable()) {
|
||||
// Store the on-disk cache record for next time.
|
||||
record->set_data(tex, tex);
|
||||
record->set_data(tex);
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
@ -1166,7 +1166,7 @@ try_load_cache(PT(Texture) &tex, BamCache *cache, const Filename &filename,
|
||||
// from the cache. To keep the cache current,
|
||||
// rewrite it to the cache now, in its newly
|
||||
// compressed form.
|
||||
record->set_data(tex, tex);
|
||||
record->set_data(tex);
|
||||
cache->store(record);
|
||||
compressed_cache_record = true;
|
||||
}
|
||||
|
@ -960,12 +960,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
// write the off planes pointers if any
|
||||
Planes::const_iterator fi;
|
||||
for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
|
||||
NodePath plane = (*fi);
|
||||
|
||||
// Since we can't write out a NodePath, we write out just the
|
||||
// plain PandaNode. The user can use the AttribNodeRegistry on
|
||||
// re-read if there is any ambiguity that needs to be resolved.
|
||||
manager->write_pointer(dg, plane.node());
|
||||
(*fi).write_datagram(manager, dg);
|
||||
}
|
||||
|
||||
// write the number of on planes
|
||||
@ -973,8 +968,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
// write the on planes pointers if any
|
||||
Planes::const_iterator nti;
|
||||
for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) {
|
||||
NodePath plane = (*nti);
|
||||
manager->write_pointer(dg, plane.node());
|
||||
(*nti).write_datagram(manager, dg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -990,38 +984,62 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = RenderAttrib::complete_pointers(p_list, manager);
|
||||
AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
|
||||
|
||||
Planes::iterator ci = _off_planes.begin();
|
||||
while (ci != _off_planes.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
|
||||
// We go through some effort to look up the node in the registry
|
||||
// without creating a NodePath around it first (which would up,
|
||||
// and then down, the reference count, possibly deleting the
|
||||
// node).
|
||||
int ni = areg->find_node(node->get_type(), node->get_name());
|
||||
if (ni != -1) {
|
||||
(*ci) = areg->get_node(ni);
|
||||
} else {
|
||||
(*ci) = NodePath(node);
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
for (int i = 0; i < _off_planes.size(); ++i) {
|
||||
pi += _off_planes[i].complete_pointers(p_list + pi, manager);
|
||||
|
||||
int n = areg->find_node(_off_planes[i]);
|
||||
if (n != -1) {
|
||||
// If it's in the registry, replace it.
|
||||
_off_planes[i] = areg->get_node(n);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _on_planes.size(); ++i) {
|
||||
pi += _on_planes[i].complete_pointers(p_list + pi, manager);
|
||||
|
||||
int n = areg->find_node(_on_planes[i]);
|
||||
if (n != -1) {
|
||||
// If it's in the registry, replace it.
|
||||
_on_planes[i] = areg->get_node(n);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Planes::iterator ci = _off_planes.begin();
|
||||
while (ci != _off_planes.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
|
||||
// We go through some effort to look up the node in the registry
|
||||
// without creating a NodePath around it first (which would up,
|
||||
// and then down, the reference count, possibly deleting the
|
||||
// node).
|
||||
int ni = areg->find_node(node->get_type(), node->get_name());
|
||||
if (ni != -1) {
|
||||
(*ci) = areg->get_node(ni);
|
||||
} else {
|
||||
(*ci) = NodePath(node);
|
||||
}
|
||||
++ci;
|
||||
}
|
||||
|
||||
ci = _on_planes.begin();
|
||||
while (ci != _on_planes.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
|
||||
int ni = areg->find_node(node->get_type(), node->get_name());
|
||||
if (ni != -1) {
|
||||
(*ci) = areg->get_node(ni);
|
||||
} else {
|
||||
(*ci) = NodePath(node);
|
||||
}
|
||||
++ci;
|
||||
}
|
||||
++ci;
|
||||
}
|
||||
|
||||
_off_planes.sort();
|
||||
|
||||
ci = _on_planes.begin();
|
||||
while (ci != _on_planes.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
|
||||
int ni = areg->find_node(node->get_type(), node->get_name());
|
||||
if (ni != -1) {
|
||||
(*ci) = areg->get_node(ni);
|
||||
} else {
|
||||
(*ci) = NodePath(node);
|
||||
}
|
||||
++ci;
|
||||
}
|
||||
_on_planes.sort();
|
||||
|
||||
return pi;
|
||||
@ -1073,31 +1091,28 @@ void ClipPlaneAttrib::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
RenderAttrib::fillin(scan, manager);
|
||||
|
||||
// We cheat a little bit here. In the middle of bam version 4.10,
|
||||
// we completely redefined the bam storage definition for
|
||||
// ClipPlaneAttribs, without bothering to up the bam version or even to
|
||||
// attempt to read the old definition. We get away with this,
|
||||
// knowing that the egg loader doesn't create ClipPlaneAttribs, and
|
||||
// hence no old bam files have the old definition for ClipPlaneAttrib
|
||||
// within them.
|
||||
|
||||
_off_all_planes = scan.get_bool();
|
||||
|
||||
int num_off_planes = scan.get_uint16();
|
||||
|
||||
|
||||
// Push back an empty NodePath for each off Plane for now, until we
|
||||
// get the actual list of pointers later in complete_pointers().
|
||||
_off_planes.reserve(num_off_planes);
|
||||
int i;
|
||||
for (i = 0; i < num_off_planes; i++) {
|
||||
manager->read_pointer(scan);
|
||||
_off_planes.push_back(NodePath());
|
||||
_off_planes.resize(num_off_planes);
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
for (int i = 0; i < num_off_planes; i++) {
|
||||
_off_planes[i].fillin(scan, manager);
|
||||
}
|
||||
} else {
|
||||
manager->read_pointers(scan, num_off_planes);
|
||||
}
|
||||
|
||||
|
||||
int num_on_planes = scan.get_uint16();
|
||||
_on_planes.reserve(num_on_planes);
|
||||
for (i = 0; i < num_on_planes; i++) {
|
||||
manager->read_pointer(scan);
|
||||
_on_planes.push_back(NodePath());
|
||||
_on_planes.resize(num_on_planes);
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
for (int i = 0; i < num_on_planes; i++) {
|
||||
manager->read_pointer(scan);
|
||||
}
|
||||
} else {
|
||||
manager->read_pointers(scan, num_on_planes);
|
||||
}
|
||||
}
|
||||
|
@ -990,12 +990,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
// write the off lights pointers if any
|
||||
Lights::const_iterator fi;
|
||||
for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
|
||||
NodePath light = (*fi);
|
||||
|
||||
// Since we can't write out a NodePath, we write out just the
|
||||
// plain PandaNode. The user can use the AttribNodeRegistry on
|
||||
// re-read if there is any ambiguity that needs to be resolved.
|
||||
manager->write_pointer(dg, light.node());
|
||||
(*fi).write_datagram(manager, dg);
|
||||
}
|
||||
|
||||
// write the number of on lights
|
||||
@ -1003,8 +998,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
// write the on lights pointers if any
|
||||
Lights::const_iterator nti;
|
||||
for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
|
||||
NodePath light = (*nti);
|
||||
manager->write_pointer(dg, light.node());
|
||||
(*nti).write_datagram(manager, dg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1019,22 +1013,33 @@ int LightAttrib::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = RenderAttrib::complete_pointers(p_list, manager);
|
||||
|
||||
BamAuxData *aux = (BamAuxData *)manager->get_aux_data(this, "lights");
|
||||
nassertr(aux != NULL, pi);
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
for (int i = 0; i < _off_lights.size(); ++i) {
|
||||
pi += _off_lights[i].complete_pointers(p_list + pi, manager);
|
||||
}
|
||||
|
||||
int i;
|
||||
aux->_off_list.reserve(aux->_num_off_lights);
|
||||
for (i = 0; i < aux->_num_off_lights; ++i) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
aux->_off_list.push_back(node);
|
||||
}
|
||||
for (int i = 0; i < _on_lights.size(); ++i) {
|
||||
pi += _on_lights[i].complete_pointers(p_list + pi, manager);
|
||||
}
|
||||
|
||||
aux->_on_list.reserve(aux->_num_on_lights);
|
||||
for (i = 0; i < aux->_num_on_lights; ++i) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
aux->_on_list.push_back(node);
|
||||
} else {
|
||||
BamAuxData *aux = (BamAuxData *)manager->get_aux_data(this, "lights");
|
||||
nassertr(aux != NULL, pi);
|
||||
|
||||
int i;
|
||||
aux->_off_list.reserve(aux->_num_off_lights);
|
||||
for (i = 0; i < aux->_num_off_lights; ++i) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
aux->_off_list.push_back(node);
|
||||
}
|
||||
|
||||
aux->_on_list.reserve(aux->_num_on_lights);
|
||||
for (i = 0; i < aux->_num_on_lights; ++i) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
aux->_on_list.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
return pi;
|
||||
@ -1049,43 +1054,68 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void LightAttrib::
|
||||
finalize(BamReader *manager) {
|
||||
// Now it's safe to convert our saved PandaNodes into NodePaths.
|
||||
BamAuxData *aux = (BamAuxData *)manager->get_aux_data(this, "lights");
|
||||
nassertv(aux != NULL);
|
||||
nassertv(aux->_num_off_lights == (int)aux->_off_list.size());
|
||||
nassertv(aux->_num_on_lights == (int)aux->_on_list.size());
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
|
||||
|
||||
AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
|
||||
// Check if any of the nodes we loaded are mentioned in the
|
||||
// AttribNodeRegistry. If so, replace them.
|
||||
for (int i = 0; i < _off_lights.size(); ++i) {
|
||||
int n = areg->find_node(_off_lights[i]);
|
||||
if (n != -1) {
|
||||
// If it's in the registry, replace it.
|
||||
_off_lights[i] = areg->get_node(n);
|
||||
}
|
||||
}
|
||||
|
||||
_off_lights.reserve(aux->_off_list.size());
|
||||
NodeList::iterator ni;
|
||||
for (ni = aux->_off_list.begin(); ni != aux->_off_list.end(); ++ni) {
|
||||
PandaNode *node = (*ni);
|
||||
int n = areg->find_node(node->get_type(), node->get_name());
|
||||
if (n != -1) {
|
||||
// If it's in the registry, add that NodePath.
|
||||
_off_lights.push_back(areg->get_node(n));
|
||||
} else {
|
||||
// Otherwise, add any arbitrary NodePath. Complain if it's
|
||||
// ambiguous.
|
||||
_off_lights.push_back(NodePath(node));
|
||||
for (int i = 0; i < _on_lights.size(); ++i) {
|
||||
int n = areg->find_node(_on_lights[i]);
|
||||
if (n != -1) {
|
||||
// If it's in the registry, replace it.
|
||||
_on_lights[i] = areg->get_node(n);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Now it's safe to convert our saved PandaNodes into NodePaths.
|
||||
BamAuxData *aux = (BamAuxData *)manager->get_aux_data(this, "lights");
|
||||
nassertv(aux != NULL);
|
||||
nassertv(aux->_num_off_lights == (int)aux->_off_list.size());
|
||||
nassertv(aux->_num_on_lights == (int)aux->_on_list.size());
|
||||
|
||||
AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
|
||||
|
||||
_off_lights.reserve(aux->_off_list.size());
|
||||
NodeList::iterator ni;
|
||||
for (ni = aux->_off_list.begin(); ni != aux->_off_list.end(); ++ni) {
|
||||
PandaNode *node = (*ni);
|
||||
int n = areg->find_node(node->get_type(), node->get_name());
|
||||
if (n != -1) {
|
||||
// If it's in the registry, add that NodePath.
|
||||
_off_lights.push_back(areg->get_node(n));
|
||||
} else {
|
||||
// Otherwise, add any arbitrary NodePath. Complain if it's
|
||||
// ambiguous.
|
||||
_off_lights.push_back(NodePath(node));
|
||||
}
|
||||
}
|
||||
|
||||
_on_lights.reserve(aux->_on_list.size());
|
||||
for (ni = aux->_on_list.begin(); ni != aux->_on_list.end(); ++ni) {
|
||||
PandaNode *node = (*ni);
|
||||
int n = areg->find_node(node->get_type(), node->get_name());
|
||||
if (n != -1) {
|
||||
// If it's in the registry, add that NodePath.
|
||||
_on_lights.push_back(areg->get_node(n));
|
||||
} else {
|
||||
// Otherwise, add any arbitrary NodePath. Complain if it's
|
||||
// ambiguous.
|
||||
_on_lights.push_back(NodePath(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that the NodePaths have been filled in, we can sort the list.
|
||||
_off_lights.sort();
|
||||
|
||||
_on_lights.reserve(aux->_on_list.size());
|
||||
for (ni = aux->_on_list.begin(); ni != aux->_on_list.end(); ++ni) {
|
||||
PandaNode *node = (*ni);
|
||||
int n = areg->find_node(node->get_type(), node->get_name());
|
||||
if (n != -1) {
|
||||
// If it's in the registry, add that NodePath.
|
||||
_on_lights.push_back(areg->get_node(n));
|
||||
} else {
|
||||
// Otherwise, add any arbitrary NodePath. Complain if it's
|
||||
// ambiguous.
|
||||
_on_lights.push_back(NodePath(node));
|
||||
}
|
||||
}
|
||||
_on_lights.sort();
|
||||
}
|
||||
|
||||
@ -1124,12 +1154,24 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
|
||||
_off_all_lights = scan.get_bool();
|
||||
|
||||
BamAuxData *aux = new BamAuxData;
|
||||
manager->set_aux_data(this, "lights", aux);
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
_off_lights.resize(scan.get_uint16());
|
||||
for (int i = 0; i < _off_lights.size(); ++i) {
|
||||
_off_lights[i].fillin(scan, manager);
|
||||
}
|
||||
|
||||
aux->_num_off_lights = scan.get_uint16();
|
||||
manager->read_pointers(scan, aux->_num_off_lights);
|
||||
|
||||
aux->_num_on_lights = scan.get_uint16();
|
||||
manager->read_pointers(scan, aux->_num_on_lights);
|
||||
_on_lights.resize(scan.get_uint16());
|
||||
for (int i = 0; i < _on_lights.size(); ++i) {
|
||||
_on_lights[i].fillin(scan, manager);
|
||||
}
|
||||
} else {
|
||||
BamAuxData *aux = new BamAuxData;
|
||||
manager->set_aux_data(this, "lights", aux);
|
||||
|
||||
aux->_num_off_lights = scan.get_uint16();
|
||||
manager->read_pointers(scan, aux->_num_off_lights);
|
||||
|
||||
aux->_num_on_lights = scan.get_uint16();
|
||||
manager->read_pointers(scan, aux->_num_on_lights);
|
||||
}
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ try_load_file(const Filename &pathname, const LoaderOptions &options,
|
||||
if (result != (PandaNode *)NULL) {
|
||||
if (record != (BamCacheRecord *)NULL) {
|
||||
// Store the loaded model in the model cache.
|
||||
record->set_data(result, result);
|
||||
record->set_data(result);
|
||||
cache->store(record);
|
||||
}
|
||||
|
||||
|
@ -6345,6 +6345,10 @@ write_bam_file(const Filename &filename) const {
|
||||
bool okflag = false;
|
||||
|
||||
if (bam_file.open_write(filename)) {
|
||||
// Tell the BamWriter which node is the root node, for making
|
||||
// NodePaths relative to when writing them out to the file.
|
||||
bam_file.get_writer()->set_root_node(node());
|
||||
|
||||
if (bam_file.write_object(node())) {
|
||||
okflag = true;
|
||||
}
|
||||
@ -6368,6 +6372,10 @@ write_bam_stream(ostream &out) const {
|
||||
bool okflag = false;
|
||||
|
||||
if (bam_file.open_write(out)) {
|
||||
// Tell the BamWriter which node is the root node, for making
|
||||
// NodePaths relative to when writing them out to the file.
|
||||
bam_file.get_writer()->set_root_node(node());
|
||||
|
||||
if (bam_file.write_object(node())) {
|
||||
okflag = true;
|
||||
}
|
||||
@ -6434,6 +6442,10 @@ encode_to_bam_stream(string &data, BamWriter *writer) const {
|
||||
num_nodes = 1;
|
||||
}
|
||||
|
||||
// Tell the BamWriter which node is the root node, for making
|
||||
// NodePaths relative to when writing them out to the file.
|
||||
writer->set_root_node(node());
|
||||
|
||||
// Write an initial Datagram to represent the error type and
|
||||
// number of nodes.
|
||||
Datagram dg;
|
||||
@ -7451,3 +7463,125 @@ r_find_all_materials(PandaNode *node, const RenderState *state,
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::write_datagram
|
||||
// Access: Public
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) const {
|
||||
PandaNode *root = DCAST(PandaNode, manager->get_root_node());
|
||||
|
||||
// We have no root node to measure from.
|
||||
if (root == (PandaNode *)NULL || root == node()) {
|
||||
manager->write_pointer(dg, node());
|
||||
manager->write_pointer(dg, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
|
||||
// Record the chain of nodes from the root to this node.
|
||||
pvector<PandaNode *> path;
|
||||
NodePathComponent *comp = _head;
|
||||
while (comp != NULL) {
|
||||
PandaNode *node = comp->get_node();
|
||||
path.push_back(node);
|
||||
|
||||
if (node == root) {
|
||||
break;
|
||||
}
|
||||
|
||||
comp = comp->get_next(pipeline_stage, current_thread);
|
||||
}
|
||||
|
||||
if (comp == (NodePathComponent *)NULL) {
|
||||
// We did not encounter the root node. Not much we can do.
|
||||
manager->write_pointer(dg, node());
|
||||
manager->write_pointer(dg, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write out the nodes in reverse order, for fast reconstructing.
|
||||
for (int i = path.size() - 1; i >= 0; --i) {
|
||||
manager->write_pointer(dg, path[i]);
|
||||
}
|
||||
manager->write_pointer(dg, NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::complete_pointers
|
||||
// Access: Public
|
||||
// Description: Receives an array of pointers, one for each time
|
||||
// manager->read_pointer() was called in fillin().
|
||||
// Returns the number of pointers processed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NodePath::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = 0;
|
||||
PT(PandaNode) node = DCAST(PandaNode, p_list[pi++]);
|
||||
if (node.is_null()) {
|
||||
// An empty NodePath.
|
||||
_head = (NodePathComponent *)NULL;
|
||||
return pi;
|
||||
}
|
||||
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
int pipeline_stage = current_thread->get_pipeline_stage();
|
||||
|
||||
// Take an arbitrary path to the root of the NodePath. This probably
|
||||
// won't be ambiguous, as this is usually the root of the model or scene
|
||||
// we are currently loading.
|
||||
PT(NodePathComponent) comp = node->get_generic_component(false, pipeline_stage, current_thread);
|
||||
nassertd(!comp.is_null()) {
|
||||
while (p_list[pi++]) {}
|
||||
return pi;
|
||||
}
|
||||
|
||||
// Build up the chain of NodePathComponents leading up to this node.
|
||||
while (p_list[pi] != NULL) {
|
||||
PT(PandaNode) node = DCAST(PandaNode, p_list[pi++]);
|
||||
|
||||
LightReMutexHolder holder(node->_paths_lock);
|
||||
|
||||
// First, walk through the list of NodePathComponents we already
|
||||
// have on the child, looking for one that already exists,
|
||||
// referencing the indicated parent component.
|
||||
PandaNode::Paths::const_iterator it;
|
||||
for (it = node->_paths.begin(); it != node->_paths.end(); ++it) {
|
||||
if ((*it)->get_next(pipeline_stage, current_thread) == comp) {
|
||||
// If we already have such a component, use that.
|
||||
comp = (*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (it == node->_paths.end()) {
|
||||
// We don't already have a NodePathComponent referring to this
|
||||
// parent-child relationship. Create a new one. Note that we can't
|
||||
// verify that they are actually related because we may not have
|
||||
// completed the node's pointers yet, so we trust that the .bam is right.
|
||||
comp = new NodePathComponent(node, comp, pipeline_stage, current_thread);
|
||||
node->_paths.insert(comp);
|
||||
}
|
||||
}
|
||||
// One more for the final NULL node.
|
||||
++pi;
|
||||
|
||||
_head = comp;
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new NodePath.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
while(manager->read_pointer(scan)) {};
|
||||
}
|
||||
|
@ -994,6 +994,11 @@ private:
|
||||
static PStatCollector _get_transform_pcollector;
|
||||
static PStatCollector _verify_complete_pcollector;
|
||||
|
||||
public:
|
||||
void write_datagram(BamWriter *manager, Datagram &dg) const;
|
||||
int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -129,6 +129,7 @@ public:
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
friend class PandaNode;
|
||||
friend class NodePath;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const NodePathComponent &comp);
|
||||
|
@ -169,8 +169,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
// write the on occluders pointers if any
|
||||
Occluders::const_iterator nti;
|
||||
for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
|
||||
NodePath occluder = (*nti);
|
||||
manager->write_pointer(dg, occluder.node());
|
||||
(*nti).write_datagram(manager, dg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,19 +185,32 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = RenderEffect::complete_pointers(p_list, manager);
|
||||
AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
|
||||
|
||||
Occluders::iterator ci;
|
||||
ci = _on_occluders.begin();
|
||||
while (ci != _on_occluders.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
for (int i = 0; i < _on_occluders.size(); ++i) {
|
||||
pi += _on_occluders[i].complete_pointers(p_list + pi, manager);
|
||||
|
||||
int ni = areg->find_node(node->get_type(), node->get_name());
|
||||
if (ni != -1) {
|
||||
(*ci) = areg->get_node(ni);
|
||||
} else {
|
||||
(*ci) = NodePath(node);
|
||||
int n = areg->find_node(_on_occluders[i]);
|
||||
if (n != -1) {
|
||||
// If it's in the registry, replace it.
|
||||
_on_occluders[i] = areg->get_node(n);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Occluders::iterator ci;
|
||||
ci = _on_occluders.begin();
|
||||
while (ci != _on_occluders.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
|
||||
int ni = areg->find_node(node->get_type(), node->get_name());
|
||||
if (ni != -1) {
|
||||
(*ci) = areg->get_node(ni);
|
||||
} else {
|
||||
(*ci) = NodePath(node);
|
||||
}
|
||||
++ci;
|
||||
}
|
||||
++ci;
|
||||
}
|
||||
_on_occluders.sort();
|
||||
|
||||
@ -250,13 +262,16 @@ make_from_bam(const FactoryParams ¶ms) {
|
||||
void OccluderEffect::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
RenderEffect::fillin(scan, manager);
|
||||
|
||||
|
||||
// Push back an empty NodePath for each Occluder for now, until we
|
||||
// get the actual list of pointers later in complete_pointers().
|
||||
int num_on_occluders = scan.get_uint16();
|
||||
_on_occluders.reserve(num_on_occluders);
|
||||
for (int i = 0; i < num_on_occluders; i++) {
|
||||
manager->read_pointer(scan);
|
||||
_on_occluders.push_back(NodePath());
|
||||
_on_occluders.resize(num_on_occluders);
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
for (int i = 0; i < num_on_occluders; i++) {
|
||||
_on_occluders[i].fillin(scan, manager);
|
||||
}
|
||||
} else {
|
||||
manager->read_pointers(scan, num_on_occluders);
|
||||
}
|
||||
}
|
||||
|
@ -48,15 +48,7 @@ register_with_read_factory() {
|
||||
void ParamNodePath::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
ParamValueBase::write_datagram(manager, dg);
|
||||
|
||||
// We can't store a NodePath, so we store a pointer to the
|
||||
// underlying node, and pray that there is an unambiguous path
|
||||
// from the root to it.
|
||||
if (_node_path.is_empty()) {
|
||||
manager->write_pointer(dg, NULL);
|
||||
} else {
|
||||
manager->write_pointer(dg, _node_path.node());
|
||||
}
|
||||
_node_path.write_datagram(manager, dg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -69,7 +61,12 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
int ParamNodePath::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = ParamValueBase::complete_pointers(p_list, manager);
|
||||
_node_path = NodePath(DCAST(PandaNode, p_list[pi++]));
|
||||
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
pi += _node_path.complete_pointers(p_list + pi, manager);
|
||||
} else {
|
||||
_node_path = NodePath(DCAST(PandaNode, p_list[pi++]));
|
||||
}
|
||||
|
||||
return pi;
|
||||
}
|
||||
@ -104,5 +101,10 @@ make_from_bam(const FactoryParams ¶ms) {
|
||||
void ParamNodePath::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
ParamValueBase::fillin(scan, manager);
|
||||
manager->read_pointer(scan);
|
||||
|
||||
if (manager->get_file_minor_ver() >= 40) {
|
||||
_node_path.fillin(scan, manager);
|
||||
} else {
|
||||
manager->read_pointer(scan);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ static const unsigned short _bam_major_ver = 6;
|
||||
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
|
||||
|
||||
static const unsigned short _bam_first_minor_ver = 14;
|
||||
static const unsigned short _bam_minor_ver = 39;
|
||||
static const unsigned short _bam_minor_ver = 40;
|
||||
// Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
|
||||
// Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
|
||||
// Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
|
||||
@ -60,5 +60,6 @@ static const unsigned short _bam_minor_ver = 39;
|
||||
// Bumped to minor version 37 on 1/22/15 to add GeomVertexArrayFormat::_divisor.
|
||||
// Bumped to minor version 38 on 4/15/15 to add various Bullet classes.
|
||||
// Bumped to minor version 39 on 1/9/16 to change lights and materials.
|
||||
// Bumped to minor version 40 on 1/11/16 to make NodePaths writable.
|
||||
|
||||
#endif
|
||||
|
@ -258,6 +258,12 @@ store(BamCacheRecord *record) {
|
||||
writer.set_file_texture_mode(BamWriter::BTM_fullpath);
|
||||
}
|
||||
|
||||
// This is necessary for relative NodePaths to work.
|
||||
TypeHandle node_type = type_registry->find_type("PandaNode");
|
||||
if (record->get_data()->is_of_type(node_type)) {
|
||||
writer.set_root_node(record->get_data());
|
||||
}
|
||||
|
||||
if (!writer.write_object(record)) {
|
||||
util_cat.error()
|
||||
<< "Unable to write object to " << temp_pathname << "\n";
|
||||
|
@ -206,6 +206,28 @@ set_data(TypedWritable *ptr, ReferenceCount *ref_ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamCacheRecord::set_data
|
||||
// Access: Published
|
||||
// Description: This variant on set_data() is provided to easily
|
||||
// pass objects deriving from TypedWritable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BamCacheRecord::
|
||||
set_data(TypedWritable *ptr) {
|
||||
set_data(ptr, ptr->as_reference_count());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamCacheRecord::set_data
|
||||
// Access: Published
|
||||
// Description: This variant on set_data() is provided to easily
|
||||
// pass objects deriving from TypedWritableReferenceCount.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BamCacheRecord::
|
||||
set_data(TypedWritableReferenceCount *ptr) {
|
||||
set_data((TypedWritable *)ptr, (ReferenceCount *)ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamCacheRecord::set_data
|
||||
// Access: Published
|
||||
|
@ -72,8 +72,12 @@ PUBLISHED:
|
||||
INLINE TypedWritable *get_data() const;
|
||||
INLINE bool extract_data(TypedWritable *&ptr, ReferenceCount *&ref_ptr);
|
||||
INLINE void set_data(TypedWritable *ptr, ReferenceCount *ref_ptr);
|
||||
INLINE void set_data(TypedWritable *ptr);
|
||||
INLINE void set_data(TypedWritableReferenceCount *ptr);
|
||||
INLINE void set_data(TypedWritable *ptr, int dummy);
|
||||
|
||||
MAKE_PROPERTY2(data, has_data, get_data, set_data, clear_data);
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
|
@ -94,3 +94,27 @@ INLINE void BamWriter::
|
||||
set_file_texture_mode(BamTextureMode file_texture_mode) {
|
||||
_file_texture_mode = file_texture_mode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamWriter::get_root_node
|
||||
// Access: Published
|
||||
// Description: Returns the root node of the part of the scene
|
||||
// graph we are currently writing out. This is used
|
||||
// for determining what to make NodePaths relative to.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypedWritable *BamWriter::
|
||||
get_root_node() const {
|
||||
return _root_node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamWriter::set_root_node
|
||||
// Access: Published
|
||||
// Description: Sets the root node of the part of the scene graph
|
||||
// we are currently writing out. NodePaths written
|
||||
// to this bam file will be relative to this node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BamWriter::
|
||||
set_root_node(TypedWritable *root_node) {
|
||||
_root_node = root_node;
|
||||
}
|
||||
|
@ -90,12 +90,16 @@ PUBLISHED:
|
||||
INLINE BamTextureMode get_file_texture_mode() const;
|
||||
INLINE void set_file_texture_mode(BamTextureMode file_texture_mode);
|
||||
|
||||
INLINE TypedWritable *get_root_node() const;
|
||||
INLINE void set_root_node(TypedWritable *root_node);
|
||||
|
||||
PUBLISHED:
|
||||
MAKE_PROPERTY(target, get_target, set_target);
|
||||
MAKE_PROPERTY(filename, get_filename);
|
||||
MAKE_PROPERTY(file_endian, get_file_endian);
|
||||
MAKE_PROPERTY(file_stdfloat_double, get_file_stdfloat_double);
|
||||
MAKE_PROPERTY(file_texture_mode, get_file_texture_mode);
|
||||
MAKE_PROPERTY(root_node, get_root_node, set_root_node);
|
||||
|
||||
public:
|
||||
// Functions to support classes that write themselves to the Bam.
|
||||
@ -125,6 +129,11 @@ private:
|
||||
bool _file_stdfloat_double;
|
||||
BamTextureMode _file_texture_mode;
|
||||
|
||||
// Stores the PandaNode representing the root of the node hierarchy
|
||||
// we are currently writing, if any, for the purpose of writing NodePaths.
|
||||
// This is a TypedWritable since PandaNode is defined in pgraph.
|
||||
TypedWritable *_root_node;
|
||||
|
||||
// This is the set of all TypeHandles already written.
|
||||
pset<int, int_hash> _types_written;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user