pgraph bam

This commit is contained in:
David Rose 2002-03-04 19:09:33 +00:00
parent 02e35e725b
commit 5306f05c77
75 changed files with 1032 additions and 309 deletions

View File

@ -75,7 +75,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int AnimBundleNode::
complete_pointers(vector_typedWritable &p_list, BamReader* manager)
complete_pointers(TypedWritable **p_list, BamReader* manager)
{
int start = NamedNode::complete_pointers(p_list, manager);
_bundle = DCAST(AnimBundle, p_list[start]);

View File

@ -48,7 +48,7 @@ private:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
static TypedWritable *make_AnimBundleNode(const FactoryParams &params);

View File

@ -221,7 +221,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int AnimGroup::
complete_pointers(vector_typedWritable &p_list, BamReader*)
complete_pointers(TypedWritable **p_list, BamReader*)
{
nassertr(p_list[0] != TypedWritable::Null, 0);
_root = DCAST(AnimBundle, p_list[0]);

View File

@ -72,7 +72,7 @@ protected:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
static TypedWritable *make_AnimGroup(const FactoryParams &params);

View File

@ -76,7 +76,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int PartBundleNode::
complete_pointers(vector_typedWritable &p_list, BamReader* manager)
complete_pointers(TypedWritable **p_list, BamReader* manager)
{
int start = NamedNode::complete_pointers(p_list, manager);
_bundle = DCAST(PartBundle, p_list[start]);

View File

@ -50,7 +50,7 @@ private:
public:
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
protected:

View File

@ -509,7 +509,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int PartGroup::
complete_pointers(vector_typedWritable &p_list, BamReader*)
complete_pointers(TypedWritable **p_list, BamReader*)
{
int i;
for(i = 0; i < _num_children; i++)

View File

@ -98,7 +98,7 @@ protected:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
static TypedWritable *make_PartGroup(const FactoryParams &params);

View File

@ -456,7 +456,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int Character::
complete_pointers(vector_typedWritable &p_list, BamReader* manager)
complete_pointers(TypedWritable **p_list, BamReader* manager)
{
int start = PartBundleNode::complete_pointers(p_list, manager);
_computed_vertices = DCAST(ComputedVertices, p_list[start]);

View File

@ -99,7 +99,7 @@ private:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
static TypedWritable *make_Character(const FactoryParams &params);

View File

@ -359,7 +359,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int CharacterJoint::
complete_pointers(vector_typedWritable &p_list, BamReader* manager)
complete_pointers(TypedWritable **p_list, BamReader* manager)
{
int i;
int start = MovingPartMatrix::complete_pointers(p_list, manager);

View File

@ -65,7 +65,7 @@ private:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
static TypedWritable *make_CharacterJoint(const FactoryParams &params);

View File

@ -303,7 +303,7 @@ fillin(DatagramIterator& scan, BamReader* manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int CollisionNode::
complete_pointers(vector_typedWritable &p_list, BamReader* manager) {
complete_pointers(TypedWritable **p_list, BamReader* manager) {
int num_solids = _solids.size();
int start = NamedNode::complete_pointers(p_list, manager);

View File

@ -80,7 +80,7 @@ private:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
static TypedWritable *make_CollisionNode(const FactoryParams &params);

View File

@ -170,13 +170,6 @@ public:
INLINE CoordinateSystem get_coordinate_system() const;
virtual CoordinateSystem get_internal_coordinate_system() const;
// This function may only be called during a render traversal; it
// will compute the distance to the indicated point, assumed to be
// in modelview coordinates, from the camera plane. This is a
// virtual function because different GSG's may define the modelview
// coordinate space differently.
virtual float compute_distance_to(const LPoint3f &point) const=0;
INLINE void clear_cached_state(void) { _state.clear(); };
virtual void issue_transform(const TransformState *transform);

View File

@ -507,7 +507,7 @@ fillin(DatagramIterator &scan, BamReader *manager)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int LensFlareNode::
complete_pointers(vector_typedWritable &p_list, BamReader *manager)
complete_pointers(TypedWritable **p_list, BamReader *manager)
{
int i;
int start = Node::complete_pointers(p_list, manager);

View File

@ -106,7 +106,7 @@ private:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
static TypedWritable *make_LensFlareNode(const FactoryParams &params);

View File

@ -18,8 +18,9 @@
#include "loaderFileTypeEgg.h"
#include "load_egg_file.h"
#include "qpload_egg_file.h"
#include <eggData.h>
#include "eggData.h"
TypeHandle LoaderFileTypeEgg::_type_handle;
@ -74,3 +75,14 @@ load_file(const Filename &path, bool) const {
PT_NamedNode result = load_egg_file(path);
return result.p();
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeEgg::load_file
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(PandaNode) LoaderFileTypeEgg::
qpload_file(const Filename &path, bool) const {
PT(PandaNode) result = qpload_egg_file(path);
return result;
}

View File

@ -19,9 +19,9 @@
#ifndef LOADERFILETYPEEGG_H
#define LOADERFILETYPEEGG_H
#include <pandabase.h>
#include "pandabase.h"
#include <loaderFileType.h>
#include "loaderFileType.h"
////////////////////////////////////////////////////////////////////
// Class : LoaderFileTypeEgg
@ -36,6 +36,7 @@ public:
virtual void resolve_filename(Filename &path) const;
virtual PT_Node load_file(const Filename &path, bool report_errors) const;
virtual PT(PandaNode) qpload_file(const Filename &path, bool report_errors) const;
public:
static TypeHandle get_class_type() {

View File

@ -152,7 +152,7 @@ register_with_read_factory(void) {
// Description:
////////////////////////////////////////////////////////////////////
int GeomSprite::
complete_pointers(vector_typedWritable &p_list, BamReader *manager) {
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int index = Geom::complete_pointers(p_list, manager);
_texture = DCAST(Texture, p_list[index]);

View File

@ -88,7 +88,7 @@ public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &me);
int complete_pointers(vector_typedWritable &plist, BamReader *manager);
int complete_pointers(TypedWritable **plist, BamReader *manager);
static TypedWritable *make_GeomSprite(const FactoryParams &params);
protected:

View File

@ -562,7 +562,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int Node::
complete_pointers(vector_typedWritable &p_list, BamReader *manager) {
complete_pointers(TypedWritable **p_list, BamReader *manager) {
if (manager->get_file_minor_ver() < 3) {
// In bam versions before 3.3, this function does nothing (since
// the arcs are completely responsible for adding themselves to

View File

@ -125,7 +125,7 @@ protected:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
static TypedWritable *make_Node(const FactoryParams &params);

View File

@ -902,7 +902,7 @@ write_datagram(BamWriter *manager, Datagram &me)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int NodeRelation::
complete_pointers(vector_typedWritable &p_list, BamReader *manager) {
complete_pointers(TypedWritable **p_list, BamReader *manager) {
nassertr(p_list[0] != TypedWritable::Null &&
p_list[1] != TypedWritable::Null, 0);
_parent = DCAST(Node, p_list[0]);

View File

@ -192,7 +192,7 @@ private:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
static TypedWritable *make_NodeRelation(const FactoryParams &params);

View File

@ -4,7 +4,7 @@
#begin lib_target
#define TARGET gsgbase
#define LOCAL_LIBS \
putil graph
putil graph linmath
#define COMBINED_SOURCES $[TARGET]_composite1.cxx

View File

@ -23,6 +23,7 @@
#include "typedReferenceCount.h"
#include "nodeTransitions.h"
#include "luse.h"
// A handful of forward references.
@ -148,6 +149,13 @@ public:
virtual void set_state_and_transform(const RenderState *state,
const TransformState *transform)=0;
// This function may only be called during a render traversal; it
// will compute the distance to the indicated point, assumed to be
// in modelview coordinates, from the camera plane. This is a
// virtual function because different GSG's may define the modelview
// coordinate space differently.
virtual float compute_distance_to(const LPoint3f &point) const=0;
// Defined here are some internal interface functions for the
// GraphicsStateGuardian. These are here to support
// double-dispatching from Geoms and NodeTransitions, and are

View File

@ -4,7 +4,7 @@
#begin lib_target
#define TARGET loader
#define LOCAL_LIBS \
event graph ipc putil express downloader
event pgraph graph ipc putil express downloader
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx

View File

@ -192,13 +192,7 @@ write_object(const TypedWritable *object) {
return false;
}
// We'll go ahead and cast the const TypedWritable pointer to a
// non-const for issuing the actual write. This allows
// write_datagram to be defined in such a way that it can modify
// itself in some minor way if it must; we assume that no class will
// abuse this privilege and modify its contents significantly during
// write_datagram().
if (!_writer->write_object((TypedWritable *)object)) {
if (!_writer->write_object(object)) {
close();
return false;
}

View File

@ -28,3 +28,16 @@ load_sync(const Filename &filename) const {
}
return load_file(filename);
}
////////////////////////////////////////////////////////////////////
// Function: Loader::load_sync
// Access: Public
// Description: Loads the file immediately, waiting for it to complete.
////////////////////////////////////////////////////////////////////
INLINE PT(PandaNode) Loader::
qpload_sync(const Filename &filename) const {
if (!_file_types_loaded) {
load_file_types();
}
return qpload_file(filename);
}

View File

@ -20,22 +20,19 @@
#include "loaderFileTypeRegistry.h"
#include "config_loader.h"
#include <event.h>
#include <pt_Event.h>
#include <throw_event.h>
#include <eventParameter.h>
#include <circBuffer.h>
#include <filename.h>
#include <load_dso.h>
#include "event.h"
#include "pt_Event.h"
#include "throw_event.h"
#include "eventParameter.h"
#include "circBuffer.h"
#include "filename.h"
#include "load_dso.h"
#include "plist.h"
#include "pvector.h"
#include <algorithm>
////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////
bool Loader::_file_types_loaded = false;
////////////////////////////////////////////////////////////////////
@ -337,6 +334,51 @@ load_file(const Filename &filename) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: Loader::load_file
// Access: Private
// Description: Loads a single scene graph file, if possible.
// Returns the Node that is the root of the file, or
// NULL if the file cannot be loaded.
////////////////////////////////////////////////////////////////////
PT(PandaNode) Loader::
qpload_file(const Filename &filename) const {
string extension = filename.get_extension();
if (extension.empty()) {
return qpload_unknown_file_type(filename);
}
LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_ptr();
LoaderFileType *requested_type =
reg->get_type_from_extension(extension);
if (requested_type == (LoaderFileType *)NULL) {
loader_cat.error()
<< "Extension of file " << filename
<< " is unrecognized; cannot load.\n";
loader_cat.error(false)
<< "Currently known scene file types are:\n";
reg->write_types(loader_cat.error(false), 2);
return NULL;
}
Filename requested_filename = filename;
if (!requested_filename.is_fully_qualified()) {
// Ask the loader type to look for the file along its paths.
requested_type->resolve_filename(requested_filename);
}
if (loader_cat.is_debug()) {
loader_cat.debug()
<< "Loading " << requested_type->get_name() << " file: "
<< requested_filename << "\n";
}
PT(PandaNode) result = requested_type->qpload_file(requested_filename, true);
return result;
}
class LoaderConsiderFile {
public:
Filename _path;
@ -436,6 +478,94 @@ load_unknown_file_type(const Filename &filename) const {
return (Node *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: Loader::load_unknown_file_type
// Access: Private
// Description: Attempts to guess which file is meant when a file
// with no extension is given. Looks around for a file
// with a suitable extension for each of our known file
// types, and loads the most recent file available of
// any file type.
////////////////////////////////////////////////////////////////////
PT(PandaNode) Loader::
qpload_unknown_file_type(const Filename &filename) const {
typedef pvector<LoaderConsiderFile> Files;
Files files;
// First, build up a list of all of the possible files it could be.
LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_ptr();
int num_types = reg->get_num_types();
if (num_types == 0) {
loader_cat.error()
<< "Can't load file " << filename
<< "; no scene file types are known.\n";
return (PandaNode *)NULL;
}
for (int i = 0; i < num_types; i++) {
LoaderConsiderFile consider;
consider._type = reg->get_type(i);
consider._path = filename;
consider._path.set_extension(consider._type->get_extension());
if (!consider._path.is_fully_qualified()) {
// Ask the loader type to look for the file along its paths.
consider._type->resolve_filename(consider._path);
}
if (consider._path.exists()) {
files.push_back(consider);
}
}
if (files.empty()) {
loader_cat.error()
<< "Couldn't find file " << filename << " as:\n";
for (int i = 0; i < num_types; i++) {
Filename p = filename;
p.set_extension(reg->get_type(i)->get_extension());
loader_cat.error(false)
<< " " << p << "\n";
}
return (PandaNode *)NULL;
}
// Now sort the list into order by timestamp, from newest to oldest.
sort(files.begin(), files.end());
// And try to load each file one at a time.
Files::const_iterator fi;
if (loader_cat.is_debug()) {
loader_cat.debug()
<< "Loading " << filename << ", one of " << files.size()
<< " possible types:\n";
for (fi = files.begin(); fi != files.end(); ++fi) {
loader_cat.debug(false)
<< " " << (*fi)._path << "\n";
}
}
for (fi = files.begin(); fi != files.end(); ++fi) {
const LoaderConsiderFile &consider = (*fi);
PT(PandaNode) result = consider._type->qpload_file(consider._path, false);
if (result != (PandaNode *)NULL) {
return result;
}
if (loader_cat.is_debug()) {
loader_cat.debug()
<< "Couldn't read " << consider._type->get_name()
<< " file " << consider._path << "\n";
}
}
loader_cat.error()
<< "Cannot read " << files.front()._path << "\n";
return (PandaNode *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: Loader::resolve_unknown_file_type
// Access: Private

View File

@ -17,18 +17,16 @@
////////////////////////////////////////////////////////////////////
#ifndef LOADER_H
#define LOADER_H
//
////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////
#include <pandabase.h>
#include <notify.h>
#include <node.h>
#include <pt_Node.h>
#include <filename.h>
#include <tokenBoard.h>
#include <asyncUtility.h>
#include "pandabase.h"
#include "notify.h"
#include "node.h"
#include "pt_Node.h"
#include "pandaNode.h"
#include "filename.h"
#include "tokenBoard.h"
#include "asyncUtility.h"
class LoaderToken;
@ -45,6 +43,7 @@ PUBLISHED:
void resolve_filename(Filename &filename) const;
INLINE PT_Node load_sync(const Filename &filename) const;
INLINE PT(PandaNode) qpload_sync(const Filename &filename) const;
uint request_load(const Filename &filename, const string &event_name);
bool check_load(uint id);
@ -57,6 +56,8 @@ private:
virtual bool process_request(void);
PT_Node load_file(const Filename &filename) const;
PT_Node load_unknown_file_type(const Filename &filename) const;
PT(PandaNode) qpload_file(const Filename &filename) const;
PT(PandaNode) qpload_unknown_file_type(const Filename &filename) const;
void resolve_unknown_file_type(Filename &filename) const;
typedef TokenBoard<LoaderToken> LoaderTokenBoard;

View File

@ -51,3 +51,16 @@ LoaderFileType::
void LoaderFileType::
resolve_filename(Filename &) const {
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileType::load_file
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(PandaNode) LoaderFileType::
qpload_file(const Filename &path, bool report_errors) const
{
loader_cat.error()
<< get_type() << " cannot read PandaNode objects.\n";
return NULL;
}

View File

@ -19,12 +19,14 @@
#ifndef LOADERFILETYPE_H
#define LOADERFILETYPE_H
#include <pandabase.h>
#include "pandabase.h"
#include <typedObject.h>
#include <node.h>
#include <pt_Node.h>
#include <filename.h>
#include "typedObject.h"
#include "node.h"
#include "pt_Node.h"
#include "filename.h"
#include "pandaNode.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : LoaderFileType
@ -45,6 +47,7 @@ public:
virtual void resolve_filename(Filename &path) const;
virtual PT_Node load_file(const Filename &path, bool report_errors) const=0;
virtual PT(PandaNode) qpload_file(const Filename &path, bool report_errors) const;
public:
static TypeHandle get_class_type() {

View File

@ -121,3 +121,53 @@ load_file(const Filename &path, bool report_errors) const
return result;
}
////////////////////////////////////////////////////////////////////
// Function: LoaderFileTypeBam::load_file
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(PandaNode) LoaderFileTypeBam::
qpload_file(const Filename &path, bool report_errors) const {
BamFile bam_file;
if (!bam_file.open_read(path, report_errors)) {
return NULL;
}
PT(PandaNode) result;
TypedWritable *object = bam_file.read_object();
if (object == TypedWritable::Null) {
if (report_errors) {
loader_cat.error() << "Bam file " << path << " is empty.\n";
}
} else if (!object->is_of_type(PandaNode::get_class_type())) {
if (report_errors) {
loader_cat.error()
<< "Bam file " << path
<< " contains a " << object->get_type() << ", not a PandaNode.\n";
}
} else {
result = DCAST(PandaNode, object);
if (report_errors) {
bam_file.read_object();
if (!bam_file.is_eof()) {
loader_cat.warning()
<< "Ignoring extra objects in " << path << "\n";
}
}
}
if (!bam_file.resolve()) {
if (report_errors) {
loader_cat.error()
<< "Unable to resolve Bam file.\n";
result = (PandaNode *)NULL;
}
}
return result;
}

View File

@ -19,13 +19,13 @@
#ifndef LOADERFILETYPEBAM_H
#define LOADERFILETYPEBAM_H
#include <pandabase.h>
#include "pandabase.h"
#include "loaderFileType.h"
////////////////////////////////////////////////////////////////////
// Class : LoaderFileTypeEgg
// Description : This defines the Loader interface to read Egg files.
// Class : LoaderFileTypeBam
// Description : This defines the Loader interface to read Bam files.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA LoaderFileTypeBam : public LoaderFileType {
public:
@ -36,6 +36,7 @@ public:
virtual void resolve_filename(Filename &path) const;
virtual PT_Node load_file(const Filename &path, bool report_errors) const;
virtual PT(PandaNode) qpload_file(const Filename &path, bool report_errors) const;
public:
static TypeHandle get_class_type() {

View File

@ -625,11 +625,9 @@ fillin(DatagramIterator &scan, BamReader *manager) {
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int PiecewiseCurve::
complete_pointers(vector_typedWritable &p_list, BamReader *manager) {
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int used = ParametricCurve::complete_pointers(p_list, manager);
nassertr(used + _segs.size() <= p_list.size(), used);
size_t i;
for (i = 0; i < _segs.size(); i++) {
_segs[i]._curve = DCAST(ParametricCurve, p_list[used + i]);

View File

@ -99,7 +99,7 @@ protected:
protected:
virtual void write_datagram(BamWriter *manager, Datagram &me);
void fillin(DatagramIterator &scan, BamReader *manager);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
public:

View File

@ -220,6 +220,16 @@ register_with_read_factory() {
void BillboardAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_bool(_off);
_up_vector.write_datagram(dg);
dg.add_bool(_eye_relative);
dg.add_bool(_axial_rotate);
dg.add_float32(_offset);
_look_at_point.write_datagram(dg);
// *** We don't write out the _look_at NodeChain right now. Maybe
// we should.
}
////////////////////////////////////////////////////////////////////
@ -239,7 +249,7 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
return attrib;
}
////////////////////////////////////////////////////////////////////
@ -252,4 +262,11 @@ make_from_bam(const FactoryParams &params) {
void BillboardAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_off = scan.get_bool();
_up_vector.read_datagram(scan);
_eye_relative = scan.get_bool();
_axial_rotate = scan.get_bool();
_offset = scan.get_float32();
_look_at_point.read_datagram(scan);
}

View File

@ -165,6 +165,9 @@ register_with_read_factory() {
void ColorAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_int8(_type);
_color.write_datagram(dg);
}
////////////////////////////////////////////////////////////////////
@ -184,7 +187,7 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
return attrib;
}
////////////////////////////////////////////////////////////////////
@ -197,4 +200,7 @@ make_from_bam(const FactoryParams &params) {
void ColorAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_type = (Type)scan.get_int8();
_color.read_datagram(scan);
}

View File

@ -91,6 +91,7 @@ init_libpgraph() {
BillboardAttrib::register_with_read_factory();
ColorAttrib::register_with_read_factory();
CullBinAttrib::register_with_read_factory();
CullFaceAttrib::register_with_read_factory();
qpGeomNode::register_with_read_factory();
PandaNode::register_with_read_factory();

View File

@ -116,6 +116,9 @@ register_with_read_factory() {
void CullBinAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_string(_bin_name);
dg.add_int32(_draw_order);
}
////////////////////////////////////////////////////////////////////
@ -135,7 +138,7 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
return attrib;
}
////////////////////////////////////////////////////////////////////
@ -148,4 +151,7 @@ make_from_bam(const FactoryParams &params) {
void CullBinAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_bin_name = scan.get_string();
_draw_order = scan.get_int32();
}

View File

@ -137,6 +137,8 @@ register_with_read_factory() {
void CullFaceAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_int8(_mode);
}
////////////////////////////////////////////////////////////////////
@ -156,7 +158,7 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
return attrib;
}
////////////////////////////////////////////////////////////////////
@ -169,4 +171,6 @@ make_from_bam(const FactoryParams &params) {
void CullFaceAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_mode = (Mode)scan.get_int8();
}

View File

@ -141,7 +141,7 @@ make_copy() const {
////////////////////////////////////////////////////////////////////
PandaNode *PandaNode::
copy_subgraph() const {
//*** Do something here.
// *** Do something here.
nassertr(false, (PandaNode *)NULL);
return (PandaNode *)NULL;
}
@ -903,6 +903,57 @@ register_with_read_factory() {
////////////////////////////////////////////////////////////////////
void PandaNode::
write_datagram(BamWriter *manager, Datagram &dg) {
CDReader cdata(_cycler);
dg.add_string(get_name());
manager->write_pointer(dg, cdata->_state);
manager->write_pointer(dg, cdata->_transform);
// When we write a PandaNode, we write out its list of child nodes,
// but not its parent nodes--so that writing out a node implicitly
// writes out all of the nodes in the subgraph below, but not the
// nodes above as well.
int num_children = cdata->_down.size();
nassertv(num_children == (int)(PN_uint16)num_children);
dg.add_uint16(num_children);
// **** We should smarten up the writing of the sort number--most of
// the time these will all be zero.
Down::const_iterator ci;
for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) {
PandaNode *child = (*ci).get_child();
int sort = (*ci).get_sort();
manager->write_pointer(dg, child);
dg.add_int32(sort);
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int PandaNode::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
CDWriter cdata(_cycler);
int pi = TypedWritable::complete_pointers(p_list, manager);
// Get the state and transform pointers.
cdata->_state = DCAST(RenderState, p_list[pi++]);
cdata->_transform = DCAST(TransformState, p_list[pi++]);
// Get the child pointers.
Down::iterator ci;
for (ci = cdata->_down.begin(); ci != cdata->_down.end(); ++ci) {
int sort = (*ci).get_sort();
PT(PandaNode) node = DCAST(PandaNode, p_list[pi++]);
(*ci) = DownConnection(node, sort);
}
return pi;
}
////////////////////////////////////////////////////////////////////
@ -934,4 +985,23 @@ make_from_bam(const FactoryParams &params) {
////////////////////////////////////////////////////////////////////
void PandaNode::
fillin(DatagramIterator &scan, BamReader *manager) {
CDWriter cdata(_cycler);
TypedWritable::fillin(scan, manager);
string name = scan.get_string();
set_name(name);
// Read the state and transform pointers.
manager->read_pointer(scan, this);
manager->read_pointer(scan, this);
int num_children = scan.get_uint16();
// Read the list of child nodes. Push back a NULL for each one.
cdata->_down.reserve(num_children);
for (int i = 0; i < num_children; i++) {
manager->read_pointer(scan, this);
int sort = scan.get_int32();
cdata->_down.push_back(DownConnection(NULL, sort));
}
}

View File

@ -235,6 +235,8 @@ public:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);

View File

@ -182,7 +182,7 @@ r_traverse(PandaNode *node,
if (node->is_final()) {
// The bounding volume is partially, but not completely,
// within the viewing frustum. Normally we'd keep testing
// child bounded volumes as we continue down. But this node
// child bounding volumes as we continue down. But this node
// has the "final" flag, so the user is claiming that there is
// some important reason we should consider everything visible
// at this point. So be it.

View File

@ -212,6 +212,42 @@ register_with_read_factory() {
void qpGeomNode::
write_datagram(BamWriter *manager, Datagram &dg) {
PandaNode::write_datagram(manager, dg);
CDReader cdata(_cycler);
int num_geoms = cdata->_geoms.size();
nassertv(num_geoms == (int)(PN_uint16)num_geoms);
dg.add_uint16(num_geoms);
Geoms::const_iterator gi;
for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
const GeomEntry &entry = (*gi);
manager->write_pointer(dg, entry._geom);
manager->write_pointer(dg, entry._state);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomNode::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int qpGeomNode::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
CDWriter cdata(_cycler);
int pi = PandaNode::complete_pointers(p_list, manager);
// Get the geom and state pointers.
Geoms::iterator gi;
for (gi = cdata->_geoms.begin(); gi != cdata->_geoms.end(); ++gi) {
GeomEntry &entry = (*gi);
entry._geom = DCAST(Geom, p_list[pi++]);
entry._state = DCAST(RenderState, p_list[pi++]);
}
return pi;
}
////////////////////////////////////////////////////////////////////
@ -243,5 +279,16 @@ make_from_bam(const FactoryParams &params) {
////////////////////////////////////////////////////////////////////
void qpGeomNode::
fillin(DatagramIterator &scan, BamReader *manager) {
CDWriter cdata(_cycler);
PandaNode::fillin(scan, manager);
int num_geoms = scan.get_uint16();
// Read the list of geoms and states. Push back a NULL for each one.
cdata->_geoms.reserve(num_geoms);
for (int i = 0; i < num_geoms; i++) {
manager->read_pointer(scan, this);
manager->read_pointer(scan, this);
cdata->_geoms.push_back(GeomEntry(NULL, NULL));
}
}

View File

@ -91,6 +91,8 @@ private:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);

View File

@ -218,7 +218,40 @@ make_default_impl() const {
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void RenderAttrib::
write_datagram(BamWriter *, Datagram &) {
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::change_this
// Access: Public, Static
// Description: Called immediately after complete_pointers(), this
// gives the object a chance to adjust its own pointer
// if desired. Most objects don't change pointers after
// completion, but some need to.
//
// Once this function has been called, the old pointer
// will no longer be accessed.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderAttrib::
change_this(TypedWritable *old_ptr, BamReader *manager) {
// First, uniquify the pointer.
RenderAttrib *attrib = DCAST(RenderAttrib, old_ptr);
CPT(RenderAttrib) pointer = return_new(attrib);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == attrib) {
pointer->ref();
manager->register_finalize(attrib);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderAttrib *)pointer.p();
}
////////////////////////////////////////////////////////////////////
@ -240,33 +273,6 @@ finalize() {
nassertv(get_ref_count() != 0);
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::new_from_bam
// Access: Protected, Static
// Description: Uniquifies the pointer for a RenderAttrib object just
// created from a bam file, and preserves its reference
// count correctly.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderAttrib::
new_from_bam(RenderAttrib *attrib, BamReader *manager) {
// First, uniquify the pointer.
CPT(RenderAttrib) pointer = return_new(attrib);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == attrib) {
pointer->ref();
manager->register_finalize(attrib);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderAttrib *)pointer.p();
}
////////////////////////////////////////////////////////////////////
// Function: RenderAttrib::fillin
// Access: Protected
@ -276,4 +282,5 @@ new_from_bam(RenderAttrib *attrib, BamReader *manager) {
////////////////////////////////////////////////////////////////////
void RenderAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
}

View File

@ -81,6 +81,7 @@ private:
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
virtual void finalize();
protected:

View File

@ -30,6 +30,19 @@ Attribute(const RenderAttrib *attrib, int override) :
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Attribute::Constructor
// Access: Public
// Description: This constructor is only used when reading the
// RenderState from a bam file. At this point, the
// attribute pointer is unknown.
////////////////////////////////////////////////////////////////////
INLINE RenderState::Attribute::
Attribute(int override) :
_override(override)
{
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::Attribute::Constructor
// Access: Public

View File

@ -929,13 +929,91 @@ register_with_read_factory() {
////////////////////////////////////////////////////////////////////
void RenderState::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
int num_attribs = _attributes.size();
nassertv(num_attribs == (int)(PN_uint16)num_attribs);
dg.add_uint16(num_attribs);
// **** We should smarten up the writing of the override
// number--most of the time these will all be zero.
Attributes::const_iterator ai;
for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
const Attribute &attribute = (*ai);
manager->write_pointer(dg, attribute._attrib);
dg.add_int32(attribute._override);
}
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int RenderState::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritable::complete_pointers(p_list, manager);
// Get the attribute pointers.
Attributes::iterator ai;
for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
Attribute &attribute = (*ai);
attribute._attrib = DCAST(RenderAttrib, p_list[pi++]);
nassertr(attribute._attrib != (RenderAttrib *)NULL, pi);
attribute._type = attribute._attrib->get_type();
}
// Now make sure the array is properly sorted. (It won't
// necessarily preserve its correct sort after being read from bam,
// because the sort is based on TypeHandle indices, which can change
// from session to session.)
_attributes.sort();
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::change_this
// Access: Public, Static
// Description: Called immediately after complete_pointers(), this
// gives the object a chance to adjust its own pointer
// if desired. Most objects don't change pointers after
// completion, but some need to.
//
// Once this function has been called, the old pointer
// will no longer be accessed.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderState::
change_this(TypedWritable *old_ptr, BamReader *manager) {
// First, uniquify the pointer.
RenderState *state = DCAST(RenderState, old_ptr);
CPT(RenderState) pointer = return_new(state);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == state) {
pointer->ref();
manager->register_finalize(state);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderState *)pointer.p();
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::finalize
// Access: Public, Virtual
// Description: Method to ensure that any necessary clean up tasks
// that have to be performed by this object are performed
// Description: Called by the BamReader to perform any final actions
// needed for setting up the object after all objects
// have been read and all pointers have been completed.
////////////////////////////////////////////////////////////////////
void RenderState::
finalize() {
@ -966,35 +1044,9 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
state->fillin(scan, manager);
manager->register_change_this(change_this, state);
return new_from_bam(state, manager);
}
////////////////////////////////////////////////////////////////////
// Function: RenderState::new_from_bam
// Access: Protected, Static
// Description: Uniquifies the pointer for a RenderState object just
// created from a bam file, and preserves its reference
// count correctly.
////////////////////////////////////////////////////////////////////
TypedWritable *RenderState::
new_from_bam(RenderState *state, BamReader *manager) {
// First, uniquify the pointer.
CPT(RenderState) pointer = return_new(state);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == state) {
pointer->ref();
manager->register_finalize(state);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (RenderState *)pointer.p();
return state;
}
////////////////////////////////////////////////////////////////////
@ -1006,4 +1058,16 @@ new_from_bam(RenderState *state, BamReader *manager) {
////////////////////////////////////////////////////////////////////
void RenderState::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
int num_attribs = scan.get_uint16();
// Push back a NULL pointer for each attribute for now, until we get
// the actual list of pointers later in complete_pointers().
_attributes.reserve(num_attribs);
for (int i = 0; i < num_attribs; i++) {
manager->read_pointer(scan, this);
int override = scan.get_int32();
_attributes.push_back(Attribute(override));
}
}

View File

@ -143,6 +143,7 @@ private:
class Attribute {
public:
INLINE Attribute(const RenderAttrib *attrib, int override);
INLINE Attribute(int override);
INLINE Attribute(TypeHandle type);
INLINE Attribute(const Attribute &copy);
INLINE void operator = (const Attribute &copy);
@ -173,11 +174,12 @@ private:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
virtual void finalize();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
static TypedWritable *new_from_bam(RenderState *state, BamReader *manager);
void fillin(DatagramIterator &scan, BamReader *manager);
public:

View File

@ -137,6 +137,27 @@ register_with_read_factory() {
void TextureAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
manager->write_pointer(dg, _texture);
}
////////////////////////////////////////////////////////////////////
// Function: TextureAttrib::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int TextureAttrib::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = RenderAttrib::complete_pointers(p_list, manager);
TypedWritable *texture = p_list[pi++];
if (texture != (TypedWritable *)NULL) {
_texture = DCAST(Texture, texture);
}
return pi;
}
////////////////////////////////////////////////////////////////////
@ -156,7 +177,7 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
return attrib;
}
////////////////////////////////////////////////////////////////////
@ -169,4 +190,7 @@ make_from_bam(const FactoryParams &params) {
void TextureAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
// Read the _texture pointer.
manager->read_pointer(scan, this);
}

View File

@ -55,6 +55,7 @@ private:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);

View File

@ -577,13 +577,69 @@ register_with_read_factory() {
////////////////////////////////////////////////////////////////////
void TransformState::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
if ((_flags & F_is_identity) != 0) {
// Identity, nothing much to that.
int flags = F_is_identity | F_singular_known;
dg.add_uint16(flags);
} else if ((_flags & F_components_given) != 0) {
// A component-based transform.
int flags = F_components_given | F_components_known | F_has_components;
dg.add_uint16(flags);
_pos.write_datagram(dg);
_hpr.write_datagram(dg);
_scale.write_datagram(dg);
} else {
// A general matrix.
nassertv((_flags & F_mat_known) != 0);
int flags = F_mat_known;
dg.add_uint16(flags);
_mat.write_datagram(dg);
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::change_this
// Access: Public, Static
// Description: Called immediately after complete_pointers(), this
// gives the object a chance to adjust its own pointer
// if desired. Most objects don't change pointers after
// completion, but some need to.
//
// Once this function has been called, the old pointer
// will no longer be accessed.
////////////////////////////////////////////////////////////////////
TypedWritable *TransformState::
change_this(TypedWritable *old_ptr, BamReader *manager) {
// First, uniquify the pointer.
TransformState *state = DCAST(TransformState, old_ptr);
CPT(TransformState) pointer = return_new(state);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == state) {
pointer->ref();
manager->register_finalize(state);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (TransformState *)pointer.p();
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::finalize
// Access: Public, Virtual
// Description: Method to ensure that any necessary clean up tasks
// that have to be performed by this object are performed
// Description: Called by the BamReader to perform any final actions
// needed for setting up the object after all objects
// have been read and all pointers have been completed.
////////////////////////////////////////////////////////////////////
void TransformState::
finalize() {
@ -614,35 +670,9 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
state->fillin(scan, manager);
manager->register_change_this(change_this, state);
return new_from_bam(state, manager);
}
////////////////////////////////////////////////////////////////////
// Function: TransformState::new_from_bam
// Access: Protected, Static
// Description: Uniquifies the pointer for a TransformState object just
// created from a bam file, and preserves its reference
// count correctly.
////////////////////////////////////////////////////////////////////
TypedWritable *TransformState::
new_from_bam(TransformState *state, BamReader *manager) {
// First, uniquify the pointer.
CPT(TransformState) pointer = return_new(state);
// But now we have a problem, since we have to hold the reference
// count and there's no way to return a TypedWritable while still
// holding the reference count! We work around this by explicitly
// upping the count, and also setting a finalize() callback to down
// it later.
if (pointer == state) {
pointer->ref();
manager->register_finalize(state);
}
// We have to cast the pointer back to non-const, because the bam
// reader expects that.
return (TransformState *)pointer.p();
return state;
}
////////////////////////////////////////////////////////////////////
@ -654,4 +684,19 @@ new_from_bam(TransformState *state, BamReader *manager) {
////////////////////////////////////////////////////////////////////
void TransformState::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
_flags = scan.get_uint16();
if ((_flags & F_components_known) != 0) {
// Componentwise transform.
_pos.read_datagram(scan);
_hpr.read_datagram(scan);
_scale.read_datagram(scan);
}
if ((_flags & F_mat_known) != 0) {
// General matrix.
_mat.read_datagram(scan);
}
}

View File

@ -151,11 +151,11 @@ private:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
static TypedWritable *change_this(TypedWritable *old_ptr, BamReader *manager);
virtual void finalize();
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
static TypedWritable *new_from_bam(TransformState *state, BamReader *manager);
void fillin(DatagramIterator &scan, BamReader *manager);
public:

View File

@ -142,6 +142,8 @@ register_with_read_factory() {
void TransparencyAttrib::
write_datagram(BamWriter *manager, Datagram &dg) {
RenderAttrib::write_datagram(manager, dg);
dg.add_int8(_mode);
}
////////////////////////////////////////////////////////////////////
@ -161,7 +163,7 @@ make_from_bam(const FactoryParams &params) {
parse_params(params, scan, manager);
attrib->fillin(scan, manager);
return new_from_bam(attrib, manager);
return attrib;
}
////////////////////////////////////////////////////////////////////
@ -174,4 +176,6 @@ make_from_bam(const FactoryParams &params) {
void TransparencyAttrib::
fillin(DatagramIterator &scan, BamReader *manager) {
RenderAttrib::fillin(scan, manager);
_mode = (Mode)scan.get_int8();
}

View File

@ -42,6 +42,7 @@ BamReader(DatagramGenerator *generator)
: _source(generator)
{
_num_extra_objects = 0;
_now_creating = _created_objs.end();
_pta_id = -1;
}
@ -177,7 +178,8 @@ read_object() {
return (TypedWritable *)NULL;
} else {
TypedWritable *object = (*oi).second;
CreatedObj &created_obj = (*oi).second;
TypedWritable *object = created_obj._ptr;
if (bam_cat.is_spam()) {
if (object != (TypedWritable *)NULL) {
@ -185,6 +187,11 @@ read_object() {
<< "Returning object of type " << object->get_type() << "\n";
}
}
if (created_obj._change_this != NULL) {
bam_cat.warning()
<< "Returning pointer to " << object->get_type()
<< " that might change.\n";
}
return object;
}
@ -210,68 +217,116 @@ read_object() {
////////////////////////////////////////////////////////////////////
bool BamReader::
resolve() {
bool all_completed = true;
bool all_completed;
bool any_completed_this_pass;
// Walk through all the objects that still have outstanding pointers.
Requests::iterator ri;
ri = _deferred_pointers.begin();
while (ri != _deferred_pointers.end()) {
TypedWritable *whom = (*ri).first;
const vector_ushort &pointers = (*ri).second;
do {
all_completed = true;
any_completed_this_pass = false;
// Now make sure we have all of the pointers this object is
// waiting for. If any of the pointers has not yet been read in,
// we can't resolve this object--we can't do anything for a given
// object until we have *all* outstanding pointers for that
// object.
bool is_complete = true;
vector_typedWritable references;
vector_ushort::const_iterator pi;
for (pi = pointers.begin(); pi != pointers.end() && is_complete; ++pi) {
int object_id = (*pi);
if (object_id == 0) {
// A NULL pointer is a NULL pointer.
references.push_back((TypedWritable *)NULL);
} else {
// See if we have the pointer available now.
CreatedObjs::const_iterator oi = _created_objs.find(object_id);
if (oi == _created_objs.end()) {
// No, too bad.
is_complete = false;
// Walk through all the objects that still have outstanding pointers.
Requests::iterator ri;
ri = _deferred_pointers.begin();
while (ri != _deferred_pointers.end()) {
int object_id = (*ri).first;
const vector_int &children = (*ri).second;
CreatedObjs::iterator ci = _created_objs.find(object_id);
nassertr(ci != _created_objs.end(), false);
CreatedObj &created_obj = (*ci).second;
TypedWritable *object_ptr = created_obj._ptr;
// Now make sure we have all of the pointers this object is
// waiting for. If any of the pointers has not yet been read
// in, we can't resolve this object--we can't do anything for a
// given object until we have *all* outstanding pointers for
// that object.
bool is_complete = true;
vector_typedWritable references;
vector_int::const_iterator pi;
for (pi = children.begin(); pi != children.end() && is_complete; ++pi) {
int child_id = (*pi);
if (child_id == 0) {
// A NULL pointer is a NULL pointer.
references.push_back((TypedWritable *)NULL);
} else {
// Yes, it's ready.
references.push_back((*oi).second);
// See if we have the pointer available now.
CreatedObjs::const_iterator oi = _created_objs.find(child_id);
if (oi == _created_objs.end()) {
// No, too bad.
is_complete = false;
} else {
const CreatedObj &child_obj = (*oi).second;
if (child_obj._change_this != NULL) {
// It's been created, but the pointer might still change.
is_complete = false;
} else {
// Yes, it's ready.
references.push_back(child_obj._ptr);
}
}
}
}
if (is_complete) {
// Okay, here's the complete list of pointers for you!
int num_completed = object_ptr->complete_pointers(&references[0], this);
if (num_completed != (int)references.size()) {
bam_cat.warning()
<< object_ptr->get_type() << " completed " << num_completed
<< " of " << references.size() << " pointers.\n";
}
// Now remove this object from the list of things that need
// completion. We have to be a bit careful when deleting things
// from the STL container while we are traversing it.
Requests::iterator old = ri;
++ri;
_deferred_pointers.erase(old);
// Does the pointer need to change?
if (created_obj._change_this != NULL) {
created_obj._ptr = created_obj._change_this(object_ptr, this);
created_obj._change_this = NULL;
}
any_completed_this_pass = true;
} else {
// Couldn't complete this object yet; it'll wait for next time.
++ri;
all_completed = false;
}
}
if (is_complete) {
// Okay, here's the complete list of pointers for you!
whom->complete_pointers(references, this);
// Now remove this object from the list of things that need
// completion. We have to be a bit careful when deleting things
// from the STL container while we are traversing it.
Requests::iterator old = ri;
++ri;
_deferred_pointers.erase(old);
} else {
// Couldn't complete this object yet; it'll wait for next time.
bam_cat.warning()
<< "Unable to complete " << whom->get_type() << "\n";
++ri;
all_completed = false;
}
}
} while (!all_completed && any_completed_this_pass);
if (all_completed) {
finalize();
} else {
// Report all the uncompleted objects for no good reason. This
// will probably have to come out later when we have cases in
// which some objects might legitimately be uncompleted after
// calling resolve(), but for now we expect resolve() to always
// succeed.
Requests::const_iterator ri;
for (ri = _deferred_pointers.begin();
ri != _deferred_pointers.end();
++ri) {
int object_id = (*ri).first;
CreatedObjs::iterator ci = _created_objs.find(object_id);
nassertr(ci != _created_objs.end(), false);
CreatedObj &created_obj = (*ci).second;
TypedWritable *object_ptr = created_obj._ptr;
bam_cat.warning()
<< "Unable to complete " << object_ptr->get_type() << "\n";
}
}
return all_completed;
@ -381,9 +436,26 @@ read_handle(DatagramIterator &scan) {
////////////////////////////////////////////////////////////////////
void BamReader::
read_pointer(DatagramIterator &scan, TypedWritable *for_whom) {
nassertv(_now_creating != _created_objs.end());
int requestor_id = (*_now_creating).first;
#ifndef NDEBUG
// A bit of sanity checking here: we look up the object ID, and
// assign the "this" pointer into the record if it's not there
// already. Then we can verify the "this" pointer later.
CreatedObj &created_obj = (*_now_creating).second;
if (created_obj._ptr == (TypedWritable *)NULL) {
created_obj._ptr = for_whom;
} else {
// We've previously assigned this pointer, and we should have
// assigned it to the same this pointer we have now.
nassertv(created_obj._ptr == for_whom);
}
#endif // NDEBUG
// Read the object ID, and associate it with the requesting object.
int object_id = scan.get_uint16();
_deferred_pointers[for_whom].push_back(object_id);
_deferred_pointers[requestor_id].push_back(object_id);
// If the object ID is zero (which indicates a NULL pointer), we
// don't have to do anything else.
@ -447,6 +519,44 @@ register_finalize(TypedWritable *whom) {
_finalize_list.insert(whom);
}
////////////////////////////////////////////////////////////////////
// Function: BamReader::register_change_this
// Access: Public
// Description: Called by an object reading itself from the bam file
// to indicate that the object pointer that will be
// returned is temporary, and will eventually need to be
// replaced with another pointer.
//
// The supplied function pointer will later be called on
// the object, immediately after complete_pointers() is
// called; it should return the new and final pointer.
//
// We use a static function pointer instead of a virtual
// function (as in finalize()), to allow the function to
// destruct the old pointer if necessary. (It is
// invalid to destruct the this pointer within a virtual
// function.)
////////////////////////////////////////////////////////////////////
void BamReader::
register_change_this(ChangeThisFunc func, TypedWritable *object) {
nassertv(_now_creating != _created_objs.end());
CreatedObj &created_obj = (*_now_creating).second;
#ifndef NDEBUG
// Sanity check the pointer--it should always be the same pointer
// after we set it the first time.
if (created_obj._ptr == (TypedWritable *)NULL) {
created_obj._ptr = object;
} else {
// We've previously assigned this pointer, and we should have
// assigned it to the same this pointer we have now.
nassertv(created_obj._ptr == object);
}
#endif // NDEBUG
created_obj._change_this = func;
}
////////////////////////////////////////////////////////////////////
// Function: BamReader::finalize_now
// Access: Public
@ -597,16 +707,43 @@ p_read_object() {
// First, we must add an entry into the map for this object ID, so
// that in case this function is called recursively during the
// object's factory constructor, we will have some definition for
// the object. It doesn't matter yet what the pointer is.
// the object. For now, we give it a NULL pointer.
CreatedObj new_created_obj;
new_created_obj._ptr = NULL;
new_created_obj._change_this = NULL;
CreatedObjs::iterator oi =
_created_objs.insert(CreatedObjs::value_type(object_id, NULL)).first;
_created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first;
CreatedObj &created_obj = (*oi).second;
// Now we can call the factory to create the object.
// Now we can call the factory to create the object. Update
// _now_creating during this call so if this function calls
// read_pointer() or register_change_this() we'll match it up
// properly. This might recursively call back into this
// p_read_object(), so be sure to save and restore the original
// value of _now_creating.
CreatedObjs::iterator was_creating = _now_creating;
_now_creating = oi;
TypedWritable *object =
_factory->make_instance_more_general(type, fparams);
_now_creating = was_creating;
// And now we can store the new object pointer in the map.
(*oi).second = object;
nassertr(created_obj._ptr == object || created_obj._ptr == NULL, object_id);
created_obj._ptr = object;
if (created_obj._change_this != NULL) {
// If the pointer is scheduled to change after
// complete_pointers(), but we have no entry in
// _deferred_pointers for this object (and hence no plan to call
// complete_pointers()), then just change the pointer
// immediately.
Requests::const_iterator ri = _deferred_pointers.find(object_id);
if (ri == _deferred_pointers.end()) {
object = created_obj._change_this(object, this);
created_obj._ptr = object;
created_obj._change_this = NULL;
}
}
//Just some sanity checks
if (object == (TypedWritable *)NULL) {

View File

@ -27,7 +27,7 @@
#include "datagramIterator.h"
#include "bamReaderParam.h"
#include "factory.h"
#include "vector_ushort.h"
#include "vector_int.h"
#include "pset.h"
#include "dcast.h"
@ -114,6 +114,9 @@ public:
void register_finalize(TypedWritable *whom);
typedef TypedWritable *(*ChangeThisFunc)(TypedWritable *object, BamReader *manager);
void register_change_this(ChangeThisFunc func, TypedWritable *whom);
void finalize_now(TypedWritable *whom);
void *get_pta(DatagramIterator &scan);
@ -143,13 +146,23 @@ private:
// This maps the object ID numbers encountered within the Bam file
// to the actual pointers of the corresponding generated objects.
typedef pmap<int, TypedWritable *> CreatedObjs;
class CreatedObj {
public:
TypedWritable *_ptr;
ChangeThisFunc _change_this;
};
typedef pmap<int, CreatedObj> CreatedObjs;
CreatedObjs _created_objs;
// This is the iterator into the above map for the object we are
// currently reading in p_read_object(). It is carefully maintained
// during recursion. We need this so we can associate
// read_pointer() calls with the proper objects.
CreatedObjs::iterator _now_creating;
// This records all the objects that still need their pointers
// completed, along with the object ID's of the pointers they need,
// in the order in which read_pointer() was called.
typedef pmap<TypedWritable *, vector_ushort> Requests;
typedef pmap<int, vector_int> Requests;
Requests _deferred_pointers;
// This is the number of extra objects that must still be read (and

View File

@ -97,7 +97,7 @@ init() {
// false otherwise.
////////////////////////////////////////////////////////////////////
bool BamWriter::
write_object(TypedWritable *object) {
write_object(const TypedWritable *object) {
nassertr(_object_queue.empty(), false);
int object_id = enqueue_object(object);
@ -132,7 +132,14 @@ write_object(TypedWritable *object) {
write_handle(dg, type);
dg.add_uint16(object_id);
object->write_datagram(this, dg);
// We cast the const pointer to non-const so that we may call
// write_datagram() on it. Really, write_datagram() should be a
// const method anyway, but there may be times when a class
// object wants to update some transparent cache value during
// writing or something like that, so it's more convenient to
// cheat and define it as a non-const method.
((TypedWritable *)object)->write_datagram(this, dg);
(*si).second._written = true;
} else {
@ -170,10 +177,10 @@ write_object(TypedWritable *object) {
// automatically be written.
////////////////////////////////////////////////////////////////////
void BamWriter::
write_pointer(Datagram &packet, TypedWritable *object) {
write_pointer(Datagram &packet, const TypedWritable *object) {
// If the pointer is NULL, we always simply write a zero for an
// object ID and leave it at that.
if (object == (TypedWritable *)NULL) {
if (object == (const TypedWritable *)NULL) {
packet.add_uint16(0);
} else {
@ -211,8 +218,8 @@ write_pointer(Datagram &packet, TypedWritable *object) {
// the work that must be done to write a PTA.
////////////////////////////////////////////////////////////////////
bool BamWriter::
register_pta(Datagram &packet, void *ptr) {
if (ptr == (void *)NULL) {
register_pta(Datagram &packet, const void *ptr) {
if (ptr == (const void *)NULL) {
// A zero for the PTA ID indicates a NULL pointer. This is a
// special case.
packet.add_uint16(0);
@ -313,7 +320,7 @@ write_handle(Datagram &packet, TypeHandle type) {
// an error.
////////////////////////////////////////////////////////////////////
int BamWriter::
enqueue_object(TypedWritable *object) {
enqueue_object(const TypedWritable *object) {
Datagram dg;
nassertr(object != TypedWritable::Null, 0);

View File

@ -77,17 +77,17 @@ public:
// The primary interface for a caller.
bool init();
bool write_object(TypedWritable *obj);
bool write_object(const TypedWritable *obj);
public:
// Functions to support classes that write themselves to the Bam.
void write_pointer(Datagram &packet, TypedWritable *dest);
bool register_pta(Datagram &packet, void *ptr);
void write_pointer(Datagram &packet, const TypedWritable *dest);
bool register_pta(Datagram &packet, const void *ptr);
void write_handle(Datagram &packet, TypeHandle type);
private:
int enqueue_object(TypedWritable *object);
int enqueue_object(const TypedWritable *object);
// This is the set of all TypeHandles already written.
@ -103,7 +103,7 @@ private:
StoreState(int object_id) : _object_id(object_id), _written(false) {}
};
typedef pmap<TypedWritable *, StoreState> StateMap;
typedef pmap<const TypedWritable *, StoreState> StateMap;
StateMap _state_map;
// This is the next object ID that will be assigned to a new object.
@ -111,12 +111,12 @@ private:
// This is the queue of objects that need to be written when the
// current object is finished.
typedef pdeque<TypedWritable *> ObjectQueue;
typedef pdeque<const TypedWritable *> ObjectQueue;
ObjectQueue _object_queue;
// These are used by register_pta() to unify multiple references to
// the same PointerToArray.
typedef pmap<void *, int> PTAMap;
typedef pmap<const void *, int> PTAMap;
PTAMap _pta_map;
int _next_pta_id;

View File

@ -82,7 +82,7 @@ fillin(Person* me, DatagramIterator& scan, BamReader* manager)
}
int Person::
complete_pointers(vector_typedWritable& p_list, BamReader *)
complete_pointers(TypedWritable **p_list, BamReader *)
{
_bro = (p_list[0] == TypedWritable::Null) ? (Person*)NULL : DCAST(Person, p_list[0]);
_sis = (p_list[1] == TypedWritable::Null) ? (Person*)NULL : DCAST(Person, p_list[1]);
@ -127,7 +127,7 @@ fillin(Parent* me, DatagramIterator& scan, BamReader* manager)
}
int Parent::
complete_pointers(vector_typedWritable& p_list, BamReader *manager)
complete_pointers(TypedWritable *p_list, BamReader *manager)
{
int start = Person::complete_pointers(p_list, manager);
_son = (p_list[start] == TypedWritable::Null) ? (Child*)NULL : DCAST(Child, p_list[2]);
@ -187,7 +187,7 @@ fillin(Child* me, DatagramIterator& scan, BamReader* manager)
}
int Child::
complete_pointers(vector_typedWritable& p_list, BamReader *manager)
complete_pointers(TypedWritable ** p_list, BamReader *manager)
{
int start = Person::complete_pointers(p_list, manager);
_dad = (p_list[start] == TypedWritable::Null) ? (Parent*)NULL : DCAST(Parent, p_list[2]);

View File

@ -38,7 +38,7 @@ public:
void write_datagram(BamWriter*, Datagram&);
static TypedWritable *make_person(const FactoryParams &params);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
protected:
void fillin(Person*,DatagramIterator&,BamReader*);
@ -93,7 +93,7 @@ public:
void write_datagram(BamWriter*, Datagram&);
static TypedWritable *make_parent(const FactoryParams &params);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable *p_list,
BamReader *manager);
protected:
void fillin(Parent*,DatagramIterator&,BamReader*);
@ -139,7 +139,7 @@ public:
void write_datagram(BamWriter*, Datagram&);
static TypedWritable *make_child(const FactoryParams &params);
virtual int complete_pointers(vector_typedWritable &p_list,
virtual int complete_pointers(TypedWritable **p_list,
BamReader *manager);
protected:
void fillin(Child*,DatagramIterator&,BamReader*);

View File

@ -26,20 +26,72 @@ TypedWritable* const TypedWritable::Null = (TypedWritable*)0L;
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
TypedWritable::~TypedWritable()
{
TypedWritable::~TypedWritable() {
}
////////////////////////////////////////////////////////////////////
// Function: TypedWritable::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void TypedWritable::
write_datagram(BamWriter *, Datagram &) {
}
////////////////////////////////////////////////////////////////////
// Function: TypedWritable::complete_pointers
// Access: Public, Virtual
// Description: Takes in a vector of pointers to TypedWritable
// objects that correspond to all the requests for
// pointers that this object made to BamReader.
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
//
// This is the callback function that is made by the
// BamReader at some later point, after all of the
// required pointers have been filled in. It is
// necessary because there might be forward references
// in a bam file; when we call read_pointer() in
// fillin(), the object may not have been read from the
// file yet, so we do not have a pointer available at
// that time. Thus, instead of returning a pointer,
// read_pointer() simply reserves a later callback.
// This function provides that callback. The calling
// object is responsible for keeping track of the number
// of times it called read_pointer() and extracting the
// same number of pointers out of the supplied vector,
// and storing them appropriately within the object.
////////////////////////////////////////////////////////////////////
int TypedWritable::
complete_pointers(vector_typedWritable &, BamReader*)
{
complete_pointers(TypedWritable **, BamReader *) {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: TypedWritable::finalize
// Access: Public, Virtual
// Description: Called by the BamReader to perform any final actions
// needed for setting up the object after all objects
// have been read and all pointers have been completed.
////////////////////////////////////////////////////////////////////
void TypedWritable::
finalize() {
}
////////////////////////////////////////////////////////////////////
// Function: TypedWritable::fillin
// Access: Protected
// Description: This internal function is intended to be called by
// each class's make_from_bam() method to read in all of
// the relevant data from the BamFile for the new
// object.
//
// It is defined at the TypedWritable level so that
// derived classes may call up the inheritance chain
// from their own fillin() method.
////////////////////////////////////////////////////////////////////
void TypedWritable::
fillin(DatagramIterator &, BamReader *) {
}

View File

@ -27,20 +27,11 @@ class BamReader;
////////////////////////////////////////////////////////////////////
// Class : TypedWritable
// Description : Convience class to not have to derive from TypedObject
// and writable all the time
//
// Important : Every class derived from TypedWritable that is
// not an abstract class, MUST define a factory method
// for creating and object of that type. This method
// must be static. This method must be of the form
// static <class type*> make_<appropriate name>(const FactoryParams &)
// Also, in the config file for each package, make sure
// to add in code to the ConfigureFN to register the
// creation function with BamReader's factory.
// Description : Base class for objects that can be written to and
// read from Bam files.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TypedWritable : public TypedObject, public Writable {
class EXPCL_PANDA TypedWritable : public TypedObject {
public:
static TypedWritable* const Null;
@ -50,30 +41,14 @@ public:
virtual ~TypedWritable();
//The essential virtual function interface to define
//how any writable object, writes itself to a datagram
virtual void write_datagram(BamWriter *, Datagram &) = 0;
virtual void write_datagram(BamWriter *, Datagram &);
//This function is the interface through which BamReader is
//able to pass the completed object references into each
//object that requested them.
//In other words, if an object (when it is creating itself
//from a datagram) requests BamReader to generate an object
//that this object points to, this is the function that is
//eventually called by BamReader to complete those references.
//Return the number of pointers read. This is useful for when
//a parent reads in a variable number of pointers, so the child
//knows where to start reading from.
virtual int complete_pointers(vector_typedWritable &p_list,
BamReader *manager);
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager);
virtual void finalize();
protected:
//This interface function is written here, as a suggestion
//for a function to write in any class that will have children
//that are also TypedWritable. To encourage code re-use
//virtual void fillin(TypedWritable*, DatagramIterator&, BamReader *);
void fillin(DatagramIterator &scan, BamReader *manager);
PUBLISHED:
static TypeHandle get_class_type() {
@ -82,6 +57,9 @@ PUBLISHED:
public:
static void init_type() {
// We no longer derive from Writable, but we continue to record
// that derivation for now, just to keep bam files consistent
// until we move to bam version 4.0.
TypedObject::init_type();
Writable::init_type();
register_type(_type_handle, "TypedWritable",

View File

@ -58,7 +58,7 @@ public:
//Return the number of pointers read. This is useful for when
//a parent reads in a variable number of pointers, so the child
//knows where to start reading from.
//virtual int complete_pointers(vector_typedWritable &p_list,
//virtual int complete_pointers(TypedWritable **p_list,
// BamReader *manager) {}

View File

@ -145,7 +145,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int MaterialTransition::
complete_pointers(vector_typedWritable &p_list, BamReader *) {
complete_pointers(TypedWritable **p_list, BamReader *) {
if (p_list[0] == TypedWritable::Null) {
if (sgattrib_cat.is_debug()) {
sgattrib_cat->debug()

View File

@ -58,7 +58,7 @@ private:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
protected:

View File

@ -146,7 +146,7 @@ write_datagram(BamWriter *manager, Datagram &me) {
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int TextureTransition::
complete_pointers(vector_typedWritable &p_list, BamReader *) {
complete_pointers(TypedWritable **p_list, BamReader *) {
if (p_list[0] == TypedWritable::Null) {
if (sgattrib_cat.is_debug()) {
sgattrib_cat->debug()

View File

@ -70,7 +70,7 @@ private:
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
protected:

View File

@ -464,7 +464,7 @@ write_datagram(BamWriter *manager, Datagram &me)
// pointers that this object made to BamReader.
////////////////////////////////////////////////////////////////////
int GeomNode::
complete_pointers(vector_typedWritable &p_list, BamReader* manager)
complete_pointers(TypedWritable **p_list, BamReader* manager)
{
int start = NamedNode::complete_pointers(p_list, manager);
for(int i = start; i < _num_geoms+start; i++)

View File

@ -88,7 +88,7 @@ private:
public:
static void register_with_read_factory(void);
virtual void write_datagram(BamWriter* manager, Datagram &me);
virtual int complete_pointers(vector_typedWritable &plist,
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
static TypedWritable *make_GeomNode(const FactoryParams &params);

View File

@ -26,14 +26,12 @@
#end bin_target
#begin test_bin_target
#begin bin_target
#define TARGET pview
#define SOURCES \
pview.cxx
#define LOCAL_LIBS egg2pg pgraph $[LOCAL_LIBS]
#end test_bin_target
#end bin_target
#begin test_bin_target
#define TARGET open_window

View File

@ -32,10 +32,8 @@
#include "geomTri.h"
#include "texture.h"
#include "texturePool.h"
// To load egg files directly.
#include "qpload_egg_file.h"
#include "eggData.h"
#include "dSearchPath.h"
#include "loader.h"
// These are in support of legacy data graph operations.
#include "namedNode.h"
@ -199,13 +197,20 @@ get_models(PandaNode *parent, int argc, char *argv[]) {
make_default_geometry(parent);
} else {
Loader loader;
DSearchPath local_path(".");
for (int i = 1; i < argc; i++) {
Filename filename = argv[i];
cerr << "Loading " << filename << "\n";
EggData::resolve_egg_filename(filename);
PT(PandaNode) node = qpload_egg_file(filename);
// First, we always try to resolve a filename from the current
// directory. This means a local filename will always be found
// before the model path is searched.
filename.resolve_filename(local_path);
PT(PandaNode) node = loader.qpload_sync(filename);
if (node == (PandaNode *)NULL) {
cerr << "Unable to load " << filename << "\n";