From 2b729db8e87c98fb450fb925de5aaf224f5e9a98 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 21 Mar 2002 23:34:55 +0000 Subject: [PATCH] better bamification --- panda/src/collide/collisionRay.cxx | 62 ++++++++++++++++++++++++++ panda/src/collide/collisionRay.h | 8 ++++ panda/src/collide/collisionSegment.cxx | 62 ++++++++++++++++++++++++++ panda/src/collide/collisionSegment.h | 8 ++++ panda/src/collide/config_collide.cxx | 2 + panda/src/pgraph/pandaNode.cxx | 1 + panda/src/pgraph/qpfog.h | 4 +- panda/src/pgraph/qplensNode.cxx | 3 ++ panda/src/putil/bamWriter.cxx | 29 ++++++++++-- panda/src/putil/factoryBase.cxx | 49 +++++++++++++++++--- panda/src/putil/factoryBase.h | 2 + 11 files changed, 220 insertions(+), 10 deletions(-) diff --git a/panda/src/collide/collisionRay.cxx b/panda/src/collide/collisionRay.cxx index 2e81729893..c653c32115 100644 --- a/panda/src/collide/collisionRay.cxx +++ b/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 ¶ms) { + 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); +} diff --git a/panda/src/collide/collisionRay.h b/panda/src/collide/collisionRay.h index 16228576a2..04e8906ee1 100644 --- a/panda/src/collide/collisionRay.h +++ b/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 ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/collide/collisionSegment.cxx b/panda/src/collide/collisionSegment.cxx index beca4fcc1f..ffe01de4e1 100644 --- a/panda/src/collide/collisionSegment.cxx +++ b/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 ¶ms) { + 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); +} diff --git a/panda/src/collide/collisionSegment.h b/panda/src/collide/collisionSegment.h index e3ac1e115a..402b70f52a 100644 --- a/panda/src/collide/collisionSegment.h +++ b/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 ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/collide/config_collide.cxx b/panda/src/collide/config_collide.cxx index 5653c53260..dc5c92ed3a 100644 --- a/panda/src/collide/config_collide.cxx +++ b/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(); } diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 1c1e6d7924..96ed270988 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/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); diff --git a/panda/src/pgraph/qpfog.h b/panda/src/pgraph/qpfog.h index a52d48ce16..54558a883e 100644 --- a/panda/src/pgraph/qpfog.h +++ b/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(); diff --git a/panda/src/pgraph/qplensNode.cxx b/panda/src/pgraph/qplensNode.cxx index 34358cf7ae..4fdad50a9c 100644 --- a/panda/src/pgraph/qplensNode.cxx +++ b/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. } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/putil/bamWriter.cxx b/panda/src/putil/bamWriter.cxx index 24ad9a6418..8d63fa11fe 100644 --- a/panda/src/putil/bamWriter.cxx +++ b/panda/src/putil/bamWriter.cxx @@ -16,12 +16,13 @@ // //////////////////////////////////////////////////////////////////// -#include -#include +#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? diff --git a/panda/src/putil/factoryBase.cxx b/panda/src/putil/factoryBase.cxx index bdcc412b63..0b583ec339 100644 --- a/panda/src/putil/factoryBase.cxx +++ b/panda/src/putil/factoryBase.cxx @@ -80,15 +80,19 @@ make_instance(TypeHandle handle, const FactoryParams ¶ms) { //////////////////////////////////////////////////////////////////// TypedObject *FactoryBase:: make_instance_more_general(TypeHandle handle, const FactoryParams ¶ms) { - // 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 ¶ms) { 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 diff --git a/panda/src/putil/factoryBase.h b/panda/src/putil/factoryBase.h index c3c4411e70..1e494c4441 100644 --- a/panda/src/putil/factoryBase.h +++ b/panda/src/putil/factoryBase.h @@ -63,6 +63,8 @@ public: INLINE TypedObject *make_instance_more_general(const string &type_name, const FactoryParams ¶ms); + TypeHandle find_registered_type(TypeHandle handle); + void register_factory(TypeHandle handle, BaseCreateFunc *func); int get_num_types() const;