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.
TypeHandle get_parent_class(int index) const
Returns the nth parent class of this type.
int get_index() const
Returns the integer index associated with this TypeHandle.
A single page of data maintained by a PipelineCycler.
Base class for objects that can be written to and read from Bam files.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
string get_name(TypedObject *object=(TypedObject *) NULL) const
Returns the name of the type.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
This is the trivial, non-threaded implementation of PipelineCyclerBase.
void set_target(DatagramSink *target)
Changes the destination of future datagrams written by the BamWriter.
void release_read(const CycleData *pointer) const
Releases a pointer previously obtained via a call to read().
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...
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...
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...
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...
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.
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.
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).
virtual void write_datagram(BamWriter *, Datagram &) const
Writes the contents of this object to the datagram for shipping out to a Bam file.
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.
UpdateSeq get_bam_modified() const
Returns the current bam_modified counter.
int get_num_parent_classes(TypedObject *object=(TypedObject *) NULL) const
Returns the number of parent classes that this type is known to have.
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.