15 #include "pandabase.h" 18 #include "typedWritable.h" 19 #include "config_util.h" 21 #include "bamWriter.h" 22 #include "bamReader.h" 23 #include "lightMutexHolder.h" 37 _next_boc = BOC_adjunct;
43 _long_object_id =
false;
47 _file_endian = bam_endian;
48 _file_stdfloat_double = bam_stdfloat_double;
49 _file_texture_mode = bam_texture_mode;
61 StateMap::iterator si;
62 for (si = _state_map.begin(); si != _state_map.end(); ++si) {
64 object->remove_bam_writer(
this);
77 if (_target != NULL) {
82 if (_needs_init && _target != NULL) {
99 nassertr(_target != NULL,
false);
100 nassertr(_needs_init,
false);
106 _long_object_id =
false;
108 _long_pta_id =
false;
110 _file_endian = bam_endian;
111 _file_texture_mode = bam_texture_mode;
119 header.
add_bool(_file_stdfloat_double);
121 if (!_target->put_datagram(header)) {
123 <<
"Unable to write Bam header.\n";
153 nassertr(_target != NULL,
false);
160 if (!_freed_object_ids.empty()) {
164 FreedObjectIds::iterator fi;
165 for (fi = _freed_object_ids.begin(); fi != _freed_object_ids.end(); ++fi) {
166 write_object_id(dg, (*fi));
168 _freed_object_ids.clear();
170 if (!_target->put_datagram(dg)) {
172 <<
"Unable to write data to output.\n";
177 nassertr(_object_queue.empty(),
false);
178 _next_boc = BOC_push;
180 int object_id = enqueue_object(
object);
181 nassertr(object_id != 0,
false);
182 if (!flush_queue()) {
187 if (_next_boc != BOC_push) {
190 if (!_target->put_datagram(dg)) {
192 <<
"Unable to write data to output.\n";
209 StateMap::const_iterator si = _state_map.find(
object);
210 return (si != _state_map.end());
221 nassertv(_target != NULL);
238 StateMap::iterator si = _state_map.find(
object);
239 if (si == _state_map.end()) {
241 enqueue_object(
object);
243 }
else if ((*si).second._written_seq.is_initial()) {
245 enqueue_object(
object);
247 }
else if ((*si).second._written_seq == _writing_seq) {
253 enqueue_object(
object);
257 (*si).second._written_seq = _writing_seq;
283 write_object_id(packet, 0);
286 StateMap::iterator si = _state_map.find(
object);
287 if (si == _state_map.end()) {
290 int object_id = enqueue_object(
object);
291 write_object_id(packet, object_id);
297 int object_id = (*si).second._object_id;
298 bool already_written = !(*si).second._written_seq.is_initial();
299 if ((*si).second._written_seq != _writing_seq &&
303 already_written =
false;
306 write_object_id(packet, object_id);
308 if (!already_written) {
310 enqueue_object(
object);
334 if (!_target->put_datagram(dg)) {
336 <<
"Unable to write data to output.\n";
344 <<
"Unable to write file data to output.\n";
368 if (!_target->put_datagram(dg)) {
370 <<
"Unable to write data to output.\n";
378 <<
"Unable to write file data to output.\n";
438 if (ptr == (
const void *)NULL) {
441 write_pta_id(packet, 0);
454 PTAMap::iterator pi = _pta_map.find(ptr);
455 if (pi == _pta_map.end()) {
457 int pta_id = _next_pta_id;
460 bool inserted = _pta_map.insert(PTAMap::value_type(ptr, pta_id)).second;
461 nassertr(inserted,
false);
463 write_pta_id(packet, pta_id);
471 int pta_id = (*pi).second;
472 write_pta_id(packet, pta_id);
500 nassertv(index <= 0xffff);
505 bool inserted = _types_written.insert(index).second;
516 nassertv(num_parent_classes <= 255);
518 for (
int i = 0; i < num_parent_classes; i++) {
537 StateMap::iterator si = _state_map.find(
object);
538 if (si != _state_map.end()) {
541 nassertv(!(*si).second._written_seq.is_initial());
543 int object_id = (*si).second._object_id;
544 _freed_object_ids.push_back(object_id);
546 _state_map.erase(si);
556 write_object_id(
Datagram &dg,
int object_id) {
557 if (_long_object_id) {
564 if (object_id == 0xffff) {
565 _long_object_id =
true;
576 write_pta_id(
Datagram &dg,
int pta_id) {
584 if (pta_id == 0xffff) {
603 nassertr(
object != TypedWritable::Null, 0);
609 if (!object->
is_of_type(TypedWritable::get_class_type())) {
611 <<
"Type " <<
object->get_type()
612 <<
" does not indicate inheritance from TypedWritable.\n" 613 <<
"(this is almost certainly an oversight in " <<
object->get_type()
614 <<
"::init_type().)\n";
622 StateMap::iterator si = _state_map.find(
object);
623 if (si == _state_map.end()) {
626 object_id = _next_object_id;
629 _state_map.insert(StateMap::value_type(
object, StoreState(_next_object_id))).second;
630 nassertr(inserted,
false);
639 object_id = (*si).second._object_id;
642 _object_queue.push_back(
object);
656 nassertr(_target != NULL,
false);
658 while (!_object_queue.empty()) {
660 _object_queue.pop_front();
663 StateMap::iterator si = _state_map.find(
object);
664 nassertr(si != _state_map.end(),
false);
666 if ((*si).second._written_seq == _writing_seq) {
671 int object_id = (*si).second._object_id;
672 bool already_written = !(*si).second._written_seq.is_initial();
676 already_written =
false;
682 _next_boc = BOC_adjunct;
684 if (!already_written) {
701 <<
"Objects of type " << type <<
" cannot be read; bam file is invalid.\n";
702 }
else if (registered_type != type) {
704 <<
"Writing " << registered_type <<
" instead of " << type <<
"\n";
705 type = registered_type;
707 }
else if (util_cat.is_debug()) {
709 <<
"Writing " << type <<
" object id " << object_id
714 write_object_id(dg, object_id);
724 (*si).second._written_seq = _writing_seq;
725 (*si).second._modified =
object->get_bam_modified();
734 write_object_id(dg, object_id);
741 if (!_target->put_datagram(dg)) {
743 <<
"Unable to write data to output.\n";
void add_uint8(PN_uint8 value)
Adds an unsigned 8-bit integer to the datagram.
void add_string(const string &str)
Adds a variable-length string to the datagram.
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
bool has_object(const TypedWritable *obj) const
Returns true if the object has previously been written (or at least requested to be written) to the b...
UpdateSeq get_bam_modified() const
Returns the current bam_modified counter.
A single page of data maintained by a PipelineCycler.
Base class for objects that can be written to and read from Bam files.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
This is the trivial, non-threaded implementation of PipelineCyclerBase.
int get_index() const
Returns the integer index associated with this TypeHandle.
string get_name(TypedObject *object=(TypedObject *) NULL) const
Returns the name of the type.
void set_target(DatagramSink *target)
Changes the destination of future datagrams written by the BamWriter.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
void set_stdfloat_double(bool stdfloat_double)
Changes the stdfloat_double flag, which defines the operation performed by add_stdfloat() and Datagra...
void write_handle(Datagram &packet, TypeHandle type)
Writes a TypeHandle to the file in such a way that the BamReader can read the same TypeHandle later v...
virtual void write_datagram(BamWriter *, Datagram &) const
Writes the contents of this object to the datagram for shipping out to a Bam file.
void add_bool(bool value)
Adds a boolean value to the datagram.
This class defines the abstract interface to sending datagrams to any target, whether it be into a fi...
The name of a file, such as a texture file or an Egg file.
virtual bool copy_datagram(SubfileInfo &result, const Filename &filename)
Copies the file data from the entire indicated file (via the vfs) as the next datagram.
bool write_object(const TypedWritable *obj)
Writes a single object to the Bam file, so that the BamReader::read_object() can later correctly rest...
bool register_pta(Datagram &packet, const void *ptr)
Prepares to write a PointerToArray to the Bam file, unifying references to the same pointer across th...
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
int get_num_parent_classes(TypedObject *object=(TypedObject *) NULL) const
Returns the number of parent classes that this type is known to have.
const CycleData * read(Thread *current_thread) const
Returns a const CycleData pointer, filled with the data for the current stage of the pipeline as seen...
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
This class records a particular byte sub-range within an existing file on disk.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
void flush()
Ensures that all data written thus far is manifested on the output stream.
void write_file_data(SubfileInfo &result, const Filename &filename)
Writes a block of auxiliary file data from the indicated file (within the vfs).
void consider_update(const TypedWritable *obj)
Should be called from TypedWritable::update_bam_nested() to recursively check the entire hiererachy o...
TypeHandle is the identifier used to differentiate C++ class types.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
bool init()
Initializes the BamWriter prior to writing any objects to its output stream.
void release_read(const CycleData *pointer) const
Releases a pointer previously obtained via a call to read().
TypeHandle get_parent_class(int index) const
Returns the nth parent class of this type.
TypeHandle find_registered_type(TypeHandle handle)
Returns the TypeHandle given, if it is a registered type, or if it is not registered, searches for the nearest ancestor of the indicated type that is registered and returns it.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.