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