Browse Source

add XFileNode::is_standard_object()

David Rose 21 years ago
parent
commit
209c02fc6e

+ 41 - 14
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);
-  }
-
-  const XFile *standard_templates = get_standard_templates();
-  if (standard_templates != this) {
-    return standard_templates->find_template(name);
+    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;
   }
 
-  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);
-  }
-
-  const XFile *standard_templates = get_standard_templates();
-  if (standard_templates != this) {
-    return standard_templates->find_template(guid);
+    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;
   }
 
-  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;

+ 32 - 0
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;
+}

+ 3 - 0
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;

+ 39 - 0
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

+ 2 - 0
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, 

+ 18 - 0
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

+ 3 - 0
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;

+ 59 - 1
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

+ 5 - 6
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);

+ 14 - 0
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

+ 23 - 0
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;
+}

+ 7 - 0
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"