Panda3D
|
00001 // Filename: bamWriter.h 00002 // Created by: jason (08Jun00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef __BAM_WRITER_ 00016 #define __BAM_WRITER_ 00017 00018 #include "pandabase.h" 00019 #include "pnotify.h" 00020 #include "bamEnums.h" 00021 #include "typedWritable.h" 00022 #include "datagramSink.h" 00023 #include "pdeque.h" 00024 #include "pset.h" 00025 #include "pmap.h" 00026 #include "vector_int.h" 00027 #include "pipelineCyclerBase.h" 00028 00029 00030 // A handy macro for writing PointerToArrays. 00031 #define WRITE_PTA(Manager, dest, Write_func, array) \ 00032 if (!Manager->register_pta(dest, array.p())) \ 00033 { \ 00034 Write_func(Manager, dest, array); \ 00035 } \ 00036 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Class : BamWriter 00040 // Description : This is the fundamental interface for writing binary 00041 // objects to a Bam file, to be extracted later by a 00042 // BamReader. 00043 // 00044 // A Bam file can be thought of as a linear collection 00045 // of objects. Each object is an instance of a class 00046 // that inherits, directly or indirectly, from 00047 // TypedWritable. The objects may include pointers to 00048 // other objects; the BamWriter automatically manages 00049 // these (with help from code within each class) and 00050 // writes all referenced objects to the file in such a 00051 // way that the pointers may be correctly restored 00052 // later. 00053 // 00054 // This is the abstract interface and does not 00055 // specifically deal with disk files, but rather with a 00056 // DatagramSink of some kind, which simply accepts a 00057 // linear stream of Datagrams. It is probably written 00058 // to a disk file, but it might conceivably be streamed 00059 // directly to a network or some such nonsense. 00060 // 00061 // Bam files are most often used to store scene graphs 00062 // or subgraphs, and by convention they are given 00063 // filenames ending in the extension ".bam" when they 00064 // are used for this purpose. However, a Bam file may 00065 // store any arbitrary list of TypedWritable objects; 00066 // in this more general usage, they are given filenames 00067 // ending in ".boo" to differentiate them from the more 00068 // common scene graph files. 00069 // 00070 // See also BamFile, which defines a higher-level 00071 // interface to read and write Bam files on disk. 00072 //////////////////////////////////////////////////////////////////// 00073 class EXPCL_PANDA_PUTIL BamWriter : public BamEnums { 00074 PUBLISHED: 00075 BamWriter(DatagramSink *target = NULL, const Filename &name = ""); 00076 ~BamWriter(); 00077 00078 void set_target(DatagramSink *target); 00079 00080 bool init(); 00081 INLINE const Filename &get_filename() const; 00082 bool write_object(const TypedWritable *obj); 00083 bool has_object(const TypedWritable *obj) const; 00084 void flush(); 00085 00086 INLINE BamEndian get_file_endian() const; 00087 00088 INLINE BamTextureMode get_file_texture_mode() const; 00089 INLINE void set_file_texture_mode(BamTextureMode file_texture_mode); 00090 00091 public: 00092 // Functions to support classes that write themselves to the Bam. 00093 00094 void consider_update(const TypedWritable *obj); 00095 00096 void write_pointer(Datagram &packet, const TypedWritable *dest); 00097 void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler); 00098 void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler, 00099 void *extra_data); 00100 bool register_pta(Datagram &packet, const void *ptr); 00101 void write_handle(Datagram &packet, TypeHandle type); 00102 00103 private: 00104 void object_destructs(TypedWritable *object); 00105 00106 void write_object_id(Datagram &dg, int object_id); 00107 void write_pta_id(Datagram &dg, int pta_id); 00108 int enqueue_object(const TypedWritable *object); 00109 bool flush_queue(); 00110 00111 // This is the filename of the BAM, or null string if not in a file. 00112 Filename _filename; 00113 00114 BamEndian _file_endian; 00115 BamTextureMode _file_texture_mode; 00116 00117 // This is the set of all TypeHandles already written. 00118 pset<int, int_hash> _types_written; 00119 00120 // This keeps track of all of the objects we have written out 00121 // already (or are about to write out), and associates a unique 00122 // object ID number to each one. 00123 class StoreState { 00124 public: 00125 int _object_id; 00126 UpdateSeq _written_seq; 00127 UpdateSeq _modified; 00128 00129 StoreState(int object_id) : _object_id(object_id) {} 00130 }; 00131 typedef phash_map<const TypedWritable *, StoreState, pointer_hash> StateMap; 00132 StateMap _state_map; 00133 00134 // This seq number is incremented each time we write a new object 00135 // using the top-level write_object() call. It indicates the 00136 // current sequence number we are writing, which is updated in the 00137 // StoreState, above, and used to keep track of which objects may 00138 // need to be checked for internal updates. 00139 UpdateSeq _writing_seq; 00140 00141 // This is initialized to BOC_push in write_object(), then cleared 00142 // to BOC_adjunct as each object is written, so that only the first 00143 // object gets written with BOC_push. 00144 BamObjectCode _next_boc; 00145 00146 // This is the next object ID that will be assigned to a new object. 00147 int _next_object_id; 00148 bool _long_object_id; 00149 00150 // This is the queue of objects that need to be written when the 00151 // current object is finished. 00152 typedef pdeque<const TypedWritable *> ObjectQueue; 00153 ObjectQueue _object_queue; 00154 00155 // This is the set of object_id's that we won't be using any more; 00156 // we'll encode this set into the bam stream so the BamReader will 00157 // be able to clean up its internal structures. 00158 typedef vector_int FreedObjectIds; 00159 FreedObjectIds _freed_object_ids; 00160 00161 // These are used by register_pta() to unify multiple references to 00162 // the same PointerToArray. 00163 typedef phash_map<const void *, int, pointer_hash> PTAMap; 00164 PTAMap _pta_map; 00165 int _next_pta_id; 00166 bool _long_pta_id; 00167 00168 // The destination to write all the output to. 00169 DatagramSink *_target; 00170 bool _needs_init; 00171 00172 friend class TypedWritable; 00173 }; 00174 00175 #include "bamWriter.I" 00176 00177 #endif 00178