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); 00076 ~BamWriter(); 00077 00078 void set_target(DatagramSink *target); 00079 INLINE DatagramSink *get_target(); 00080 00081 bool init(); 00082 INLINE const Filename &get_filename() const; 00083 bool write_object(const TypedWritable *obj); 00084 bool has_object(const TypedWritable *obj) const; 00085 void flush(); 00086 00087 INLINE BamEndian get_file_endian() const; 00088 INLINE bool get_file_stdfloat_double() const; 00089 00090 INLINE BamTextureMode get_file_texture_mode() const; 00091 INLINE void set_file_texture_mode(BamTextureMode file_texture_mode); 00092 00093 public: 00094 // Functions to support classes that write themselves to the Bam. 00095 00096 void consider_update(const TypedWritable *obj); 00097 00098 void write_pointer(Datagram &packet, const TypedWritable *dest); 00099 00100 void write_file_data(SubfileInfo &result, const Filename &filename); 00101 void write_file_data(SubfileInfo &result, const SubfileInfo &source); 00102 00103 void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler); 00104 void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler, 00105 void *extra_data); 00106 bool register_pta(Datagram &packet, const void *ptr); 00107 void write_handle(Datagram &packet, TypeHandle type); 00108 00109 private: 00110 void object_destructs(TypedWritable *object); 00111 00112 void write_object_id(Datagram &dg, int object_id); 00113 void write_pta_id(Datagram &dg, int pta_id); 00114 int enqueue_object(const TypedWritable *object); 00115 bool flush_queue(); 00116 00117 BamEndian _file_endian; 00118 bool _file_stdfloat_double; 00119 BamTextureMode _file_texture_mode; 00120 00121 // This is the set of all TypeHandles already written. 00122 pset<int, int_hash> _types_written; 00123 00124 // This keeps track of all of the objects we have written out 00125 // already (or are about to write out), and associates a unique 00126 // object ID number to each one. 00127 class StoreState { 00128 public: 00129 int _object_id; 00130 UpdateSeq _written_seq; 00131 UpdateSeq _modified; 00132 00133 StoreState(int object_id) : _object_id(object_id) {} 00134 }; 00135 typedef phash_map<const TypedWritable *, StoreState, pointer_hash> StateMap; 00136 StateMap _state_map; 00137 00138 // This seq number is incremented each time we write a new object 00139 // using the top-level write_object() call. It indicates the 00140 // current sequence number we are writing, which is updated in the 00141 // StoreState, above, and used to keep track of which objects may 00142 // need to be checked for internal updates. 00143 UpdateSeq _writing_seq; 00144 00145 // This is initialized to BOC_push in write_object(), then cleared 00146 // to BOC_adjunct as each object is written, so that only the first 00147 // object gets written with BOC_push. 00148 BamObjectCode _next_boc; 00149 00150 // This is the next object ID that will be assigned to a new object. 00151 int _next_object_id; 00152 bool _long_object_id; 00153 00154 // This is the queue of objects that need to be written when the 00155 // current object is finished. 00156 typedef pdeque<const TypedWritable *> ObjectQueue; 00157 ObjectQueue _object_queue; 00158 00159 // This is the set of object_id's that we won't be using any more; 00160 // we'll encode this set into the bam stream so the BamReader will 00161 // be able to clean up its internal structures. 00162 typedef vector_int FreedObjectIds; 00163 FreedObjectIds _freed_object_ids; 00164 00165 // These are used by register_pta() to unify multiple references to 00166 // the same PointerToArray. 00167 typedef phash_map<const void *, int, pointer_hash> PTAMap; 00168 PTAMap _pta_map; 00169 int _next_pta_id; 00170 bool _long_pta_id; 00171 00172 // The destination to write all the output to. 00173 DatagramSink *_target; 00174 bool _needs_init; 00175 00176 friend class TypedWritable; 00177 }; 00178 00179 #include "bamWriter.I" 00180 00181 #endif 00182