add XFileNode::is_standard_object()

This commit is contained in:
David Rose 2004-10-13 13:37:06 +00:00
parent 81aa4087ee
commit 209c02fc6e
12 changed files with 246 additions and 21 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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"