Pārlūkot izejas kodu

better bamification

David Rose 24 gadi atpakaļ
vecāks
revīzija
2b729db8e8

+ 62 - 0
panda/src/collide/collisionRay.cxx

@@ -28,6 +28,10 @@
 #include "boundingLine.h"
 #include "qplensNode.h"
 #include "lens.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+#include "bamReader.h"
+#include "bamWriter.h"
 
 #include "lensNode.h"
 #include "geomNode.h"
@@ -259,3 +263,61 @@ fill_viz_geom() {
 
   _viz_geom->add_geom(ray, get_other_viz_state());
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionRay::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               CollisionRay.
+////////////////////////////////////////////////////////////////////
+void CollisionRay::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionRay::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void CollisionRay::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  CollisionSolid::write_datagram(manager, dg);
+  _origin.write_datagram(dg);
+  _direction.write_datagram(dg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionRay::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type CollisionRay is encountered
+//               in the Bam file.  It should create the CollisionRay
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *CollisionRay::
+make_from_bam(const FactoryParams &params) {
+  CollisionRay *node = new CollisionRay();
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  node->fillin(scan, manager);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionRay::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new CollisionRay.
+////////////////////////////////////////////////////////////////////
+void CollisionRay::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  CollisionSolid::fillin(scan, manager);
+  _origin.read_datagram(scan);
+  _direction.read_datagram(scan);
+}

+ 8 - 0
panda/src/collide/collisionRay.h

@@ -86,6 +86,14 @@ private:
   LPoint3f _origin;
   LVector3f _direction;
 
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 62 - 0
panda/src/collide/collisionSegment.cxx

@@ -30,6 +30,10 @@
 #include "lens.h"
 #include "geomLine.h"
 #include "geometricBoundingVolume.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+#include "bamReader.h"
+#include "bamWriter.h"
 
 #include "geomNode.h"
 #include "lensNode.h"
@@ -241,3 +245,61 @@ fill_viz_geom() {
 
   _viz_geom->add_geom(segment, get_other_viz_state());
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               CollisionSegment.
+////////////////////////////////////////////////////////////////////
+void CollisionSegment::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void CollisionSegment::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  CollisionSolid::write_datagram(manager, dg);
+  _a.write_datagram(dg);
+  _b.write_datagram(dg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type CollisionSegment is encountered
+//               in the Bam file.  It should create the CollisionSegment
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *CollisionSegment::
+make_from_bam(const FactoryParams &params) {
+  CollisionSegment *node = new CollisionSegment();
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  node->fillin(scan, manager);
+
+  return node;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CollisionSegment::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new CollisionSegment.
+////////////////////////////////////////////////////////////////////
+void CollisionSegment::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  CollisionSolid::fillin(scan, manager);
+  _a.read_datagram(scan);
+  _b.read_datagram(scan);
+}

+ 8 - 0
panda/src/collide/collisionSegment.h

@@ -88,6 +88,14 @@ protected:
 private:
   LPoint3f _a, _b;
 
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 2 - 0
panda/src/collide/config_collide.cxx

@@ -93,5 +93,7 @@ init_libcollide() {
   qpCollisionNode::register_with_read_factory();
   CollisionPlane::register_with_read_factory();
   CollisionPolygon::register_with_read_factory();
+  CollisionRay::register_with_read_factory();
+  CollisionSegment::register_with_read_factory();
   CollisionSphere::register_with_read_factory();
 }

+ 1 - 0
panda/src/pgraph/pandaNode.cxx

@@ -1821,6 +1821,7 @@ register_with_read_factory() {
 ////////////////////////////////////////////////////////////////////
 void PandaNode::
 write_datagram(BamWriter *manager, Datagram &dg) {
+  TypedWritable::write_datagram(manager, dg);
   dg.add_string(get_name());
 
   manager->write_cdata(dg, _cycler);

+ 2 - 2
panda/src/pgraph/qpfog.h

@@ -123,9 +123,9 @@ public:
     return _type_handle;
   }
   static void init_type() {
-    TypedReferenceCount::init_type();
+    PandaNode::init_type();
     register_type(_type_handle, "qpFog",
-                  TypedReferenceCount::get_class_type());
+                  PandaNode::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();

+ 3 - 0
panda/src/pgraph/qplensNode.cxx

@@ -100,6 +100,9 @@ register_with_read_factory() {
 void qpLensNode::
 write_datagram(BamWriter *manager, Datagram &dg) {
   PandaNode::write_datagram(manager, dg);
+
+  // We should actually write out the lens.  Easy to do, but not
+  // immediately pressing; I hope no one gets burned by the omission.
 }
 
 ////////////////////////////////////////////////////////////////////

+ 26 - 3
panda/src/putil/bamWriter.cxx

@@ -16,12 +16,13 @@
 //
 ////////////////////////////////////////////////////////////////////
 
-#include <pandabase.h>
-#include <notify.h>
+#include "pandabase.h"
+#include "notify.h"
 
 #include "config_util.h"
 #include "bam.h"
 #include "bamWriter.h"
+#include "bamReader.h"
 
 ////////////////////////////////////////////////////////////////////
 //     Function: BamWriter::Constructor
@@ -129,6 +130,20 @@ write_object(const TypedWritable *object) {
       TypeHandle type = object->get_type();
       nassertr(type != TypeHandle::none(), false);
 
+      // Determine what the nearest kind of type is that the reader
+      // will be able to handle, and write that instead.
+      TypeHandle registered_type = 
+        BamReader::get_factory()->find_registered_type(type);
+      if (registered_type == TypeHandle::none()) {
+        // We won't be able to read this type again.
+        util_cat.warning()
+          << "Objects of type " << type << " cannot be read; bam file is invalid.\n";
+      } else if (registered_type != type) {
+        util_cat.info()
+          << "Writing " << registered_type << " instead of " << type << "\n";
+        type = registered_type;
+      }
+
       write_handle(dg, type);
       dg.add_uint16(object_id);
 
@@ -358,7 +373,15 @@ enqueue_object(const TypedWritable *object) {
   // No object should ever be written out that is not registered as a
   // child of TypedWritable.  The only way this can happen is if
   // someone failed to initialize their type correctly in init_type().
-  nassertr(object->is_of_type(TypedWritable::get_class_type()), 0);
+#ifndef NDEBUG
+  if (!object->is_of_type(TypedWritable::get_class_type())) {
+    util_cat.error()
+      << "Type " << object->get_type() 
+      << " does not indicate inheritance from TypedWritable.\n"
+      << "(this is almost certainly an oversight in " << object->get_type()
+      << "::init_type().)\n";
+  }
+#endif
 
   // We need to assign a unique index number to every object we write
   // out.  Has this object been assigned a number yet?

+ 44 - 5
panda/src/putil/factoryBase.cxx

@@ -80,15 +80,19 @@ make_instance(TypeHandle handle, const FactoryParams &params) {
 ////////////////////////////////////////////////////////////////////
 TypedObject *FactoryBase::
 make_instance_more_general(TypeHandle handle, const FactoryParams &params) {
-  // Walk up the left side of the inheritance tree until we find
-  // something we know about.
   TypedObject *object = make_instance_exact(handle, params);
-  while (object == (TypedObject *)NULL) {
+
+  if (object == (TypedObject *)NULL) {
+    // Recursively search through the entire inheritance tree until we
+    // find something we know about.
     if (handle.get_num_parent_classes() == 0) {
       return NULL;
     }
-    handle = handle.get_parent_class(0);
-    object = make_instance_exact(handle, params);
+
+    int num_parents = handle.get_num_parent_classes();
+    for (int i = 0; i < num_parents && object == (TypedObject *)NULL; i++) {
+      object = make_instance_more_general(handle.get_parent_class(i), params);
+    }
   }
 
   if (util_cat.is_debug()) {
@@ -105,6 +109,41 @@ make_instance_more_general(TypeHandle handle, const FactoryParams &params) {
   return object;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: FactoryBase::find_registered_type
+//       Access: Public
+//  Description: 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.  If no ancestor of the
+//               indicated type is registered, returns
+//               TypeHandle::none().
+////////////////////////////////////////////////////////////////////
+TypeHandle FactoryBase::
+find_registered_type(TypeHandle handle) {
+  Creators::const_iterator ci = _creators.find(handle);
+  if (ci != _creators.end()) {
+    // This type is registered.
+    return handle;
+  }
+
+  // Recursively search through the entire inheritance tree until we
+  // find something we know about.
+  if (handle.get_num_parent_classes() == 0) {
+    return TypeHandle::none();
+  }
+
+  int num_parents = handle.get_num_parent_classes();
+  for (int i = 0; i < num_parents; i++) {
+    TypeHandle result = find_registered_type(handle.get_parent_class(i));
+    if (result != TypeHandle::none()) {
+      return result;
+    }
+  }
+
+  // No known types.
+  return TypeHandle::none();
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: FactoryBase::register_factory

+ 2 - 0
panda/src/putil/factoryBase.h

@@ -63,6 +63,8 @@ public:
   INLINE TypedObject *make_instance_more_general(const string &type_name,
                                                  const FactoryParams &params);
 
+  TypeHandle find_registered_type(TypeHandle handle);
+
   void register_factory(TypeHandle handle, BaseCreateFunc *func);
 
   int get_num_types() const;