| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- // Filename: xFileNode.cxx
- // Created by: drose (03Oct04)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // PANDA 3D SOFTWARE
- // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
- //
- // All use of this software is subject to the terms of the Panda 3d
- // Software license. You should have received a copy of this license
- // along with this source code; you will also find a current copy of
- // the license at http://etc.cmu.edu/panda3d/docs/license/ .
- //
- // To contact the maintainers of this program write to
- // [email protected] .
- //
- ////////////////////////////////////////////////////////////////////
- #include "xFileNode.h"
- #include "windowsGuid.h"
- #include "xFile.h"
- #include "xLexerDefs.h"
- #include "xFileParseData.h"
- #include "xFile.h"
- #include "xFileDataNodeTemplate.h"
- #include "filename.h"
- #include "string_utils.h"
- TypeHandle XFileNode::_type_handle;
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::Constructor
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- XFileNode::
- XFileNode(XFile *x_file, const string &name) :
- Namable(make_nice_name(name)),
- _x_file(x_file)
- {
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::Destructor
- // Access: Public, Virtual
- // Description:
- ////////////////////////////////////////////////////////////////////
- XFileNode::
- ~XFileNode() {
- clear();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::find_child
- // Access: Public
- // Description: Returns the child with the indicated name, if any, or
- // NULL if none.
- ////////////////////////////////////////////////////////////////////
- XFileNode *XFileNode::
- find_child(const string &name) const {
- ChildrenByName::const_iterator ni;
- ni = _children_by_name.find(downcase(name));
- if (ni != _children_by_name.end()) {
- return get_child((*ni).second);
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::find_child_index
- // Access: Public
- // Description: Returns the index number of the child with the
- // indicated name, if any, or -1 if none.
- ////////////////////////////////////////////////////////////////////
- int XFileNode::
- find_child_index(const string &name) const {
- ChildrenByName::const_iterator ni;
- ni = _children_by_name.find(downcase(name));
- if (ni != _children_by_name.end()) {
- return (*ni).second;
- }
- 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
- // Description: Returns the first child or descendent found with the
- // indicated name after a depth-first search, if any, or
- // NULL if none.
- ////////////////////////////////////////////////////////////////////
- XFileNode *XFileNode::
- find_descendent(const string &name) const {
- XFileNode *child = find_child(name);
- if (child != (XFileNode *)NULL) {
- return child;
- }
- Children::const_iterator ci;
- for (ci = _children.begin(); ci != _children.end(); ++ci) {
- XFileNode *child = (*ci)->find_descendent(name);
- if (child != (XFileNode *)NULL){
- return child;
- }
- }
- return NULL;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::has_guid
- // Access: Public, Virtual
- // Description: Returns true if this node has a GUID associated.
- ////////////////////////////////////////////////////////////////////
- bool XFileNode::
- has_guid() const {
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::get_guid
- // Access: Public, Virtual
- // Description: If has_guid() returned true, returns the particular
- // GUID associated with this node.
- ////////////////////////////////////////////////////////////////////
- const WindowsGuid &XFileNode::
- get_guid() const {
- static WindowsGuid empty;
- return empty;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::is_template_def
- // Access: Public, Virtual
- // Description: Returns true if this node represents the definition
- // of some template. This is the template definition,
- // not an actual data object that represents an instance
- // of the template. If the file strictly uses standard
- // templates, the presence of template definitions is
- // optional.
- //
- // If this returns true, the node must be of type
- // XFileTemplate.
- ////////////////////////////////////////////////////////////////////
- bool XFileNode::
- is_template_def() const {
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::is_reference
- // Access: Public, Virtual
- // Description: Returns true if this node represents an indirect
- // reference to an object defined previously in the
- // file. References are generally transparent, so in
- // most cases you never need to call this, unless you
- // actually need to differentiate between references and
- // instances; you can simply use the reference node as
- // if it were itself the object it references.
- //
- // If this returns true, the node must be of type
- // XFileDataNodeReference.
- ////////////////////////////////////////////////////////////////////
- bool XFileNode::
- is_reference() const {
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::is_object
- // Access: Public, Virtual
- // Description: Returns true if this node represents a data object
- // that is the instance of some template, or false
- // otherwise. This also returns true for references to
- // objects (which are generally treated just like the
- // objects themselves).
- //
- // If this returns true, the node must be of type
- // XFileDataNode (it is either an XFileDataNodeTemplate
- // or an XFileDataNodeReference).
- ////////////////////////////////////////////////////////////////////
- bool XFileNode::
- is_object() const {
- return false;
- }
- ////////////////////////////////////////////////////////////////////
- // 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. This returns also returns true for
- // references to standard objects.
- //
- // If this returns true, the node must be of type
- // XFileDataNode (it is either an XFileDataNodeTemplate
- // or an XFileDataNodeReference).
- ////////////////////////////////////////////////////////////////////
- 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::
- add_child(XFileNode *node) {
- if (node->has_name()) {
- _children_by_name[downcase(node->get_name())] = (int)_children.size();
- }
- if (node->has_guid()) {
- _x_file->_nodes_by_guid[node->get_guid()] = node;
- }
- if (node->is_of_type(XFileDataNode::get_class_type())) {
- _objects.push_back(DCAST(XFileDataNode, node));
- }
- _children.push_back(node);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::clear
- // Access: Public, Virtual
- // Description: Removes all children from the node, and otherwise
- // resets it to its initial state.
- ////////////////////////////////////////////////////////////////////
- void XFileNode::
- clear() {
- _children.clear();
- _objects.clear();
- _children_by_name.clear();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::write_text
- // Access: Public, Virtual
- // Description: Writes a suitable representation of this node to an
- // .x file in text mode.
- ////////////////////////////////////////////////////////////////////
- void XFileNode::
- write_text(ostream &out, int indent_level) const {
- Children::const_iterator ci;
- for (ci = _children.begin(); ci != _children.end(); ++ci) {
- (*ci)->write_text(out, indent_level);
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::repack_data
- // Access: Public, Virtual
- // Description: This is called on the template that defines an
- // object, once the data for the object has been parsed.
- // It is responsible for identifying which component of
- // the template owns each data element, and packing the
- // data elements appropriately back into the object.
- //
- // It returns true on success, or false on an error
- // (e.g. not enough data elements, mismatched data
- // type).
- ////////////////////////////////////////////////////////////////////
- bool XFileNode::
- repack_data(XFileDataObject *object,
- const XFileParseDataList &parse_data_list,
- XFileNode::PrevData &prev_data,
- size_t &index, size_t &sub_index) const {
- // This method should be specialized for data types that actually
- // consume a data element. Here in the base class, it just walks
- // through its children, asking each one to pull off the appropriate
- // number of data elements.
- Children::const_iterator ci;
- for (ci = _children.begin(); ci != _children.end(); ++ci) {
- if (!(*ci)->repack_data(object, parse_data_list,
- prev_data, index, sub_index)) {
- return false;
- }
- }
- return true;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::fill_zero_data
- // Access: Public, Virtual
- // Description: This is similar to repack_data(), except it is used
- // to fill the initial values for a newly-created
- // template object to zero.
- ////////////////////////////////////////////////////////////////////
- bool XFileNode::
- fill_zero_data(XFileDataObject *object) const {
- Children::const_iterator ci;
- for (ci = _children.begin(); ci != _children.end(); ++ci) {
- if (!(*ci)->fill_zero_data(object)) {
- return false;
- }
- }
- 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
- // Description: Creates a new Mesh instance, as a child of this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_Mesh(const string &name) {
- XFileTemplate *xtemplate = XFile::find_standard_template("Mesh");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_MeshNormals
- // Access: Public
- // Description: Creates a new MeshNormals instance, as a child of
- // this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_MeshNormals(const string &name) {
- XFileTemplate *xtemplate = XFile::find_standard_template("MeshNormals");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_MeshVertexColors
- // Access: Public
- // Description: Creates a new MeshVertexColors instance, as a child of
- // this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_MeshVertexColors(const string &name) {
- XFileTemplate *xtemplate = XFile::find_standard_template("MeshVertexColors");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_MeshTextureCoords
- // Access: Public
- // Description: Creates a new MeshTextureCoords instance, as a child of
- // this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_MeshTextureCoords(const string &name) {
- XFileTemplate *xtemplate = XFile::find_standard_template("MeshTextureCoords");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_MeshMaterialList
- // Access: Public
- // Description: Creates a new MeshMaterialList instance, as a child of
- // this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_MeshMaterialList(const string &name) {
- XFileTemplate *xtemplate = XFile::find_standard_template("MeshMaterialList");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_Material
- // Access: Public
- // Description: Creates a new Material instance, as a child of
- // this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_Material(const string &name, const Colorf &face_color,
- double power, const RGBColorf &specular_color,
- const RGBColorf &emissive_color) {
- XFileTemplate *xtemplate = XFile::find_standard_template("Material");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- (*node)["faceColor"]["red"] = face_color[0];
- (*node)["faceColor"]["green"] = face_color[1];
- (*node)["faceColor"]["blue"] = face_color[2];
- (*node)["faceColor"]["alpha"] = face_color[3];
- (*node)["power"] = power;
- (*node)["specularColor"]["red"] = specular_color[0];
- (*node)["specularColor"]["green"] = specular_color[1];
- (*node)["specularColor"]["blue"] = specular_color[2];
- (*node)["emissiveColor"]["red"] = emissive_color[0];
- (*node)["emissiveColor"]["green"] = emissive_color[1];
- (*node)["emissiveColor"]["blue"] = emissive_color[2];
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_TextureFilename
- // Access: Public
- // Description: Creates a new TextureFilename instance, as a child of
- // this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_TextureFilename(const string &name, const Filename &filename) {
- XFileTemplate *xtemplate = XFile::find_standard_template("TextureFilename");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- (*node)["filename"] = filename.to_os_specific();
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_Frame
- // Access: Public
- // Description: Creates a new Frame instance, as a child of this
- // node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_Frame(const string &name) {
- XFileTemplate *xtemplate = XFile::find_standard_template("Frame");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
- add_child(node);
- node->zero_fill();
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::add_FrameTransformMatrix
- // Access: Public
- // Description: Creates a new FrameTransformMatrix instance, as a
- // child of this node.
- ////////////////////////////////////////////////////////////////////
- XFileDataNode *XFileNode::
- add_FrameTransformMatrix(const LMatrix4d &mat) {
- XFileTemplate *xtemplate =
- XFile::find_standard_template("FrameTransformMatrix");
- nassertr(xtemplate != (XFileTemplate *)NULL, NULL);
- XFileDataNodeTemplate *node =
- new XFileDataNodeTemplate(get_x_file(), "", xtemplate);
- add_child(node);
- node->zero_fill();
- XFileDataObject &xmat = (*node)["frameMatrix"]["matrix"];
- xmat[0] = mat(0, 0);
- xmat[1] = mat(0, 1);
- xmat[2] = mat(0, 2);
- xmat[3] = mat(0, 3);
- xmat[4] = mat(1, 0);
- xmat[5] = mat(1, 1);
- xmat[6] = mat(1, 2);
- xmat[7] = mat(1, 3);
- xmat[8] = mat(2, 0);
- xmat[9] = mat(2, 1);
- xmat[10] = mat(2, 2);
- xmat[11] = mat(2, 3);
- xmat[12] = mat(3, 0);
- xmat[13] = mat(3, 1);
- xmat[14] = mat(3, 2);
- xmat[15] = mat(3, 3);
- return node;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileNode::make_nice_name
- // Access: Protected, Static
- // Description: Transforms the indicated egg name to a name that is
- // acceptable for a node in the X File format.
- ////////////////////////////////////////////////////////////////////
- string XFileNode::
- make_nice_name(const string &str) {
- string result;
- string::const_iterator si;
- for (si = str.begin(); si != str.end(); ++si) {
- if (isalnum(*si)) {
- result += (*si);
- } else {
- switch (*si) {
- case '-':
- result += (*si);
- break;
- default:
- result += "_";
- }
- }
- }
- if (!str.empty() && isdigit(str[0])) {
- // If the name begins with a digit, we must make it begin with
- // something else, like for instance an underscore.
- result = '_' + result;
- }
- return result;
- }
|