Panda3D
Loading...
Searching...
No Matches
xFileNode.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file xFileNode.cxx
10 * @author drose
11 * @date 2004-10-03
12 */
13
14#include "xFileNode.h"
15#include "windowsGuid.h"
16#include "xFile.h"
17#include "xLexerDefs.h"
18#include "xFileParseData.h"
19#include "xFile.h"
21#include "filename.h"
22#include "string_utils.h"
23
24using std::string;
25
26TypeHandle XFileNode::_type_handle;
27
28/**
29 *
30 */
31XFileNode::
32XFileNode(XFile *x_file, const string &name) :
33 Namable(),
34 _x_file(x_file)
35{
36 if (x_file && x_file->_keep_names) {
37 set_name(name);
38 } else {
39 set_name(make_nice_name(name));
40 }
41}
42
43/**
44 *
45 */
46XFileNode::
47~XFileNode() {
48 clear();
49}
50
51/**
52 * Returns the child with the indicated name, if any, or NULL if none.
53 */
55find_child(const string &name) const {
56 ChildrenByName::const_iterator ni;
57 ni = _children_by_name.find(downcase(name));
58 if (ni != _children_by_name.end()) {
59 return get_child((*ni).second);
60 }
61
62 return nullptr;
63}
64
65/**
66 * Returns the index number of the child with the indicated name, if any, or
67 * -1 if none.
68 */
70find_child_index(const string &name) const {
71 ChildrenByName::const_iterator ni;
72 ni = _children_by_name.find(downcase(name));
73 if (ni != _children_by_name.end()) {
74 return (*ni).second;
75 }
76
77 return -1;
78}
79
80/**
81 * Returns the index number of the indicated child, or -1 if none.
82 */
84find_child_index(const XFileNode *child) const {
85 for (int i = 0; i < (int)_children.size(); i++) {
86 if (_children[i] == child) {
87 return i;
88 }
89 }
90
91 return -1;
92}
93
94/**
95 * Returns the first child or descendent found with the indicated name after a
96 * depth-first search, if any, or NULL if none.
97 */
99find_descendent(const string &name) const {
100 XFileNode *child = find_child(name);
101 if (child != nullptr) {
102 return child;
103 }
104
105 Children::const_iterator ci;
106 for (ci = _children.begin(); ci != _children.end(); ++ci) {
107 XFileNode *child = (*ci)->find_descendent(name);
108 if (child != nullptr){
109 return child;
110 }
111 }
112
113 return nullptr;
114}
115
116/**
117 * Returns true if this node has a GUID associated.
118 */
120has_guid() const {
121 return false;
122}
123
124/**
125 * If has_guid() returned true, returns the particular GUID associated with
126 * this node.
127 */
129get_guid() const {
130 static WindowsGuid empty;
131 return empty;
132}
133
134/**
135 * Returns true if this node represents the definition of some template. This
136 * is the template definition, not an actual data object that represents an
137 * instance of the template. If the file strictly uses standard templates,
138 * the presence of template definitions is optional.
139 *
140 * If this returns true, the node must be of type XFileTemplate.
141 */
143is_template_def() const {
144 return false;
145}
146
147/**
148 * Returns true if this node represents an indirect reference to an object
149 * defined previously in the file. References are generally transparent, so
150 * in most cases you never need to call this, unless you actually need to
151 * differentiate between references and instances; you can simply use the
152 * reference node as if it were itself the object it references.
153 *
154 * If this returns true, the node must be of type XFileDataNodeReference.
155 */
157is_reference() const {
158 return false;
159}
160
161/**
162 * Returns true if this node represents a data object that is the instance of
163 * some template, or false otherwise. This also returns true for references
164 * to objects (which are generally treated just like the objects themselves).
165 *
166 * If this returns true, the node must be of type XFileDataNode (it is either
167 * an XFileDataNodeTemplate or an XFileDataNodeReference).
168 */
170is_object() const {
171 return false;
172}
173
174/**
175 * Returns true if this node represents an instance of the standard template
176 * with the indicated name, or false otherwise. This returns also returns
177 * true for references to standard objects.
178 *
179 * If this returns true, the node must be of type XFileDataNode (it is either
180 * an XFileDataNodeTemplate or an XFileDataNodeReference).
181 */
183is_standard_object(const string &template_name) const {
184 return false;
185}
186
187/**
188 * Adds the indicated node as a child of this node.
189 */
191add_child(XFileNode *node) {
192 if (node->has_name()) {
193 _children_by_name[downcase(node->get_name())] = (int)_children.size();
194 }
195 if (node->has_guid()) {
196 _x_file->_nodes_by_guid[node->get_guid()] = node;
197 }
198 if (node->is_of_type(XFileDataNode::get_class_type())) {
199 _objects.push_back(DCAST(XFileDataNode, node));
200 }
201 _children.push_back(node);
202}
203
204/**
205 * Removes all children from the node, and otherwise resets it to its initial
206 * state.
207 */
209clear() {
210 _children.clear();
211 _objects.clear();
212 _children_by_name.clear();
213}
214
215/**
216 * Writes a suitable representation of this node to an .x file in text mode.
217 */
219write_text(std::ostream &out, int indent_level) const {
220 Children::const_iterator ci;
221 for (ci = _children.begin(); ci != _children.end(); ++ci) {
222 (*ci)->write_text(out, indent_level);
223 }
224}
225
226/**
227 * This is called on the template that defines an object, once the data for
228 * the object has been parsed. It is responsible for identifying which
229 * component of the template owns each data element, and packing the data
230 * elements appropriately back into the object.
231 *
232 * It returns true on success, or false on an error (e.g. not enough data
233 * elements, mismatched data type).
234 */
237 const XFileParseDataList &parse_data_list,
238 XFileNode::PrevData &prev_data,
239 size_t &index, size_t &sub_index) const {
240 // This method should be specialized for data types that actually consume a
241 // data element. Here in the base class, it just walks through its
242 // children, asking each one to pull off the appropriate number of data
243 // elements.
244
245 Children::const_iterator ci;
246 for (ci = _children.begin(); ci != _children.end(); ++ci) {
247 if (!(*ci)->repack_data(object, parse_data_list,
248 prev_data, index, sub_index)) {
249 return false;
250 }
251 }
252
253 return true;
254}
255
256/**
257 * This is similar to repack_data(), except it is used to fill the initial
258 * values for a newly-created template object to zero.
259 */
261fill_zero_data(XFileDataObject *object) const {
262 Children::const_iterator ci;
263 for (ci = _children.begin(); ci != _children.end(); ++ci) {
264 if (!(*ci)->fill_zero_data(object)) {
265 return false;
266 }
267 }
268
269 return true;
270}
271
272/**
273 * Returns true if the node, particularly a template node, is structurally
274 * equivalent to the other node (which must be of the same type). This checks
275 * data element types, but does not compare data element names.
276 */
278matches(const XFileNode *other) const {
279 if (other->get_type() != get_type()) {
280 return false;
281 }
282
283 if (other->get_num_children() != get_num_children()) {
284 return false;
285 }
286
287 for (int i = 0; i < get_num_children(); i++) {
288 if (!get_child(i)->matches(other->get_child(i))) {
289 return false;
290 }
291 }
292
293 return true;
294}
295
296/**
297 * Creates a new Mesh instance, as a child of this node.
298 */
300add_Mesh(const string &name) {
301 XFileTemplate *xtemplate = XFile::find_standard_template("Mesh");
302 nassertr(xtemplate != nullptr, nullptr);
304 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
305 add_child(node);
306 node->zero_fill();
307
308 return node;
309}
310
311/**
312 * Creates a new MeshNormals instance, as a child of this node.
313 */
315add_MeshNormals(const string &name) {
316 XFileTemplate *xtemplate = XFile::find_standard_template("MeshNormals");
317 nassertr(xtemplate != nullptr, nullptr);
319 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
320 add_child(node);
321 node->zero_fill();
322
323 return node;
324}
325
326/**
327 * Creates a new MeshVertexColors instance, as a child of this node.
328 */
330add_MeshVertexColors(const string &name) {
331 XFileTemplate *xtemplate = XFile::find_standard_template("MeshVertexColors");
332 nassertr(xtemplate != nullptr, nullptr);
334 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
335 add_child(node);
336 node->zero_fill();
337
338 return node;
339}
340
341/**
342 * Creates a new MeshTextureCoords instance, as a child of this node.
343 */
345add_MeshTextureCoords(const string &name) {
346 XFileTemplate *xtemplate = XFile::find_standard_template("MeshTextureCoords");
347 nassertr(xtemplate != nullptr, nullptr);
349 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
350 add_child(node);
351 node->zero_fill();
352
353 return node;
354}
355
356/**
357 * Creates a new MeshMaterialList instance, as a child of this node.
358 */
360add_MeshMaterialList(const string &name) {
361 XFileTemplate *xtemplate = XFile::find_standard_template("MeshMaterialList");
362 nassertr(xtemplate != nullptr, nullptr);
364 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
365 add_child(node);
366 node->zero_fill();
367
368 return node;
369}
370
371/**
372 * Creates a new Material instance, as a child of this node.
373 */
375add_Material(const string &name, const LColor &face_color,
376 double power, const LRGBColor &specular_color,
377 const LRGBColor &emissive_color) {
378 XFileTemplate *xtemplate = XFile::find_standard_template("Material");
379 nassertr(xtemplate != nullptr, nullptr);
381 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
382 add_child(node);
383 node->zero_fill();
384
385 (*node)["faceColor"]["red"] = face_color[0];
386 (*node)["faceColor"]["green"] = face_color[1];
387 (*node)["faceColor"]["blue"] = face_color[2];
388 (*node)["faceColor"]["alpha"] = face_color[3];
389 (*node)["power"] = power;
390 (*node)["specularColor"]["red"] = specular_color[0];
391 (*node)["specularColor"]["green"] = specular_color[1];
392 (*node)["specularColor"]["blue"] = specular_color[2];
393 (*node)["emissiveColor"]["red"] = emissive_color[0];
394 (*node)["emissiveColor"]["green"] = emissive_color[1];
395 (*node)["emissiveColor"]["blue"] = emissive_color[2];
396
397 return node;
398}
399
400/**
401 * Creates a new TextureFilename instance, as a child of this node.
402 */
404add_TextureFilename(const string &name, const Filename &filename) {
405 XFileTemplate *xtemplate = XFile::find_standard_template("TextureFilename");
406 nassertr(xtemplate != nullptr, nullptr);
408 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
409 add_child(node);
410 node->zero_fill();
411
412 (*node)["filename"] = filename.to_os_specific();
413
414 return node;
415}
416
417/**
418 * Creates a new Frame instance, as a child of this node.
419 */
421add_Frame(const string &name) {
422 XFileTemplate *xtemplate = XFile::find_standard_template("Frame");
423 nassertr(xtemplate != nullptr, nullptr);
425 new XFileDataNodeTemplate(get_x_file(), name, xtemplate);
426 add_child(node);
427 node->zero_fill();
428
429 return node;
430}
431
432/**
433 * Creates a new FrameTransformMatrix instance, as a child of this node.
434 */
436add_FrameTransformMatrix(const LMatrix4d &mat) {
437 XFileTemplate *xtemplate =
438 XFile::find_standard_template("FrameTransformMatrix");
439 nassertr(xtemplate != nullptr, nullptr);
441 new XFileDataNodeTemplate(get_x_file(), "", xtemplate);
442 add_child(node);
443 node->zero_fill();
444
445 XFileDataObject &xmat = (*node)["frameMatrix"]["matrix"];
446 xmat[0] = mat(0, 0);
447 xmat[1] = mat(0, 1);
448 xmat[2] = mat(0, 2);
449 xmat[3] = mat(0, 3);
450
451 xmat[4] = mat(1, 0);
452 xmat[5] = mat(1, 1);
453 xmat[6] = mat(1, 2);
454 xmat[7] = mat(1, 3);
455
456 xmat[8] = mat(2, 0);
457 xmat[9] = mat(2, 1);
458 xmat[10] = mat(2, 2);
459 xmat[11] = mat(2, 3);
460
461 xmat[12] = mat(3, 0);
462 xmat[13] = mat(3, 1);
463 xmat[14] = mat(3, 2);
464 xmat[15] = mat(3, 3);
465
466 return node;
467}
468
469/**
470 * Transforms the indicated egg name to a name that is acceptable for a node
471 * in the X File format.
472 */
474make_nice_name(const string &str) {
475 string result;
476
477 string::const_iterator si;
478 for (si = str.begin(); si != str.end(); ++si) {
479 if (isalnum(*si)) {
480 result += (*si);
481 } else {
482 switch (*si) {
483 case '-':
484 result += (*si);
485 break;
486 default:
487 result += "_";
488 }
489 }
490 }
491
492 if (str.empty() || isdigit(str[0])) {
493 // If the name begins with a digit, or if it is empty, then we must make
494 // it begin with something else, like for instance an underscore.
495 result = '_' + result;
496 }
497
498 return result;
499}
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
std::string to_os_specific() const
Converts the filename from our generic Unix-like convention (forward slashes starting with the root a...
A base class for all things which can have a name.
Definition namable.h:26
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition namable.I:44
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
This is an implementation of the Windows GUID object, used everywhere as a world-unique identifier fo...
Definition windowsGuid.h:26
This is a node which contains all of the data elements defined by a template.
void zero_fill()
Fills the data node with zero-valued elements appropriate to the template.
This is an abstract base class for an XFileNode which is also an XFileDataObject.
The abstract base class for a number of different types of data elements that may be stored in the X ...
A single node of an X file.
Definition xFileNode.h:40
virtual bool has_guid() const
Returns true if this node has a GUID associated.
XFileNode * find_descendent(const std::string &name) const
Returns the first child or descendent found with the indicated name after a depth-first search,...
Definition xFileNode.cxx:99
XFileDataNode * add_Frame(const std::string &name)
Creates a new Frame instance, as a child of this node.
XFileDataNode * add_MeshTextureCoords(const std::string &name)
Creates a new MeshTextureCoords instance, as a child of this node.
virtual const WindowsGuid & get_guid() const
If has_guid() returned true, returns the particular GUID associated with this node.
int get_num_children() const
Returns the list of children of this node.
Definition xFileNode.I:37
virtual bool is_standard_object(const std::string &template_name) const
Returns true if this node represents an instance of the standard template with the indicated name,...
virtual void write_text(std::ostream &out, int indent_level) const
Writes a suitable representation of this node to an .x file in text mode.
virtual bool is_reference() const
Returns true if this node represents an indirect reference to an object defined previously in the fil...
XFileDataNode * add_TextureFilename(const std::string &name, const Filename &filename)
Creates a new TextureFilename instance, as a child of this node.
virtual bool is_template_def() const
Returns true if this node represents the definition of some template.
XFileDataNode * add_MeshVertexColors(const std::string &name)
Creates a new MeshVertexColors instance, as a child of this node.
XFileDataNode * add_Material(const std::string &name, const LColor &face_color, double power, const LRGBColor &specular_color, const LRGBColor &emissive_color)
Creates a new Material instance, as a child of this node.
void add_child(XFileNode *node)
Adds the indicated node as a child of this node.
XFileDataNode * add_MeshNormals(const std::string &name)
Creates a new MeshNormals instance, as a child of this node.
XFileDataNode * add_FrameTransformMatrix(const LMatrix4d &mat)
Creates a new FrameTransformMatrix instance, as a child of this node.
static std::string make_nice_name(const std::string &str)
Transforms the indicated egg name to a name that is acceptable for a node in the X File format.
XFileNode * find_child(const std::string &name) const
Returns the child with the indicated name, if any, or NULL if none.
Definition xFileNode.cxx:55
virtual void clear()
Removes all children from the node, and otherwise resets it to its initial state.
virtual bool matches(const XFileNode *other) const
Returns true if the node, particularly a template node, is structurally equivalent to the other node ...
virtual bool repack_data(XFileDataObject *object, const XFileParseDataList &parse_data_list, PrevData &prev_data, size_t &index, size_t &sub_index) const
This is called on the template that defines an object, once the data for the object has been parsed.
XFileDataNode * add_MeshMaterialList(const std::string &name)
Creates a new MeshMaterialList instance, as a child of this node.
virtual bool is_object() const
Returns true if this node represents a data object that is the instance of some template,...
XFileNode * get_child(int n) const
Returns the nth child of this node.
Definition xFileNode.I:46
XFileDataNode * add_Mesh(const std::string &name)
Creates a new Mesh instance, as a child of this node.
virtual bool fill_zero_data(XFileDataObject *object) const
This is similar to repack_data(), except it is used to fill the initial values for a newly-created te...
int find_child_index(const std::string &name) const
Returns the index number of the child with the indicated name, if any, or -1 if none.
Definition xFileNode.cxx:70
A container for a pvector of the above objects.
A template definition in the X file.
This represents the complete contents of an X file (file.x) in memory.
Definition xFile.h:32
static XFileTemplate * find_standard_template(const std::string &name)
Returns the standard template associated with the indicated name, if any, or NULL if none.
Definition xFile.cxx:237
This is our own Panda specialization on the default STL map.
Definition pmap.h:49
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.