From 209c02fc6e3d6d8dc9512d53c830985a113e7343 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 13 Oct 2004 13:37:06 +0000 Subject: [PATCH] add XFileNode::is_standard_object() --- pandatool/src/xfile/xFile.cxx | 55 ++++++++++++----- pandatool/src/xfile/xFileArrayDef.cxx | 32 ++++++++++ pandatool/src/xfile/xFileArrayDef.h | 3 + pandatool/src/xfile/xFileDataDef.cxx | 39 ++++++++++++ pandatool/src/xfile/xFileDataDef.h | 2 + pandatool/src/xfile/xFileDataNodeTemplate.cxx | 18 ++++++ pandatool/src/xfile/xFileDataNodeTemplate.h | 3 + pandatool/src/xfile/xFileNode.cxx | 60 ++++++++++++++++++- pandatool/src/xfile/xFileNode.h | 11 ++-- pandatool/src/xfile/xFileTemplate.I | 14 +++++ pandatool/src/xfile/xFileTemplate.cxx | 23 +++++++ pandatool/src/xfile/xFileTemplate.h | 7 +++ 12 files changed, 246 insertions(+), 21 deletions(-) diff --git a/pandatool/src/xfile/xFile.cxx b/pandatool/src/xfile/xFile.cxx index 0b95428f6b..76e1966487 100644 --- a/pandatool/src/xfile/xFile.cxx +++ b/pandatool/src/xfile/xFile.cxx @@ -207,18 +207,27 @@ write(ostream &out) const { //////////////////////////////////////////////////////////////////// XFileTemplate *XFile:: find_template(const string &name) const { + XFileTemplate *standard = (XFileTemplate *)NULL; + const XFile *standard_templates = get_standard_templates(); + if (standard_templates != this) { + standard = standard_templates->find_template(name); + } + XFileNode *child = find_child(name); if (child != (XFileNode *)NULL && child->is_of_type(XFileTemplate::get_class_type())) { - return DCAST(XFileTemplate, child); + XFileTemplate *xtemplate = DCAST(XFileTemplate, child); + if (standard != (XFileTemplate *)NULL && xtemplate->matches(standard)) { + // If the template matches a standard template, return the + // standard instead. The assumption is that code may expect a + // certain naming scheme for the data elements of the standard + // template, so we want to be sure to provide it. + return standard; + } + return xtemplate; } - const XFile *standard_templates = get_standard_templates(); - if (standard_templates != this) { - return standard_templates->find_template(name); - } - - return NULL; + return standard; } //////////////////////////////////////////////////////////////////// @@ -229,19 +238,28 @@ find_template(const string &name) const { //////////////////////////////////////////////////////////////////// XFileTemplate *XFile:: find_template(const WindowsGuid &guid) const { + XFileTemplate *standard = (XFileTemplate *)NULL; + const XFile *standard_templates = get_standard_templates(); + if (standard_templates != this) { + standard = standard_templates->find_template(guid); + } + NodesByGuid::const_iterator gi; gi = _nodes_by_guid.find(guid); if (gi != _nodes_by_guid.end() && (*gi).second->is_of_type(XFileTemplate::get_class_type())) { - return DCAST(XFileTemplate, (*gi).second); + XFileTemplate *xtemplate = DCAST(XFileTemplate, (*gi).second); + if (standard != (XFileTemplate *)NULL && xtemplate->matches(standard)) { + // If the template matches a standard template, return the + // standard instead. The assumption is that code may expect a + // certain naming scheme for the data elements of the standard + // template, so we want to be sure to provide it. + return standard; + } + return xtemplate; } - const XFile *standard_templates = get_standard_templates(); - if (standard_templates != this) { - return standard_templates->find_template(guid); - } - - return NULL; + return standard; } //////////////////////////////////////////////////////////////////// @@ -497,6 +515,15 @@ get_standard_templates() { xfile_cat.error() << "Internal error: Unable to parse built-in standardTemplates.x!\n"; } + + // Now flag all of these templates as "standard". + for (int i = 0; i < _standard_templates->get_num_children(); i++) { + XFileNode *child = _standard_templates->get_child(i); + if (child->is_of_type(XFileTemplate::get_class_type())) { + XFileTemplate *xtemplate = DCAST(XFileTemplate, child); + xtemplate->_is_standard = true; + } + } } return _standard_templates; diff --git a/pandatool/src/xfile/xFileArrayDef.cxx b/pandatool/src/xfile/xFileArrayDef.cxx index fd0e3c4215..2b294f5d51 100644 --- a/pandatool/src/xfile/xFileArrayDef.cxx +++ b/pandatool/src/xfile/xFileArrayDef.cxx @@ -56,3 +56,35 @@ output(ostream &out) const { out << "[" << _dynamic_size->get_name() << "]"; } } + +//////////////////////////////////////////////////////////////////// +// Function: XFileArrayDef::matches +// Access: Public, Virtual +// Description: Returns true if the node, particularly a template +// node, is structurally equivalent to the other node +// (which must be of the same type). This checks data +// element types, but does not compare data element +// names. +//////////////////////////////////////////////////////////////////// +bool XFileArrayDef:: +matches(const XFileArrayDef &other, const XFileDataDef *parent, + const XFileDataDef *other_parent) const { + if (other.is_fixed_size() != is_fixed_size()) { + return false; + } + if (is_fixed_size()) { + if (other.get_fixed_size() != get_fixed_size()) { + return false; + } + + } else { + int child_index = parent->find_child_index(get_dynamic_size()); + int other_child_index = + other_parent->find_child_index(other.get_dynamic_size()); + if (other_child_index != child_index) { + return false; + } + } + + return true; +} diff --git a/pandatool/src/xfile/xFileArrayDef.h b/pandatool/src/xfile/xFileArrayDef.h index 1b4107629d..4856fab86a 100644 --- a/pandatool/src/xfile/xFileArrayDef.h +++ b/pandatool/src/xfile/xFileArrayDef.h @@ -43,6 +43,9 @@ public: void output(ostream &out) const; + bool matches(const XFileArrayDef &other, const XFileDataDef *parent, + const XFileDataDef *other_parent) const; + private: int _fixed_size; XFileDataDef *_dynamic_size; diff --git a/pandatool/src/xfile/xFileDataDef.cxx b/pandatool/src/xfile/xFileDataDef.cxx index 97391b2693..df07b79a84 100644 --- a/pandatool/src/xfile/xFileDataDef.cxx +++ b/pandatool/src/xfile/xFileDataDef.cxx @@ -253,6 +253,45 @@ fill_zero_data(XFileDataObject *object) const { return XFileNode::fill_zero_data(object); } +//////////////////////////////////////////////////////////////////// +// Function: XFileDataDef::matches +// Access: Public, Virtual +// Description: Returns true if the node, particularly a template +// node, is structurally equivalent to the other node +// (which must be of the same type). This checks data +// element types, but does not compare data element +// names. +//////////////////////////////////////////////////////////////////// +bool XFileDataDef:: +matches(const XFileNode *other) const { + if (!XFileNode::matches(other)) { + return false; + } + + const XFileDataDef *data_def = DCAST(XFileDataDef, other); + if (data_def->get_data_type() != get_data_type()) { + return false; + } + + if (get_data_type() == T_template && + !get_template()->matches(data_def->get_template())) { + return false; + } + + if (data_def->get_num_array_defs() != get_num_array_defs()) { + return false; + } + + for (int i = 0; i < get_num_array_defs(); i++) { + if (!get_array_def(i).matches(data_def->get_array_def(i), + this, data_def)) { + return false; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: XFileDataDef::unpack_integer_value diff --git a/pandatool/src/xfile/xFileDataDef.h b/pandatool/src/xfile/xFileDataDef.h index 8374206171..2315a8c259 100644 --- a/pandatool/src/xfile/xFileDataDef.h +++ b/pandatool/src/xfile/xFileDataDef.h @@ -75,6 +75,8 @@ public: virtual bool fill_zero_data(XFileDataObject *object) const; + virtual bool matches(const XFileNode *other) const; + private: typedef PT(XFileDataObject) (XFileDataDef::*UnpackMethod)(const XFileParseDataList &parse_data_list, diff --git a/pandatool/src/xfile/xFileDataNodeTemplate.cxx b/pandatool/src/xfile/xFileDataNodeTemplate.cxx index a19221d0ac..f8673d7313 100644 --- a/pandatool/src/xfile/xFileDataNodeTemplate.cxx +++ b/pandatool/src/xfile/xFileDataNodeTemplate.cxx @@ -36,6 +36,24 @@ XFileDataNodeTemplate(XFile *x_file, const string &name, { } +//////////////////////////////////////////////////////////////////// +// Function: XFileDataNodeTemplate::is_standard_object +// Access: Public, Virtual +// Description: Returns true if this node represents an instance of +// the standard template with the indicated name, or +// false otherwise. If this returns true, the object +// must be of type XFileDataNodeTemplate. +//////////////////////////////////////////////////////////////////// +bool XFileDataNodeTemplate:: +is_standard_object(const string &template_name) const { + if (_template->is_standard() && + _template->get_name() == template_name) { + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////// // Function: XFileDataNodeTemplate::zero_fill // Access: Public diff --git a/pandatool/src/xfile/xFileDataNodeTemplate.h b/pandatool/src/xfile/xFileDataNodeTemplate.h index 0fc65c79d9..b4827ec700 100644 --- a/pandatool/src/xfile/xFileDataNodeTemplate.h +++ b/pandatool/src/xfile/xFileDataNodeTemplate.h @@ -39,6 +39,9 @@ class XFileDataNodeTemplate : public XFileDataNode { public: XFileDataNodeTemplate(XFile *x_file, const string &name, XFileTemplate *xtemplate); + + virtual bool is_standard_object(const string &template_name) const; + void zero_fill(); virtual bool is_complex_object() const; diff --git a/pandatool/src/xfile/xFileNode.cxx b/pandatool/src/xfile/xFileNode.cxx index 0ee57245a0..b0f5a08a4b 100644 --- a/pandatool/src/xfile/xFileNode.cxx +++ b/pandatool/src/xfile/xFileNode.cxx @@ -83,6 +83,23 @@ find_child_index(const string &name) const { return -1; } +//////////////////////////////////////////////////////////////////// +// Function: XFileNode::find_child_index +// Access: Public +// Description: Returns the index number of the indicated child, +// or -1 if none. +//////////////////////////////////////////////////////////////////// +int XFileNode:: +find_child_index(const XFileNode *child) const { + for (int i = 0; i < (int)_children.size(); i++) { + if (_children[i] == child) { + return i; + } + } + + return -1; +} + //////////////////////////////////////////////////////////////////// // Function: XFileNode::find_descendent // Access: Public @@ -131,8 +148,21 @@ get_guid() const { } //////////////////////////////////////////////////////////////////// -// Function: XFileNode::add_child +// Function: XFileNode::is_standard_object // Access: Public, Virtual +// Description: Returns true if this node represents an instance of +// the standard template with the indicated name, or +// false otherwise. If this returns true, the object +// must be of type XFileDataNodeTemplate. +//////////////////////////////////////////////////////////////////// +bool XFileNode:: +is_standard_object(const string &template_name) const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileNode::add_child +// Access: Public // Description: Adds the indicated node as a child of this node. //////////////////////////////////////////////////////////////////// void XFileNode:: @@ -225,6 +255,34 @@ fill_zero_data(XFileDataObject *object) const { return true; } +//////////////////////////////////////////////////////////////////// +// Function: XFileNode::matches +// Access: Public, Virtual +// Description: Returns true if the node, particularly a template +// node, is structurally equivalent to the other node +// (which must be of the same type). This checks data +// element types, but does not compare data element +// names. +//////////////////////////////////////////////////////////////////// +bool XFileNode:: +matches(const XFileNode *other) const { + if (other->get_type() != get_type()) { + return false; + } + + if (other->get_num_children() != get_num_children()) { + return false; + } + + for (int i = 0; i < get_num_children(); i++) { + if (!get_child(i)->matches(other->get_child(i))) { + return false; + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: XFileNode::add_Mesh // Access: Public diff --git a/pandatool/src/xfile/xFileNode.h b/pandatool/src/xfile/xFileNode.h index d5ebf28deb..42402e48ef 100644 --- a/pandatool/src/xfile/xFileNode.h +++ b/pandatool/src/xfile/xFileNode.h @@ -54,12 +54,15 @@ public: INLINE XFileNode *get_child(int n) const; XFileNode *find_child(const string &name) const; int find_child_index(const string &name) const; + int find_child_index(const XFileNode *child) const; XFileNode *find_descendent(const string &name) const; virtual bool has_guid() const; virtual const WindowsGuid &get_guid() const; - virtual void add_child(XFileNode *node); + virtual bool is_standard_object(const string &template_name) const; + + void add_child(XFileNode *node); virtual void clear(); virtual void write_text(ostream &out, int indent_level) const; @@ -73,16 +76,12 @@ public: virtual bool fill_zero_data(XFileDataObject *object) const; + virtual bool matches(const XFileNode *other) const; // The following methods can be used to create instances of the // standard template objects. These definitions match those defined // in standardTemplates.x in this directory (and compiled into the // executable). - /* - PT(XFileNode) make_Header(int major, int minor, int flags); - PT(XFileNode) make_Vector(const LVecBase3d &vector); - PT(XFileNode) make_MeshFace(int num_vertex_indices, const int *vertex_indices); - */ XFileDataNode *add_Mesh(const string &name); XFileDataNode *add_MeshNormals(const string &name); XFileDataNode *add_MeshVertexColors(const string &name); diff --git a/pandatool/src/xfile/xFileTemplate.I b/pandatool/src/xfile/xFileTemplate.I index 598f31255b..a33d599b21 100644 --- a/pandatool/src/xfile/xFileTemplate.I +++ b/pandatool/src/xfile/xFileTemplate.I @@ -17,6 +17,20 @@ //////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +// Function: XFileTemplate::is_standard +// Access: Public +// Description: Returns true if this particular template is one of +// the "standard" templates defined by +// standardTemplates.x in this directory (and compiled +// into the binary), or false if it is a user-custom +// template. +//////////////////////////////////////////////////////////////////// +INLINE bool XFileTemplate:: +is_standard() const { + return _is_standard; +} + //////////////////////////////////////////////////////////////////// // Function: XFileTemplate::set_open // Access: Public diff --git a/pandatool/src/xfile/xFileTemplate.cxx b/pandatool/src/xfile/xFileTemplate.cxx index f7f1f5a617..20dadc2c0e 100644 --- a/pandatool/src/xfile/xFileTemplate.cxx +++ b/pandatool/src/xfile/xFileTemplate.cxx @@ -30,6 +30,7 @@ XFileTemplate:: XFileTemplate(XFile *x_file, const string &name, const WindowsGuid &guid) : XFileNode(x_file, name), _guid(guid), + _is_standard(false), _open(false) { } @@ -115,3 +116,25 @@ write_text(ostream &out, int indent_level) const { indent(out, indent_level) << "}\n"; } + +//////////////////////////////////////////////////////////////////// +// Function: XFileTemplate::matches +// Access: Public, Virtual +// Description: Returns true if the node, particularly a template +// node, is structurally equivalent to the other node +// (which must be of the same type). This checks data +// element types, but does not compare data element +// names. +//////////////////////////////////////////////////////////////////// +bool XFileTemplate:: +matches(const XFileNode *other) const { + if (!XFileNode::matches(other)) { + return false; + } + + // We *could* compare the open/closed/options associated with the + // template, but since this is only used for validating the set of + // children for the instances of this template (which we don't even + // bother to do anyway), it doesn't seem to matter. + return true; +} diff --git a/pandatool/src/xfile/xFileTemplate.h b/pandatool/src/xfile/xFileTemplate.h index 4bd32afa22..2210d06198 100644 --- a/pandatool/src/xfile/xFileTemplate.h +++ b/pandatool/src/xfile/xFileTemplate.h @@ -41,15 +41,20 @@ public: virtual void clear(); virtual void write_text(ostream &out, int indent_level) const; + INLINE bool is_standard() const; + INLINE void set_open(bool open); INLINE bool get_open() const; INLINE void add_option(XFileTemplate *option); INLINE int get_num_options() const; INLINE XFileTemplate *get_option(int n) const; + + virtual bool matches(const XFileNode *other) const; private: WindowsGuid _guid; + bool _is_standard; bool _open; typedef pvector< PT(XFileTemplate) > Options; @@ -71,6 +76,8 @@ public: private: static TypeHandle _type_handle; + + friend class XFile; }; #include "xFileTemplate.I"