mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
AttribNodeRegistry, ordering in BamReader::complete_pointers()
This commit is contained in:
parent
05e24493fc
commit
c60379d898
@ -64,7 +64,6 @@ ALLOC_DELETED_CHAIN_DEF(GeomVertexArrayDataHandle);
|
||||
GeomVertexArrayData::
|
||||
GeomVertexArrayData() : SimpleLruPage(0) {
|
||||
_contexts = NULL;
|
||||
_endian_reversed = false;
|
||||
|
||||
// Can't put it in the LRU until it has been read in and made valid.
|
||||
}
|
||||
@ -97,7 +96,6 @@ GeomVertexArrayData(const GeomVertexArrayFormat *array_format,
|
||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
||||
|
||||
_contexts = NULL;
|
||||
_endian_reversed = false;
|
||||
|
||||
set_lru_size(0);
|
||||
nassertv(_array_format->is_registered());
|
||||
@ -116,7 +114,6 @@ GeomVertexArrayData(const GeomVertexArrayData ©) :
|
||||
_cycler(copy._cycler)
|
||||
{
|
||||
_contexts = NULL;
|
||||
_endian_reversed = false;
|
||||
|
||||
copy.mark_used_lru();
|
||||
|
||||
@ -511,11 +508,14 @@ finalize(BamReader *manager) {
|
||||
manager->change_pointer(_array_format, new_array_format);
|
||||
_array_format = new_array_format;
|
||||
|
||||
if (_endian_reversed) {
|
||||
// Now is the time to endian-reverse the data.
|
||||
VertexDataBuffer new_buffer(cdata->_buffer.get_size());
|
||||
reverse_data_endianness(new_buffer.get_write_pointer(), cdata->_buffer.get_read_pointer(true), cdata->_buffer.get_size());
|
||||
cdata->_buffer.swap(new_buffer);
|
||||
PT(BamAuxData) aux_data = (BamAuxData *)manager->get_aux_data(this, "");
|
||||
if (aux_data != (BamAuxData *)NULL) {
|
||||
if (aux_data->_endian_reversed) {
|
||||
// Now is the time to endian-reverse the data.
|
||||
VertexDataBuffer new_buffer(cdata->_buffer.get_size());
|
||||
reverse_data_endianness(new_buffer.get_write_pointer(), cdata->_buffer.get_read_pointer(true), cdata->_buffer.get_size());
|
||||
cdata->_buffer.swap(new_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
set_lru_size(cdata->_buffer.get_size());
|
||||
@ -632,13 +632,15 @@ fillin(DatagramIterator &scan, BamReader *manager, void *extra_data) {
|
||||
scan.skip_bytes(size);
|
||||
}
|
||||
|
||||
bool endian_reversed = false;
|
||||
|
||||
if (manager->get_file_endian() != BE_native) {
|
||||
// For non-native endian files, we have to convert the data.
|
||||
|
||||
if (array_data->_array_format == (GeomVertexArrayFormat *)NULL) {
|
||||
// But we can't do that until we've completed the _array_format
|
||||
// pointer, which tells us how to convert it.
|
||||
array_data->_endian_reversed = true;
|
||||
endian_reversed = true;
|
||||
} else {
|
||||
// Since we have the _array_format pointer now, we can reverse
|
||||
// it immediately (and we should, to support threaded CData
|
||||
@ -649,6 +651,12 @@ fillin(DatagramIterator &scan, BamReader *manager, void *extra_data) {
|
||||
}
|
||||
}
|
||||
|
||||
if (endian_reversed) {
|
||||
PT(BamAuxData) aux_data = new BamAuxData;
|
||||
aux_data->_endian_reversed = endian_reversed;
|
||||
manager->set_aux_data(array_data, "", aux_data);
|
||||
}
|
||||
|
||||
array_data->set_lru_size(_buffer.get_size());
|
||||
|
||||
_modified = Geom::get_next_modified();
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "simpleLru.h"
|
||||
#include "vertexDataBuffer.h"
|
||||
#include "config_gobj.h"
|
||||
#include "bamReader.h"
|
||||
|
||||
class PreparedGraphicsObjects;
|
||||
class VertexBufferContext;
|
||||
@ -135,9 +136,13 @@ private:
|
||||
typedef pmap<PreparedGraphicsObjects *, VertexBufferContext *> Contexts;
|
||||
Contexts *_contexts;
|
||||
|
||||
// This is only used when reading from a bam file. It is set true
|
||||
// to indicate the data must be endian-reversed in finalize().
|
||||
bool _endian_reversed;
|
||||
// This data is only needed when reading from a bam file.
|
||||
class BamAuxData : public BamReader::AuxData {
|
||||
public:
|
||||
// set true to indicate the data must be endian-reversed in
|
||||
// finalize().
|
||||
bool _endian_reversed;
|
||||
};
|
||||
|
||||
// This is the data that must be cycled between pipeline stages.
|
||||
class EXPCL_PANDA CData : public CycleData {
|
||||
|
@ -17,6 +17,7 @@
|
||||
alphaTestAttrib.I alphaTestAttrib.h \
|
||||
ambientLight.I ambientLight.h \
|
||||
antialiasAttrib.I antialiasAttrib.h \
|
||||
attribNodeRegistry.I attribNodeRegistry.h \
|
||||
attribSlots.h attribSlots.I \
|
||||
audioVolumeAttrib.I audioVolumeAttrib.h \
|
||||
auxSceneData.I auxSceneData.h \
|
||||
@ -127,6 +128,7 @@
|
||||
alphaTestAttrib.cxx \
|
||||
ambientLight.cxx \
|
||||
antialiasAttrib.cxx \
|
||||
attribNodeRegistry.cxx \
|
||||
attribSlots.cxx \
|
||||
audioVolumeAttrib.cxx \
|
||||
auxSceneData.cxx \
|
||||
@ -232,6 +234,7 @@
|
||||
alphaTestAttrib.I alphaTestAttrib.h \
|
||||
ambientLight.I ambientLight.h \
|
||||
antialiasAttrib.I antialiasAttrib.h \
|
||||
attribNodeRegistry.I attribNodeRegistry.h \
|
||||
attribSlots.h attribSlots.I \
|
||||
audioVolumeAttrib.I audioVolumeAttrib.h \
|
||||
auxSceneData.I auxSceneData.h \
|
||||
|
69
panda/src/pgraph/attribNodeRegistry.I
Normal file
69
panda/src/pgraph/attribNodeRegistry.I
Normal file
@ -0,0 +1,69 @@
|
||||
// Filename: attribNodeRegistry.I
|
||||
// Created by: drose (07Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::get_global_ptr
|
||||
// Access: Published, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AttribNodeRegistry *AttribNodeRegistry::
|
||||
get_global_ptr() {
|
||||
if (_global_ptr == (AttribNodeRegistry *)NULL) {
|
||||
make_global_ptr();
|
||||
}
|
||||
return _global_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::Entry::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AttribNodeRegistry::Entry::
|
||||
Entry(const NodePath &node) :
|
||||
_type(node.node()->get_type()),
|
||||
_name(node.get_name()),
|
||||
_node(node)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::Entry::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AttribNodeRegistry::Entry::
|
||||
Entry(TypeHandle type, const string &name) :
|
||||
_type(type),
|
||||
_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::Entry::operator <
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AttribNodeRegistry::Entry::
|
||||
operator < (const Entry &other) const {
|
||||
if (_type != other._type) {
|
||||
return _type < other._type;
|
||||
}
|
||||
return _name < other._name;
|
||||
}
|
275
panda/src/pgraph/attribNodeRegistry.cxx
Normal file
275
panda/src/pgraph/attribNodeRegistry.cxx
Normal file
@ -0,0 +1,275 @@
|
||||
// Filename: attribNodeRegistry.cxx
|
||||
// Created by: drose (07Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "attribNodeRegistry.h"
|
||||
#include "mutexHolder.h"
|
||||
|
||||
AttribNodeRegistry * TVOLATILE AttribNodeRegistry::_global_ptr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AttribNodeRegistry::
|
||||
AttribNodeRegistry() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::add_node
|
||||
// Access: Published
|
||||
// Description: Adds the indicated NodePath to the registry. The
|
||||
// name and type of the node are noted at the time of
|
||||
// this call; if the name changes later, it will not
|
||||
// update the registry index.
|
||||
//
|
||||
// The NodePath must reference some kind of an attribute
|
||||
// node, such as a LightNode or a PlaneNode. When bam
|
||||
// files that reference an attribute node of the same
|
||||
// type and the same name are loaded, they will quietly
|
||||
// be redirected to reference this NodePath.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AttribNodeRegistry::
|
||||
add_node(const NodePath &attrib_node) {
|
||||
nassertv(!attrib_node.is_empty());
|
||||
MutexHolder holder(_lock);
|
||||
_entries.insert(Entry(attrib_node));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::remove_node
|
||||
// Access: Published
|
||||
// Description: Removes the indicated NodePath from the registry.
|
||||
// The name of the node must not have changed since the
|
||||
// matching call to add_node(), or it will not be
|
||||
// successfully removed.
|
||||
//
|
||||
// Returns true if the NodePath is found and removed,
|
||||
// false if it is not found (for instance, because the
|
||||
// name has changed).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AttribNodeRegistry::
|
||||
remove_node(const NodePath &attrib_node) {
|
||||
nassertr(!attrib_node.is_empty(), false);
|
||||
MutexHolder holder(_lock);
|
||||
Entries::iterator ei = _entries.find(Entry(attrib_node));
|
||||
if (ei != _entries.end()) {
|
||||
_entries.erase(ei);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::lookup_node
|
||||
// Access: Published
|
||||
// Description: Looks up the indicated NodePath in the registry. If
|
||||
// there is a node already in the registry with the
|
||||
// matching name and type, returns that NodePath
|
||||
// instead; otherwise, returns the original NodePath.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NodePath AttribNodeRegistry::
|
||||
lookup_node(const NodePath &orig_node) const {
|
||||
nassertr(!orig_node.is_empty(), orig_node);
|
||||
|
||||
MutexHolder holder(_lock);
|
||||
Entries::const_iterator ei = _entries.find(Entry(orig_node));
|
||||
if (ei != _entries.end()) {
|
||||
return (*ei)._node;
|
||||
}
|
||||
return orig_node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::get_num_nodes
|
||||
// Access: Published
|
||||
// Description: Returns the total number of nodes in the registry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int AttribNodeRegistry::
|
||||
get_num_nodes() const {
|
||||
MutexHolder holder(_lock);
|
||||
return _entries.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::get_node
|
||||
// Access: Published
|
||||
// Description: Returns the nth NodePath recorded in the registry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NodePath AttribNodeRegistry::
|
||||
get_node(int n) const {
|
||||
MutexHolder holder(_lock);
|
||||
nassertr(n >= 0 && n < (int)_entries.size(), NodePath());
|
||||
return _entries[n]._node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::get_node_type
|
||||
// Access: Published
|
||||
// Description: Returns the type of the nth node, as recorded in the
|
||||
// registry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle AttribNodeRegistry::
|
||||
get_node_type(int n) const {
|
||||
MutexHolder holder(_lock);
|
||||
nassertr(n >= 0 && n < (int)_entries.size(), TypeHandle::none());
|
||||
return _entries[n]._type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::get_node_name
|
||||
// Access: Published
|
||||
// Description: Returns the name of the nth node, as recorded in the
|
||||
// registry. This will be the node name as it was at
|
||||
// the time the node was recorded; if the node has
|
||||
// changed names since then, this will still return the
|
||||
// original name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string AttribNodeRegistry::
|
||||
get_node_name(int n) const {
|
||||
MutexHolder holder(_lock);
|
||||
nassertr(n >= 0 && n < (int)_entries.size(), string());
|
||||
return _entries[n]._name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::find_node
|
||||
// Access: Published
|
||||
// Description: Returns the index number of the indicated NodePath in
|
||||
// the registry (assuming its name hasn't changed since
|
||||
// it was recorded in the registry), or -1 if the
|
||||
// NodePath cannot be found (for instance, because its
|
||||
// name has changed).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int AttribNodeRegistry::
|
||||
find_node(const NodePath &attrib_node) const {
|
||||
nassertr(!attrib_node.is_empty(), -1);
|
||||
MutexHolder holder(_lock);
|
||||
Entries::const_iterator ei = _entries.find(Entry(attrib_node));
|
||||
if (ei != _entries.end()) {
|
||||
return ei - _entries.begin();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::find_node
|
||||
// Access: Published
|
||||
// Description: Returns the index number of the node with the
|
||||
// indicated type and name in the registry, or -1 if
|
||||
// there is no such node in the registry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int AttribNodeRegistry::
|
||||
find_node(TypeHandle type, const string &name) const {
|
||||
MutexHolder holder(_lock);
|
||||
Entries::const_iterator ei = _entries.find(Entry(type, name));
|
||||
if (ei != _entries.end()) {
|
||||
return ei - _entries.begin();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::remove_node
|
||||
// Access: Published
|
||||
// Description: Removes the nth node from the registry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AttribNodeRegistry::
|
||||
remove_node(int n) {
|
||||
MutexHolder holder(_lock);
|
||||
nassertv(n >= 0 && n < (int)_entries.size());
|
||||
_entries.erase(_entries.begin() + n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::clear
|
||||
// Access: Published
|
||||
// Description: Removes all nodes from the registry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AttribNodeRegistry::
|
||||
clear() {
|
||||
MutexHolder holder(_lock);
|
||||
_entries.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::output
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AttribNodeRegistry::
|
||||
output(ostream &out) const {
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
typedef pmap<TypeHandle, int> Counts;
|
||||
Counts counts;
|
||||
|
||||
Entries::const_iterator ei;
|
||||
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
|
||||
TypeHandle type = (*ei)._type;
|
||||
Counts::iterator ci = counts.insert(Counts::value_type(type, 0)).first;
|
||||
++((*ci).second);
|
||||
}
|
||||
|
||||
out << _entries.size() << " entries";
|
||||
|
||||
if (!counts.empty()) {
|
||||
Counts::iterator ci = counts.begin();
|
||||
out << " (" << (*ci).first << ":" << (*ci).second;
|
||||
++ci;
|
||||
while (ci != counts.end()) {
|
||||
out << ", " << (*ci).first << ":" << (*ci).second;
|
||||
++ci;
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::write
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AttribNodeRegistry::
|
||||
write(ostream &out) const {
|
||||
MutexHolder holder(_lock);
|
||||
|
||||
Entries::const_iterator ei;
|
||||
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
|
||||
const Entry &entry = (*ei);
|
||||
out << entry._type << ", \"" << entry._name << "\": " << entry._node
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AttribNodeRegistry::make_global_ptr
|
||||
// Access: Private, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AttribNodeRegistry::
|
||||
make_global_ptr() {
|
||||
AttribNodeRegistry *ptr = new AttribNodeRegistry;
|
||||
void *result = AtomicAdjust::compare_and_exchange_ptr
|
||||
((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr);
|
||||
if (result != NULL) {
|
||||
// Someone else got there first.
|
||||
delete ptr;
|
||||
}
|
||||
assert(_global_ptr != (AttribNodeRegistry *)NULL);
|
||||
}
|
91
panda/src/pgraph/attribNodeRegistry.h
Normal file
91
panda/src/pgraph/attribNodeRegistry.h
Normal file
@ -0,0 +1,91 @@
|
||||
// Filename: attribNodeRegistry.h
|
||||
// Created by: drose (07Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ATTRIBNODEREGISTRY_H
|
||||
#define ATTRIBNODEREGISTRY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "nodePath.h"
|
||||
#include "ordered_vector.h"
|
||||
#include "pmutex.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AttribNodeRegistry
|
||||
// Description : This global object records NodePaths that are
|
||||
// referenced by scene graph attribs, such as
|
||||
// ClipPlaneAttribs and LightAttribs.
|
||||
//
|
||||
// Its primary purpose is to unify attribs that are
|
||||
// loaded in from bam files. Attrib nodes are
|
||||
// identified by name and type; when a bam file that
|
||||
// contains references to some attrib nodes is loaded,
|
||||
// those nodes are first looked up here in the
|
||||
// AttribNodeRegistry. If there is a match (by name and
|
||||
// node type), the identified node is used instead of
|
||||
// the node referenced within the bam file itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA AttribNodeRegistry {
|
||||
protected:
|
||||
AttribNodeRegistry();
|
||||
|
||||
PUBLISHED:
|
||||
void add_node(const NodePath &attrib_node);
|
||||
bool remove_node(const NodePath &attrib_node);
|
||||
NodePath lookup_node(const NodePath &orig_node) const;
|
||||
|
||||
int get_num_nodes() const;
|
||||
NodePath get_node(int n) const;
|
||||
TypeHandle get_node_type(int n) const;
|
||||
string get_node_name(int n) const;
|
||||
|
||||
int find_node(const NodePath &attrib_node) const;
|
||||
int find_node(TypeHandle type, const string &name) const;
|
||||
void remove_node(int n);
|
||||
void clear();
|
||||
|
||||
void output(ostream &out) const;
|
||||
void write(ostream &out) const;
|
||||
|
||||
INLINE static AttribNodeRegistry *get_global_ptr();
|
||||
|
||||
private:
|
||||
static void make_global_ptr();
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
INLINE Entry(const NodePath &node);
|
||||
INLINE Entry(TypeHandle type, const string &name);
|
||||
INLINE bool operator < (const Entry &other) const;
|
||||
|
||||
TypeHandle _type;
|
||||
string _name;
|
||||
NodePath _node;
|
||||
};
|
||||
|
||||
typedef ov_set<Entry> Entries;
|
||||
Entries _entries;
|
||||
|
||||
Mutex _lock;
|
||||
|
||||
static AttribNodeRegistry * TVOLATILE _global_ptr;
|
||||
};
|
||||
|
||||
#include "attribNodeRegistry.I"
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "config_pgraph.h"
|
||||
#include "attribNodeRegistry.h"
|
||||
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::_empty_attrib;
|
||||
CPT(RenderAttrib) ClipPlaneAttrib::_all_off_attrib;
|
||||
@ -937,7 +938,9 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
|
||||
NodePath plane = (*fi);
|
||||
|
||||
// Whoops, we don't have a way to write out a NodePath right now.
|
||||
// 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());
|
||||
}
|
||||
|
||||
@ -961,28 +964,46 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
int ClipPlaneAttrib::
|
||||
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);
|
||||
NodePath np(node);
|
||||
(*ci) = np;
|
||||
(*ci) = areg->lookup_node(np);
|
||||
++ci;
|
||||
}
|
||||
_off_planes.sort();
|
||||
|
||||
ci = _on_planes.begin();
|
||||
while (ci != _on_planes.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
NodePath np(node);
|
||||
(*ci) = np;
|
||||
(*ci) = areg->lookup_node(np);
|
||||
++ci;
|
||||
}
|
||||
_on_planes.sort();
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClipPlaneAttrib::require_fully_complete
|
||||
// Access: Public, Virtual
|
||||
// Description: Some objects require all of their nested pointers to
|
||||
// have been completed before the objects themselves can
|
||||
// be completed. If this is the case, override this
|
||||
// method to return true, and be careful with circular
|
||||
// references (which would make the object unreadable
|
||||
// from a bam file).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ClipPlaneAttrib::
|
||||
require_fully_complete() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ClipPlaneAttrib::make_from_bam
|
||||
// Access: Protected, Static
|
||||
@ -1026,19 +1047,19 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
|
||||
int num_off_planes = scan.get_uint16();
|
||||
|
||||
// Push back a NULL pointer for each off Plane for now, until
|
||||
// we get the actual list of pointers later in complete_pointers().
|
||||
// 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(NULL);
|
||||
_off_planes.push_back(NodePath());
|
||||
}
|
||||
|
||||
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(NULL);
|
||||
_on_planes.push_back(NodePath());
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual bool require_fully_complete() const;
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "config_pgraph.h"
|
||||
#include "attribNodeRegistry.h"
|
||||
|
||||
CPT(RenderAttrib) LightAttrib::_empty_attrib;
|
||||
CPT(RenderAttrib) LightAttrib::_all_off_attrib;
|
||||
@ -916,7 +917,9 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
|
||||
NodePath light = (*fi);
|
||||
|
||||
// Whoops, we don't have a way to write out a NodePath right now.
|
||||
// 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());
|
||||
}
|
||||
|
||||
@ -940,28 +943,46 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
int LightAttrib::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = RenderAttrib::complete_pointers(p_list, manager);
|
||||
AttribNodeRegistry *areg = AttribNodeRegistry::get_global_ptr();
|
||||
|
||||
Lights::iterator ci = _off_lights.begin();
|
||||
while (ci != _off_lights.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
NodePath np(node);
|
||||
(*ci) = np;
|
||||
(*ci) = areg->lookup_node(np);
|
||||
++ci;
|
||||
}
|
||||
_off_lights.sort();
|
||||
|
||||
ci = _on_lights.begin();
|
||||
while (ci != _on_lights.end()) {
|
||||
PandaNode *node;
|
||||
DCAST_INTO_R(node, p_list[pi++], pi);
|
||||
NodePath np(node);
|
||||
(*ci) = np;
|
||||
(*ci) = areg->lookup_node(np);
|
||||
++ci;
|
||||
}
|
||||
_on_lights.sort();
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightAttrib::require_fully_complete
|
||||
// Access: Public, Virtual
|
||||
// Description: Some objects require all of their nested pointers to
|
||||
// have been completed before the objects themselves can
|
||||
// be completed. If this is the case, override this
|
||||
// method to return true, and be careful with circular
|
||||
// references (which would make the object unreadable
|
||||
// from a bam file).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool LightAttrib::
|
||||
require_fully_complete() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: LightAttrib::make_from_bam
|
||||
// Access: Protected, Static
|
||||
@ -1005,19 +1026,19 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
|
||||
int num_off_lights = scan.get_uint16();
|
||||
|
||||
// Push back a NULL pointer for each off Light for now, until
|
||||
// we get the actual list of pointers later in complete_pointers().
|
||||
// Push back an empty NodePath for each off Light for now, until we
|
||||
// get the actual list of pointers later in complete_pointers().
|
||||
_off_lights.reserve(num_off_lights);
|
||||
int i;
|
||||
for (i = 0; i < num_off_lights; i++) {
|
||||
manager->read_pointer(scan);
|
||||
_off_lights.push_back(NULL);
|
||||
_off_lights.push_back(NodePath());
|
||||
}
|
||||
|
||||
int num_on_lights = scan.get_uint16();
|
||||
_on_lights.reserve(num_on_lights);
|
||||
for (i = 0; i < num_on_lights; i++) {
|
||||
manager->read_pointer(scan);
|
||||
_on_lights.push_back(NULL);
|
||||
_on_lights.push_back(NodePath());
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +125,7 @@ public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
|
||||
virtual bool require_fully_complete() const;
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "accumulatedAttribs.cxx"
|
||||
#include "ambientLight.cxx"
|
||||
#include "antialiasAttrib.cxx"
|
||||
#include "attribNodeRegistry.cxx"
|
||||
#include "audioVolumeAttrib.cxx"
|
||||
#include "auxSceneData.cxx"
|
||||
#include "attribSlots.cxx"
|
||||
|
@ -173,6 +173,15 @@ get_datagram(Datagram &datagram) {
|
||||
return _source->get_datagram(datagram);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::AuxData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BamReader::AuxData::
|
||||
AuxData() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: parse_params
|
||||
// Access: Private, Static
|
||||
|
@ -135,20 +135,44 @@ init() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::set_aux_data
|
||||
// Access: Public
|
||||
// Description: Associates an arbitrary pointer to the bam reader
|
||||
// with the indicated name. The name is an arbitrary
|
||||
// user-defined key to access the data later. This data
|
||||
// is typically queried by objects reading themselves
|
||||
// from the bam file; this is intended to provide some
|
||||
// context information to objects in the bam file. Set
|
||||
// the aux data to NULL to remove it.
|
||||
// Description: Associates an arbitrary block of data with the
|
||||
// indicated object (or NULL), and the indicated name.
|
||||
//
|
||||
// This is intended to provide a place for temporary
|
||||
// storage for objects reading themselves from the bam
|
||||
// file. To use it, inherit from BamReader::AuxData and
|
||||
// store whatever data you like there. Then associate
|
||||
// your AuxData with the object as it is being read with
|
||||
// set_aux_data(). You may later set the aux data to
|
||||
// NULL to remove it; or it will automatically be
|
||||
// removed (and deleted) after finalize() is called for
|
||||
// the object in question.
|
||||
//
|
||||
// If the TypedWritable pointer is NULL, the the aux
|
||||
// data is stored globally for the BamReader in general.
|
||||
// This pointer is available to any bam objects, and
|
||||
// will not be automatically removed until the BamReader
|
||||
// itself destructs.
|
||||
//
|
||||
// In either case, the name is just an arbitrary
|
||||
// user-defined key. If there is already a data pointer
|
||||
// stored for the obj/name pair, that data pointer will
|
||||
// be replaced (and deleted).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BamReader::
|
||||
set_aux_data(const string &name, void *data) {
|
||||
set_aux_data(TypedWritable *obj, const string &name, BamReader::AuxData *data) {
|
||||
if (data == (void *)NULL) {
|
||||
_aux_data.erase(name);
|
||||
AuxDataTable::iterator ti = _aux_data.find(obj);
|
||||
if (ti != _aux_data.end()) {
|
||||
AuxDataNames &names = (*ti).second;
|
||||
names.erase(name);
|
||||
if (names.empty()) {
|
||||
_aux_data.erase(ti);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
_aux_data[name] = data;
|
||||
_aux_data[obj][name] = data;
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,15 +181,19 @@ set_aux_data(const string &name, void *data) {
|
||||
// Access: Public
|
||||
// Description: Returns the pointer previously associated with the
|
||||
// bam reader by a previous call to set_aux_data(), or
|
||||
// NULL if the data with the indicated key has not been
|
||||
// set.
|
||||
// NULL if data with the indicated key has not been set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *BamReader::
|
||||
get_aux_data(const string &name) const {
|
||||
AuxData::const_iterator di = _aux_data.find(name);
|
||||
if (di != _aux_data.end()) {
|
||||
return (*di).second;
|
||||
BamReader::AuxData *BamReader::
|
||||
get_aux_data(TypedWritable *obj, const string &name) const {
|
||||
AuxDataTable::const_iterator ti = _aux_data.find(obj);
|
||||
if (ti != _aux_data.end()) {
|
||||
const AuxDataNames &names = (*ti).second;
|
||||
AuxDataNames::const_iterator ni = names.find(name);
|
||||
if (ni != names.end()) {
|
||||
return (*ni).second;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -272,8 +300,31 @@ resolve() {
|
||||
do {
|
||||
all_completed = true;
|
||||
any_completed_this_pass = false;
|
||||
|
||||
// Walk through all the objects that still have outstanding pointers.
|
||||
|
||||
// First do the PipelineCycler objects.
|
||||
CyclerPointers::iterator ci;
|
||||
ci = _cycler_pointers.begin();
|
||||
while (ci != _cycler_pointers.end()) {
|
||||
PipelineCyclerBase *cycler = (*ci).first;
|
||||
const vector_int &pointer_ids = (*ci).second;
|
||||
|
||||
if (resolve_cycler_pointers(cycler, pointer_ids)) {
|
||||
// Now remove this cycler from the list of things that need
|
||||
// completion. We have to be a bit careful when deleting things
|
||||
// from the STL container while we are traversing it.
|
||||
CyclerPointers::iterator old = ci;
|
||||
++ci;
|
||||
_cycler_pointers.erase(old);
|
||||
any_completed_this_pass = true;
|
||||
|
||||
} else {
|
||||
// Couldn't complete this cycler yet; it'll wait for next time.
|
||||
++ci;
|
||||
all_completed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now do the main objects.
|
||||
ObjectPointers::iterator oi;
|
||||
oi = _object_pointers.begin();
|
||||
while (oi != _object_pointers.end()) {
|
||||
@ -320,32 +371,9 @@ resolve() {
|
||||
all_completed = false;
|
||||
}
|
||||
}
|
||||
|
||||
} while (!all_completed && any_completed_this_pass);
|
||||
|
||||
// Also do the PipelineCycler objects. We only need to try these
|
||||
// once, since they don't depend on each other.
|
||||
|
||||
CyclerPointers::iterator ci;
|
||||
ci = _cycler_pointers.begin();
|
||||
while (ci != _cycler_pointers.end()) {
|
||||
PipelineCyclerBase *cycler = (*ci).first;
|
||||
const vector_int &pointer_ids = (*ci).second;
|
||||
|
||||
if (resolve_cycler_pointers(cycler, pointer_ids)) {
|
||||
// Now remove this cycler from the list of things that need
|
||||
// completion. We have to be a bit careful when deleting things
|
||||
// from the STL container while we are traversing it.
|
||||
CyclerPointers::iterator old = ci;
|
||||
++ci;
|
||||
_cycler_pointers.erase(old);
|
||||
|
||||
} else {
|
||||
// Couldn't complete this cycler yet; it'll wait for next time.
|
||||
++ci;
|
||||
all_completed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_completed) {
|
||||
finalize();
|
||||
} else {
|
||||
@ -396,6 +424,12 @@ change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_point
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "change_pointer(" << (void *)orig_pointer << ", "
|
||||
<< (void *)new_pointer << ") (" << new_pointer->get_type() << ")\n";
|
||||
}
|
||||
|
||||
const vector_int &old_refs = (*ci).second;
|
||||
vector_int &new_refs = _created_objs_by_pointer[new_pointer];
|
||||
|
||||
@ -638,10 +672,14 @@ read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BamReader::
|
||||
register_finalize(TypedWritable *whom) {
|
||||
if (whom == TypedWritable::Null) {
|
||||
bam_cat.error() << "Can't register a null pointer to finalize!" << endl;
|
||||
return;
|
||||
nassertv(whom != (TypedWritable *)NULL);
|
||||
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "register_finalize(" << (void *)whom << ") (" << whom->get_type()
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
_finalize_list.insert(whom);
|
||||
}
|
||||
|
||||
@ -698,6 +736,11 @@ finalize_now(TypedWritable *whom) {
|
||||
Finalize::iterator fi = _finalize_list.find(whom);
|
||||
if (fi != _finalize_list.end()) {
|
||||
_finalize_list.erase(fi);
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "finalizing " << (void *)whom << " (" << whom->get_type()
|
||||
<< ")\n";
|
||||
}
|
||||
whom->finalize(this);
|
||||
}
|
||||
}
|
||||
@ -994,7 +1037,7 @@ p_read_object() {
|
||||
} else {
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "Read a " << object->get_type() << "\n";
|
||||
<< "Read a " << object->get_type() << ": " << (void *)object << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1018,12 +1061,17 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
|
||||
// given object until we have *all* outstanding pointers for
|
||||
// that object.
|
||||
bool is_complete = true;
|
||||
|
||||
// Some objects further require all of their nested objects to have
|
||||
// been completed (i.e. complete_pointers has been called on each
|
||||
// nested object) before they can themselves be completed.
|
||||
bool require_fully_complete = object->require_fully_complete();
|
||||
|
||||
vector_typedWritable references;
|
||||
|
||||
|
||||
vector_int::const_iterator pi;
|
||||
for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
|
||||
int child_id = (*pi);
|
||||
|
||||
if (child_id == 0) {
|
||||
// A NULL pointer is a NULL pointer.
|
||||
references.push_back((TypedWritable *)NULL);
|
||||
@ -1042,8 +1090,15 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
|
||||
is_complete = false;
|
||||
|
||||
} else {
|
||||
// Yes, it's ready.
|
||||
references.push_back(child_obj._ptr);
|
||||
if (require_fully_complete &&
|
||||
_object_pointers.find(child_id) != _object_pointers.end()) {
|
||||
// It's not yet complete itself.
|
||||
is_complete = false;
|
||||
|
||||
} else {
|
||||
// Yes, it's ready.
|
||||
references.push_back(child_obj._ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1051,6 +1106,14 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
|
||||
|
||||
if (is_complete) {
|
||||
// Okay, here's the complete list of pointers for you!
|
||||
nassertr(references.size() == pointer_ids.size(), false);
|
||||
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "complete_pointers for " << (void *)object
|
||||
<< " (" << object->get_type() << "), " << references.size()
|
||||
<< " pointers.\n";
|
||||
}
|
||||
int num_completed = object->complete_pointers(&references[0], this);
|
||||
if (num_completed != (int)references.size()) {
|
||||
bam_cat.warning()
|
||||
@ -1058,6 +1121,13 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
|
||||
<< " of " << references.size() << " pointers.\n";
|
||||
}
|
||||
return true;
|
||||
|
||||
} else {
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "not ready: complete_pointers for " << (void *)object
|
||||
<< " (" << object->get_type() << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -1115,6 +1185,11 @@ resolve_cycler_pointers(PipelineCyclerBase *cycler,
|
||||
if (is_complete) {
|
||||
// Okay, here's the complete list of pointers for you!
|
||||
CycleData *cdata = cycler->write(Thread::get_current_thread());
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "complete_pointers for CycleData object " << (void *)cdata
|
||||
<< "\n";
|
||||
}
|
||||
int num_completed = cdata->complete_pointers(&references[0], this);
|
||||
cycler->release_write(cdata);
|
||||
if (num_completed != (int)references.size()) {
|
||||
@ -1147,8 +1222,42 @@ finalize() {
|
||||
TypedWritable *object = (*fi);
|
||||
nassertv(object != (TypedWritable *)NULL);
|
||||
_finalize_list.erase(fi);
|
||||
if (bam_cat.is_spam()) {
|
||||
bam_cat.spam()
|
||||
<< "finalizing " << (void *)object << " (" << object->get_type()
|
||||
<< ")\n";
|
||||
}
|
||||
object->finalize(this);
|
||||
|
||||
_aux_data.erase(object);
|
||||
fi = _finalize_list.begin();
|
||||
}
|
||||
|
||||
// Now clear the aux data of all objects, except the NULL object.
|
||||
if (!_aux_data.empty()) {
|
||||
AuxDataTable::iterator ti = _aux_data.find((TypedWritable *)NULL);
|
||||
|
||||
if (ti != _aux_data.end()) {
|
||||
if (_aux_data.size() > 1) {
|
||||
// Move the NULL data to the new table; remove the rest.
|
||||
AuxDataTable new_aux_data;
|
||||
AuxDataTable::iterator nti =
|
||||
new_aux_data.insert(AuxDataTable::value_type(NULL, AuxDataNames())).first;
|
||||
(*nti).second.swap((*ti).second);
|
||||
_aux_data.swap(new_aux_data);
|
||||
}
|
||||
} else {
|
||||
// There's no NULL data; clear the whole table.
|
||||
_aux_data.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::AuxData::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BamReader::AuxData::
|
||||
~AuxData() {
|
||||
}
|
||||
|
||||
|
@ -98,8 +98,10 @@ public:
|
||||
|
||||
bool init();
|
||||
|
||||
void set_aux_data(const string &name, void *data);
|
||||
void *get_aux_data(const string &name) const;
|
||||
class AuxData;
|
||||
void set_aux_data(TypedWritable *obj, const string &name, AuxData *data);
|
||||
AuxData *get_aux_data(TypedWritable *obj, const string &name) const;
|
||||
|
||||
INLINE const Filename &get_filename() const;
|
||||
|
||||
TypedWritable *read_object();
|
||||
@ -115,10 +117,6 @@ public:
|
||||
INLINE int get_current_major_ver() const;
|
||||
INLINE int get_current_minor_ver() const;
|
||||
|
||||
// This special TypeHandle is written to the bam file to indicate an
|
||||
// object id is no longer needed.
|
||||
static TypeHandle _remove_flag;
|
||||
|
||||
public:
|
||||
// Functions to support classes that read themselves from the Bam.
|
||||
|
||||
@ -161,6 +159,20 @@ private:
|
||||
|
||||
INLINE bool get_datagram(Datagram &datagram);
|
||||
|
||||
public:
|
||||
// This special TypeHandle is written to the bam file to indicate an
|
||||
// object id is no longer needed.
|
||||
static TypeHandle _remove_flag;
|
||||
|
||||
// Inherit from this class to piggyback additional temporary data on
|
||||
// the bamReader (via set_aux_data() and get_aux_data()) for any
|
||||
// particular objects during the bam reading process.
|
||||
class AuxData : public ReferenceCount {
|
||||
public:
|
||||
INLINE AuxData();
|
||||
virtual ~AuxData();
|
||||
};
|
||||
|
||||
private:
|
||||
static WritableFactory *_factory;
|
||||
|
||||
@ -234,8 +246,9 @@ private:
|
||||
static NewTypes _new_types;
|
||||
|
||||
// This is used in support of set_aux_data() and get_aux_data().
|
||||
typedef phash_map<string, void *, string_hash> AuxData;
|
||||
AuxData _aux_data;
|
||||
typedef pmap<string, PT(AuxData)> AuxDataNames;
|
||||
typedef phash_map<TypedWritable *, AuxDataNames, pointer_hash> AuxDataTable;
|
||||
AuxDataTable _aux_data;
|
||||
|
||||
int _file_major, _file_minor;
|
||||
BamEndian _file_endian;
|
||||
|
@ -85,7 +85,21 @@ int TypedWritable::
|
||||
complete_pointers(TypedWritable **, BamReader *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypedWritable::require_fully_complete
|
||||
// Access: Public, Virtual
|
||||
// Description: Some objects require all of their nested pointers to
|
||||
// have been completed before the objects themselves can
|
||||
// be completed. If this is the case, override this
|
||||
// method to return true, and be careful with circular
|
||||
// references (which would make the object unreadable
|
||||
// from a bam file).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TypedWritable::
|
||||
require_fully_complete() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypedWritable::finalize
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
virtual void write_datagram(BamWriter *, Datagram &);
|
||||
|
||||
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager);
|
||||
virtual bool require_fully_complete() const;
|
||||
|
||||
virtual void finalize(BamReader *manager);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user