Panda3D

bamWriter.h

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 
 All Classes Functions Variables Enumerations